Compare commits

..

No commits in common. "41514a7f5116452c3466f63cb098828e393b641c" and "f1b2c33996777ce27b09aecd5b500ecefb64ddc6" have entirely different histories.

4 changed files with 28 additions and 54 deletions

View File

@ -1,12 +1,3 @@
[DEFAULT] [DEFAULT]
# Whitelist: Localhost, private Docker-Netze und die Office-IP in Texas # Whitelist: Localhost, private Docker-Netze und die Office-IP in Texas
ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 69.223.70.143 ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 69.223.70.143
[dovecot]
# Erhöht die Anzahl der erlaubten Fehlversuche auf 20
maxretry = 20
[postfix]
# Erhöht die Anzahl der erlaubten Fehlversuche auf 20
maxretry = 20

0
DMS/docker-data/dms/config/user-patches.sh Executable file → Normal file
View File

View File

@ -54,17 +54,17 @@ class BlocklistChecker:
return False return False
def batch_check_blocked_senders( def batch_check_blocked_senders(
self, self,
recipients: List[str], recipients: List[str],
senders: List[str], # <-- Geändert: Erwartet nun eine Liste sender: str,
worker_name: str worker_name: str
) -> Dict[str, bool]: ) -> Dict[str, bool]:
""" """
Batch check if ANY of the senders are blocked for multiple recipients (more efficient) Batch check if sender is blocked for multiple recipients (more efficient)
Args: Args:
recipients: List of recipient email addresses recipients: List of recipient email addresses
senders: List of sender email addresses (Envelope & Header) sender: Sender email address
worker_name: Worker name for logging worker_name: Worker name for logging
Returns: Returns:
@ -73,8 +73,7 @@ class BlocklistChecker:
# Get all blocked patterns in one batch call # Get all blocked patterns in one batch call
patterns_by_recipient = self.dynamodb.batch_get_blocked_patterns(recipients) patterns_by_recipient = self.dynamodb.batch_get_blocked_patterns(recipients)
# Alle übergebenen Adressen bereinigen sender_clean = parseaddr(sender)[1].lower()
senders_clean = [parseaddr(s)[1].lower() for s in senders if s]
result = {} result = {}
for recipient in recipients: for recipient in recipients:
@ -82,18 +81,15 @@ class BlocklistChecker:
is_blocked = False is_blocked = False
for pattern in patterns: for pattern in patterns:
for sender_clean in senders_clean: if fnmatch.fnmatch(sender_clean, pattern.lower()):
if fnmatch.fnmatch(sender_clean, pattern.lower()): log(
log( f"⛔ BLOCKED: Sender {sender_clean} matches pattern '{pattern}' "
f"⛔ BLOCKED: Sender {sender_clean} matches pattern '{pattern}' " f"for inbox {recipient}",
f"for inbox {recipient}", 'WARNING',
'WARNING', worker_name
worker_name )
) is_blocked = True
is_blocked = True break
break # Bricht die Senders-Schleife ab
if is_blocked:
break # Bricht die Pattern-Schleife ab
result[recipient] = is_blocked result[recipient] = is_blocked

View File

@ -4,9 +4,12 @@ Email message processing worker
""" """
import json import json
import time
import traceback import traceback
from typing import List, Tuple
from logger import log from logger import log
from config import config, domain_to_bucket_name
from aws import S3Handler, SQSHandler, SESHandler, DynamoDBHandler from aws import S3Handler, SQSHandler, SESHandler, DynamoDBHandler
from email_processing import EmailParser, BounceHandler, RulesProcessor, BlocklistChecker from email_processing import EmailParser, BounceHandler, RulesProcessor, BlocklistChecker
from smtp.delivery import EmailDelivery from smtp.delivery import EmailDelivery
@ -14,7 +17,6 @@ from metrics.prometheus import MetricsCollector
from email.parser import BytesParser # War wahrscheinlich schon da, prüfen from email.parser import BytesParser # War wahrscheinlich schon da, prüfen
from email.policy import compat32 # <--- NEU: Hinzufügen from email.policy import compat32 # <--- NEU: Hinzufügen
class MessageProcessor: class MessageProcessor:
"""Processes individual email messages""" """Processes individual email messages"""
@ -103,6 +105,7 @@ class MessageProcessor:
log("⚠ Warning: No recipients in event", 'WARNING', worker_name) log("⚠ Warning: No recipients in event", 'WARNING', worker_name)
return True return True
bucket = domain_to_bucket_name(domain)
key = message_id key = message_id
# Compact single-line log for email processing # Compact single-line log for email processing
@ -120,7 +123,7 @@ class MessageProcessor:
skip_rules = self.parser.is_processed_by_worker(temp_parsed) skip_rules = self.parser.is_processed_by_worker(temp_parsed)
if skip_rules: if skip_rules:
log("🔄 Loop prevention: Already processed by worker", 'INFO', worker_name) log(f"🔄 Loop prevention: Already processed by worker", 'INFO', worker_name)
# 5. PARSING & BOUNCE LOGIC # 5. PARSING & BOUNCE LOGIC
try: try:
@ -143,7 +146,7 @@ class MessageProcessor:
log(f" 🔧 Sanitized malformed Message-ID via Legacy Mode: {clean_id}", 'INFO', worker_name) log(f" 🔧 Sanitized malformed Message-ID via Legacy Mode: {clean_id}", 'INFO', worker_name)
if self.metrics: if self.metrics:
self.metrics.increment_bounce(domain, 'sanitized_header') self.metrics.increment_bounce(domain, 'sanitized_header')
except Exception as e_sanitize: except Exception as e_sanitize:
# Sollte nicht passieren, aber wir wollen hier nicht abbrechen # Sollte nicht passieren, aber wir wollen hier nicht abbrechen
@ -160,7 +163,7 @@ class MessageProcessor:
# Klammern entfernen, aber spitze Klammern behalten # Klammern entfernen, aber spitze Klammern behalten
clean_id = current_msg_id.replace('[', '').replace(']', '') clean_id = current_msg_id.replace('[', '').replace(']', '')
parsed.replace_header('Message-ID', clean_id) parsed.replace_header('Message-ID', clean_id)
log(" 🔧 Sanitized malformed Message-ID", 'INFO', worker_name) log(f" 🔧 Sanitized malformed Message-ID", 'INFO', worker_name)
# --- FIX END --- # --- FIX END ---
subject = parsed.get('Subject', '(no subject)') subject = parsed.get('Subject', '(no subject)')
@ -200,25 +203,9 @@ class MessageProcessor:
skip_rules = False skip_rules = False
# 6. BLOCKLIST CHECK (Batch for efficiency) # 6. BLOCKLIST CHECK (Batch for efficiency)
senders_to_check = []
# 1. Die Envelope-Adresse (aus dem SES Event / Return-Path)
if from_addr:
senders_to_check.append(from_addr)
# 2. Die echte Header-Adresse (aus der MIME-E-Mail geparst)
header_from = parsed.get('From')
if header_from and header_from not in senders_to_check:
senders_to_check.append(header_from)
# 3. Falls die Bounce-Logik die Adresse umgeschrieben hat
if from_addr_final and from_addr_final not in senders_to_check:
senders_to_check.append(from_addr_final)
# Prüfe nun alle extrahierten Adressen gegen die Datenbank
blocked_by_recipient = self.blocklist.batch_check_blocked_senders( blocked_by_recipient = self.blocklist.batch_check_blocked_senders(
recipients, recipients,
senders_to_check, # <-- Übergabe der Liste from_addr_final,
worker_name worker_name
) )