stefan21 That’s right, from what I can gather its where all the MIME stuff happens.
The do a restart on docker compose restart rspamd-mailcow, it will then pick up the changes. Best to run the logs to ensure there are no error messages. afterwards.
2025_07 is slightly different to 2025_03a/b here is what needs to change in the –add footer
if name:lower() == 'content-type' then
- local nct = string.format('%s: %s/%s; charset=utf-8',
- 'Content-Type', rewrite.new_ct.type, rewrite.new_ct.subtype)
- out[#out + 1] = nct
- -- update Content-Type header
- task:set_milter_reply({
- remove_headers = {['Content-Type'] = 0},
- })
- task:set_milter_reply({
- add_headers = {['Content-Type'] = string.format('%s/%s; charset=utf-8', rewrite.new_ct.type, rewrite.new_ct.subtype)}
- })
+ local boundary_part = rewrite.new_ct.boundary and
+ string.format('; boundary="%s"', rewrite.new_ct.boundary) or ''
+ local nct = string.format('%s: %s/%s; charset=utf-8%s',
+ 'Content-Type', rewrite.new_ct.type, rewrite.new_ct.subtype, boundary_part)
+ out[#out + 1] = nct
+ -- update Content-Type header (include boundary if present)
+ task:set_milter_reply({
+ remove_headers = {['Content-Type'] = 0},
+ })
+ task:set_milter_reply({
+ add_headers = {['Content-Type'] = string.format('%s/%s; charset=utf-8%s',
+ rewrite.new_ct.type, rewrite.new_ct.subtype, boundary_part)}
+ })
Before:
Always rewrote the Content-Type as type/subtype; charset=utf-8 with no boundary.
This meant if the message actually needed a boundary (e.g., after adding a footer or extra MIME part), that boundary was missing in the header.
Without the correct boundary, mail clients will keep using the old one, which could “trap” the footer inside the wrong MIME section or make it invisible and subsequent attachments.
It still removes and re-adds the header in the milter reply, but its re-adding a broken header.
Simple Terms:
“Here’s a Content-Type but I’m not telling you about the new boundary.”
After:
Checks if a boundary exists (rewrite.new_ct.boundary) and, if so, appends ; boundary=“…” to the header.
Keeps it clean by leaving the boundary out entirely if it’s not needed.
The re-added header now matches the actual MIME structure after modification, so clients can parse all parts correctly — including the new footer.
This prevents the “footer stuck in the previous MIME section” removing the break in MIME email layout.
What it does now “Here’s a Content-Type with the boundary info if it exists, so your email client knows exactly where each part starts and ends.”