#!/usr/bin/python3 import smtplib import subprocess import sys SMTP_HOST = "127.0.0.1" SMTP_PORT = 10028 DECISION_SCRIPT = "/usr/local/sbin/srs-alias-decision.py" SRS_MAP = "socketmap:inet:127.0.0.1:10003:forward" EX_TEMPFAIL = 75 EX_UNAVAILABLE = 69 def run_command(args): result = subprocess.run( args, capture_output=True, text=True, timeout=30 ) if result.returncode != 0: raise RuntimeError( result.stderr.strip() or result.stdout.strip() or f"Exit-Code {result.returncode}" ) return result.stdout.strip() def determine_sender(sender, recipient, original_recipient): decision = run_command([ DECISION_SCRIPT, sender, recipient, original_recipient ]) if decision.startswith("NO_SRS:"): return sender if not decision.startswith("SRS:"): raise RuntimeError( f"Keine eindeutige SRS-Entscheidung: {decision}" ) rewritten_sender = run_command([ "/usr/sbin/postmap", "-q", sender, SRS_MAP ]) if not rewritten_sender: raise RuntimeError("PostSRSd lieferte keinen Absender") if not rewritten_sender.lower().endswith("@srs.warenform.de"): raise RuntimeError( f"Unerwartete SRS-Domain: {rewritten_sender}" ) if not rewritten_sender.upper().startswith(("SRS0=", "SRS1=")): raise RuntimeError( f"Ungueltige SRS-Adresse: {rewritten_sender}" ) return rewritten_sender def main(): if len(sys.argv) not in (5, 6): print( "Aufruf: srs-forward.py " "sender recipient original_recipient queue_id [envid]", file=sys.stderr ) return EX_TEMPFAIL sender, recipient, original_recipient, queue_id = sys.argv[1:5] envid = sys.argv[5] if len(sys.argv) == 6 else "" if envid.startswith("envid="): envid = envid[len("envid="):] try: envelope_sender = determine_sender( sender, recipient, original_recipient ) message = sys.stdin.buffer.read() with smtplib.SMTP( SMTP_HOST, SMTP_PORT, timeout=30 ) as smtp: smtp.ehlo() mail_options = [] rcpt_options = [] if envid: if not smtp.has_extn("dsn"): raise RuntimeError( "SMTP-Ziel unterstuetzt kein DSN/ENVID" ) mail_options.append(f"ENVID={envid}") if original_recipient and smtp.has_extn("dsn"): rcpt_options.append( f"ORCPT=rfc822;{original_recipient}" ) smtp.sendmail( envelope_sender, [recipient], message, mail_options=mail_options, rcpt_options=rcpt_options ) except smtplib.SMTPRecipientsRefused as exc: codes = [ code for code, response in exc.recipients.values() ] permanent = bool(codes) and all( 500 <= code < 600 for code in codes ) result = EX_UNAVAILABLE if permanent else EX_TEMPFAIL enhanced_status = "5.0.0" if permanent else "4.0.0" print( f"{enhanced_status} SRS queue_id={queue_id}: " f"SMTP-Empfaengerablehnung: {exc.recipients!r}", file=sys.stderr ) return result except smtplib.SMTPResponseException as exc: code = exc.smtp_code result = EX_UNAVAILABLE if 500 <= code < 600 else EX_TEMPFAIL enhanced_status = "5.0.0" if result == EX_UNAVAILABLE else "4.0.0" print( f"{enhanced_status} SRS queue_id={queue_id}: " f"SMTP {code}: {exc.smtp_error!r}", file=sys.stderr ) return result except ( subprocess.TimeoutExpired, RuntimeError, smtplib.SMTPException, OSError ) as exc: print( f"SRS queue_id={queue_id}: temporaerer Fehler: {exc}", file=sys.stderr ) return EX_TEMPFAIL return 0 if __name__ == "__main__": sys.exit(main())