Safeguard
Supply Chain Security•

SMTP Explained: RFC 5321, STARTTLS, MTA-STS and SPF, DKIM, DMARC

SMTP (RFC 5321) moves mail between servers in plaintext by default. See how STARTTLS, MTA-STS, DANE, SPF, DKIM and DMARC each fix a different part of it.

Safeguard Security Team
42 min read

SMTP, the Simple Mail Transfer Protocol defined in RFC 5321 (October 2008), is the protocol mail servers use to hand messages to each other and the protocol your mail client uses to submit a message in the first place. It carries an envelope (who the message is from and to, for delivery purposes) plus the message itself, over TCP, with no encryption or sender authentication built in. Everything that makes modern email safer, STARTTLS, MTA-STS, DANE, SPF, DKIM and DMARC, was bolted on later, and each one fixes a different part of the problem.

STARTTLS encrypts one hop and can be silently skipped. MTA-STS and DANE stop it being skipped. SPF checks the envelope sender, DKIM signs the content, and DMARC ties both to the address a reader sees. This post covers the transaction, the ports and both layers of protection, checked against the RFCs, and ends with defender-side commands for domains and servers you own.

Key takeaways

  • SMTP is specified in RFC 5321 (October 2008), which obsoletes RFC 821 (August 1982), RFC 974, RFC 1869 and RFC 2821. The message format it carries is RFC 5322 (October 2008). Its approved revision is still in the RFC Editor queue.
  • A transaction is a short command and reply dialogue: greeting, EHLO, MAIL FROM, one or more RCPT TO, DATA, the message, a line containing a single dot, then QUIT. The envelope addresses in MAIL FROM and RCPT TO are separate from the From header a reader sees.
  • Port 25 is server to server relay. Port 587 is message submission (RFC 6409) with STARTTLS and authentication. Port 465 is message submission over implicit TLS (RFC 8314, January 2018).
  • STARTTLS (RFC 3207, February 2002) is opportunistic on port 25. RFC 3207 itself warns that an attacker on the path can delete the STARTTLS advertisement and force plaintext.
  • MTA-STS (RFC 8461) and DANE for SMTP (RFC 7672) let a receiving domain demand authenticated TLS. TLS-RPT (RFC 8460) sends daily reports when that fails.
  • SPF (RFC 7208) authorises the envelope sender, DKIM (RFC 6376) signs the message, DMARC aligns them with the visible From domain. DMARC moved to the Standards Track in May 2026 as RFC 9989, with reporting split into RFC 9990 and RFC 9991, all obsoleting RFC 7489. ARC (RFC 8617, Experimental) preserves results across forwarding.
  • SMTP smuggling (December 2023) abused disagreement about where a message ends; the fix is a strict receiving server.

What SMTP is for, where it sits, and the standards that define it

RFC 5321 describes it as a protocol that "transports a mail object", and it defines that object as "an envelope and content".

SMTP is an application layer protocol that runs over TCP. It is a text protocol: the client sends commands as lines of ASCII, the server answers with three digit reply codes and human readable text. RFC 5321 requires every line to end with a carriage return followed by a line feed (CRLF) and says conforming implementations "MUST NOT recognize or generate any other character or character sequence as a line terminator". That rule turned out to matter a great deal in 2023, as you will see below.

How RFC 5321 and RFC 5322 divide the work

RFC 5321 owns the envelope and the transfer: how a client finds the next server (through DNS MX records), how it introduces itself, how it names the return path and the recipients, how it sends the content, what the server replies, how retries and bounces work, and what trace information each relay must add. Every server that accepts a message must insert a Received header field, which is where the trail of hops in a message's headers comes from.

RFC 5322 (October 2008, obsoleting RFC 2822) owns the content: the header fields such as From, To, Subject, Date and Message-ID, and the body. RFC 5322 is explicit that the envelope is outside its scope. In its words, the "From:" field "specifies the author(s) of the message", while the "Sender:" field names the agent responsible for transmission.

So a message has two sets of addresses. The envelope sender in MAIL FROM is where bounces go. The header From is who the reader is told wrote it. SMTP itself does not require them to match, and RFC 5321 section 7.1 argues that trying to force them to match is "largely misguided" because forwarding, mailing lists and sending on someone's behalf all legitimately produce differences. That gap is exactly what SPF, DKIM and DMARC were later built to manage.

Roles in the path

A Mail User Agent (MUA) is the program a person uses. A Message Submission Agent (MSA, RFC 6409) accepts that user's mail after authentication. A Mail Transfer Agent (MTA) relays between domains, and a delivery agent stores the message for IMAP or POP3 to retrieve. One program, such as Postfix, can be MSA and MTA on different ports.

How SMTP works on the wire

A full transaction

RFC 5321 Appendix D.1 gives a typical transaction. The version below follows the same shape, with an added STARTTLS step as RFC 3207 section 5 shows it. S is the server and C is the client.

