SMTP Smuggling: The Email Spoof That Rides Past SPF, DKIM, and DMARC

SMTP Smuggling: The Email Spoof That Rides Past SPF, DKIM, and DMARC

Written by

in

SMTP smuggling is an email spoofing technique that slips a second, forged message past SPF, DKIM, and DMARC by exploiting a disagreement between two mail servers about where a message actually ends. It was disclosed in December 2023 by researcher Timo Longin, working with SEC Consult, and it earned a reputation as uncommon but popular: rare in the wild, yet widely studied, because it defeats the exact controls built to stop spoofing. The trick is not that it breaks those checks. It is that the sending server and the receiving server read one byte stream two different ways, and the attacker lives in the gap between the two readings.

Where a message is supposed to end

To see the bug you have to see the protocol. When one mail server hands a message to another, it opens a session and issues the DATA command. Everything typed after that is the message body. The body finishes with a specific marker: a carriage return and line feed, then a single dot on a line by itself, then another carriage return and line feed. On the wire that is <CR><LF>.<CR><LF>. The receiving server watches for exactly that sequence. When it sees the lone dot, it knows the body is over and it accepts the message.

The standard is precise about this. The problem is that the world is not. Some servers, trying to be forgiving of clients that send slightly malformed line endings, also treat non standard variants as an end of data marker. A bare line feed with a dot, written <LF>.<LF>, or a lone carriage return version, <CR>.<CR>, might be accepted as the end of the body even though it is not the sequence the standard names. One server is strict. Another is lenient. That difference is the whole attack.

The message never changes on the wire. What changes is where each server decides it stopped, and an attacker who controls that split controls what the receiver thinks was sent.

How SMTP smuggling turns one message into two

Here is the mechanism in plain terms, using invented hosts. An attacker has a normal, authenticated account on an outbound provider, call it send.example. They compose a message to a victim domain served by receive.example. The visible message looks harmless. But buried in the body, the attacker places a sequence that the outbound server does not recognise as the end of data, while the inbound server does.

Because the outbound server does not see an end marker there, it keeps treating everything as body text and forwards the entire blob over its trusted, already authenticated connection to receive.example. The inbound server, being lenient, reads that same non standard sequence as a real end of data. It closes off the first message, then starts reading what follows as a brand new SMTP conversation on the same connection. That second conversation is fully attacker written. It can name any MAIL FROM sender it likes.

A stripped down, clearly sanitized illustration of the idea, not a working payload:

MAIL FROM:<attacker@send.example>
RCPT TO:<victim@receive.example>
DATA
Subject: a normal looking first message

Nothing to see here.
[a NON STANDARD end sequence the sender ignores
 but the receiver treats as end of data]
MAIL FROM:<ceo@trusted-brand.example>
RCPT TO:<victim@receive.example>
DATA
Subject: please approve this transfer

This is the smuggled message.
<CR><LF>.<CR><LF>

The outbound server sees one message with a slightly odd body. The inbound server sees two messages: the innocent one, and then a second one that claims to come from ceo@trusted-brand.example. Nobody forged a cryptographic signature. The two parsers simply disagreed on where the first message ended, and the attacker wrote their forgery into the space that disagreement created.

Why the smuggled message inherits trust

This is the part that makes SMTP smuggling matter. SPF, DKIM, and DMARC all answer one question: did this message come from a server authorized to send for its claimed domain? SPF checks the connecting IP against the sending domain’s published list. DKIM checks a signature. DMARC ties the two together and tells the receiver what to do on failure.

The smuggled message rides in on the outbound provider’s own connection, from the outbound provider’s own IP, inside a session the provider already authenticated for the attacker’s legitimate account. So when the inbound server evaluates that second message, the connection it arrived on belongs to a well known, authorized sender. The checks look at the trusted infrastructure the message rode in on and pass it. The forgery inherits the reputation of the connection it was smuggled through. The controls did their job correctly on the wrong message, because they were never told a second message existed.

