I have some servers that create automated emails which all pass through a Postfix MTA. The software that generates the email does not strictly follow RFCs, and sometimes generates emails with duplicate message-ID headers. The software cannot be changed, so I am trying to intercept and fix these messages on their way through the MTA.
I have a milter daemon written in Python that is attempting to remove duplicate message IDs from inbound messages.
The code is below:
import Milter
import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
file_handler = logging.FileHandler('/var/log/milter.log')
file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
logger.addHandler(file_handler)
seen_message_ids = set()
class MessageIDMilter(Milter.Base):
def __init__(self):
self.id = Milter.uniqueID()
@Milter.noreply
def connect(self, IPname, family, hostaddr):
logger.debug("Milter connected to %s family %s at address %s" % (IPname, family, hostaddr))
self.IPname = IPname
self.family = family
self.hostaddr = hostaddr
return Milter.CONTINUE
@Milter.noreply
def header(self, name, hval):
logger.debug("Received header %s with value %s" % (name, hval))
if name.lower() == "message-id":
logger.debug("Found message ID: %s" % hval)
if hval in seen_message_ids:
logger.debug("Deleting duplicate message ID: %s" % hval)
try:
self.chgheader(name, 1, "")
except Exception as e:
logger.error("Error removing from: %s error message: %s" % (name, e))
else:
seen_message_ids.add(hval)
return Milter.CONTINUE
@Milter.noreply
def eoh(self):
logger.debug("Reached end of headers")
return Milter.ACCEPT
if __name__ == "__main__":
logger.debug("Script started OK")
Milter.factory = MessageIDMilter
Milter.runmilter("message-id-milter", "inet:10001@localhost", 0)
The script runs and can be called from Postfix. When attempting to delete the duplicate header with chgheader, the following error is thrown:
2023-02-03 18:22:44,983 ERROR Error removing from: Message-ID error message: cannot change header
I cannot see anything wrong with this request, nor any other method to remove the header. The docs suggest this should work: https://pythonhosted.org/pymilter/milter_api/smfi_chgheader.html