S: 220 mx.example.net ESMTP ready                 (greeting after TCP connect)
C: EHLO mail.example.org                          (client names itself)
S: 250-mx.example.net
S: 250-SIZE 52428800
S: 250-8BITMIME
S: 250-STARTTLS                                   (TLS is on offer)
S: 250 PIPELINING
C: STARTTLS
S: 220 Ready to start TLS
   ... TLS handshake; everything after this is encrypted ...
C: EHLO mail.example.org                          (state is reset; ask again)
S: 250-mx.example.net
S: 250-SIZE 52428800
S: 250 8BITMIME
C: MAIL FROM:<alice@example.org>                  (envelope sender)
S: 250 OK
C: RCPT TO:<bob@example.net>                      (envelope recipient)
S: 250 OK
C: RCPT TO:<nobody@example.net>
S: 550 No such user here                          (rejected per recipient)
C: DATA
S: 354 Start mail input; end with <CRLF>.<CRLF>
C: From: Alice <alice@example.org>                (RFC 5322 header fields)
C: To: Bob <bob@example.net>
C: Subject: Quarterly numbers
C:
C: Body text...
C: . (end of data)
S: 250 OK queued
C: QUIT
S: 221 mx.example.net Service closing transmission channel

EHLO and extensions. The original command was HELO. ESMTP, introduced by RFC 1869 (November 1995) and folded into RFC 5321, uses EHLO so the server can list the service extensions it supports, one per line. SIZE, 8BITMIME, PIPELINING, STARTTLS, AUTH, CHUNKING and DSN are all extensions advertised this way. IANA keeps the registry of SMTP service extensions.

One message, many recipients. RCPT TO can repeat, and each recipient is accepted or rejected separately.

DATA and the end of data marker. After a 354 reply the client sends the RFC 5322 message. The message ends with a line holding only a period. Because a real line of text could start with a period, RFC 5321 section 4.5.2 defines "transparency": the client adds an extra period to any line that begins with one, and the server strips it. The standard end of data sequence is therefore CRLF, period, CRLF.

The null reverse path. Bounce messages are sent with an empty MAIL FROM, so that a bounce about a bounce cannot loop. RFC 5321 requires that empty reverse path for delivery failure notifications.

Limits. RFC 5321 section 4.5.3 sets a 512 octet command line and a 1,000 octet text line, and timeouts such as 5 minutes for the greeting and 10 minutes after the final dot.

Reply codes

CodeMeaning in RFC 5321Where you see it
220Service readyGreeting; also "Ready to start TLS" after STARTTLS
221Service closing transmission channelAfter QUIT
250Requested mail action okay, completedEHLO lines, MAIL, RCPT, end of data
354Start mail input; end with CRLF . CRLFAfter DATA
421Service not available, closing channelServer shutting down or overloaded
450, 451, 452Temporary failure (mailbox busy, local error, too many recipients)Client should retry later
454TLS not available due to temporary reasonRFC 3207, after STARTTLS
530Authentication requiredRFC 6409 submission without AUTH
550Mailbox unavailable or rejected for policyUnknown user, relay denied
554Transaction failedAlso used by RFC 3207 to refuse commands without TLS

The first digit drives behaviour: 2 success, 3 send more, 4 retry later, 5 permanent failure.

Ports and what each one is for

PortIANA service nameDefined byPurposeTLS mode
25/tcpsmtpRFC 5321Relay between MTAs, and the only port MX delivery usesOpportunistic STARTTLS (RFC 3207)
587/tcpsubmissionRFC 6409 (November 2011)A user's client hands new mail to its own providerSTARTTLS, with authentication required
465/tcpsubmissionsRFC 8314 (January 2018)Same as 587, but TLS starts immediatelyImplicit TLS

The IANA service name registry confirms all three: smtp on 25, submission on 587 referencing RFC 6409, and submissions on 465 referencing RFC 8314. Port 465 has an odd history that RFC 8314 section 7.3 explains. It was briefly registered as "smtps", the registration was revoked and reassigned because MX delivery has no way to name a port other than 25, but widely deployed mail software kept using 465 for secure submission anyway. RFC 8314 made that existing practice official as "submissions". It calls the arrangement "a one-time procedural exception".

Two rules matter for security here. RFC 6409 section 4.3 says the MSA "MUST, by default, issue an error response to the MAIL command if the session has not been authenticated", so a submission port that accepts unauthenticated mail is misconfigured. And RFC 8314 recommends that clients connect to submission and mail access servers with implicit TLS in preference to STARTTLS, while saying servers and clients should support both 587 and 465 during a transition period. It adds that there is "no significant difference" in security between the two when both sides require TLS.

STARTTLS: opportunistic encryption and why it can be downgraded

RFC 3207 (February 2002, obsoleting RFC 2487) defines STARTTLS as an SMTP service extension. The server lists STARTTLS in its EHLO reply. The client sends the bare command STARTTLS. The server answers 220 "Ready to start TLS", 501 for a syntax error, or 454 "TLS not available due to temporary reason". After the handshake, section 4.2 requires both sides to forget everything learned before it: the server discards the client's EHLO argument and the client discards the extension list, and the client sends EHLO again.

