MTA Hook raw message support

Your question

I have looked into the MTA Hooks draft specification at draft-degennaro-mta-hooks-01 - MTA Hooks: An HTTP-Based Mail Processing Protocol, it states the following:

5.6.2.  Raw Message

   The rawMessage property contains the complete message in Internet
   Message Format as defined in [RFC5322], including all MIME parts and
   attachments.  In JSON serialization, the value is Base64-encoded.  In
   CBOR serialization, the value is a raw byte string.

   The rawMessage property represents the entire message as stored or
   received by the MTA.  When present, it provides byte-exact access to
   the message content, which is necessary for operations such as
   cryptographic signature verification.

   Scanners MAY request both message and rawMessage properties.  If a
   scanner's response modifies both properties, only rawMessage
   modifications are applied; message modifications are ignored.

   The raw message content MUST NOT appear within the message property
   as a blob value.  The message property contains only the structured
   parsed representation with individual body part contents available
   via bodyValues, while rawMessage contains the complete unparsed
   message.

My question is what is the roadmap for support for this feature? I am looking to migrate to Stalwart, but the one missing piece for me at the moment is the limitation on the current MTA Hooks implementation not having access to the full raw EML message.

I am looking to emulate Exim’s pipe transport, but currently the message body and headers are passed to me separately by Stalwart’s MTA via the hook.

The example use case that I have is when rewriting an email, I would sometimes change the root mail part’s type, e.g. from text/plain to multipart/alternative, which requires me to edit a top level header.

Though it is possible for me to keep these headers in sync manually, I would prefer to have access to the raw email message including headers during the data phase of the transport for consistency.

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

Based on the current documentation and source code, the rawMessage property from the MTA Hooks draft specification (section 5.6.2) is not currently implemented in Stalwart’s MTA Hooks support. The existing implementation sends headers and body contents separately in the structured message object - specifically, message.headers, message.serverHeaders, and message.contents (the raw body bytes via raw_body()), along with message.size (which does use raw_message().len() for the byte count). There is no field that exposes the complete, unparsed RFC 5322 message as a single Base64-encoded blob.

Your use case - needing the complete raw EML during the DATA stage, particularly for rewriting messages including top-level headers in a single operation - is a valid gap. Since Stalwart was actually the originating project behind the MTA Hooks draft spec (as noted in the docs), implementing rawMessage would be a natural alignment with the draft’s progress, but there is no mention of it in the current docs or roadmap materials I can find.

For now, the workaround within the current API is exactly what you described: reconstructing the message yourself from the separate headers, serverHeaders, and contents fields and keeping them in sync manually when rewriting. The response similarly allows header modifications separately from body modifications.

A human community member or Stalwart staff will be better placed to comment on the roadmap for this. The current MTA Hooks documentation is at: MTA Hooks | Stalwart

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

The MTA hooks draft is currently under active development. As soon as the new protocol format is more stable, the latest spec will be implemented in Stalwart.