Fix Nodemailer TLS Certificate Hostname Errors
What ERR_TLS_CERT_ALTNAME_INVALID means when Nodemailer connects to an SMTP server, why it happens, and how to fix it without disabling certificate verification.
On this page
Nodemailer can fail to send mail with an error that looks like a networking problem but is actually about identity verification: the TLS certificate the SMTP server presented does not cover the hostname Nodemailer connected to.
ERR_TLS_CERT_ALTNAME_INVALID:
Hostname/IP does not match certificate's altnamesThis article explains what that error means, why it's different from most other SMTP connection failures, and how to fix it correctly.
What the error actually checks
Every TLS connection, SMTP included, verifies two separate things: that the certificate is signed by a trusted authority, and that the certificate was actually issued for the host you're connecting to. The second check compares the hostname you connected with against the certificate's Subject Alternative Names (SAN) — the list of hostnames the certificate is valid for.
Node.js performs this comparison in tls.checkServerIdentity(hostname, cert). Per the Node.js TLS documentation, it returns an Error populated with reason, host, and cert when the hostname doesn't match any entry in subjectaltname, and undefined on success. ERR_TLS_CERT_ALTNAME_INVALID is that failure surfacing as a thrown error.
This means the connection itself worked, and the certificate itself may be entirely valid — just not valid for the hostname you used.
Four different things that are easy to confuse
A working SMTP configuration depends on four values that are conceptually separate, even though they often look similar:
| Value | What it is |
|---|---|
| SMTP hostname | The host Nodemailer opens a TCP/TLS connection to (smtp.example.com). |
| Certificate SAN entries | The hostname(s) the SMTP server's TLS certificate was actually issued for. |
| Mailbox address | The user/from email address (billing@example.com) — unrelated to either of the above. |
| SMTP port and encryption mode | 465 (implicit TLS) vs. 587 (STARTTLS) vs. 25 — determines when TLS negotiation happens, not which hostname is checked. |
ERR_TLS_CERT_ALTNAME_INVALID is specifically a mismatch between the first two. It has nothing to do with your mailbox address, and nothing to do with your SMTP username or password — this is not an authentication error, even though it happens during connection setup and can feel like one.
Why the mismatch happens
The most common cause is connecting to a hostname that isn't the one the certificate was issued for — even when the underlying server is correct. This happens when:
- The
SMTP_HOSTvalue is an IP address instead of a hostname. Certificates are issued for hostnames; connecting by IP means there is normally nothing in the SAN list to match against, unless the certificate specifically lists that IP. - The
SMTP_HOSTvalue is an internal, load-balancer, or CDN-fronted hostname that differs from the public hostname the certificate actually covers. - The provider migrated or renamed its mail infrastructure and the old hostname you're still using now points to (or is proxied through) a server presenting a different certificate.
- A self-signed or internally issued certificate simply doesn't have your hostname in its SAN list at all.
Fixing it: use the certificate-covered hostname
The direct fix is to connect using the exact hostname your SMTP provider documents and that the certificate actually covers — not an IP address, and not an internal alias, unless the provider specifically states that alias is what the certificate is issued for:
const nodemailer = require("nodemailer");
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST, // must match the certificate's SAN entries
port: Number(process.env.SMTP_PORT) || 587,
secure: false, // false = STARTTLS on 587; true = implicit TLS on 465
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
},
});Check your provider's SMTP documentation for the exact hostname it issues certificates for — this is provider-specific, and guessing at a plausible-looking hostname is how the mismatch happens in the first place.
If you must connect by IP address
If a network constraint genuinely requires connecting by IP (rare for outbound SMTP, but possible behind certain firewalls or split-horizon DNS setups), Nodemailer exposes tls.servername for exactly this case. Per Nodemailer's SMTP documentation, tls.servername sets the hostname used for certificate validation independently of the host you connect to — and is "required when host is set to an IP address":
const transporter = nodemailer.createTransport({
host: "203.0.113.10", // example IP — replace with the provider's documented address
port: 587,
secure: false,
tls: {
servername: "smtp.example.com", // the hostname the certificate is actually issued for
},
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
},
});This keeps full certificate validation active — it just tells Node.js which hostname to validate the certificate against, separately from where the TCP connection goes.
Understanding secure vs. STARTTLS
Nodemailer's secure option is not "TLS on or off" — both settings encrypt the connection in a correctly configured setup, they just differ in when:
secure: true— implicit TLS. The TLS handshake happens immediately when the connection opens. Typically port465.secure: false— the connection starts in plaintext, then upgrades to TLS via STARTTLS "automatically if it's supported by the server, unless you explicitly disable it" per the Nodemailer SMTP documentation. Typically port587(or25).
secure: false does not mean unencrypted. It means STARTTLS negotiation, which is the standard mode for port 587. Setting requireTLS: true makes the STARTTLS upgrade mandatory — the connection fails outright rather than silently falling back to plaintext if the server doesn't offer it. ignoreTLS: true disables STARTTLS entirely and should not be used for a production mail path.
The certificate hostname check happens as part of this same TLS negotiation, regardless of which mode you're in — implicit TLS and STARTTLS both end up validating the certificate against the hostname you connected to.
What not to do: disabling certificate verification
Nodemailer's tls object accepts rejectUnauthorized: false, which disables certificate verification — including the hostname check — entirely.
// Do not use this as a production fix.
tls: {
rejectUnauthorized: false,
}This makes the error disappear because Node.js stops checking the certificate at all, not because the underlying mismatch was resolved. The Node.js TLS documentation is explicit that rejectUnauthorized defaults to true for this reason: with it disabled, there is no verification that you're actually talking to your real SMTP provider rather than an attacker positioned between you and it (a man-in-the-middle). Credentials sent over that connection — your SMTP username and password — are exposed to whoever is in that position.
If you need the connection to succeed while you sort out the correct hostname, prefer a temporary, clearly-labeled development-only override, and never ship rejectUnauthorized: false to a production mail path.
A short diagnostic sequence
- Read the exact hostname from
SMTP_HOST(without printing the full transport config, which includes credentials). - Confirm that hostname against your provider's current SMTP documentation — not an old configuration example or a previous provider's docs.
- Confirm whether
SMTP_HOSTis an IP address. If so, that's almost certainly the mismatch; switch to the documented hostname or settls.servername. - Confirm the port and
securevalue match what the provider documents for that hostname (implicit TLS vs. STARTTLS use different ports). - Retry with the corrected hostname and capture the sanitized result.
Common mistakes
Treating this as an authentication failure
ERR_TLS_CERT_ALTNAME_INVALID happens during the TLS handshake, before SMTP authentication is even attempted. Changing the SMTP username or password will not fix it.
Copying a hostname from an old integration or a different provider's example
SMTP hostnames are provider-specific and sometimes account-specific. A hostname that worked for a previous mail provider, or that appears in a generic tutorial, is not guaranteed to match your current provider's certificate.
Reaching for rejectUnauthorized: false as the first fix
It resolves the symptom, not the cause, and removes protection against the exact class of failure (server impersonation) this check exists to catch.
Publishing SMTP credentials while debugging
When sharing logs, screenshots, or a sanitized .env for troubleshooting, remove SMTP_USER and SMTP_PASSWORD entirely — don't just blur them. Never paste a complete .env file, sanitized or not, into a public issue, forum post, or article; recreate only the specific lines that are relevant with placeholder values.
Verification checklist
-
SMTP_HOSTis set to the exact hostname your provider documents for its certificate, not an IP address or internal alias. -
SMTP_PORTandsecurematch the connection mode your provider expects for that hostname. - The application connects and authenticates successfully with
rejectUnauthorizedleft at its default (true). - No
.envvalues, SMTP credentials, or full connection details appear in shared logs or screenshots. - Sending a real test message succeeds after the fix, and the original error no longer appears in logs.
Claims to manually verify before publishing
-
Claim: You personally encountered
ERR_TLS_CERT_ALTNAME_INVALIDin a specific project.- Why verification is needed: This draft was written from Node.js/Nodemailer documentation and the error pattern supplied for the article, not a captured incident.
- Suggested evidence: The sanitized original error output, the SMTP host/port/secure values in use (with credentials removed), and confirmation of which change resolved it.
-
Claim: Switching to the provider-documented hostname (or setting
tls.servername) was the fix that worked.- Why verification is needed: This is the technically correct fix per Node.js/Nodemailer documentation, but it has not been confirmed against a real failing case in this project.
- Suggested evidence: Before-and-after sanitized connection logs showing the hostname change and a successful send.
-
Claim: The mail provider referenced in your final version documents the hostname/certificate behavior described here.
- Why verification is needed: Certificate SAN coverage and documented hostnames are provider-specific and can change.
- Suggested evidence: A link to the specific provider's current SMTP setup documentation.
Related writing
- JWT Access and Refresh Token StrategyDesign short-lived access tokens and rotating refresh-token sessions with revocation, browser protections, and key rotation.
- Hashing vs Encryption vs Encoding — The Differences Developers Must UnderstandA production-minded map of encoding, hashing, and encryption—salts, passwords, JWTs, Base64 myths, interview answers, and the mistakes reviewers catch.
- JWT authentication without mythology — rotations, revocation, and session ergonomicsSymmetric versus asymmetric verification, JWKS fleets, leaky storage pitfalls, and when opaque cookies outperform bearer tokens.