That reset is a direct defence. Anything said before the handshake travelled in plaintext and could have been altered, so neither side may trust it.

Why port 25 cannot simply require TLS

RFC 3207 section 4 contains the rule that shapes everything else: "A publicly-referenced SMTP server MUST NOT require use of the STARTTLS extension in order to deliver mail locally." A publicly referenced server is the one on port 25 named in a domain's MX record. The reason is interoperability. In 2002 most mail servers had no TLS, and refusing their mail would have broken email.

The sending side faces the same problem in reverse. A sending MTA delivering to millions of domains cannot know in advance which ones support TLS and which have valid certificates. Postfix's own documentation for its client says mandatory TLS "is not viable as a default security level for mail delivery to the public Internet" because some MX hosts do not support TLS at all and others have broken implementations.

The result is opportunistic TLS. The client uses TLS if the server offers it, and if not, or if the handshake fails, it sends in plaintext. Certificate checks are usually relaxed too. Postfix's documentation says mandatory certificate verification "is not viable as a default Internet mail delivery policy", because many TLS-enabled MTAs use self-signed or privately issued certificates.

The downgrade, as a concept

RFC 3207 section 6 names the weakness itself: a man-in-the-middle attack "can be launched by deleting the '250 STARTTLS' response from the server", so the client never tries TLS. Another variant lets the advertisement through but tampers with the STARTTLS command and its reply. Because the greeting and EHLO exchange happen in cleartext, and because opportunistic policy says plaintext is acceptable, the client has no signal that anything is wrong. The message goes in the clear.

Even when TLS is negotiated, an unauthenticated session only protects against passive eavesdropping. If the client does not verify the certificate against a name it expected, an attacker who can redirect the connection (for example by forging the MX answer in DNS) can present any certificate. RFC 8461 describes both cases: foiling TLS negotiation, and redirecting the whole session by "overwriting the resolved MX record".

RFC 3207 also reminds readers of a limit that no transport fix removes: SMTP "is not an end-to-end mechanism". TLS between two servers protects that hop only, not the previous or the next.

MTA-STS, TLS-RPT and DANE: making TLS on port 25 mandatory

Three later standards let a receiving domain say "do not send me mail without authenticated TLS" in a way the sender can trust.

MTA-STS (RFC 8461, September 2018)

MTA-STS publishes a policy in two parts. A DNS TXT record at _mta-sts.example.com says a policy exists and carries an id that changes whenever the policy changes, for example v=STSv1; id=20160831085700Z;. The policy itself is a small text file served over HTTPS from https://mta-sts.example.com/.well-known/mta-sts.txt. RFC 8461 gives this example:

version: STSv1
mode: enforce
mx: mail.example.com
mx: *.example.net
mx: backupmx.example.com
max_age: 604800

The mx lines list the host names the domain's MX records may point to. The max_age is how long, in seconds, a sender should cache the policy, with a maximum of 31,557,600 (about a year). The mode is one of three values:

  • enforce: a sending MTA "MUST NOT deliver the message to hosts that fail MX matching or certificate validation or that do not support STARTTLS".
  • testing: failures are reported through TLS-RPT, but mail is delivered as if there were no policy.
  • none: treat the domain as having no active policy, used when removing MTA-STS.

HTTPS with a public CA certificate authenticates the policy instead of DNSSEC. The RFC states the trade openly: it "does not require DNSSEC, at a cost of risking malicious downgrades". Section 10.2 explains the weak moment, first contact: an attacker who blocks DNS when a sender first looks up a domain can make it appear to have no policy. Caching for max_age shrinks that window but does not close it.

TLS-RPT (RFC 8460, September 2018)

TLS-RPT is the feedback loop. A domain publishes a TXT record at _smtp._tls.example.com such as v=TLSRPTv1;rua=mailto:reports@example.com, and sending MTAs that support it send aggregate reports, each covering a full UTC day, about TLS successes and failures when delivering to that domain. Failure types include starttls-not-supported, certificate-host-mismatch, certificate-expired, sts-policy-fetch-error and validation-failure. RFC 8460 allows mailto and https URIs for rua. Running MTA-STS in testing mode with TLS-RPT turned on is how you find out what would break before you switch to enforce.

DANE for SMTP (RFC 7672, October 2015)

DANE takes the other route. The receiving domain signs its DNS zone with DNSSEC and publishes a TLSA record for each MX host at a name such as _25._tcp.mx.example.com. The TLSA record says which certificate or key to expect. Because the answer is DNSSEC validated, a sender can trust both the MX record and the TLSA record, and the abstract of RFC 7672 describes the result as "a downgrade-resistant protocol for SMTP transport security".

RFC 7672 recommends "DANE-EE(3) SPKI(1) SHA2-256(1)" records, which pin the server's own public key, with "DANE-TA(2) Cert(0) SHA2-256(1)" as a second choice, and explains why the PKIX-TA(0) and PKIX-EE(1) usages do not apply to opportunistic DANE on port 25. The cost is operational: the zones holding the MX and TLSA records must be signed, the sending MTA must use a validating resolver, and every key rollover must publish the new TLSA record before the new key goes live.

