Merge branch 'main' of git.bizmatch.net:aknuth/email-amazon

This commit is contained in:
Andreas Knuth 2026-02-09 13:13:39 -06:00
commit 6bfe33d3af
1 changed files with 89 additions and 18 deletions

View File

@ -77,7 +77,8 @@ class RulesProcessor:
forwards, forwards,
domain, domain,
worker_name, worker_name,
metrics_callback metrics_callback,
rule=rule
) )
def _handle_ooo( def _handle_ooo(
@ -141,33 +142,103 @@ class RulesProcessor:
forwards: list, forwards: list,
domain: str, domain: str,
worker_name: str, worker_name: str,
metrics_callback=None metrics_callback=None,
rule: dict = None # NEU
): ):
"""Handle email forwarding""" """Handle email forwarding"""
# NEU: SMTP Override aus Rule lesen
smtp_override = None
if rule:
smtp_override = rule.get('forward_smtp_override')
for forward_to in forwards: for forward_to in forwards:
try: try:
fwd_msg = self._create_forward_message(parsed, recipient, forward_to, original_from) fwd_msg = self._create_forward_message(
parsed, recipient, forward_to, original_from
)
fwd_bytes = fwd_msg.as_bytes() fwd_bytes = fwd_msg.as_bytes()
# Distinguish: Internal (Port 2525) vs External (SES) # NEU: Legacy SMTP Override (Migration)
if is_internal_address(forward_to): if smtp_override:
# Internal address → direct via Port 2525 (no loop!) success = self._send_via_legacy_smtp(
success = self._send_internal_email(recipient, forward_to, fwd_bytes, worker_name) recipient, forward_to, fwd_bytes,
smtp_override, worker_name
)
if success: if success:
log(f"✓ Forwarded internally to {forward_to}", 'SUCCESS', worker_name) log(f"✓ Forwarded via legacy SMTP to {forward_to} "
f"({smtp_override.get('host', '?')})",
'SUCCESS', worker_name)
else: else:
log(f"⚠ Internal forward failed to {forward_to}", 'WARNING', worker_name) log(f"⚠ Legacy SMTP forward failed to {forward_to}",
else: 'WARNING', worker_name)
# External address → via SES
success = self.ses.send_raw_email(recipient, forward_to, fwd_bytes, worker_name) elif is_internal_address(forward_to):
success = self._send_internal_email(
recipient, forward_to, fwd_bytes, worker_name
)
if success: if success:
log(f"✓ Forwarded externally to {forward_to} via SES", 'SUCCESS', worker_name) log(f"✓ Forwarded internally to {forward_to}",
'SUCCESS', worker_name)
else:
log(f"⚠ Internal forward failed to {forward_to}",
'WARNING', worker_name)
else:
success = self.ses.send_raw_email(
recipient, forward_to, fwd_bytes, worker_name
)
if success:
log(f"✓ Forwarded externally to {forward_to} via SES",
'SUCCESS', worker_name)
if metrics_callback: if metrics_callback:
metrics_callback('forward', domain) metrics_callback('forward', domain)
except Exception as e: except Exception as e:
log(f"⚠ Forward failed to {forward_to}: {e}", 'ERROR', worker_name) log(f"⚠ Forward failed to {forward_to}: {e}",
'ERROR', worker_name)
@staticmethod
def _send_via_legacy_smtp(
from_addr: str,
to_addr: str,
raw_message: bytes,
smtp_config: dict,
worker_name: str
) -> bool:
"""
Send email directly to a legacy SMTP server (for migration).
Bypasses SES completely to avoid mail loops.
"""
try:
host = smtp_config.get('host', '')
# DynamoDB speichert Zahlen als Decimal, daher int()
port = int(smtp_config.get('port', 25))
use_tls = smtp_config.get('tls', False)
username = smtp_config.get('username')
password = smtp_config.get('password')
if not host:
log(f" ✗ Legacy SMTP: no host configured", 'ERROR', worker_name)
return False
with smtplib.SMTP(host, port, timeout=30) as conn:
conn.ehlo()
if use_tls:
conn.starttls()
conn.ehlo()
if username and password:
conn.login(username, password)
conn.sendmail(from_addr, [to_addr], raw_message)
return True
except Exception as e:
log(
f" ✗ Legacy SMTP failed ({smtp_config.get('host', '?')}:"
f"{smtp_config.get('port', '?')}): {e}",
'ERROR', worker_name
)
return False
@staticmethod @staticmethod
def _send_internal_email(from_addr: str, to_addr: str, raw_message: bytes, worker_name: str) -> bool: def _send_internal_email(from_addr: str, to_addr: str, raw_message: bytes, worker_name: str) -> bool: