diff --git a/api/src/config.ts b/api/src/config.ts
index 7bf144b..985f813 100644
--- a/api/src/config.ts
+++ b/api/src/config.ts
@@ -99,7 +99,7 @@ function loadConfig(): Config {
webhookSecret: optional("STRIPE_WEBHOOK_SECRET", ""),
},
smtp: {
- host: optional("SMTP_HOST", "mail.smtp2go.com"),
+ host: optional("SMTP_HOST", "co.carrierone.com"),
port: parseInt(optional("SMTP_PORT", "587"), 10),
user: optional("SMTP_USER", ""),
pass: optional("SMTP_PASS", ""),
diff --git a/api/src/email.ts b/api/src/email.ts
index 5dcda6a..59f83bc 100644
--- a/api/src/email.ts
+++ b/api/src/email.ts
@@ -6,7 +6,7 @@
* - Portal access link emails (JWT-signed links)
*
* All transactional emails go through Carbonio: co.carrierone.com:587
- * (SMTP2GO is used only by Listmonk for mass-mail campaigns.)
+ * (Listmonk mass-mail relays through the local Postfix MTA, not this path.)
* Env vars: SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, SMTP_FROM
*/
diff --git a/docs/architecture.svg b/docs/architecture.svg
index 5953473..9ebfc3c 100644
--- a/docs/architecture.svg
+++ b/docs/architecture.svg
@@ -165,7 +165,7 @@
Anytime MB
- SMTP2GO
+ Local MTA
TronGrid
diff --git a/docs/crm.md b/docs/crm.md
index 8a5e82f..9ca0b14 100644
--- a/docs/crm.md
+++ b/docs/crm.md
@@ -270,7 +270,7 @@ store customer orders or tickets — ERPNext is the CRM source of truth.
3. Listmonk tracks email opens/clicks and manages subscriber lists
4. Bounce processing via POP3 from Carbonio (`co.carrierone.com`)
-**Mass email:** SMTP2GO is used for Listmonk campaign sends (not Carbonio — Carbonio is for transactional email only).
+**Mass email:** Listmonk campaign sends relay through the local Postfix MTA (172.18.0.1:25 from the Docker network), which DKIM-signs and delivers direct-to-recipient-MX. Carbonio (co.carrierone.com) is for transactional email only. (SMTP2GO was decommissioned — no external relay is used.)
**Campaigns:**
diff --git a/docs/go-live-todo.md b/docs/go-live-todo.md
index 53087a0..64c697f 100644
--- a/docs/go-live-todo.md
+++ b/docs/go-live-todo.md
@@ -140,7 +140,7 @@
## PRIORITY 7 — Listmonk (Email Marketing) ~~COMPLETE~~
- [x] Deploy Listmonk at lists.performancewest.net (Docker, PostgreSQL-backed)
-- [x] Configure SMTP2GO outbound email (separate from Carbonio transactional SMTP)
+- [x] Configure Listmonk mass-mail via the local Postfix MTA (SMTP2GO decommissioned; separate from Carbonio transactional SMTP)
- [x] Import 10,191 FCC RMD contacts into Listmonk (3 subscriber lists)
- [x] Configure bounce processing via POP3 from Carbonio (bounces@performancewest.net)
- [x] Create 22 scheduled campaigns across 4 lists
diff --git a/infra/ansible/inventory/group_vars/all.yml b/infra/ansible/inventory/group_vars/all.yml
index ccdb5f4..174e465 100644
--- a/infra/ansible/inventory/group_vars/all.yml
+++ b/infra/ansible/inventory/group_vars/all.yml
@@ -80,13 +80,17 @@ smtp_pass: "{{ vault_smtp_pass }}"
smtp_from: "Performance West "
smtp_admin_email: ops@performancewest.net
-# ── Listmonk (mass-mail via SMTP2GO) ─────────────────────────────────────────
-# Listmonk SMTP is configured via its web admin UI, not env vars.
-# These vars are kept here for documentation and manual reference.
-listmonk_smtp_host: mail.smtp2go.com
-listmonk_smtp_port: 587
-listmonk_smtp_user: "{{ vault_listmonk_smtp_user | default(smtp_user) }}"
-listmonk_smtp_pass: "{{ vault_listmonk_smtp_pass }}"
+# ── Listmonk (mass-mail via the LOCAL MTA) ───────────────────────────────────
+# Listmonk SMTP is configured via its web admin UI, not env vars. Listmonk relays
+# through the host Postfix (172.18.0.1:25 from inside the Docker network), which
+# DKIM-signs and delivers direct-to-recipient-MX. We no longer use any external
+# relay (SMTP2GO was decommissioned). These vars are kept here for documentation
+# and manual reference.
+listmonk_smtp_host: 172.18.0.1
+listmonk_smtp_port: 25
+# The local Postfix relay requires no auth (auth_protocol: none, tls_type: none).
+listmonk_smtp_user: ""
+listmonk_smtp_pass: ""
listmonk_admin_user: "{{ vault_listmonk_admin_user }}"
listmonk_admin_password: "{{ vault_listmonk_admin_password }}"
diff --git a/infra/ansible/roles/app/templates/app.env.j2 b/infra/ansible/roles/app/templates/app.env.j2
index 857df22..ffdf36d 100644
--- a/infra/ansible/roles/app/templates/app.env.j2
+++ b/infra/ansible/roles/app/templates/app.env.j2
@@ -54,7 +54,7 @@ WORKER_URL=http://workers:8090
# ── Transactional email — Carbonio (co.carrierone.com) ───────────────────────
# All transactional mail: order confirmations, worker notifications, ERPNext alerts.
-# Listmonk mass-mail uses SMTP2GO — configured separately in the Listmonk admin UI.
+# Listmonk mass-mail relays through the local Postfix MTA — configured separately in the Listmonk admin UI.
SMTP_HOST={{ smtp_host }}
SMTP_PORT={{ smtp_port }}
SMTP_USER={{ smtp_user }}
diff --git a/scripts/workers/crypto_payment_worker.py b/scripts/workers/crypto_payment_worker.py
index 2247feb..b384bf4 100644
--- a/scripts/workers/crypto_payment_worker.py
+++ b/scripts/workers/crypto_payment_worker.py
@@ -809,7 +809,7 @@ automate this process.
import smtplib
from email.mime.text import MIMEText
- smtp_host = os.environ.get("SMTP_HOST", "mail.smtp2go.com")
+ smtp_host = os.environ.get("SMTP_HOST", "co.carrierone.com")
smtp_port = int(os.environ.get("SMTP_PORT", "587"))
smtp_user = os.environ.get("SMTP_USER", "")
smtp_pass = os.environ.get("SMTP_PASS", "")