Opportunistic STARTTLSMTA-STSDANE for SMTP
StandardRFC 3207RFC 8461RFC 7672
Who decides TLS is requiredNobodyReceiving domain, by policy over HTTPSReceiving domain, by TLSA records in DNS
Trust anchor for the server certificateNone in practicePublic CAs (WebPKI)DNSSEC
Resists active strippingNoYes, after the policy is cachedYes, from the first connection if DNSSEC validates
Needs DNSSECNoNoYes
ReportingNoneTLS-RPT (RFC 8460)TLS-RPT (RFC 8460)
Main operational costNoneHost an HTTPS policy and keep it in sync with MXSign zones; manage TLSA through key rollovers

Domains can publish both. RFC 8461 says senders implementing MTA-STS "MUST NOT allow MTA-STS Policy validation to override a failing DANE validation". Our existing post on MTA-STS and TLS-RPT covers the deployment steps in more depth.

Where SPF, DKIM, DMARC and ARC attach to the transaction

Transport security answers "can someone read or change this message on the way". Sender authentication answers a different question: "is this message really from the domain it claims". RFC 5321 deliberately leaves that question alone. Section 3.6.2 notes that work "such as that on SPF and DKIM" exists to check whether an address belongs to the sender, but says that methods "are not defined here". Each mechanism hooks into a different part of the transaction.

MechanismStandardWhat it checksWhere in the transactionDNS record
SPFRFC 7208 (April 2014)Is the connecting IP allowed to send for this domain?The HELO/EHLO name and the MAIL FROM domain, before DATATXT at the domain itself
DKIMRFC 6376 (September 2011)Was this content signed by a key the domain published, and has it changed?The DKIM-Signature header and body, after DATATXT at selector._domainkey.domain
DMARCRFC 9989 (May 2026), reporting in RFC 9990 and RFC 9991Does a passing SPF or DKIM domain align with the RFC 5322 From domain? What does the owner want done if not?Evaluated after DATA, against the From headerTXT at _dmarc.domain
ARCRFC 8617 (July 2019, Experimental)What did earlier hops conclude before they modified or forwarded the message?ARC-Seal, ARC-Message-Signature and ARC-Authentication-Results headers added by intermediariesUses DKIM style keys

SPF: the envelope

SPF looks at the envelope, not the header. RFC 7208 section 2.4 says verifiers "MUST check the 'MAIL FROM' identity" if a HELO check has not already given a definitive answer, and section 2.3 recommends checking the HELO identity as well. Because the check runs on the IP address and the MAIL FROM domain, a receiver can reject before the message content is even sent. SPF's weaknesses follow from that design: it says nothing about the From header a reader sees, and it breaks when a forwarder resends the message from its own IP. RFC 7208 also limits evaluation to 10 DNS querying terms, a constraint our post on the SPF 10 DNS lookup limit covers.

DKIM: the content

DKIM signs selected header fields and the body with a private key, and puts the signature in a DKIM-Signature header. The receiver fetches the public key from a TXT record under _domainkey (RFC 6376 gives the example foo.bar._domainkey.example.com). The signing domain, carried in the d= tag, need not be the From domain. DKIM survives forwarding as long as the signed parts are not changed, but mailing lists that add footers or change subject lines break it.

DMARC: alignment with what the reader sees

DMARC connects authentication to the From header. A message passes if SPF or DKIM passes for a domain aligned with the From domain, and the owner's TXT record at _dmarc says what to do with failures and where to send reports.

DMARC changed this year. RFC 9989 (May 2026) is a Standards Track document that obsoletes both RFC 7489, which was an Informational RFC published through the Independent Submissions stream in March 2015, and RFC 9091 (public suffix domain DMARC). Its Appendix C lists the main changes: the public suffix list is replaced by a "DNS Tree Walk" to find the organizational domain and policy record; the np (non-existent subdomain policy), psd and t tags are added; and the pct, rf and ri tags are removed. Aggregate reporting moved to RFC 9990 and failure reporting to RFC 9991. Our post on what changed in DMARC RFC 9989 goes through each change, and the SPF, DKIM and DMARC setup guide covers the records themselves.

ARC: keeping results across forwarding

Forwarding and mailing lists break SPF (new sending IP) and often DKIM (modified content), so legitimate mail can fail DMARC. ARC lets each intermediary record what it saw, as a numbered chain of ARC-Authentication-Results, ARC-Message-Signature and ARC-Seal header fields, so a final receiver can decide whether to trust an intermediary's earlier verdict. RFC 8617 is Experimental, which is worth remembering when planning around it. We explain the forwarding problem in why email forwarding breaks SPF and DKIM, and how ARC helps.

Versions and history

DateDocumentWhat changed
August 1982RFC 821Original SMTP. HELO, MAIL, RCPT, DATA, QUIT; no extensions
November 1995RFC 1869Service extensions (ESMTP): EHLO and the extension model
April 2001RFC 2821Consolidated SMTP, obsoleting RFC 821, RFC 974 and RFC 1869
February 2002RFC 3207STARTTLS for SMTP, obsoleting RFC 2487
October 2008RFC 5321 and RFC 5322Current SMTP and message format; obsoletes RFC 2821 and RFC 2822
September 2011RFC 6376DKIM, obsoleting RFC 4871 and RFC 5672
November 2011RFC 6409Message submission on port 587, obsoleting RFC 4409
April 2014RFC 7208SPF, obsoleting RFC 4408
March 2015RFC 7489DMARC, Informational, Independent Submission stream
October 2015RFC 7672DANE for SMTP
January 2018RFC 8314"Cleartext Considered Obsolete": implicit TLS for submission, port 465 as submissions
September 2018RFC 8460 and RFC 8461TLS-RPT and MTA-STS
July 2019RFC 8617ARC, Experimental
December 2023CVE-2023-51764 and related CVEsSMTP smuggling disclosed; MTAs tighten end of data handling
May 2026RFC 9989, RFC 9990, RFC 9991DMARC on the Standards Track; reporting split out; RFC 7489 obsoleted
2026 (pending)draft-ietf-emailcore-rfc5321bisApproved revision of RFC 5321, in the RFC Editor queue as of 23 October 2026

RFC 5321 says it consolidates and clarifies earlier documents without adding new function, so the 1982 dialogue is still what servers speak. What has gone is plaintext submission and the idea of port 465 as "SMTP over SSL" for relaying. What remains common is opportunistic STARTTLS on port 25, which is why MTA-STS and DANE matter.

The IANA registry entry for port 25 already points to the emailcore draft, which the datatracker lists as approved and with the RFC Editor. Check the published text when it gets its RFC number.

Security properties and weakness classes

What SMTP does and does not guarantee

PropertyPlain SMTP (RFC 5321)With STARTTLS, opportunisticWith MTA-STS or DANE enforced
Confidentiality on a hopNoneAgainst passive listeners onlyAgainst passive and active attackers on that hop
Integrity on a hopNone beyond TCP checksumsYes, once TLS is upYes
Server authenticationNoneUsually none (certificate often not checked)Yes (WebPKI or DNSSEC)
Sender authenticationNoneNoneNone; that is SPF, DKIM and DMARC
End to end protectionNoneNoneNone; use S/MIME or OpenPGP
Replay protectionNoneWithin the TLS session onlyWithin the TLS session only
AvailabilityRetries and queues for daysSame, may fall back to plaintextMail is queued, not sent, if TLS fails

RFC 5321 section 7.1 puts the baseline bluntly: SMTP mail "inherently cannot be authenticated, or integrity checks provided, at the transport level", and "Real mail security lies only in end-to-end methods involving the message bodies", such as S/MIME or PGP. Our post on TLS in transit versus S/MIME covers that difference.

The weakness classes below are described as concepts, mainly from the RFCs' own Security Considerations sections.

Open relay

A relay accepts mail for a domain it does not host and passes it on; RFC 5321 section 3.6.2 says it may refuse with 550. Section 7.9 notes that relaying "through arbitrary sites has been used as part of hostile efforts to hide the actual origins of mail" and says implementations "SHOULD provide the capability" to limit relaying to known sources. An open relay is a server that relays for anyone. It is almost always a configuration mistake, such as a trusted network range set too wide, and it ends with your IP addresses on block lists.

Envelope sender versus header sender spoofing

Nothing in SMTP ties MAIL FROM to the connecting host, or the From header to MAIL FROM. A sender can put any domain in either. SPF limits who can use a domain in MAIL FROM. DKIM proves a domain signed the content. Neither by itself constrains the From header a reader sees, because the SPF domain and DKIM d= domain can both differ from it. DMARC alignment is what closes that gap, and only for domains that publish an enforcing DMARC policy. Lookalike domains and display names are outside what any of these protocols can check.

STARTTLS stripping and MX redirection

Covered above: an active attacker removes the STARTTLS offer or redirects the session through DNS, and opportunistic TLS accepts either silently. MTA-STS, DANE and certificate verification fix it; TLS-RPT tells you it is happening.

Pre-TLS command injection

STARTTLS has a quieter class of bug. If a server reads the STARTTLS command and any further plaintext bytes that arrived in the same packet, then keeps those bytes after the handshake, they get processed as if they had arrived over TLS. RFC 3207 sections 4.2 and 6 prevent this: both sides "MUST discard any knowledge obtained prior to the start of the TLS handshake". An implementation that keeps buffered plaintext across the switch breaks that rule.

SMTP smuggling: end of data ambiguity

SMTP smuggling, published in December 2023, is a desynchronisation bug that comes straight from the line ending rule at the start of this post. The standard end of data marker is CRLF, period, CRLF. Many servers historically also accepted a bare line feed as a line ending, for compatibility with older UNIX mailers. Postfix's write-up traces this tolerance back decades and notes other servers, Postfix included, copied it for compatibility.

