106 lines
3.1 KiB
Python
106 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
# check-dlq.py
|
|
"""
|
|
Überprüft Dead Letter Queues und zeigt fehlgeschlagene E-Mails
|
|
"""
|
|
|
|
import boto3
|
|
import json
|
|
from datetime import datetime
|
|
|
|
sqs = boto3.client('sqs', region_name='eu-central-1')
|
|
s3 = boto3.client('s3', region_name='eu-central-1')
|
|
|
|
DOMAINS = ['andreasknuth.de', 'bizmatch.net']
|
|
|
|
def check_dlq_for_domain(domain):
|
|
"""Überprüft DLQ für eine Domain"""
|
|
dlq_name = domain.replace('.', '-') + '-queue-dlq'
|
|
|
|
try:
|
|
dlq_url = sqs.get_queue_url(QueueName=dlq_name)['QueueUrl']
|
|
except:
|
|
print(f"⚠️ DLQ not found for {domain}")
|
|
return
|
|
|
|
# DLQ Stats
|
|
attrs = sqs.get_queue_attributes(
|
|
QueueUrl=dlq_url,
|
|
AttributeNames=['ApproximateNumberOfMessages']
|
|
)['Attributes']
|
|
|
|
count = int(attrs.get('ApproximateNumberOfMessages', 0))
|
|
|
|
if count == 0:
|
|
print(f"✅ {domain}: No failed messages")
|
|
return
|
|
|
|
print(f"\n{'='*70}")
|
|
print(f"⚠️ {domain}: {count} failed message(s)")
|
|
print(f"{'='*70}\n")
|
|
|
|
# Messages holen
|
|
response = sqs.receive_message(
|
|
QueueUrl=dlq_url,
|
|
MaxNumberOfMessages=10,
|
|
WaitTimeSeconds=0,
|
|
AttributeNames=['All']
|
|
)
|
|
|
|
messages = response.get('Messages', [])
|
|
|
|
for i, msg in enumerate(messages, 1):
|
|
try:
|
|
body = json.loads(msg['Body'])
|
|
|
|
print(f"{i}. Failed Message:")
|
|
print(f" MessageId: {body.get('message_id', 'unknown')}")
|
|
print(f" From: {body.get('from', 'unknown')}")
|
|
print(f" To: {body.get('recipient', 'unknown')}")
|
|
print(f" Subject: {body.get('subject', 'unknown')}")
|
|
|
|
# S3 Metadata für Fehlerdetails
|
|
bucket = body.get('bucket')
|
|
key = body.get('key')
|
|
|
|
if bucket and key:
|
|
try:
|
|
head = s3.head_object(Bucket=bucket, Key=key)
|
|
metadata = head.get('Metadata', {})
|
|
|
|
error = metadata.get('error', 'Unknown error')
|
|
failed_at = metadata.get('failed_at', 'unknown')
|
|
|
|
if failed_at != 'unknown':
|
|
failed_dt = datetime.fromtimestamp(int(failed_at))
|
|
print(f" Failed at: {failed_dt}")
|
|
|
|
print(f" Error: {error}")
|
|
|
|
except:
|
|
print(f" (Could not retrieve error details)")
|
|
|
|
print()
|
|
|
|
except Exception as e:
|
|
print(f" Error parsing message: {e}\n")
|
|
|
|
|
|
def main():
|
|
print(f"\n{'='*70}")
|
|
print(f"Dead Letter Queue Check - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
print(f"{'='*70}")
|
|
|
|
for domain in DOMAINS:
|
|
check_dlq_for_domain(domain)
|
|
|
|
print(f"\n{'='*70}")
|
|
print("Options:")
|
|
print(" - Fix SMTP server issues")
|
|
print(" - Re-queue: python requeue-dlq.py <domain>")
|
|
print(" - Delete: python purge-dlq.py <domain>")
|
|
print(f"{'='*70}\n")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main() |