#!/bin/bash # awsses.sh - Konfiguriert Amazon SES mit SNS->SQS Fanout Architektur & Outbound Tracking # # Ablauf: # 1. SES Domain Identity erstellen/verifizieren # 2. Domain mit Configuration Set verknüpfen (für Outbound Tracking) # 3. SNS Topic erstellen # 4. SNS Topic Policy setzen (damit SES hineinschreiben darf) # 5. SQS Queue verbinden (Subscription) # 6. SQS Queue Policy setzen (damit SNS hineinschreiben darf) # 7. SES Receipt Rule erstellen (S3 Action + SNS Action) set -e # Überprüfen, ob jq installiert ist if ! command -v jq &> /dev/null; then echo "Fehler: 'jq' ist nicht installiert. Bitte installieren (sudo apt-get install jq)." exit 1 fi # Überprüfen, ob die Domain-Variable gesetzt ist if [ -z "$DOMAIN_NAME" ]; then echo "Fehler: DOMAIN_NAME ist nicht gesetzt." echo "Bitte setzen Sie die Variable mit: export DOMAIN_NAME='IhreDomain.de'" exit 1 fi # Überprüfen, ob S3_BUCKET_NAME gesetzt ist if [ -z "$S3_BUCKET_NAME" ]; then echo "Warnung: S3_BUCKET_NAME ist nicht gesetzt." S3_BUCKET_NAME=$(echo "$DOMAIN_NAME" | tr '.' '-' | awk '{print $0 "-emails"}') echo "Generierter Bucket-Name: $S3_BUCKET_NAME" fi # Konfiguration AWS_REGION=${AWS_REGION:-"us-east-2"} EMAIL_PREFIX=${EMAIL_PREFIX:-""} CONFIGURATION_SET_NAME="relay-outbound" # Name deines globalen Config Sets # Naming Conventions RULE_SET_NAME="bizmatch-ruleset" RULE_NAME="store-${DOMAIN_NAME//./-}-to-s3" TOPIC_NAME="${DOMAIN_NAME//./-}-topic" QUEUE_NAME="${DOMAIN_NAME//./-}-queue" echo "========================================================" echo " SES Setup (Full Architecture) für $DOMAIN_NAME" echo "========================================================" echo "Region: $AWS_REGION" echo "S3 Bucket: $S3_BUCKET_NAME" echo "Config Set: $CONFIGURATION_SET_NAME" echo "--------------------------------------------------------" # ------------------------ # 1. SES Domain Identität # ------------------------ echo "[1/7] Prüfe SES Domain Identität..." if ! aws sesv2 get-email-identity --email-identity ${DOMAIN_NAME} --region ${AWS_REGION} >/dev/null 2>&1; then echo "-> Erstelle Identity..." aws sesv2 create-email-identity --email-identity ${DOMAIN_NAME} --region ${AWS_REGION} >/dev/null else echo "-> Identity existiert bereits." fi # Config Updates (Idempotent) echo "-> Konfiguriere DKIM & Mail-From..." aws sesv2 put-email-identity-dkim-attributes --email-identity ${DOMAIN_NAME} --signing-enabled --region ${AWS_REGION} aws sesv2 put-email-identity-mail-from-attributes --email-identity ${DOMAIN_NAME} --mail-from-domain "mail.${DOMAIN_NAME}" --behavior-on-mx-failure USE_DEFAULT_VALUE --region ${AWS_REGION} # ------------------------ # 2. Configuration Set Verknüpfung (NEU!) # ------------------------ echo "[2/7] Verknüpfe Domain mit Outbound Configuration Set..." # Dies sorgt dafür, dass ausgehende Mails getrackt werden (für OOO/Bounces) aws sesv2 put-email-identity-configuration-set-attributes \ --email-identity ${DOMAIN_NAME} \ --configuration-set-name "$CONFIGURATION_SET_NAME" \ --region ${AWS_REGION} # ------------------------ # 3. SNS Topic erstellen # ------------------------ echo "[3/7] Erstelle/Prüfe SNS Topic..." TOPIC_ARN=$(aws sns create-topic --name "$TOPIC_NAME" --region "$AWS_REGION" --output text --query 'TopicArn') echo "-> Topic ARN: $TOPIC_ARN" # ------------------------ # 4. SNS Policy (SES -> SNS) # ------------------------ echo "[4/7] Setze SNS Policy (SES darf publishen)..." ACCOUNT_ID=$(echo "$TOPIC_ARN" | cut -d: -f5) SNS_POLICY=$(jq -n \ --arg topic_arn "$TOPIC_ARN" \ --arg account_id "$ACCOUNT_ID" \ '{ Version: "2008-10-17", Id: "__default_policy_ID", Statement: [ { Sid: "Allow-SES-Publish", Effect: "Allow", Principal: { Service: "ses.amazonaws.com" }, Action: "sns:Publish", Resource: $topic_arn, Condition: { StringEquals: { "AWS:SourceAccount": $account_id } } } ] }' | jq -c .) aws sns set-topic-attributes --topic-arn "$TOPIC_ARN" --attribute-name Policy --attribute-value "$SNS_POLICY" --region "$AWS_REGION" # ------------------------ # 5. SQS Queue Verbindung # ------------------------ echo "[5/7] Verbinde SQS Queue..." # Queue URL & ARN holen (Queue muss existieren -> create-queue.sh vorher ausführen!) QUEUE_URL=$(aws sqs get-queue-url --queue-name "$QUEUE_NAME" --region "$AWS_REGION" --output text --query 'QueueUrl' 2>/dev/null) if [ -z "$QUEUE_URL" ]; then echo "FEHLER: Queue $QUEUE_NAME nicht gefunden!" echo "Bitte führen Sie erst ./create-queue.sh aus." exit 1 fi QUEUE_ARN=$(aws sqs get-queue-attributes --queue-url "$QUEUE_URL" --attribute-names QueueArn --region "$AWS_REGION" --output text --query 'Attributes.QueueArn') # Subscription erstellen (Idempotent) aws sns subscribe --topic-arn "$TOPIC_ARN" --protocol sqs --notification-endpoint "$QUEUE_ARN" --region "$AWS_REGION" > /dev/null # ------------------------ # 6. SQS Policy (SNS -> SQS) # ------------------------ echo "[6/7] Setze SQS Policy (SNS darf schreiben)..." SQS_POLICY=$(jq -n \ --arg queue_arn "$QUEUE_ARN" \ --arg topic_arn "$TOPIC_ARN" \ '{ Version: "2012-10-17", Id: "SNS-to-SQS", Statement: [ { Sid: "Allow-SNS-SendMessage", Effect: "Allow", Principal: { Service: "sns.amazonaws.com" }, Action: "sqs:SendMessage", Resource: $queue_arn, Condition: { ArnEquals: { "aws:SourceArn": $topic_arn } } } ] }' | jq -c .) # Policy setzen (mit Single-Quote Schutz für AWS CLI) aws sqs set-queue-attributes --queue-url "$QUEUE_URL" --attributes Policy="'$SQS_POLICY'" --region "$AWS_REGION" # ------------------------ # 7. SES Rule Set & Rule # ------------------------ echo "[7/7] Konfiguriere SES Receipt Rule..." # Rule Set prüfen RULESET_EXISTS=$(aws ses list-receipt-rule-sets --region ${AWS_REGION} | jq -r '.RuleSets[] | select(.Name == "bizmatch-ruleset") | .Name') if [ "$RULESET_EXISTS" != "bizmatch-ruleset" ]; then echo "-> Erstelle Rule Set 'bizmatch-ruleset'..." aws ses create-receipt-rule-set --rule-set-name "bizmatch-ruleset" --region ${AWS_REGION} fi # Rule prüfen/erstellen if ! aws ses describe-receipt-rule --rule-set-name "$RULE_SET_NAME" --rule-name "${RULE_NAME}" --region ${AWS_REGION} >/dev/null 2>&1; then echo "-> Erstelle Receipt Rule '${RULE_NAME}'..." # Rule mit S3 Action UND SNS Action # HINWEIS: Hier fügen wir initial die Hauptdomain als Recipient hinzu. # Denke daran, später ./manage_mail_user.sh sync ... auszuführen! aws ses create-receipt-rule --rule-set-name "$RULE_SET_NAME" --rule '{ "Name": "'"${RULE_NAME}"'", "Enabled": true, "ScanEnabled": true, "Actions": [ { "S3Action": { "BucketName": "'"${S3_BUCKET_NAME}"'", "ObjectKeyPrefix": "'"${EMAIL_PREFIX}"'" } }, { "SNSAction": { "TopicArn": "'"${TOPIC_ARN}"'", "Encoding": "UTF-8" } } ], "TlsPolicy": "Require", "Recipients": ["'"${DOMAIN_NAME}"'"] }' --region ${AWS_REGION} else echo "-> Receipt Rule '${RULE_NAME}' existiert bereits (Überspringe Erstellung)." fi # Rule Set aktivieren ACTIVE_RULESET=$(aws ses describe-active-receipt-rule-set --region ${AWS_REGION} | jq -r '.Metadata.Name') if [ "$ACTIVE_RULESET" != "bizmatch-ruleset" ]; then echo "-> Aktiviere Rule Set..." aws ses set-active-receipt-rule-set --rule-set-name "bizmatch-ruleset" --region ${AWS_REGION} fi echo "========================================================" echo "✅ Setup erfolgreich abgeschlossen für $DOMAIN_NAME" echo "========================================================"