The problem appears when two servers disagree. If an outbound service passes a non-standard sequence such as a bare LF, period, LF through unchanged inside a message, and the receiving server treats that as the end of the message, the receiver sees the rest of the data as new SMTP commands and a second message. Postfix's page notes the injected message can pass SPF-based DMARC checks at the receiver, because it really did arrive from the outbound service's IP addresses with a MAIL FROM domain hosted there. The CVE record for Postfix, CVE-2023-51764 (published 24 December 2023), describes the result as injection of messages with a spoofed MAIL FROM address, bypassing SPF. Related CVEs were assigned to other open source MTAs.

The RFC is not ambiguous; the bug is in implementations that accepted more than it allows. The fix is a strict receiving server. Postfix 3.9 and later default smtpd_forbid_bare_newline to normalize, which requires the standard end of data sequence. DKIM alignment helps too, since the smuggled message would not carry a valid signature from the spoofed domain.

Information disclosure and abuse of debugging commands

RFC 5321 section 7.3 discusses VRFY and EXPN, which confirm whether an address exists or expand a mailing list. Sites may disable them, and a disabled VRFY must answer 252 rather than a reply that looks like real verification. Sections 7.5 and 7.6 warn that banners and Received headers can reveal software and internal host names.

Credential exposure on submission

If a submission server offers SMTP AUTH before TLS, passwords can cross the network in the clear. RFC 8314, "Cleartext Considered Obsolete", says submission and access servers "MUST support TLS 1.2 or later".

Secure configuration, with defender-side checks

Only run these commands against domains and servers you own or are authorised to test. They are read-only checks of published records and of your own configuration. Every option shown comes from the tool's official documentation, linked in Sources.

1. Find your MX hosts and published policies

The dig utility from BIND documents +short for terse output and +dnssec to request DNSSEC records.

# MX hosts for your domain, in preference order
dig MX example.com +short

# SPF (TXT at the domain), DMARC and the MTA-STS / TLS-RPT records
dig TXT example.com +short
dig TXT _dmarc.example.com +short
dig TXT _mta-sts.example.com +short
dig TXT _smtp._tls.example.com +short

# DANE: TLSA record for each MX host, with DNSSEC data
dig TLSA _25._tcp.mx.example.com +dnssec

Check the _mta-sts record starts with v=STSv1; and the _smtp._tls record with v=TLSRPTv1;. Per RFC 8461 and RFC 8460, other records are discarded, and if the number left is not exactly one, senders treat the domain as having no policy. For DANE, the ad flag in the response header shows that your resolver validated the answer.

2. Read your MTA-STS policy

curl -s https://mta-sts.example.com/.well-known/mta-sts.txt

Confirm the mode, that every mx line matches the host names your MX records actually return, and that max_age is what you intend. A mismatch between the policy and your real MX hosts is the most common way an enforcing policy blocks your own inbound mail.

3. Check STARTTLS and the certificate on port 25

The OpenSSL s_client manual documents -starttls smtp ("Send the protocol-specific message(s) to switch to TLS"), -servername for SNI, -verify_return_error to fail on certificate errors, -brief for a short summary and -crlf to send CRLF line endings when typing commands.

# Does the MX offer STARTTLS, which protocol and cipher, and does the
# certificate verify for the MX host name?
openssl s_client -starttls smtp -connect mx.example.com:25 \
  -servername mx.example.com -verify_return_error -brief

# Implicit TLS on the submissions port
openssl s_client -connect smtp.example.com:465 -servername smtp.example.com -brief

# STARTTLS on the submission port
openssl s_client -starttls smtp -connect smtp.example.com:587 -crlf -brief

The same manual shows how to check a server against DANE TLSA data with -dane_tlsa_domain and one or more -dane_tlsa_rrdata values copied from your TLSA record, which confirms the certificate the server presents matches what DNS publishes.

4. Use posttls-finger if you run Postfix

Postfix ships posttls-finger, documented as a tool to "Probe the TLS properties of an ESMTP or LMTP server". By default it uses the dane security level when DNSSEC is available, otherwise secure. Its -c option turns off SMTP chat logging so only TLS details are shown, and -P names a CA directory (by default "no public CAs are trusted").

# DANE check of a domain's MX hosts
posttls-finger -c -l dane example.com

# WebPKI check, trusting the system CA directory (path varies by distribution)
posttls-finger -c -l secure -P /etc/ssl/certs/ example.com

It is an unsupported test program that ignores Postfix's policy tables, so treat it as a probe.

5. Review your Postfix configuration

The postconf(1) manual documents -n to show only settings explicitly set in main.cf and -d to show built-in defaults.

postconf -n
postconf smtpd_relay_restrictions mynetworks
postconf smtpd_tls_security_level smtp_tls_security_level smtpd_tls_auth_only
postconf smtpd_forbid_bare_newline smtp_dns_support_level
postconf -d smtpd_forbid_bare_newline

