Submission and delivery
Protect and authenticate submission
Separate transport encryption, certificate validation, and user authentication in an SMTP connection.
Three different things make a submission connection safe. People mix them up constantly, so let’s name them.
TLS encrypts the connection. Nobody on the network can read what passes through.
Certificate validation checks that the server on the other end is really smtp.fastmail.com, not someone pretending to be it.
Authentication proves which account is sending. That’s your password or token.
Each one solves a different problem. You need all three.
Where TLS starts
On port 587, the connection starts in cleartext. The client sends EHLO, sees STARTTLS in the list, and asks for the upgrade. On port 465, TLS starts before any SMTP command.
Either way, the client should only authenticate once encryption is active. Here is the 587 flow:
C: EHLO laptop.local
S: 250-STARTTLS
C: STARTTLS
S: 220 Ready to start TLS
... TLS handshake ...
C: EHLO laptop.local
S: 250-AUTH PLAIN OAUTHBEARER
Notice the second EHLO. It isn’t cleanup. After TLS, the server forgets the earlier capability exchange and often advertises AUTH only now, inside the protected channel. Skip it and you never learn which mechanisms are available.
AUTH is not encryption
An AUTH mechanism defines how credentials travel. PLAIN sends the username and password base64-encoded. OAUTHBEARER sends a token.
Base64 is not protection. Anyone capturing a cleartext session decodes it in one line. The encryption comes from TLS, never from the mechanism.
My advice: prefer short-lived tokens or app-specific passwords when the provider offers them. And never paste real credentials into a transcript you share, including base64 ones.
Validate the certificate
Encryption alone is not enough. A TLS handshake with the wrong server still encrypts everything perfectly, straight to the attacker.
Validation checks three things: the certificate chains to a trusted authority, it’s valid for the hostname you connected to, and it hasn’t expired.
The tempting shortcut is turning validation off when setup fails. Something like this in a Node.js mailer:
tls: { rejectUnauthorized: false }
That makes the error go away and silently accepts any certificate, including a forged one. The real fix is to use the hostname on the certificate, usually the provider’s documented submission host, instead of an IP address or an alias.
Try drawing three states on paper: before TLS, during the handshake, and after the second EHLO. Mark the earliest point where sending AUTH is acceptable.
Lesson completed