new scripts & new mail from
This commit is contained in:
parent
38fcf8c4d8
commit
8c3db9db95
|
|
@ -1,7 +1,16 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# awsses_lambda_global.sh - SES Setup mit S3 + Global Lambda Shim -> SQS
|
# awsses.sh - SES Setup mit S3 + Global Lambda Shim -> SQS
|
||||||
# Dieses Skript ist idempotent: Es kann sicher mehrfach ausgeführt werden.
|
# Dieses Skript ist idempotent: Es kann sicher mehrfach ausgeführt werden.
|
||||||
# Globale Lambda für alle Domains.
|
# Globale Lambda für alle Domains.
|
||||||
|
#
|
||||||
|
# MAIL FROM Subdomain:
|
||||||
|
# Standard: mail.${DOMAIN_NAME}
|
||||||
|
# Override: export MAIL_FROM_SUBDOMAIN="mailfrom" (nur der Prefix, ohne Domain)
|
||||||
|
#
|
||||||
|
# Beispiel:
|
||||||
|
# export DOMAIN_NAME="buddelectric.net"
|
||||||
|
# export MAIL_FROM_SUBDOMAIN="mailfrom" # → mailfrom.buddelectric.net
|
||||||
|
# ./awsses.sh
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
|
@ -21,6 +30,10 @@ AWS_REGION=${AWS_REGION:-"us-east-2"}
|
||||||
EMAIL_PREFIX=${EMAIL_PREFIX:-""}
|
EMAIL_PREFIX=${EMAIL_PREFIX:-""}
|
||||||
CONFIGURATION_SET_NAME="relay-outbound"
|
CONFIGURATION_SET_NAME="relay-outbound"
|
||||||
|
|
||||||
|
# MAIL FROM Subdomain (konfigurierbar)
|
||||||
|
MAIL_FROM_SUBDOMAIN=${MAIL_FROM_SUBDOMAIN:-"mail"}
|
||||||
|
MAIL_FROM_DOMAIN="${MAIL_FROM_SUBDOMAIN}.${DOMAIN_NAME}"
|
||||||
|
|
||||||
# Bucket Name generieren falls leer
|
# Bucket Name generieren falls leer
|
||||||
if [ -z "$S3_BUCKET_NAME" ]; then
|
if [ -z "$S3_BUCKET_NAME" ]; then
|
||||||
S3_BUCKET_NAME=$(echo "$DOMAIN_NAME" | tr '.' '-' | awk '{print $0 "-emails"}')
|
S3_BUCKET_NAME=$(echo "$DOMAIN_NAME" | tr '.' '-' | awk '{print $0 "-emails"}')
|
||||||
|
|
@ -35,6 +48,7 @@ LAMBDA_ROLE_NAME="SesShimGlobalRole"
|
||||||
|
|
||||||
echo "=========================================================="
|
echo "=========================================================="
|
||||||
echo " SES Setup (S3 -> Global Lambda Shim -> SQS) für $DOMAIN_NAME"
|
echo " SES Setup (S3 -> Global Lambda Shim -> SQS) für $DOMAIN_NAME"
|
||||||
|
echo " MAIL FROM: $MAIL_FROM_DOMAIN"
|
||||||
echo "=========================================================="
|
echo "=========================================================="
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
|
|
@ -46,9 +60,11 @@ if ! aws sesv2 get-email-identity --email-identity ${DOMAIN_NAME} --region ${AWS
|
||||||
fi
|
fi
|
||||||
# Update Attributes (Idempotent)
|
# Update Attributes (Idempotent)
|
||||||
aws sesv2 put-email-identity-dkim-attributes --email-identity ${DOMAIN_NAME} --signing-enabled --region ${AWS_REGION}
|
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}
|
aws sesv2 put-email-identity-mail-from-attributes --email-identity ${DOMAIN_NAME} --mail-from-domain "${MAIL_FROM_DOMAIN}" --behavior-on-mx-failure USE_DEFAULT_VALUE --region ${AWS_REGION}
|
||||||
aws sesv2 put-email-identity-configuration-set-attributes --email-identity ${DOMAIN_NAME} --configuration-set-name "$CONFIGURATION_SET_NAME" --region ${AWS_REGION}
|
aws sesv2 put-email-identity-configuration-set-attributes --email-identity ${DOMAIN_NAME} --configuration-set-name "$CONFIGURATION_SET_NAME" --region ${AWS_REGION}
|
||||||
|
|
||||||
|
echo " -> MAIL FROM Domain: ${MAIL_FROM_DOMAIN}"
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
# 2. SQS Queue holen (nur zur Validierung, Lambda holt dynamisch)
|
# 2. SQS Queue holen (nur zur Validierung, Lambda holt dynamisch)
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
|
|
@ -149,7 +165,7 @@ RULE_JSON=$(jq -n \
|
||||||
--arg larn "$LAMBDA_ARN" \
|
--arg larn "$LAMBDA_ARN" \
|
||||||
--arg rule "$RULE_NAME" \
|
--arg rule "$RULE_NAME" \
|
||||||
--arg domain "$DOMAIN_NAME" \
|
--arg domain "$DOMAIN_NAME" \
|
||||||
--arg subdomain "mail.$DOMAIN_NAME" \
|
--arg subdomain "${MAIL_FROM_DOMAIN}" \
|
||||||
'{
|
'{
|
||||||
Name: $rule,
|
Name: $rule,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
|
|
@ -181,7 +197,12 @@ else
|
||||||
fi
|
fi
|
||||||
# Aktivieren
|
# Aktivieren
|
||||||
aws ses set-active-receipt-rule-set --rule-set-name "bizmatch-ruleset" --region ${AWS_REGION}
|
aws ses set-active-receipt-rule-set --rule-set-name "bizmatch-ruleset" --region ${AWS_REGION}
|
||||||
|
|
||||||
echo "========================================================"
|
echo "========================================================"
|
||||||
echo "✅ Setup erfolgreich. Globale Lambda ($LAMBDA_NAME) für alle Domains."
|
echo "✅ Setup erfolgreich."
|
||||||
echo " S3 -> Lambda -> Domain-spezifische SQS"
|
echo " Domain: $DOMAIN_NAME"
|
||||||
|
echo " MAIL FROM: $MAIL_FROM_DOMAIN"
|
||||||
|
echo " S3 Bucket: $S3_BUCKET_NAME"
|
||||||
|
echo " SQS Queue: $QUEUE_NAME"
|
||||||
|
echo " Lambda: $LAMBDA_NAME (global)"
|
||||||
echo "========================================================"
|
echo "========================================================"
|
||||||
|
|
@ -0,0 +1,358 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# cloudflareMigrationDns.sh - DNS Setup für sanfte E-Mail-Migration
|
||||||
|
#
|
||||||
|
# Dieses Script ist speziell für die Migration von einem alten Provider
|
||||||
|
# zu Bay Area Email (Amazon SES + DMS). Es:
|
||||||
|
# - Erkennt automatisch die MAIL FROM Subdomain aus SES
|
||||||
|
# - Prüft auf CNAME-Konflikte bevor Records gesetzt werden
|
||||||
|
# - Enthält den alten Provider SPF während der Migration
|
||||||
|
# - Setzt KEINE Autodiscover/SRV Records (das kommt erst in Phase 3)
|
||||||
|
#
|
||||||
|
# Voraussetzungen:
|
||||||
|
# - awsses.sh wurde bereits ausgeführt (SES Identity existiert)
|
||||||
|
# - Domain ist bereits in Cloudflare
|
||||||
|
#
|
||||||
|
# Verwendung:
|
||||||
|
# export DOMAIN_NAME="buddelectric.net"
|
||||||
|
# export CF_API_TOKEN="xxx"
|
||||||
|
# export OLD_PROVIDER_SPF="include:_spf.hostedemail.com" # SPF des alten Providers
|
||||||
|
# ./cloudflareMigrationDns.sh
|
||||||
|
#
|
||||||
|
# Optionale Parameter:
|
||||||
|
# export OLD_PROVIDER_SPF="" # Kein alter SPF nötig
|
||||||
|
# export DRY_RUN="true" # Nur anzeigen, nichts ändern
|
||||||
|
# export SKIP_MX="true" # MX nicht setzen (für Tests)
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# KONFIGURATION & CHECKS
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
AWS_REGION=${AWS_REGION:-"us-east-2"}
|
||||||
|
DRY_RUN=${DRY_RUN:-"false"}
|
||||||
|
SKIP_MX=${SKIP_MX:-"false"}
|
||||||
|
|
||||||
|
if [ -z "$DOMAIN_NAME" ]; then
|
||||||
|
echo "❌ Fehler: DOMAIN_NAME ist nicht gesetzt."
|
||||||
|
echo " export DOMAIN_NAME='buddelectric.net'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ -z "$CF_API_TOKEN" ]; then
|
||||||
|
echo "❌ Fehler: CF_API_TOKEN fehlt."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! command -v jq &> /dev/null; then
|
||||||
|
echo "❌ Fehler: 'jq' fehlt."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! command -v aws &> /dev/null; then
|
||||||
|
echo "❌ Fehler: 'aws' CLI fehlt."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "============================================================"
|
||||||
|
echo " 📧 Migration DNS Setup für: $DOMAIN_NAME"
|
||||||
|
echo "============================================================"
|
||||||
|
if [ "$DRY_RUN" = "true" ]; then
|
||||||
|
echo " ⚠️ DRY RUN - Es werden KEINE Änderungen vorgenommen!"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 1. MAIL FROM Subdomain aus SES ermitteln
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
echo "--- [1/7] MAIL FROM Subdomain aus SES ermitteln ---"
|
||||||
|
|
||||||
|
SES_IDENTITY=$(aws sesv2 get-email-identity \
|
||||||
|
--email-identity "${DOMAIN_NAME}" \
|
||||||
|
--region "${AWS_REGION}" \
|
||||||
|
--output json 2>/dev/null)
|
||||||
|
|
||||||
|
if [ $? -ne 0 ] || [ -z "$SES_IDENTITY" ]; then
|
||||||
|
echo "❌ SES Identity für ${DOMAIN_NAME} nicht gefunden!"
|
||||||
|
echo " Bitte zuerst ./awsses.sh ausführen."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
MAIL_FROM_DOMAIN=$(echo "$SES_IDENTITY" | jq -r '.MailFromAttributes.MailFromDomain // empty')
|
||||||
|
|
||||||
|
if [ -z "$MAIL_FROM_DOMAIN" ]; then
|
||||||
|
echo "⚠️ Keine MAIL FROM Domain in SES konfiguriert. Verwende mail.${DOMAIN_NAME}"
|
||||||
|
MAIL_FROM_DOMAIN="mail.${DOMAIN_NAME}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extrahiere den Subdomain-Prefix (z.B. "mailfrom" aus "mailfrom.buddelectric.net")
|
||||||
|
MAIL_FROM_PREFIX=$(echo "$MAIL_FROM_DOMAIN" | sed "s/\.${DOMAIN_NAME}$//")
|
||||||
|
|
||||||
|
echo " ✓ MAIL FROM Domain: ${MAIL_FROM_DOMAIN} (Prefix: ${MAIL_FROM_PREFIX})"
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 2. Cloudflare Zone ID ermitteln
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "--- [2/7] Cloudflare Zone ID ermitteln ---"
|
||||||
|
|
||||||
|
ZONE_RESPONSE=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN_NAME" \
|
||||||
|
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||||
|
-H "Content-Type: application/json")
|
||||||
|
|
||||||
|
if [ "$(echo $ZONE_RESPONSE | jq -r '.success')" != "true" ]; then
|
||||||
|
echo "❌ Fehler beim Abrufen der Zone ID:"
|
||||||
|
echo $ZONE_RESPONSE | jq .
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
CF_ZONE_ID=$(echo $ZONE_RESPONSE | jq -r '.result[0].id')
|
||||||
|
if [ "$CF_ZONE_ID" = "null" ] || [ -z "$CF_ZONE_ID" ]; then
|
||||||
|
echo "❌ Zone für $DOMAIN_NAME nicht in Cloudflare gefunden!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo " ✓ Zone ID: $CF_ZONE_ID"
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 3. Bestehende Records prüfen (Konflikte erkennen)
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "--- [3/7] Bestehende DNS Records prüfen ---"
|
||||||
|
|
||||||
|
# Alle Records der Zone abrufen
|
||||||
|
EXISTING_RECORDS=$(curl -s -X GET \
|
||||||
|
"https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records?per_page=100" \
|
||||||
|
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||||
|
-H "Content-Type: application/json")
|
||||||
|
|
||||||
|
# Prüfe auf CNAME-Konflikt mit MAIL FROM Subdomain
|
||||||
|
MAIL_FROM_CNAME=$(echo "$EXISTING_RECORDS" | jq -r \
|
||||||
|
--arg name "${MAIL_FROM_DOMAIN}" \
|
||||||
|
'.result[] | select(.type == "CNAME" and .name == $name) | .content')
|
||||||
|
|
||||||
|
if [ -n "$MAIL_FROM_CNAME" ]; then
|
||||||
|
echo ""
|
||||||
|
echo " ⚠️ KONFLIKT ERKANNT!"
|
||||||
|
echo " ${MAIL_FROM_DOMAIN} hat einen CNAME → ${MAIL_FROM_CNAME}"
|
||||||
|
echo " Ein CNAME erlaubt keine weiteren Records (MX, TXT)."
|
||||||
|
echo ""
|
||||||
|
echo " Optionen:"
|
||||||
|
echo " 1) CNAME löschen lassen (falls kein Client diesen Hostnamen nutzt)"
|
||||||
|
echo " 2) awsses.sh mit MAIL_FROM_SUBDOMAIN='mailfrom' nochmal ausführen"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Prüfe ob es ein alternativer MAIL FROM wäre
|
||||||
|
if [ "$MAIL_FROM_PREFIX" = "mail" ]; then
|
||||||
|
echo " 💡 Empfehlung: Führe folgendes aus und starte dann dieses Script neu:"
|
||||||
|
echo ""
|
||||||
|
echo " export MAIL_FROM_SUBDOMAIN=\"mailfrom\""
|
||||||
|
echo " export DOMAIN_NAME=\"${DOMAIN_NAME}\""
|
||||||
|
echo " ./awsses.sh"
|
||||||
|
echo ""
|
||||||
|
echo " Dann dieses Script erneut starten."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prüfe auf bestehenden MX Record
|
||||||
|
EXISTING_MX=$(echo "$EXISTING_RECORDS" | jq -r \
|
||||||
|
--arg name "${DOMAIN_NAME}" \
|
||||||
|
'.result[] | select(.type == "MX" and .name == $name) | "\(.priority) \(.content)"')
|
||||||
|
|
||||||
|
if [ -n "$EXISTING_MX" ]; then
|
||||||
|
echo " ℹ️ Bestehende MX Records:"
|
||||||
|
echo "$EXISTING_MX" | while read line; do echo " $line"; done
|
||||||
|
echo " → Diese müssen manuell gelöscht werden bevor der neue MX gesetzt wird!"
|
||||||
|
echo " (Script erstellt nur neue Records, löscht keine alten)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prüfe auf bestehenden SPF
|
||||||
|
EXISTING_SPF=$(echo "$EXISTING_RECORDS" | jq -r \
|
||||||
|
--arg name "${DOMAIN_NAME}" \
|
||||||
|
'.result[] | select(.type == "TXT" and .name == $name and (.content | contains("v=spf1"))) | .content')
|
||||||
|
|
||||||
|
if [ -n "$EXISTING_SPF" ]; then
|
||||||
|
echo " ℹ️ Bestehender SPF: $EXISTING_SPF"
|
||||||
|
echo " → Muss manuell gelöscht/ersetzt werden!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# HILFSFUNKTIONEN
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
create_dns_record() {
|
||||||
|
local TYPE=$1
|
||||||
|
local NAME=$2
|
||||||
|
local CONTENT=$3
|
||||||
|
local PROXIED=${4:-"false"}
|
||||||
|
local TTL=${5:-3600}
|
||||||
|
local PRIORITY=$6
|
||||||
|
|
||||||
|
if [ "$DRY_RUN" = "true" ]; then
|
||||||
|
echo " [DRY RUN] Würde erstellen: $TYPE $NAME → $CONTENT"
|
||||||
|
[ -n "$PRIORITY" ] && echo " Priorität: $PRIORITY"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local JSON_DATA=""
|
||||||
|
|
||||||
|
if [ "$TYPE" = "MX" ]; then
|
||||||
|
if [ -z "$PRIORITY" ]; then PRIORITY=10; fi
|
||||||
|
JSON_DATA="{
|
||||||
|
\"type\": \"$TYPE\", \"name\": \"$NAME\", \"content\": \"$CONTENT\",
|
||||||
|
\"ttl\": $TTL, \"priority\": $PRIORITY, \"proxied\": $PROXIED
|
||||||
|
}"
|
||||||
|
elif [ "$TYPE" = "TXT" ]; then
|
||||||
|
CONTENT=$(echo "$CONTENT" | sed 's/"//g')
|
||||||
|
JSON_DATA="{
|
||||||
|
\"type\": \"$TYPE\", \"name\": \"$NAME\", \"content\": \"\\\"$CONTENT\\\"\",
|
||||||
|
\"ttl\": $TTL, \"proxied\": $PROXIED
|
||||||
|
}"
|
||||||
|
else
|
||||||
|
JSON_DATA="{
|
||||||
|
\"type\": \"$TYPE\", \"name\": \"$NAME\", \"content\": \"$CONTENT\",
|
||||||
|
\"ttl\": $TTL, \"proxied\": $PROXIED
|
||||||
|
}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
RESULT=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records" \
|
||||||
|
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--data "$JSON_DATA")
|
||||||
|
|
||||||
|
SUCCESS=$(echo "$RESULT" | jq -r '.success')
|
||||||
|
if [ "$SUCCESS" = "true" ]; then
|
||||||
|
echo " ✓ $TYPE $NAME → $CONTENT"
|
||||||
|
else
|
||||||
|
ERROR_MSG=$(echo "$RESULT" | jq -r '.errors[0].message // "Unbekannt"')
|
||||||
|
ERROR_CODE=$(echo "$RESULT" | jq -r '.errors[0].code // 0')
|
||||||
|
if [ "$ERROR_CODE" = "81057" ]; then
|
||||||
|
echo " ⏭ $TYPE $NAME existiert bereits (übersprungen)"
|
||||||
|
else
|
||||||
|
echo " ✗ $TYPE $NAME FEHLER: $ERROR_MSG"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 4. DKIM Records (aus SES API)
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
echo "--- [4/7] SES DKIM Records ---"
|
||||||
|
|
||||||
|
DKIM_TOKENS=$(aws ses get-identity-dkim-attributes \
|
||||||
|
--identities ${DOMAIN_NAME} --region ${AWS_REGION} \
|
||||||
|
--query "DkimAttributes.\"${DOMAIN_NAME}\".DkimTokens" --output text 2>/dev/null)
|
||||||
|
|
||||||
|
if [ -n "$DKIM_TOKENS" ] && [ "$DKIM_TOKENS" != "None" ]; then
|
||||||
|
for TOKEN in ${DKIM_TOKENS}; do
|
||||||
|
create_dns_record "CNAME" "${TOKEN}._domainkey.${DOMAIN_NAME}" "${TOKEN}.dkim.amazonses.com" "false"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo " ⚠️ Keine DKIM Tokens gefunden. SES Identity evtl. noch nicht verifiziert?"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# SES Verification Token
|
||||||
|
VERIFICATION_TOKEN=$(aws ses get-identity-verification-attributes \
|
||||||
|
--identities ${DOMAIN_NAME} --region ${AWS_REGION} \
|
||||||
|
--query "VerificationAttributes.\"${DOMAIN_NAME}\".VerificationToken" --output text 2>/dev/null)
|
||||||
|
|
||||||
|
if [ -n "$VERIFICATION_TOKEN" ] && [ "$VERIFICATION_TOKEN" != "None" ]; then
|
||||||
|
create_dns_record "TXT" "_amazonses.${DOMAIN_NAME}" "${VERIFICATION_TOKEN}" "false"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 5. MX Record (SES Inbound)
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "--- [5/7] MX Record ---"
|
||||||
|
|
||||||
|
if [ "$SKIP_MX" = "true" ]; then
|
||||||
|
echo " ⏭ MX übersprungen (SKIP_MX=true)"
|
||||||
|
echo " → Setze MX manuell wenn du bereit bist:"
|
||||||
|
echo " ${DOMAIN_NAME} MX 10 inbound-smtp.${AWS_REGION}.amazonaws.com"
|
||||||
|
else
|
||||||
|
echo " ⚠️ ACHTUNG: Alte MX Records müssen VORHER manuell gelöscht werden!"
|
||||||
|
echo " Alter MX vorhanden? Siehe Prüfung oben."
|
||||||
|
echo ""
|
||||||
|
create_dns_record "MX" "${DOMAIN_NAME}" "inbound-smtp.${AWS_REGION}.amazonaws.com" "false" 3600 10
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 6. MAIL FROM Subdomain (MX + SPF)
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "--- [6/7] MAIL FROM Subdomain: ${MAIL_FROM_DOMAIN} ---"
|
||||||
|
|
||||||
|
create_dns_record "MX" "${MAIL_FROM_DOMAIN}" "feedback-smtp.${AWS_REGION}.amazonses.com" "false" 3600 10
|
||||||
|
create_dns_record "TXT" "${MAIL_FROM_DOMAIN}" "v=spf1 include:amazonses.com ~all" "false"
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 7. SPF & DMARC (mit altem Provider!)
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "--- [7/7] SPF & DMARC ---"
|
||||||
|
|
||||||
|
# SPF mit beiden Providern (Migration!)
|
||||||
|
if [ -n "$OLD_PROVIDER_SPF" ]; then
|
||||||
|
SPF_RECORD="v=spf1 include:amazonses.com ${OLD_PROVIDER_SPF} ~all"
|
||||||
|
echo " ℹ️ Migrations-SPF (enthält alten Provider):"
|
||||||
|
else
|
||||||
|
SPF_RECORD="v=spf1 include:amazonses.com ~all"
|
||||||
|
echo " ℹ️ Standard-SPF (kein alter Provider angegeben):"
|
||||||
|
fi
|
||||||
|
echo " ${SPF_RECORD}"
|
||||||
|
|
||||||
|
create_dns_record "TXT" "${DOMAIN_NAME}" "${SPF_RECORD}" "false"
|
||||||
|
|
||||||
|
# DMARC
|
||||||
|
create_dns_record "TXT" "_dmarc.${DOMAIN_NAME}" "v=DMARC1; p=none; pct=100; rua=mailto:postmaster@${DOMAIN_NAME}" "false"
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# ZUSAMMENFASSUNG
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================================"
|
||||||
|
if [ "$DRY_RUN" = "true" ]; then
|
||||||
|
echo " ⚠️ DRY RUN abgeschlossen - keine Änderungen gemacht"
|
||||||
|
else
|
||||||
|
echo " ✅ Migration DNS Setup abgeschlossen"
|
||||||
|
fi
|
||||||
|
echo "============================================================"
|
||||||
|
echo ""
|
||||||
|
echo " Domain: $DOMAIN_NAME"
|
||||||
|
echo " MAIL FROM: $MAIL_FROM_DOMAIN"
|
||||||
|
echo " SPF: $SPF_RECORD"
|
||||||
|
if [ "$SKIP_MX" = "true" ]; then
|
||||||
|
echo " MX: ⏭ ÜBERSPRUNGEN (manuelle Aktivierung nötig)"
|
||||||
|
else
|
||||||
|
echo " MX: inbound-smtp.${AWS_REGION}.amazonaws.com"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
echo " 📋 MANUELLE SCHRITTE (falls noch nicht erledigt):"
|
||||||
|
echo " ─────────────────────────────────────────────────"
|
||||||
|
echo " 1. Alte MX Records für ${DOMAIN_NAME} löschen"
|
||||||
|
echo " 2. Alten SPF Record für ${DOMAIN_NAME} löschen"
|
||||||
|
echo " 3. Alten DKIM Record löschen (falls vorhanden)"
|
||||||
|
|
||||||
|
if [ -n "$MAIL_FROM_CNAME" ]; then
|
||||||
|
echo " 4. CNAME ${MAIL_FROM_DOMAIN} → ${MAIL_FROM_CNAME} löschen"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo " ⚠️ NICHT LÖSCHEN während Migration:"
|
||||||
|
echo " ─────────────────────────────────────"
|
||||||
|
echo " - imap.${DOMAIN_NAME} (Clients holen noch dort ab)"
|
||||||
|
echo " - pop.${DOMAIN_NAME} (Clients holen noch dort ab)"
|
||||||
|
echo " - smtp.${DOMAIN_NAME} (Clients senden noch dort)"
|
||||||
|
echo " - webmail.${DOMAIN_NAME} (falls vorhanden)"
|
||||||
|
echo ""
|
||||||
|
echo " Diese Records werden erst in Phase 3 (nach vollständiger"
|
||||||
|
echo " Client-Umstellung) gelöscht mit cloudflareDns.sh"
|
||||||
|
echo "============================================================"
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# test_migration_email.sh - Stellt eine Test-EMail in S3 + SQS ein
|
||||||
|
#
|
||||||
|
# Simuliert den kompletten SES-Eingang: Mail landet in S3, Metadaten in SQS.
|
||||||
|
# Der Worker holt sie dann ab und verarbeitet sie (Delivery oder Forward).
|
||||||
|
#
|
||||||
|
# Verwendung:
|
||||||
|
# ./test_migration_email.sh cielectrical.com carlosr@cielectrical.com
|
||||||
|
# ./test_migration_email.sh buddelectric.net service@buddelectric.net
|
||||||
|
#
|
||||||
|
# Optionale Absenderadresse:
|
||||||
|
# ./test_migration_email.sh cielectrical.com carlosr@cielectrical.com test@example.com
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# --- Parameter ---
|
||||||
|
DOMAIN="$1"
|
||||||
|
RECIPIENT="$2"
|
||||||
|
FROM_ADDR="${3:-migration-test@andreasknuth.de}"
|
||||||
|
AWS_REGION=${AWS_REGION:-"us-east-2"}
|
||||||
|
|
||||||
|
if [ -z "$DOMAIN" ] || [ -z "$RECIPIENT" ]; then
|
||||||
|
echo "Verwendung: $0 <domain> <recipient> [from-address]"
|
||||||
|
echo "Beispiel: $0 cielectrical.com carlosr@cielectrical.com"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Abgeleitete Variablen ---
|
||||||
|
BUCKET_NAME=$(echo "$DOMAIN" | tr '.' '-')"-emails"
|
||||||
|
QUEUE_NAME=$(echo "$DOMAIN" | tr '.' '-')"-queue"
|
||||||
|
MESSAGE_ID="test-migration-$(date +%s)-$$"
|
||||||
|
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
DATE_RFC2822=$(date -R)
|
||||||
|
|
||||||
|
echo "============================================================"
|
||||||
|
echo " 📧 Test-Mail für Migration"
|
||||||
|
echo "============================================================"
|
||||||
|
echo " Domain: $DOMAIN"
|
||||||
|
echo " Empfänger: $RECIPIENT"
|
||||||
|
echo " Absender: $FROM_ADDR"
|
||||||
|
echo " Bucket: $BUCKET_NAME"
|
||||||
|
echo " Queue: $QUEUE_NAME"
|
||||||
|
echo " Key: $MESSAGE_ID"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# --- Schritt 1: E-Mail als RFC822 erstellen ---
|
||||||
|
echo "[1/3] Erstelle Test-Email..."
|
||||||
|
|
||||||
|
MAIL_CONTENT="From: Migration Test <${FROM_ADDR}>
|
||||||
|
To: ${RECIPIENT}
|
||||||
|
Subject: Migration Test $(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
Date: ${DATE_RFC2822}
|
||||||
|
Message-ID: <${MESSAGE_ID}@test.email-srvr.com>
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
|
||||||
|
Hallo!
|
||||||
|
|
||||||
|
Dies ist eine Test-EMail zur Validierung der E-Mail-Migration.
|
||||||
|
|
||||||
|
Gesendet: $(date)
|
||||||
|
Domain: ${DOMAIN}
|
||||||
|
Empfaenger: ${RECIPIENT}
|
||||||
|
Message-ID: ${MESSAGE_ID}
|
||||||
|
|
||||||
|
Wenn du diese Mail in deiner Inbox siehst, funktioniert der
|
||||||
|
komplette Pfad: S3 -> SQS -> Worker -> Forward/Delivery.
|
||||||
|
|
||||||
|
--
|
||||||
|
Bay Area Affiliates Migration Test"
|
||||||
|
|
||||||
|
TMP_FILE=$(mktemp /tmp/test-mail-XXXXXX.eml)
|
||||||
|
echo "$MAIL_CONTENT" > "$TMP_FILE"
|
||||||
|
|
||||||
|
echo " ✓ Mail erstellt ($(wc -c < "$TMP_FILE") Bytes)"
|
||||||
|
|
||||||
|
# --- Schritt 2: In S3 Bucket ablegen ---
|
||||||
|
echo "[2/3] Lade Mail in S3 hoch: s3://${BUCKET_NAME}/${MESSAGE_ID} ..."
|
||||||
|
|
||||||
|
aws s3 cp "$TMP_FILE" "s3://${BUCKET_NAME}/${MESSAGE_ID}" \
|
||||||
|
--region "$AWS_REGION" \
|
||||||
|
--quiet
|
||||||
|
|
||||||
|
echo " ✓ S3 Upload erfolgreich"
|
||||||
|
|
||||||
|
# --- Schritt 3: SQS Message im Fake-SNS-Format einstellen ---
|
||||||
|
echo "[3/3] Stelle Message in SQS Queue..."
|
||||||
|
|
||||||
|
QUEUE_URL=$(aws sqs get-queue-url \
|
||||||
|
--queue-name "$QUEUE_NAME" \
|
||||||
|
--region "$AWS_REGION" \
|
||||||
|
--output text \
|
||||||
|
--query 'QueueUrl')
|
||||||
|
|
||||||
|
if [ -z "$QUEUE_URL" ]; then
|
||||||
|
echo " ❌ Queue $QUEUE_NAME nicht gefunden!"
|
||||||
|
rm -f "$TMP_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# SES Event Payload (das was die Lambda normalerweise erzeugt)
|
||||||
|
SES_DATA=$(jq -n \
|
||||||
|
--arg msgId "$MESSAGE_ID" \
|
||||||
|
--arg source "$FROM_ADDR" \
|
||||||
|
--arg recipient "$RECIPIENT" \
|
||||||
|
--arg ts "$TIMESTAMP" \
|
||||||
|
'{
|
||||||
|
mail: {
|
||||||
|
messageId: $msgId,
|
||||||
|
source: $source,
|
||||||
|
timestamp: $ts,
|
||||||
|
destination: [$recipient]
|
||||||
|
},
|
||||||
|
receipt: {
|
||||||
|
recipients: [$recipient],
|
||||||
|
timestamp: $ts,
|
||||||
|
action: {
|
||||||
|
type: "S3",
|
||||||
|
bucketName: "test",
|
||||||
|
objectKey: $msgId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}')
|
||||||
|
|
||||||
|
# Fake SNS Wrapper (so wie deine Lambda es erzeugt)
|
||||||
|
SQS_BODY=$(jq -n \
|
||||||
|
--arg sesData "$SES_DATA" \
|
||||||
|
--arg ts "$TIMESTAMP" \
|
||||||
|
'{
|
||||||
|
Type: "Notification",
|
||||||
|
MessageId: "test-\(now | tostring)",
|
||||||
|
TopicArn: "arn:aws:sns:ses-shim:global-topic",
|
||||||
|
Subject: "Amazon SES Email Receipt Notification",
|
||||||
|
Message: $sesData,
|
||||||
|
Timestamp: $ts
|
||||||
|
}')
|
||||||
|
|
||||||
|
aws sqs send-message \
|
||||||
|
--queue-url "$QUEUE_URL" \
|
||||||
|
--region "$AWS_REGION" \
|
||||||
|
--message-body "$SQS_BODY" \
|
||||||
|
--output text \
|
||||||
|
--query 'MessageId'
|
||||||
|
|
||||||
|
echo " ✓ SQS Message eingestellt"
|
||||||
|
|
||||||
|
# --- Aufräumen ---
|
||||||
|
rm -f "$TMP_FILE"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================================"
|
||||||
|
echo " ✅ Test-Mail eingestellt!"
|
||||||
|
echo "============================================================"
|
||||||
|
echo ""
|
||||||
|
echo " Jetzt Worker-Logs beobachten:"
|
||||||
|
echo " docker logs -f email-worker --tail 50"
|
||||||
|
echo ""
|
||||||
|
echo " Der Worker sollte folgendes zeigen:"
|
||||||
|
echo " 📧 Processing: ${MESSAGE_ID:0:20}... -> ${RECIPIENT}"
|
||||||
|
echo " ✓ Forwarded via legacy SMTP ... (falls Forward-Rule existiert)"
|
||||||
|
echo " ODER"
|
||||||
|
echo " ✓ Delivered to ${RECIPIENT} (falls DMS-Mailbox existiert)"
|
||||||
|
echo ""
|
||||||
|
echo " S3 Objekt prüfen:"
|
||||||
|
echo " aws s3 ls s3://${BUCKET_NAME}/${MESSAGE_ID} --region ${AWS_REGION}"
|
||||||
|
echo ""
|
||||||
|
echo " Falls etwas schief geht - SQS Message manuell prüfen:"
|
||||||
|
echo " aws sqs receive-message --queue-url ${QUEUE_URL} --region ${AWS_REGION}"
|
||||||
|
echo "============================================================"
|
||||||
Loading…
Reference in New Issue