What to look for, from the postconf(5) reference and TLS_README:

  • Relay control. smtpd_relay_restrictions defaults to permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination (added in Postfix 2.10). Keep mynetworks to hosts that truly need unauthenticated relay.
  • Inbound TLS on port 25. smtpd_tls_security_level = may announces STARTTLS without requiring it. The documentation notes that encrypt "MUST NOT be applied in case of a publicly-referenced SMTP server" (a rule inherited from the STARTTLS RFC) and belongs on dedicated submission services.
  • Submission. Use encrypt on port 587, which implies smtpd_tls_auth_only = yes, so SASL authentication is never offered without TLS. For port 465, TLS_README shows a submissions service in master.cf with -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes, and recommends not enabling wrapper mode in main.cf.
  • Outbound TLS. smtp_tls_security_level defaults to may (opportunistic) from Postfix 3.11 and empty in earlier versions. Mandatory encrypt is "not an appropriate default" for Internet delivery, but you can require it per destination through smtp_tls_policy_maps. The dane level uses TLSA records and needs smtp_dns_support_level = dnssec and a validating resolver.
  • SMTP smuggling. smtpd_forbid_bare_newline defaults to normalize in Postfix 3.9 and later. On older supported branches the Postfix smuggling page recommends setting smtpd_forbid_bare_newline = normalize with smtpd_forbid_bare_newline_exclusions = $mynetworks, and documents a short-term workaround of smtpd_data_restrictions = reject_unauth_pipelining with smtpd_discard_ehlo_keywords = chunking, silent-discard.

The Postfix TLS documentation covers DANE natively and does not describe built-in MTA-STS enforcement in the MTA itself. If you need your outbound mail to honour other domains' MTA-STS policies, check what your MTA supports before assuming it does.

6. Publish your own receiving policy

The order that avoids self-inflicted outages: give every MX host a certificate valid for its own name; publish TLS-RPT; publish MTA-STS in testing mode; read a few weeks of reports; then move to enforce. With a DNSSEC signed zone, add DANE TLSA records and publish each new one before its key goes live.

When to use SMTP versus the alternatives

SMTP has no replacement for mail between organisations. The choices are which mode and protections to use, and when not to use email.

Use caseBest fitSecurity propertiesOperational cost
Server to server delivery between organisationsSMTP on 25 with STARTTLS, plus MTA-STS or DANEHop by hop TLS, authenticated when a policy is enforcedLow for STARTTLS; moderate for MTA-STS; higher for DANE (DNSSEC)
A person's mail client sending mailSubmission on 465 (implicit TLS) or 587 (STARTTLS), with authenticationTLS from client to provider; credentials protectedLow; enforce TLS before AUTH
An application sending mail through a providerSubmission on 465 or 587, or the provider's HTTPS APISimilar; an HTTPS API also avoids SMTP parsing differencesLow; keep credentials out of code
Proving who sent a messageSPF, DKIM and DMARC at enforcementDomain level authentication; nothing about the author as a personModerate; needs an inventory of every sending service
Keeping content confidential from mail providersS/MIME or OpenPGPEnd to end confidentiality and signaturesHigh; key distribution and client support
Highly sensitive files or regulated dataA secure portal or file transfer with access controlAccess control, audit and revocation that email cannot provideVaries; email becomes a notification only
Internal service notificationsAn internal relay that accepts only authenticated or listed hostsDepends on relay controlsLow; watch for open relay drift

Common mistakes

  • Treating STARTTLS as encryption that is always on. On port 25 it is opportunistic and can be removed by an attacker on the path. Without MTA-STS or DANE, a sender will deliver in plaintext and log at most a note.
  • Requiring TLS on the public MX with encrypt. RFC 3207 forbids it for publicly referenced servers, and senders without TLS will be refused. Use MTA-STS or DANE to ask senders to require TLS instead.
  • Publishing MTA-STS in enforce mode before checking certificates. If an MX host's certificate does not match its name, or the mx lines in the policy do not cover every MX, senders that honour the policy will hold your mail.
  • Forgetting to update the id in _mta-sts. Senders only refetch the policy when the id changes or the cache expires, so a changed policy file with the same id may be ignored for up to max_age.
  • Assuming SPF protects the From address. SPF checks the envelope sender. Only DMARC alignment ties authentication to the visible From domain.
  • Leaving relay permission wide. A mynetworks range that includes a whole cloud provider block or a NAT gateway shared with untrusted hosts is an open relay in practice.
  • Offering AUTH before TLS. On submission ports, credentials must never cross in plaintext. In Postfix, encrypt on the submission service or smtpd_tls_auth_only = yes prevents it.
  • Running an MTA that accepts bare line feeds as end of data. Patch or configure strict end of data handling, and remember that the receiving server is the one that must be strict.
  • Ignoring TLS-RPT and DMARC reports. Publishing the record without reading the reports gives you the cost and none of the benefit.

FAQ

What port does SMTP use?

Server to server SMTP uses TCP port 25, and it is the only port MX delivery uses. A mail client submitting new mail should use port 465 (implicit TLS, RFC 8314) or port 587 (STARTTLS, RFC 6409), with authentication. IANA registers 25 as smtp, 465 as submissions and 587 as submission.

Is SMTP encrypted?

Not by itself. RFC 5321 has no encryption. STARTTLS (RFC 3207) adds TLS one hop at a time, and on port 25 it is opportunistic, so mail can still travel in plaintext if TLS is unavailable or removed. Port 465 uses TLS from the first byte. Each server on the path still sees the message.

