[{"data":1,"prerenderedAt":494},["ShallowReactive",2],{"search-de":3,"content-de-developer\u002Fdecisions\u002F005-custom-mta":4,"surround-de-\u002Fdeveloper\u002Fdecisions\u002F005-custom-mta":485},[],{"id":5,"title":6,"body":7,"description":477,"extension":478,"meta":479,"navigation":480,"path":481,"seo":482,"stem":483,"__hash__":484},"content_de\u002F3.developer\u002Fdecisions\u002F6.005-custom-mta.md","ADR-005: Eigener MTA",{"type":8,"value":9,"toc":469},"minimark",[10,27,32,36,63,66,86,90,125,136,139,254,258,263,286,291,308,312],[11,12,13,21],"ul",{},[14,15,16,20],"li",{},[17,18,19],"strong",{},"Status:"," Angenommen",[14,22,23,26],{},[17,24,25],{},"Datum:"," 2025-03-20",[28,29,31],"h2",{"id":30},"kontext","Kontext",[33,34,35],"p",{},"Owlat war für die E-Mail-Zustellung früher vollständig von AWS SES und Resend abhängig. Diese Anbieter bieten zwar zuverlässige APIs und Managed Infrastructure, bringen im großen Maßstab jedoch Einschränkungen mit sich:",[37,38,39,45,51,57],"ol",{},[14,40,41,44],{},[17,42,43],{},"Kosten"," — die Preisbildung pro E-Mail skaliert linear. Versender mit hohem Volumen zahlen deutlich mehr als die Kosten einer direkten SMTP-Zustellung von dedizierten IPs.",[14,46,47,50],{},[17,48,49],{},"Kontrolle über die Zustellbarkeit"," — Drittanbieter verwalten die Reputation gemeinsam genutzter und dedizierter IPs stellvertretend für viele Kunden. Owlat hat keine Möglichkeit, ISP-spezifisches Throttling, IP-Warming-Zeitpläne oder engagementbasierte Sendepriorität umzusetzen.",[14,52,53,56],{},[17,54,55],{},"Bounce-Latenz"," — Bounce- und Beschwerdedaten treffen mit variabler Verzögerung über Anbieter-Webhooks ein, was eine schnelle Reaktion auf Reputationsprobleme erschwert.",[14,58,59,62],{},[17,60,61],{},"Rate Limits"," — vom Anbieter auferlegte Sendekontingente (insbesondere in der SES-Sandbox) begrenzen den Kampagnendurchsatz. Owlat kann den Backpressure pro ISP nicht eigenständig steuern.",[33,64,65],{},"Die wesentlichen Optionen:",[37,67,68,74,80],{},[14,69,70,73],{},[17,71,72],{},"Nur SES\u002FResend beibehalten"," — operativ am einfachsten, doch die Einschränkungen bei Kosten und Kontrolle bleiben bestehen.",[14,75,76,79],{},[17,77,78],{},"Einen eigenen MTA bauen"," — direkte SMTP-Zustellung mit voller Kontrolle über IPs, Throttling, Warming und Bounce-Verarbeitung. Höhere Infrastrukturkomplexität, dafür deutlich geringere Kosten pro E-Mail und bessere Feinabstimmung der Zustellbarkeit.",[14,81,82,85],{},[17,83,84],{},"Einen Open-Source-MTA verwenden (Postfix, Haraka)"," — erspart den Bau von Grund auf, erfordert aber die Anpassung universeller Software an Owlats spezifische Anforderungen (GroupMQ-Integration, Circuit Breaker pro Organisation, Engagement-Priorität).",[28,87,89],{"id":88},"entscheidung","Entscheidung",[33,91,92,93,97,98,101,102,101,105,108,109,112,113,116,117,120,121,124],{},"Einen eigenen MTA als eigenständigen Dienst (",[94,95,96],"code",{},"apps\u002Fmta\u002F",") bauen, der E-Mail per direkter SMTP-Zustellung an die Mailserver der Empfänger versendet. Der MTA ist einer von drei auswählbaren Zustellanbietern (",[94,99,100],{},"mta","|",[94,103,104],{},"resend",[94,106,107],{},"ses","), gewählt über ",[94,110,111],{},"EMAIL_PROVIDER"," oder über das Send-Provider-Routing pro Organisation (",[94,114,115],{},"apps\u002Fapi\u002Fconvex\u002Flib\u002FsendProviders\u002Frouting.ts",", genutzt über ",[94,118,119],{},"apps\u002Fapi\u002Fconvex\u002Flib\u002FsendProviders\u002Froute.ts","). Es gibt keinen impliziten Standard — ist kein Anbieter konfiguriert, löst die Route zu ",[94,122,123],{},"null"," auf und die Instanz ist fail-closed (versendet nichts).",[33,126,127,128,131,132,135],{},"Der Dienst ist seither über den ausgehenden Versand hinausgewachsen und übernimmt inzwischen auch eingehendes Routing\u002FWeiterleiten (",[94,129,130],{},"apps\u002Fmta\u002Fsrc\u002Finbound\u002F",") sowie die Zustellbarkeitsfläche rund um SMTP — DKIM-Schlüsselverwaltung und -Rotation, MTA-STS und TLS-RPT (",[94,133,134],{},"apps\u002Fmta\u002Fsrc\u002Fsmtp\u002F","). Die nachstehende Sendeentscheidung bleibt der Kern dieses ADR.",[33,137,138],{},"Zentrale Designentscheidungen:",[11,140,141,200,210,242,248],{},[14,142,143,146,147,150,151,154,155,158,159,150,162,150,165,150,168,150,171,150,174,150,177,150,180,150,183,150,186,150,189,192,193,150,196,199],{},[17,144,145],{},"Hono-HTTP-API"," — leichtgewichtiger, standardkonformer HTTP-Server zur Entgegennahme von Sendeanfragen aus dem Convex-Backend. Zu den Endpunkten zählen ",[94,148,149],{},"\u002Fsend",", ",[94,152,153],{},"\u002Fhealth"," und ",[94,156,157],{},"\u002Fmetrics",", dazu Admin-\u002FVerwaltungsrouten (",[94,160,161],{},"\u002Fcredentials",[94,163,164],{},"\u002Forg-limits",[94,166,167],{},"\u002Fsuppression",[94,169,170],{},"\u002Fdkim",[94,172,173],{},"\u002Fpool-rules",[94,175,176],{},"\u002Fisp-profiles",[94,178,179],{},"\u002Fip-reputation",[94,181,182],{},"\u002Fqueue",[94,184,185],{},"\u002Fdlq",[94,187,188],{},"\u002Fdelivery-logs",[94,190,191],{},"\u002Fscan",") sowie eingehendes Routing (",[94,194,195],{},"\u002Finbound\u002Froutes",[94,197,198],{},"\u002Fmailboxes",").",[14,201,202,205,206,209],{},[17,203,204],{},"GroupMQ + Redis"," — Job-Queue mit gruppenbasierter Verarbeitung. Jobs werden nach ",[94,207,208],{},"{ipPool}:{recipientDomain}"," gruppiert, sodass E-Mails an denselben ISP aus demselben IP-Pool sequenziell verarbeitet werden und Rate Limits pro Domain eingehalten werden.",[14,211,212,215,216,219,220,223,224,227,228,150,231,234,235,238,239,199],{},[17,213,214],{},"Dispatch-Pipeline"," — eine zusammengesetzte Pipeline (",[94,217,218],{},"apps\u002Fmta\u002Fsrc\u002Fdispatch\u002Fphases\u002F",") führt vor jeder Zustellung Prüfungen pro Versuch aus: Inhaltsprüfung, Suppression, Circuit Breaker pro Organisation, Rate Limits pro Organisation, auf SMTP-Antworten basierendes Throttling (",[94,221,222],{},"smtpIntel","), Domain-Backoff, Auflösung und Auswahl des IP-Pools, Slot-Belegung und Warming-Obergrenzen. Zwei verwandte Belange laufen außerhalb der Pipeline pro Sendung: ",[17,225,226],{},"Engagement-Priorität"," wird beim Einreihen als GroupMQ-Ordnung angewendet (",[94,229,230],{},"apps\u002Fmta\u002Fsrc\u002Froutes\u002Fsend.ts",[94,232,233],{},"apps\u002Fmta\u002Fsrc\u002Fqueue\u002Fgroups.ts","), und ",[17,236,237],{},"DNSBL-Monitoring"," ist eine 15-minütige Hintergrundprüfung, die gelistete IPs aus dem aktiven Pool entfernt (",[94,240,241],{},"apps\u002Fmta\u002Fsrc\u002Fintelligence\u002Fdnsbl.ts",[14,243,244,247],{},[17,245,246],{},"VERP-Return-Path"," — die Variable-Envelope-Return-Path-Kodierung korreliert Bounce-Nachrichten mit den ursprünglichen Sendungen, ohne dass eine Lookup-Tabelle gepflegt werden muss.",[14,249,250,253],{},[17,251,252],{},"Webhook-Rückkopplung"," — Zustellereignisse (gesendet, gebounct, beschwert) werden über authentifizierte Webhooks an das Convex-Backend zurückgemeldet und nutzen die bestehende Bounce-\u002FBeschwerde-Verarbeitungspipeline weiter.",[28,255,257],{"id":256},"konsequenzen","Konsequenzen",[33,259,260],{},[17,261,262],{},"Ermöglicht:",[11,264,265,268,271,274,277,280,283],{},[14,266,267],{},"Adaptives Rate Limiting pro ISP (Gmail 100\u002Fmin, Outlook 80\u002Fmin, Yahoo 50\u002Fmin) mit automatischem Backoff bei 4xx-Antworten",[14,269,270],{},"Automatisiertes IP-Warming über 30 Tage mit adaptiver Beschleunigung\u002FVerlangsamung anhand von Zustellbarkeitssignalen",[14,272,273],{},"Engagementbasierte Sendepriorität — Kontakte mit hohem Engagement werden zuerst beliefert",[14,275,276],{},"Circuit Breaker pro Organisation — pausiert den Versand automatisch, wenn Bounce-Raten Schwellenwerte überschreiten",[14,278,279],{},"DNS-Blocklist-Monitoring mit automatischer Entfernung von IPs aus dem aktiven Pool",[14,281,282],{},"Direkte Kosteneinsparungen im großen Maßstab (keine API-Gebühren pro E-Mail über die Infrastruktur hinaus)",[14,284,285],{},"Vollständige Bounce-\u002FBeschwerde-Verarbeitungspipeline mit DSN-Parsing und ARF-\u002FFBL-Unterstützung",[33,287,288],{},[17,289,290],{},"Abwägungen:",[11,292,293,296,299,302],{},[14,294,295],{},"Erfordert dedizierte IPs mit korrekten rDNS-\u002FPTR-Records und DKIM-Schlüsselverwaltung",[14,297,298],{},"Infrastrukturkomplexität: Redis für Zustand, Zugang zu SMTP-Port 25, separater containerisierter Dienst",[14,300,301],{},"Operativer Aufwand: DNSBL-Listungen überwachen, IP-Warming steuern, Zustellbarkeitsprobleme untersuchen",[14,303,304,305,307],{},"Alle drei Anbieter (mta, resend, ses) sind explizite Opt-in-Entscheidungen über ",[94,306,111],{}," \u002F das Send-Provider-Routing pro Organisation; der MTA ist kein impliziter Standard-Zustellweg — eine nicht konfigurierte Instanz ist fail-closed und versendet nichts",[28,309,311],{"id":310},"vergleich-mit-alternativen","Vergleich mit Alternativen",[313,314,315,334],"table",{},[316,317,318],"thead",{},[319,320,321,325,328,331],"tr",{},[322,323,324],"th",{},"Fähigkeit",[322,326,327],{},"Owlat MTA",[322,329,330],{},"Postal",[322,332,333],{},"SES\u002FResend",[335,336,337,352,364,376,388,400,412,425,442,455],"tbody",{},[319,338,339,343,346,349],{},[340,341,342],"td",{},"Adaptives Throttling pro ISP",[340,344,345],{},"Ja (10+ ISP-Profile)",[340,347,348],{},"Nein",[340,350,351],{},"Vom Anbieter verwaltet",[319,353,354,357,360,362],{},[340,355,356],{},"IP-Warming",[340,358,359],{},"Ja (30 Tage, adaptiv)",[340,361,348],{},[340,363,351],{},[319,365,366,369,372,374],{},[340,367,368],{},"Circuit Breaker pro Organisation",[340,370,371],{},"Ja (3 Zustände)",[340,373,348],{},[340,375,348],{},[319,377,378,381,384,386],{},[340,379,380],{},"Engagementbasierte Priorität",[340,382,383],{},"Ja",[340,385,348],{},[340,387,348],{},[319,389,390,393,396,398],{},[340,391,392],{},"DNSBL-Auto-Remediation",[340,394,395],{},"Ja (15-Minuten-Prüfungen)",[340,397,348],{},[340,399,351],{},[319,401,402,405,407,410],{},[340,403,404],{},"Nachrichtenspeicherung\u002F-suche",[340,406,348],{},[340,408,409],{},"Ja (MySQL pro Server)",[340,411,348],{},[319,413,414,417,419,422],{},[340,415,416],{},"Web-Admin-UI",[340,418,348],{},[340,420,421],{},"Ja (Rails-Dashboard)",[340,423,424],{},"Anbieterkonsole",[319,426,427,430,437,440],{},[340,428,429],{},"Spam-Inhaltsbewertung",[340,431,432,433,436],{},"Ja (Prüfung pro Sendung: Pflichtfelder, DKIM-Alignment, Größe, URL-Blocklist sowie optionales Rspamd-Scoring; Malware-Scan von Anhängen über ClamAV\u002F",[94,434,435],{},"@owlat\u002Femail-scanner",")",[340,438,439],{},"Ja (einsteckbare Inspektoren)",[340,441,351],{},[319,443,444,447,450,453],{},[340,445,446],{},"Klick-\u002FÖffnungs-Tracking",[340,448,449],{},"Nein (Plattformschicht)",[340,451,452],{},"Ja (integriert)",[340,454,351],{},[319,456,457,460,463,466],{},[340,458,459],{},"Kosten im großen Maßstab",[340,461,462],{},"Niedrig (nur Infrastruktur)",[340,464,465],{},"Niedrig (selbst gehostet)",[340,467,468],{},"Hoch (pro E-Mail)",{"title":470,"searchDepth":471,"depth":471,"links":472},"",2,[473,474,475,476],{"id":30,"depth":471,"text":31},{"id":88,"depth":471,"text":89},{"id":256,"depth":471,"text":257},{"id":310,"depth":471,"text":311},"Warum Owlat einen eigenen Mail Transfer Agent gebaut hat, statt sich ausschließlich auf E-Mail-Anbieter von Drittanbietern zu verlassen.","md",{},true,"\u002Fdeveloper\u002Fdecisions\u002F005-custom-mta",{"title":6,"description":477},"3.developer\u002Fdecisions\u002F6.005-custom-mta","RdmGHdFNf2DxFMOjyOz2qPrCvqyugsswgukZUzFxTY4",[486,490],{"title":487,"path":488,"stem":489,"children":-1},"ADR-004: Monorepo mit Bun Workspaces","\u002Fdeveloper\u002Fdecisions\u002F004-monorepo-bun-workspaces","3.developer\u002Fdecisions\u002F5.004-monorepo-bun-workspaces",{"title":491,"path":492,"stem":493,"children":-1},"ADR-006: Selbst gehostetes Convex","\u002Fdeveloper\u002Fdecisions\u002F006-self-hosted-convex","3.developer\u002Fdecisions\u002F7.006-self-hosted-convex",1786915110639]