Skip to content

fix(deps): upgrade nodemailer to 10 and mailparser to 3.12 - #482

Closed
KMKoushik wants to merge 1 commit into
mainfrom
hq/nodemailer-10
Closed

KMKoushik wants to merge 1 commit into
mainfrom
hq/nodemailer-10

Conversation

@KMKoushik

@KMKoushik KMKoushik commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

Summary

Upgrades the mail libraries flagged by Dependabot:

  • nodemailer ^8.0.5 → ^10.2.1 (apps/web, apps/smtp-server)
  • mailparser ^3.9.8 → ^3.12.4 (apps/smtp-server), which moves it to nodemailer 10.2.1 and html-to-text 10.0.1 → deepmerge-ts 8
  • smtp-server ^3.18.4 → ^3.21.1 (apps/smtp-server). The old version pinned its own copy of nodemailer 9.0.3, which is still affected by the alerts below. 3.21.1 depends on nodemailer 10.2.1.
  • Removed @types/nodemailer. nodemailer 10 is written in TypeScript and ships its own declarations, and there is no @types/nodemailer 10. TypeScript was already picking the bundled types.

Alerts fixed

nodemailer:

  • addressparser quadratic backtracking DoS (fixed in 10.0.6, high)
  • addressparser O(n²) address-list DoS (9.1.0, high)
  • Message-level raw option bypasses disableFileAccess/disableUrlAccess (9.0.1, high)
  • Recipient-domain validation bypass via RFC 5322 comments (9.1.0)
  • IDN/punycode domain allow-list bypass (9.1.0)
  • resolveContent() bypasses disableFileAccess/disableUrlAccess (9.1.1)
  • Nested recipient arrays stack exhaustion (10.0.2)
  • Process-global DNS cache reusing the TLS servername across transports (10.0.2)
  • DKIM header unfolding O(n²) (10.0.10), plus three addressparser group/quote/comment parsing issues (10.1.4)

mailparser → html-to-text → deepmerge-ts: stack exhaustion when merging recursive object graphs (deepmerge-ts < 8, high)

Breaking changes reviewed

  • 9.0.0: TLS certificates are now validated when nodemailer fetches remote content (attachment href/path URLs, OAuth2 token endpoints, proxy CONNECT). This doesn't affect us. sendRawEmail passes attachments as inline base64 content, and nothing in the repo uses href, path, OAuth2, or proxies.
  • 10.0.0: Requires Node.js 20 or newer. The repo requires >=22.13, and the smtp-server image uses node:22-alpine.
  • 10.0.0: Rewritten in TypeScript with dual ESM/CJS builds and a strict exports map. Everything we import still resolves:
  • @auth/core/next-auth declare an optional peer range of ^7.0.7 || ^8.0.5 for nodemailer, so pnpm warns about an unmet peer. This only matters for next-auth's default email sender, which we don't use, and createTransport behaves the same.
  • smtp-server 3.20–3.21 adds features and hardening (TS/ESM build, line limits, rejectOversized opt-in) with no breaking options. We only use onData, onAuth, secure, key/cert and size.

Raw MIME regression check

Added apps/web/src/server/aws/ses.unit.test.ts. It captures the SendEmailCommand that sendRawEmail builds and pins:

  • the configuration set and tenant
  • From/To/Cc/Bcc/Reply-To, the encoded Subject, Message-ID, Date and MIME-Version
  • X-Entity-Ref-ID, X-Usesend-Email-ID, List-Unsubscribe, List-Unsubscribe-Post, Precedence, In-Reply-To and References, and custom headers
  • the multipart/mixed → multipart/alternative structure, the text/html parts and the base64 attachment part
  • that optional headers are left out when they aren't set

The test passes on nodemailer 8.0.11 and on 10.2.1. I also dumped the full raw message for three cases (everything set, including unicode names/subject/attachment filename and a long folded List-Unsubscribe; html only; text only), normalizing boundaries, Message-ID, Date and X-Entity-Ref-ID. The output was byte-identical between 8.0.11 and 10.2.1.

Audit (pnpm audit --prod)

total critical high moderate low nodemailer deepmerge-ts
before 80 1 36 39 4 12 1
after 68 1 33 30 4 0 1

The remaining deepmerge-ts 7.1.5 finding comes from prisma → @prisma/config, not from mailparser. Prisma needs its own upgrade, which isn't part of this PR. The other remaining findings are in unrelated packages.

Verification

  • pnpm --filter=web typecheck ✅
  • web unit: 23 files / 135 tests ✅
  • web api: 7 files / 22 tests ✅
  • web trpc: 4 files / 10 tests ✅
  • smtp-server vitest run: 2 files / 8 tests ✅ (mailparser parsing of headers and recipients); tsc --noEmit ✅
  • CJS smoke test: require("nodemailer"), require("smtp-server") and require("mailparser") all load

No migrations. I didn't run a build.

Summary by CodeRabbit

  • Tests
    • Added coverage for email sending, including message identifiers, configuration values, MIME content, attachments, and optional headers. No end-user-visible behavior changes are noted.

@vercel

vercel Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
unsend-marketing Ready Ready Preview Oct 25, 2026 10:43pm UTC

@coderabbitai

coderabbitai Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 660a4741-ab38-4f29-a466-c39412c0cad3
Commits

Reviewing files that changed from the base of the PR and between 7634811 and 08fb7b1.

Files ignored due to path filters: 1
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
Files selected for processing: 3
  • apps/smtp-server/package.json
  • apps/web/package.json
  • apps/web/src/server/aws/ses.unit.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 1 remain after this review.

Walkthrough

The pull request updates mail-related dependency versions and removes the @types/nodemailer development dependency. It also adds tests for sendRawEmail using a mocked SESv2 client. The tests check SES command values, MIME headers and content, and behavior when selected optional inputs are undefined.

Possibly related PRs

Priority: Low

Change: Other

Merge Risk: Minimal · up to 08fb7

No concrete issue identified here prevents merging after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 1 files. (2 skipped: 2 … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the main dependency upgrades: Nodemailer to version 10 and mailparser to version 3.12.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 1 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/smtp-server/package.json

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

apps/web/package.json

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

apps/web/src/server/aws/ses.unit.test.ts

ESLint skipped: the matched ESLint configuration already failed (missing-dependency).

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@KMKoushik

Copy link
Copy Markdown
Member Author

Folded into #470 so the two lockfile changes land together.

@KMKoushik KMKoushik closed this Oct 25, 2026

This branch was successfully deployed

1 active deployment
Preview — 08fb7b11 Deployed Oct 25, 2026 by vercel[bot]
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