What is the difference between port 465 and port 587?

Both are for submitting mail from a client to its provider. On 465 the TLS handshake happens immediately on connect (implicit TLS). On 587 the session starts in plaintext and upgrades with STARTTLS. RFC 8314 says there is no significant security difference when both sides require TLS, and recommends supporting both while preferring implicit TLS.

What is STARTTLS stripping?

A downgrade where an attacker on the path removes the STARTTLS offer or breaks the handshake, so the sender falls back to plaintext. RFC 3207 describes it; MTA-STS and DANE prevent it.

MTA-STS vs DANE: which should I use?

Use MTA-STS if your DNS zone is not signed with DNSSEC; it relies on HTTPS and public certificate authorities and has a weak first contact. Use DANE if your zones are signed and you can manage TLSA records through key changes; it is resistant to downgrade from the first connection. Many domains publish both, and TLS-RPT works with either.

Where do SPF, DKIM and DMARC fit in SMTP?

SPF checks the connecting IP against the HELO name and the MAIL FROM domain, before the message content is sent. DKIM verifies a signature in the message headers after DATA. DMARC, now RFC 9989, checks that a passing SPF or DKIM domain aligns with the From header domain and applies the domain owner's policy.

What is SMTP smuggling?

It is a class of bug where two mail servers disagree on where a message ends. If one passes a non-standard end of data sequence through and the next accepts it as the end, the remaining data is processed as a second, injected message that can appear to come from the first service. It was disclosed in December 2023 (CVE-2023-51764 for Postfix).

What is an open relay?

An SMTP server that accepts mail from anyone for delivery to any domain. RFC 5321 says servers should be able to restrict relaying to known sources and answer 550 otherwise. Check rules such as Postfix's smtpd_relay_restrictions and mynetworks.

Is RFC 5321 still the current SMTP standard?

Yes, as of 23 October 2026. Its revision, draft-ietf-emailcore-rfc5321bis, has been approved and is in the RFC Editor queue. When published it will have a new RFC number and obsolete RFC 5321.

Where Safeguard fits

Safeguard does not filter, inspect or relay email, and it does not test SMTP servers or check MTA-STS and DNS records; use the tools above for that. The honest connection is the software that speaks these protocols: mail servers in containers, SMTP client libraries in applications, and TLS libraries such as OpenSSL. Safeguard's software composition analysis, generally available, inventories those libraries across your full transitive dependency tree and in container images, generates SBOMs in SPDX and CycloneDX, and enriches matched vulnerabilities with EPSS and CISA KEV data, with reachability analysis to rank what your code actually calls. When the next MTA or TLS library advisory lands, that is how you find every image and service carrying the affected version. Our post on using SBOMs to find affected products fast shows the workflow.

Fix it without waiting for upstream

Protocol bugs like SMTP smuggling or STARTTLS input buffering live in a mail server, a TLS library or an SMTP client library that your systems depend on. When the fix is in a package you build and ship, you do not have to wait for the next scheduled upgrade to get it.

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

These demos show dependency and SBOM workflows, not email security. You can download Safeguard and follow the CLI docs to try them on your own projects.

This demo sets up the Safeguard runner on your own machine, approves it with its device code and then scans from the terminal. Pointed at the container image that runs your mail relay or a service that sends notification email, the same scan lists the MTA, TLS and SMTP client libraries inside it with their versions and any known vulnerabilities.

Click through it at your own pace, or open it full screen.

This demo is a real CLI session: install, open the interactive terminal, ask it to fix the lodash CVE in a repository, and watch it read the finding and advisory, ask before each command, move lodash to 4.17.21, run npm install and npm test with approval, and print a summary without pushing anything. The same approve each step flow applies when the package to bump is an SMTP client library or a TLS library pinned in your manifest.

Click through it at your own pace, or open it full screen.

This demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. Once connected, you can ask in plain language which of your projects include a particular mail or TLS library version, and get the answer from your own scan data.

Click through it at your own pace, or open it full screen.

Quick check

Your MX servers all offer STARTTLS. Is mail sent to your domain protected from an attacker on the network path?

Not reliably. On port 25 STARTTLS is opportunistic, so an active attacker can remove the STARTTLS offer and the sending server will fall back to plaintext without complaint. Publishing an MTA-STS policy in enforce mode, or DANE TLSA records in a DNSSEC signed zone, tells senders to refuse delivery without valid TLS. TLS-RPT then reports failures to you.

A message passes SPF for the envelope sender's domain. Does that prove the From address a reader sees is genuine?

No. SPF checks the connecting IP against the HELO name and the MAIL FROM domain, which can differ from the RFC 5322 From header. Only DMARC alignment, now specified in RFC 9989, connects a passing SPF or DKIM result to the From domain, and only if the domain publishes a DMARC policy.

Sources

Last reviewed: 23 October 2026. RFC 5321bis is in the RFC Editor queue; when it is published, check the new RFC for any changes to the details above.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.