Kaynağa Gözat

fix: route self-hosted MX mail to inbound SMTP

Use Postfix best_mx_transport to hand destinations whose best MX loops back to MailHub into the app inbound listener.

AI-Co-Authored-By: Codex
chendeben 1 ay önce
ebeveyn
işleme
f125a8355c
2 değiştirilmiş dosya ile 8 ekleme ve 0 silme
  1. 1 0
      docker/postfix/entrypoint.sh
  2. 7 0
      test/dovecot-config.test.js

+ 1 - 0
docker/postfix/entrypoint.sh

@@ -23,6 +23,7 @@ postconf -e "smtp_tls_security_level = may"
 postconf -e "smtp_tls_loglevel = 1"
 postconf -e "smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt"
 postconf -e "smtp_helo_name = ${MAIL_HOSTNAME}"
+postconf -e "best_mx_transport = smtp:[app]:25"
 postconf -e "disable_vrfy_command = yes"
 postconf -e "maximal_queue_lifetime = 2d"
 postconf -e "bounce_queue_lifetime = 2d"

+ 7 - 0
test/dovecot-config.test.js

@@ -13,6 +13,7 @@ const authConfig = readFileSync(new URL('../docker/dovecot/auth.conf', import.me
 const mailConfig = readFileSync(new URL('../docker/dovecot/mailhub.conf', import.meta.url), 'utf8');
 const sslConfig = readFileSync(new URL('../docker/dovecot/ssl.conf', import.meta.url), 'utf8');
 const authLua = readFileSync(new URL('../docker/dovecot/auth.lua', import.meta.url), 'utf8');
+const postfixEntrypoint = readFileSync(new URL('../docker/postfix/entrypoint.sh', import.meta.url), 'utf8');
 
 test('Maildir reconciliation defaults to a five-minute polling interval', () => {
   assert.match(serverSource, /MAILDIR_SYNC_INTERVAL_MS \|\| 300000/);
@@ -81,6 +82,12 @@ test('Dovecot uses Lua passdb, a static rootless userdb, and Maildir storage', (
   assert.match(sslConfig, /^ssl_server_key_file = \$ENV:SUBMISSION_TLS_KEY$/m);
 });
 
+test('Postfix hands self-referential MX destinations to the MailHub inbound listener', () => {
+  assert.match(postfixEntrypoint, /postconf -e "mydestination ="/);
+  assert.match(postfixEntrypoint, /postconf -e "best_mx_transport = smtp:\[app\]:25"/);
+  assert.match(appService, /networks:\n\s+- mailhub/);
+});
+
 test('Lua passdb sends both IMAP and POP3 to the private auth bridge', () => {
   assert.match(authLua, /http:\/\/app:3001\/internal\/dovecot\/auth/);
   assert.match(authLua, /\/run\/secrets\/dovecot_auth_secret/);