fix(email): greet SMTP relays with a qualified hostname instead of [127.0.0.1] - #6799
Conversation
…27.0.0.1] Nodemailer derives the EHLO greeting from os.hostname() and substitutes the address literal [127.0.0.1] whenever that name contains no dot. Kubernetes pod hostnames never contain one, so every k8s deployment introduced itself to the relay as loopback and strict relays refused the session before any mail moved. Send the domain the app is served from instead, as RFC 5321 4.1.4 asks, with SMTP_EHLO_NAME to override it for relays that expect a different identity.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview
Both SMTP nodemailer transports now set Configuration and docs add Reviewed by Cursor Bugbot for commit 3334de8. Configure here. |
Greptile SummaryThe PR gives both Nodemailer SMTP transports a validated EHLO identity derived from an explicit override or the application domain.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| apps/sim/lib/messaging/email/ehlo.ts | Resolves and validates the SMTP EHLO identity, including correctly parsed IPv4 literals and case-insensitive tagged IPv6 literals. |
| apps/sim/lib/messaging/email/ehlo.test.ts | Covers fallback, override, malformed input, CRLF rejection, ports, and the previously reported address-literal cases. |
| apps/sim/lib/messaging/email/providers/smtp.ts | Applies the resolved EHLO name to the platform SMTP provider. |
| apps/sim/app/api/tools/smtp/send/route.ts | Applies the same resolved EHLO name to the SMTP tool transport. |
| apps/sim/lib/core/config/env.ts | Adds the optional SMTP_EHLO_NAME environment setting. |
| helm/sim/values.schema.json | Exposes SMTP_EHLO_NAME through the Helm values schema. |
| helm/sim/values.yaml | Adds the Helm value and documents its fallback behavior. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
Config[SMTP_EHLO_NAME] --> Resolver[getSmtpEhloName]
Domain[NEXT_PUBLIC_APP_URL domain] --> Resolver
Resolver --> Validation{Valid FQDN or address literal?}
Validation -->|Yes| Name[Nodemailer name option]
Validation -->|No override| Fallback[Validated application domain]
Fallback --> Name
Validation -->|No valid source| Default[Nodemailer default]
Name --> SMTP[SMTP EHLO greeting]
Default --> SMTP
Reviews (3): Last reviewed commit: "fix(email): accept any casing of the IPv..." | Re-trigger Greptile
…domain Review round 1. The bracketed branch matched a character class rather than an address, so [::::] and [13] reached the relay as a greeting it would refuse. Parse the address with node:net instead, which also admits the RFC 5321 IPv6: form. getEmailDomain reports a URL host, so a deployment served on a non-default port failed the qualified-name check and fell back to nodemailer's default — [127.0.0.1] again on Kubernetes, the exact failure this change exists to fix. Strip the port before validating.
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 43b2c70. Configure here.
…g SMTP_EHLO_NAME in setup Review round 2. RFC 5321 tags the IPv6 address-literal form, and RFC 5234 makes ABNF string literals case-insensitive, so [ipv6:2001:db8::1] is as valid as [IPv6:...]. The exact-prefix check routed it to isIPv4 and discarded it. Drop SMTP_EHLO_NAME from the email capability's optional fields. SMTP_SECURE, the same kind of optional transport knob on the same provider, is not modelled there either, and claiming the field obliged the setup wizard to prompt for it — a field whose entire purpose is to stay unset now that the default is right.
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 3334de8. Configure here.
Summary
EHLOgreeting fromos.hostname()and substitutes the address literal[127.0.0.1]whenever that name contains no dot. Kubernetes pod hostnames never contain one, so every k8s deployment introduced itself to the relay as loopback.smtp-relay.gmail.comanswers421-4.7.0 Try again later, closing connection. (EHLO), which surfaces as "All email providers failed" on invitations and verification mail. Our own self-hosting docs recommend that relay, so this broke the documented path.SMTP_EHLO_NAMEto override it for relays that expect a different identity. Names that are not a dotted FQDN or an address literal are rejected and logged rather than passed into the command..env.example, Helm values + schema, and the self-hosting docs.Fixes #6778
Type of Change
Testing
bun run type-check,bun run lint,bun run check:audits(29/29),helm lintandhelm templatewith the new key all pass.Checklist