For those still looking for a solution. I wrote my own lua script to remove the attachments in rspamd. This will rewrite the entire message without the attachment part.
`local rspamd_logger = require “rspamd_logger”
local rspamd_text = require “rspamd_text”
rspamd_config:register_post_filter(function(task)
rspamd_logger.infox(“Starting EML attachment removal and reconstruction”)
-- Get the "From" header
local from_header = task:get_header("From") or "unknown"
local clean_from = from_header:gsub("[^%w@.-]", "_")
-- Get the full MIME message
local raw_message = task:get_message()
if not raw_message then
rspamd_logger.errx("No raw message found; aborting process")
return
end
-- Convert raw message to string
local message = raw_message:str()
rspamd_logger.infox("Retrieved raw message for processing")
-- Extract and log all boundaries
local boundaries = {}
for boundary in message:gmatch('boundary="?([^"\r\n;]+)"?') do
rspamd_logger.infox("Found boundary: %1", boundary)
table.insert(boundaries, boundary)
end
-- Use the first boundary as the top-level boundary
local top_boundary = boundaries[1]
if not top_boundary then
rspamd_logger.errx("No MIME boundary found; skipping processing")
return
end
rspamd_logger.infox("Using top-level boundary: %1", top_boundary)
-- Process MIME parts
local new_message = {}
local boundary_marker = "--" .. top_boundary
local closing_marker = boundary_marker .. "--"
local in_attachment = false
for line in message:gmatch("(.-)\r?\n") do
if line == boundary_marker then
if in_attachment then
rspamd_logger.infox("Finished skipping attachment content")
table.insert(new_message, "")
end
in_attachment = false -- Reset
table.insert(new_message, line) -- Keep the boundary
elseif line == closing_marker then
rspamd_logger.infox("Closing boundary detected: %1", line)
table.insert(new_message, "")
table.insert(new_message, line)
elseif line:lower():find("content%-disposition: attachment") or line:find("filename=") then
rspamd_logger.infox("Attachment header detected: %1", line)
in_attachment = true -- Start skipping attachment content
-- remove remaining headers
while (string.match(new_message[#new_message], "^[%w%-]+:%s?.*"))
do
table.remove(new_message, nil)
end
elseif not in_attachment then
table.insert(new_message, line)
end
end
-- Concatenate the new message
local concatenated_message = table.concat(new_message, "\r\n")
-- Save the modified message to a file
local final_file = "/tmp/cleaned_" .. clean_from .. ".eml"
local file = io.open(final_file, "w")
if file then
file:write(concatenated_message)
file:close()
rspamd_logger.infox("Final cleaned email saved to %1", final_file)
else
rspamd_logger.errx("Failed to write final email to %1", final_file)
end
-- Replace the original message with the reconstructed content
local success = task:set_message(rspamd_text.fromstring(concatenated_message))
if success then
task:process_message()
rspamd_logger.infox("Successfully removed attachments and replaced email content")
else
rspamd_logger.errx("Failed to update the message content")
end
end)`