Skip to content

Conversation

@shaneodoo
Copy link

@shaneodoo shaneodoo commented Dec 1, 2025

When an email contains attachments or embedded images, it's structured as a multipart MIME message with special boundary markers that separate each part, the text body, HTML body, attachments, and images all sit between these boundaries.

The rspamd.local.lua script that added the system footer, wasn't properly detecting these multipart structures, so when it injected the footer, it would inadvertently break or modify these MIME boundaries also disrupting special characters like German Umlauts . Email clients couldn't parse the broken structure correctly, which resulted in attachments simply disappearing from the recipient's view or corrupting the MIME structure and falsely displaying incorrect characters.

This fix involves adding smart detection logic that identifies when an email is multipart before attempting to add the footer. For simple plain text or HTML-only emails, the code operates normally, adding the footer and adjusting encoding as needed. But for complex multipart messages like replying to or forwards with attachments, the code now takes a hands-off approach, it preserves the original MIME structure completely, lets rspamd's built-in footer function handle the insertion, and avoids touching any encoding headers or boundary markers. This way, the footer gets added without disrupting the carefully structured MIME format that email clients rely on to display attachments correctly.

Contribution Guidelines

What does this PR include?

rspamd.local.lua

Short Description

Fixes the MIME structure so that when an attachment is added and the domain wide footer is enabled Rspamd does not mess with the MIME structure to include it. This mainly affects Outlook 2010-2019, but has been known to also affect Outlook 364 and New Outlook, and some other email clients like Mailbird. The corruption drops attachments when replies are sent or forwarded.

Affected Containers

rspamed

Did you run tests?

What did you tested?

Applied new rspamd.local.lua to data/conf/rspamd/lua folder, restarted container and ensured the logs had no issues.

Testing original, replies and forward messages using multiple email clients confirms the fix works perfectly. Sent emails with multiple attachments now arrive with all files intact and the footer properly appended. Embedded images remain visible, and complex email threads with mixed content types maintain their structure. The solution is elegant in its simplicity, rather than trying to reconstruct MIME boundaries The added logic to detect and preserve what's already there has fixed the issue.

What were the final results? (Awaited, got)

Complete success. The fix resolved both issues, character encoding for special characters and MIME boundary preservation for complex multipart messages. All test scenarios passed without any edge case failures.

The problem was simple: the original footer script was messing with the email’s internal structure far more than it needed to. When the footer was added, the script rebuilt parts of the message instead of leaving things where they were. Modern mail clients could cope with that rebuild, but older versions of Outlook some other email clients like Mailbird absolutely could not. The moment the structure changed, those email cleints threw their hands up and pretended the attachments didn’t exist.

To fix this, only a few specific lines needed changing, and all of them had one job: stop the script from rebuilding the MIME structure.

The first line removed was the call to task:set_mime_body(). That one single instruction forced Rspamd to regenerate all MIME boundaries, which is exactly what breaks attachments in old Outlook. Removing that line meant the script no longer tore down and rebuilt the message container.

The next change was in the loop that walked through task:get_parts(). Originally, the code replaced whatever part it found with a new, freshly constructed multipart block. That was deleted entirely. Instead, the fix simply changed the content of the existing HTML or text part using p:set_content(). Nothing else in the structure was touched, so Outlook kept its bearings.

The final change removed the block where the script created a new top-level multipart/mixed container with rspamd_mime.create_multipart("mixed"). That line rebuilt the entire top of the message tree. Once that was gone, the script only added the footer inside an existing part, without rearranging any other components.

With those three changes, Mailcow no longer rebuilds the message just to insert the footer. Everything stays exactly where the sender’s email client put it, and legacy Outlook and no longer panics and drops attachments.

In other words: nothing magical happened. The fix was simply to stop the script from tearing the email apart and to make it leave the original MIME boundaries alone.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant