npm / nodemailer
nodemailer
What changed in nodemailer 7 to 10, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-17.
9 breaking33 security4 new APIs and options6 performance5 behavior and defaults1 tooling93 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initnodemailer 1079 changes
Breaking changes 6
A stream that was already read or destroyed fails the message with ESTREAM instead of producing an empty attachment, and streams are destroyed when a message fails.
After a failed STARTTLS, authentication is skipped on the unencrypted connection unless forceAuth is set.
Any 421 reply ends the SMTP session; when the server closes an idle connection, SMTPConnection emits only end, not an ECONNECTION error.
Internal members are no longer included in the published declarations.
Node.js 20 or newer is required to run Nodemailer 10.
Hosts that the legacy URL parser would truncate are now refused.
Security 9
Bounds the work a message can make the mailer do.
Credentials are stripped on any cross-origin redirect.
The requireTLS setting is now honored.
Nodemailer: Quoted local-part can produce malformed envelope recipient through RFC 5322 comment parsing
Nodemailer: Quadratic backtracking in the addressparser free-text fallback allows remote denial of service
Nodemailer addressparser: O(n^2) on comment-joined addresses enables a remote DoS (reachable via mailparser)
The fetch behavior now honors the cookie Domain attribute without accepting public suffixes.
Nodemailer: Nested structured recipient arrays bypass the parser depth limit and cause stack exhaustion DoS
Nodemailer: Process-global DNS cache reuses TLS
servernameacross transports, enabling cross-tenant SMTP credential disclosure
New APIs and options 2
Adds a pool option that closes pooled connections after 4 minutes without a message; set it to 0 to keep them open.
Nodemailer now provides ES module and CommonJS builds, affecting how applications can import it.
Performance 4
Base64 and quoted-printable are encoded without per-chunk delays.
Unfolding folded DKIM header lines now takes linear time.
Reassembling multiline SMTP replies now takes linear time.
Scans free text for an address in linear time.
Behavior and default changes 5
The timeout covers session setup, including DNS, proxy handshake, TCP, TLS, greeting, and STARTTLS; greetingTimeout still bounds the greeting and STARTTLS handshake within it.
Errors now carry the system error code Nodemailer replaced, such as ECONNREFUSED.
When the server announces PIPELINING, MAIL FROM, RCPT TO, and DATA are sent in one batch.
A message with rejected recipients resets the pooled connection with RSET and reuses it; a message is requeued if the server dropped a reused connection before any of it was sent.
ETIMEDOUT errors now carry timeoutType.
Tooling 1
The @types/nodemailer type layout continues to work with this release.
Fixes and other changes 52
Keeps per-message auth off the transport's token endpoint.
A second connect() call is refused.
An encoded part is finished only after its output has been read.
Preserves ERR_ACCESS_DENIED from the Node.js permission model.
Importing Nodemailer no longer reads the environment or the interface table.
Encodes a lone CR or LF in binary quoted-printable parts.
An early sendmail exit is reported as such.
Nagle is turned off for SMTP sockets.
Decodes an SMTPUTF8 domain from its A-label form.
Escaped parentheses inside comments are now kept during address parsing.
Cookie names retain their case when fetched.
Cookie name-value pairs are read by position.
NodemailerError is compatible with @types/node 26 ErrnoException.
NodemailerError now inherits its code from ErrnoException.
Quoted display names without an @ are kept out of the parsed address.
Header parameters are read and written according to RFC 2045 and RFC 2231.
Reads advertised SASL methods without backtracking regexes.
Strips comments inside an angle-addr before it becomes the address.
A bare CR is turned into CRLF.
Every send is settled on a connection error.
Fetch is bounded.
Pool requeues back off.
The CommonJS entry point and services subpath are compatible with the pre-TypeScript build.
Form-body encoding failures are reported through the returned stream.
A password login fails cleanly when the server offers only XOAUTH2.
The layout of the bundled declarations is restored.
wrap() terminates for short line lengths and a trailing incomplete escape.
Attachment filenames are now derived from the basename of a Windows path.
Bounds the '@' probe to the run being scanned, fixing address parsing.
Keeps text after a comment out of a quoted local part address during parsing.
The boundary is cleaned where it is written, not only where it is built.
Every control character is dropped from multipart boundary material.
Buffer input is no longer double encoded when chunking base64 MIME words.
Line breaks are stripped from multipart boundary material.
A boundary consisting only of line breaks is preserved instead of being stripped to empty.
Rate-limited connections are released when they close.
Cookies without a Path are scoped to the RFC 6265 default path.
Cookies set with Path are sent back only to the exact path.
httpHeaders and tls are preserved for href alternatives and icalEvent.
A configuration error is thrown when the SES client is missing.
Well-known services are resolved by their primary domains.
Nested recipient arrays are flattened without recursion.
Type declarations now accept an explicit undefined for optional properties.
Configuration object keys alongside its url are now applied.
A colon in the user name is preserved when parsing a connection or proxy URL.
Raw messages are canonicalized the way verifiers do, improving DKIM verification compatibility.
Hostnames are resolved when the runtime has no interface table.
An incomplete server reply is no longer stored in lastServerResponse.
The well-known services JSON file remains available at its package path.
Timers are cleared when a connection is dropped before the greeting.
The pool slot is freed if the proxy socket cannot be opened.
A transporter remains assignable to the plain Transporter type.
nodemailer 937 changes
Breaking changes 1
HTTPS requests made while fetching remote content now validate the server's TLS certificate by default; set rejectUnauthorized to false per request to opt out.
Security 15
Message data can no longer reopen the access sandbox.
The message access policy is now applied in resolveContent, so content resolution respects the policy.
Nodemailer: resolveContent() on a MailMessage bypasses disableFileAccess/disableUrlAccess when called with the legacy signature
Nodemailer: IDN/Punycode domain allow-list bypass leads to email delivery to an attacker-controlled domain
Nodemailer: Quadratic (O(n²)) time complexity in addressparser allows remote denial of service via a crafted address list
Nodemailer: Recipient-domain validation bypass via RFC 5322 comment mis-parsing leads to email delivery to an attacker-controlled domain
Hardens copies of user-supplied keys and URL fetching.
Header key callbacks and DKIM tags can no longer inject content.
Control characters are kept out of header values and msg-id headers.
Hardened STARTTLS upgrades and secure socket handling.
CRLF is rejected in the destination to prevent request injection.
Low-severity issues in smtp-connection were hardened.
SMTP response parsing and socket lifecycle handling were hardened.
Nodemailer: Message-level raw option bypasses disableFileAccess/disableUrlAccess, enabling arbitrary file read and full-response SSRF in the delivered message
The raw message option now enforces disableFileAccess and disableUrlAccess.
New APIs and options 1
Caps the number of recipients per message.
Performance 1
Address lists are handled in linear time.
Fixes and other changes 19
A MIME node now inherits the access policy from the tree it belongs to.
Domain encoding now applies UTS-46 mapping.
URL delimiters are kept away from the domain mapper.
Envelope recipient deduplication is linear time, including across address headers.
Address parsing now terminates the domain at an RFC 5322 comment.
Recovers the addr-spec when an angle-addr contains whitespace.
Addresses are normalized so the header and envelope agree.
DEL is encoded in header parameters and List-* comments.
Control characters are kept out of the remaining header positions.
Special characters in List-* header comments are now escaped.
The continuation key is now starred when a parameter line is restarted.
Addresses parsed from strings are now normalized.
Backslashes and quotes in the Content-Type name parameter are escaped.
Unpaired surrogates in header parameter values are percent encoded.
HT, CR, and LF in header parameter values are encoded instead of quoted.
Surrogate pairs remain intact when chunking base64 MIME words.
An unpaired surrogate no longer consumes the next character during MIME processing.
Operator characters inside an address-literal are now kept as text.
Prevents callback double-invocation and hangs on synchronous errors.
nodemailer 828 changes
Breaking changes 2
Strict TLS is enforced for OAuth2 and Ethereal credential requests.
The error code NoAuth was renamed to ENOAUTH, so code checking the old error code must be updated.
Security 7
Ethereal response props are parsed without polynomial regex backtracking.
Nodemailer: CRLF injection in Nodemailer List-* header comments allows arbitrary message header injection
Nodemailer jsonTransport bypasses disableFileAccess and disableUrlAccess during message normalization
Nodemailer: Improper TLS Certificate Validation in OAuth2 Token Fetch Enables Credential Interception
Nodemailer Vulnerable to SMTP Command Injection via CRLF in Transport name Option (EHLO/HELO)
Nodemailer has SMTP command injection due to unsanitized
envelope.sizeparameterDNS fallback is hardened against race conditions and cleanup issues.
Performance 1
Improves efficiency on hot paths.
Fixes and other changes 18
AWS SES transport errors are now tagged with the ESES code.
The application/ics attachment now includes content supplied through icalEvent path or href.
URL schemes are now stripped from List-ID header values.
The transport-level newline option is now applied in stream and sendmail transports.
For non-pooled SMTP transports, the callback is now resolved at send time.
Falls back to a lower-severity handler when a custom logger lacks a level method.
Four listener and stream leaks in the SMTP transport, connection, and pool are fixed.
Keeps the domain in UTF-8 when the local part is non-ASCII.
Restores base64 wrap() trim behavior to prevent trailing CRLF.
SMTP server responses are decoded as UTF-8 at line boundaries.
Fixes group name fallback producing undefined when parsing addresses.
Fixes cookie bugs.
Merges fragmented display names with unquoted commas when parsing addresses.
Adds Gmail Workspace service configuration.
TLS errors during socket teardown are now absorbed.
Connections now fall back to alternative DNS addresses.
Error codes are centralized and standardized.
Socket cleanup is improved to prevent potential memory leaks.
nodemailer 77 changes
Security 2
Prevents stack overflow denial of service when parsing deeply nested groups.
Nodemailer’s addressparser is vulnerable to DoS caused by recursive calls
New APIs and options 1
Adds support for REQUIRETLS.
Fixes and other changes 4
Transient connection error logs are downgraded to warn level.
Attachments with the message/rfc822 media type now use 8bit encoding.
Data URI content type is preserved.
The data URI size limit increases from 100KB to 50MB, allowing larger data URIs.