Streaming decoder for SMTP DATA content (RFC 5321 §4.1.1.4, §4.5.2).
It removes dot-stuffing and finds the end of data without buffering the message: feed it bytes as they arrive and it returns the decoded content as iodata.
Only <CRLF>.<CRLF> ends the data. A bare LF or bare CR (one not part
of a CRLF pair) is handled by the policy, so it can never be read as a
line ending by one MTA and as content by another (SMTP smuggling):
:reject- stop with{:error, :bare_lf | :bare_cr}.:normalize- convert it to CRLF in the output. The line it ends cannot end the data, even if it is a single dot.
The decoded content keeps CRLF line endings, and the final CRLF before the terminating dot is part of the content.
Summary
Types
Functions
@spec decode(t(), binary()) :: {:more, iodata(), t()} | {:done, iodata(), binary()} | {:error, :bare_lf | :bare_cr, iodata()}
Decodes bytes.
{:more, content, decoder}- the data has not ended yet.{:done, content, rest}- the data ended;restis the input after the terminating.<CRLF>, such as pipelined commands.{:error, reason, content}- a bare line ending under:reject.contentis what was decoded before it.
Returns a decoder for content right after the 354 reply.