The email cousin of HTTP request smuggling

If this shape feels familiar, it should. It is a parser differential attack: two parsers, one stream, two interpretations. That is exactly the pattern behind HTTP request smuggling, the parser differential cousin, where a front end and a back end disagree about where one HTTP request ends and the next begins. Same idea, different protocol. In HTTP the disagreement is over content length and chunk framing. In SMTP the disagreement is over the end of data marker. In both, an attacker who understands the boundary better than the servers do can hide a whole second message in the seam.

How to detect SMTP smuggling exposure

You detect this by testing your own parsing, not by watching for a signature.

  • Probe the end of data handling. In a controlled test, send messages whose bodies contain bare <LF>.<LF> and lone <CR>.<CR> sequences. A standards compliant receiver should treat only <CR><LF>.<CR><LF> as end of data and should never split the stream on the non standard variants.
  • Watch for phantom second messages. If a single inbound session ever yields a second MAIL FROM that your outbound path did not intend, that split is the fingerprint of the bug.
  • Look for authentication that passes on impossible senders. A message that passes SPF and DMARC while claiming a sender that has nothing to do with the connecting infrastructure is worth a hard look.
  • Compare outbound and inbound behavior side by side. The vulnerability only exists when your sender and your receiver disagree. Test them against the same set of odd line endings and see if their answers match.

How to fix it

The fix is alignment and strictness. Neither server should be creative about where a message ends.

  • Parse the end of data marker strictly. Accept only the standard <CR><LF>.<CR><LF> sequence as the terminator. Do not treat bare line feed or lone carriage return dot sequences as end of data.
  • Reject or normalise malformed line endings. A message that mixes bare <LF> or lone <CR> into its framing is either broken or hostile. Normalise it to the standard form before any parsing decision, or refuse it outright.
  • Align outbound and inbound handling. The bug is a disagreement. If the server that sends and the server that receives apply the same strict rule, there is no gap to hide in.
  • Take the provider side fixes. After disclosure, major email providers were found affected and updated their parsers. Keep your mail infrastructure patched, because the durable fix lives in the servers that frame and unframe the message.

Notice that none of these fixes touch SPF, DKIM, or DMARC. Those controls were never the weak point. The weak point was an assumption underneath them: that the sending server and the receiving server agree on what a message even is. Fix the framing and the authentication starts guarding the right message again.

That gap between two parsers is the kind of thing an attacker finds by questioning an assumption everyone treated as settled. UnboundCompute is an autonomous security researcher built to do exactly that, to test the assumptions a system makes rather than replay a fixed list of payloads, and in this case the assumption is a quiet one: that two parsers reading the same stream will always agree on where it ends. You can read more about that approach on our about page.

Frequently asked questions

What is SMTP smuggling?

It is an email spoofing technique that hides a second, forged message inside a first one by exploiting a disagreement between two mail servers about where a message ends, letting the forged message ride a trusted, already authenticated connection.

How does it get past SPF, DKIM, and DMARC?

It does not break those checks. The smuggled message arrives on the outbound provider’s authenticated connection and IP, so the checks evaluate trusted infrastructure and pass a message they never knew was there.

How is it like HTTP request smuggling?

Both are parser differential attacks: two parsers read one stream and split it differently. In HTTP the disagreement is over where one request ends, in SMTP it is over the end of data marker that closes a message body.

How do you prevent SMTP smuggling?

Parse the end of data marker strictly, accepting only the standard sequence, reject or normalise bare line feed and lone carriage return variants, and align outbound and inbound handling so there is no gap to hide a second message in.


Put an autonomous researcher on your own systems

UnboundCompute is an autonomous security researcher that reasons about how an application fits together and proves the access control and injection bugs it finds. We are opening a small number of founding design partner seats: private early access pointed at a staging target you choose, and a say in what it looks for. If your team ships software worth pressure testing, apply to the design partner program.