Skip to content

fix(email): greet SMTP relays with a qualified hostname instead of [127.0.0.1] - #6799

Merged
waleedlatif1 merged 3 commits into
stagingfrom
fix/smtp-ehlo-name
Aug 18, 2026
Merged

fix(email): greet SMTP relays with a qualified hostname instead of [127.0.0.1]#6799
waleedlatif1 merged 3 commits into
stagingfrom
fix/smtp-ehlo-name

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • 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.
  • Strict relays refuse that greeting before any mail moves — Google Workspace's smtp-relay.gmail.com answers 421-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.
  • Sim now greets with the domain it is served from, as RFC 5321 §4.1.4 asks, with SMTP_EHLO_NAME to 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.
  • Applied to both nodemailer SMTP transports: the platform mail provider and the SMTP block's send route. SES/Resend/Azure/Gmail go over HTTP APIs and are unaffected.
  • Plumbed through the env schema, capability definition, .env.example, Helm values + schema, and the self-hosting docs.

Fixes #6778

Type of Change

  • Bug fix

Testing

  • New unit tests for the resolver, including the k8s fallback, the override, a dotless name, and a CRLF-carrying name. Verified they fail when the fix is reverted.
  • bun run type-check, bun run lint, bun run check:audits (29/29), helm lint and helm template with the new key all pass.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…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.
@vercel

vercel Bot commented Aug 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Aug 18, 2026 12:48am

Request Review

@cursor

cursor Bot commented Aug 18, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes only SMTP greeting behavior on a path that was broken on Kubernetes; validation limits malformed EHLO values, but misconfigured overrides could still break relay acceptance for SMTP-only deployments.

Overview
Fixes SMTP sessions that fail at EHLO on Kubernetes (and other hosts with dotless names), where nodemailer would greet as [127.0.0.1] and strict relays such as Google Workspace’s smtp-relay.gmail.com close with 421-4.7.0.

getSmtpEhloName() resolves the nodemailer name field: optional SMTP_EHLO_NAME, otherwise the app’s served domain from NEXT_PUBLIC_APP_URL (with port stripped). Invalid values (dotless hostnames, malformed address literals, CRLF) are rejected with a one-time warning and fall back rather than being sent on the wire.

Both SMTP nodemailer transports now set name: getSmtpEhloName() — the platform SMTP mail provider and the workflow SMTP send API route. HTTP-based providers are unchanged.

Configuration and docs add SMTP_EHLO_NAME (env schema, .env.example, Helm values/schema 1.5.3, self-hosting email troubleshooting and FAQ). Unit tests cover k8s fallback, overrides, literals, and injection-style names.

Reviewed by Cursor Bugbot for commit 3334de8. Configure here.

@greptile-apps

greptile-apps Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR gives both Nodemailer SMTP transports a validated EHLO identity derived from an explicit override or the application domain.

  • Adds strict FQDN and IPv4/IPv6 address-literal validation with fallback behavior.
  • Wires SMTP_EHLO_NAME through application and Helm configuration.
  • Adds resolver tests and updates self-hosting documentation.
  • The current HEAD fixes both previously reported address-literal validation issues.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

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
Loading

Reviews (3): Last reviewed commit: "fix(email): accept any casing of the IPv..." | Re-trigger Greptile

Comment thread apps/sim/lib/messaging/email/ehlo.ts Outdated
Comment thread apps/sim/lib/messaging/email/ehlo.ts
…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.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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.

Comment thread apps/sim/lib/messaging/email/ehlo.ts Outdated
…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.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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.

@waleedlatif1
waleedlatif1 merged commit 9dc828f into staging Aug 18, 2026
33 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/smtp-ehlo-name branch August 18, 2026 01:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant