worker with ooo & forward logic
This commit is contained in:
64
worker.py
64
worker.py
@@ -35,12 +35,15 @@ SMTP_PASS = os.environ.get('SMTP_PASS')
|
||||
shutdown_requested = False
|
||||
|
||||
# DynamoDB Ressource für Bounce-Lookup
|
||||
# DynamoDB Ressource für Bounce-Lookup und Rules
|
||||
try:
|
||||
dynamo = boto3.resource('dynamodb', region_name=AWS_REGION)
|
||||
msg_table = dynamo.Table('ses-outbound-messages')
|
||||
rules_table = dynamo.Table('email-rules') # Neu: Für OOO/Forwards
|
||||
except Exception as e:
|
||||
log(f"Warning: Could not connect to DynamoDB: {e}", 'WARNING')
|
||||
msg_table = None
|
||||
rules_table = None
|
||||
|
||||
def get_bucket_name(domain):
|
||||
"""Konvention: domain.tld -> domain-tld-emails"""
|
||||
@@ -511,7 +514,66 @@ def process_message(message_body: dict, receive_count: int) -> bool:
|
||||
log(f"⚠ Parsing/Logic Error: {e}. Sending original.", 'WARNING')
|
||||
from_addr_final = from_addr
|
||||
|
||||
# 5. SMTP VERSAND (Loop über Recipients)
|
||||
# 5. OOO & FORWARD LOGIC (neu, vor SMTP-Versand)
|
||||
if rules_table and not is_ses_bounce_or_autoreply(parsed): # Vermeide Loops bei Bounces/Auto-Replies
|
||||
for recipient in recipients:
|
||||
try:
|
||||
rule = rules_table.get_item(Key={'email_address': recipient}).get('Item', {})
|
||||
|
||||
# OOO handling
|
||||
if rule.get('ooo_active', False):
|
||||
ooo_msg = rule.get('ooo_message', 'Default OOO message.')
|
||||
content_type = rule.get('ooo_content_type', 'text') # Default: text
|
||||
sender = parsed.get('From') # Original-Sender
|
||||
|
||||
reply_subject = f"Out of Office: {subject}"
|
||||
original_body = str(parsed.get_payload(decode=True)) # Original für Quote
|
||||
|
||||
if content_type == 'html':
|
||||
reply_body = {'Html': {'Data': f"<p>{ooo_msg}</p><br><blockquote>Original Message:<br>Subject: {parsed.get('Subject')}<br>From: {sender}<br><br>{original_body}</blockquote>"}}
|
||||
else:
|
||||
reply_body = {'Text': {'Data': f"{ooo_msg}\n\nOriginal Message:\nSubject: {parsed.get('Subject')}\nFrom: {sender}\n\n{original_body}"}}
|
||||
|
||||
ses.send_email(
|
||||
Source=recipient, # Verifizierte eigene Adresse
|
||||
Destination={'ToAddresses': [sender]},
|
||||
Message={
|
||||
'Subject': {'Data': reply_subject},
|
||||
'Body': reply_body # Dynamisch Text oder Html
|
||||
},
|
||||
ReplyToAddresses=[recipient] # Optional: Für Replies
|
||||
)
|
||||
log(f"✓ Sent OOO reply to {sender} from {recipient}")
|
||||
|
||||
# Forward handling
|
||||
forwards = rule.get('forwards', [])
|
||||
if forwards:
|
||||
original_from = parsed.get('From') # Für Headers
|
||||
fwd_subject = f"FWD: {subject}"
|
||||
fwd_body_text = f"Forwarded from: {original_from}\n\n{original_body}"
|
||||
fwd_body = {'Text': {'Data': fwd_body_text}} # Erweiterbar auf HTML
|
||||
|
||||
for forward_to in forwards:
|
||||
ses.send_email(
|
||||
Source=recipient, # Verifizierte eigene Adresse
|
||||
Destination={'ToAddresses': [forward_to]},
|
||||
Message={
|
||||
'Subject': {'Data': fwd_subject},
|
||||
'Body': fwd_body
|
||||
},
|
||||
ReplyToAddresses=[original_from] # Original-Sender für Replies
|
||||
)
|
||||
log(f"✓ Forwarded to {forward_to} from {recipient} (original: {original_from})")
|
||||
|
||||
except boto3.exceptions.ClientError as e:
|
||||
if 'MessageRejected' in str(e):
|
||||
log(f"⚠ SES rejected: {e}. Check verification.", 'ERROR')
|
||||
else:
|
||||
log(f"⚠ Rules error for {recipient}: {e}", 'WARNING')
|
||||
except Exception as e:
|
||||
log(f"⚠ General error: {e}", 'WARNING')
|
||||
|
||||
# 6. SMTP VERSAND (Loop über Recipients)
|
||||
log(f"📤 Sending to {len(recipients)} recipient(s)...")
|
||||
|
||||
successful = []
|
||||
|
||||
Reference in New Issue
Block a user