dsn-processor/app/dsn_processor.py
2023-12-10 01:04:42 +01:00

85 lines
2.3 KiB
Python

import Milter
import sys
import traceback
import email
import json
class DsnProcessorMilter(Milter.Base):
def __init__(self):
self.mail_data: str = ""
def process_dsn(self, mail_data: str):
msg = email.message_from_string(mail_data)
recipients = []
for part in msg.walk():
if part.get_content_type() == "message/delivery-status":
for subpart in part.walk():
rcpt = {}
if 'Action' in subpart and 'Original-Recipient' in subpart:
rcpt["action"] = subpart['Action']
rcpt["orig_rcpt"] = subpart['Original-Recipient'].replace('rfc822;', '')
rcpt["diag_code"] = None
if 'Diagnostic-Code' in subpart:
rcpt["diag_code"] = subpart['Diagnostic-Code']
rcpt["status"] = None
if 'Status' in subpart:
rcpt["status"] = subpart['Status']
recipients.append(rcpt)
return recipients
# Not registered/used callbacks
@Milter.nocallback
def hello(self, heloname):
return Milter.CONTINUE
@Milter.nocallback
def data(self):
return Milter.CONTINUE
def connect(self, IPname, family, hostaddr):
print("CONN: Client: {}".format(hostaddr[0]))
return Milter.CONTINUE
# Mandatory callback
def envfrom(self, mailfrom, *str):
print("MAIL FROM: {}".format(mailfrom))
self.mail_data = ""
return Milter.CONTINUE
# Mandatory callback
def envrcpt(self, to, *str):
print("RCPT TO: {}".format(to))
return Milter.CONTINUE
def header(self, name, hval):
print("HDR: {0}: {1}".format(name, hval))
self.mail_data += "{0}: {1}\n".format(name, hval)
return Milter.CONTINUE
def eoh(self):
self.mail_data += "\n"
return Milter.CONTINUE
def body(self, chunk):
self.mail_data += chunk.decode()
return Milter.CONTINUE
def eom(self):
dsn_details = self.process_dsn(self.mail_data)
for d in dsn_details:
print(json.dumps(d))
return Milter.CONTINUE
def close(self):
print("CLOSE")
self.mail_data = ""
return Milter.CONTINUE
if __name__ == "__main__":
try:
timeout = 600
Milter.factory = DsnProcessorMilter
print("Starting dsn-processor-milter...")
Milter.runmilter("dsn-processor-milter", "inet:4321@127.0.0.1" , timeout, True)
except:
print("MAIN-EXCEPTION: {}".format(traceback.format_exc()))
sys.exit(1)