Postfix

Postfix - 多個域的發件人依賴中繼

  • March 28, 2017

在過去的幾天裡,我一直在研究 SO 問題和 Postfix 文件,但沒有成功找出我做錯了什麼。我的情況如下:

  • 我有一個執行 Postfix 的伺服器,它有自己的 FQDN(DomainA)。DomainA 的郵件通過 MailGun 中繼。
  • 該伺服器託管多個網站域,現在計劃是確保這些域的郵件通過 MailGun 中繼,但作為一個單獨的域。這將創建單獨的退回地址等。呼叫此 DomainB
  • 根據標頭中存在的域,配置 Postfix 以選擇適當的 SASL 身份驗證,以確保添加適當的標頭。

版本資訊:Debian 7 上的 Postfix 2.11.2 (Wheezy)

postconf -n 的輸出:

alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
append_at_myorigin = no
append_dot_mydomain = no
biff = no
canonical_maps = regexp:/etc/postfix/canonical
canonical_classes = envelope_sender, header_sender
config_directory = /etc/postfix
inet_interfaces = localhost
inet_protocols = ipv4
mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
mydestination = localhost.com, localhost
myhostname = DomainA.com
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
myorigin = /etc/mailname
readme_directory = no
recipient_delimiter = +
sender_dependent_relayhost_maps = hash:/etc/postfix/relayhost_map
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_sender_dependent_authentication = yes
smtp_tls_note_starttls_offer = yes
smtp_tls_security_level = may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_security_level = may
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_use_tls = yes

relayhost_map 文件內容:

@DomainA.com      [smtp.mailgun.org]:587
@DomainB.name     [smtp.mailgun.org]:587

嘗試 #1 of canonical_maps -將所有電子郵件地址重新寫入 sender@DomainB.name

/./ post@domainB.name

從命令行發送電子郵件時的 mail.log 輸出:

   Aug 18 01:55:12 DomainA postfix/pickup[3572]: C72492A00B8: uid=0 from=<root>
   Aug 18 01:55:12 DomainA postfix/cleanup[3591]: C72492A00B8: message-id=<20150818055512.GA3580@DomainA.com>
   Aug 18 01:55:12 DomainA postfix/qmgr[3573]: C72492A00B8: from=<post@DomainB.name>, size=437, nrcpt=1 (queue active)
   Aug 18 01:55:13 DomainA postfix/smtp[3593]: C72492A00B8: to=<me@DomainB.name>, relay=smtp.mailgun.org[50.56.21.178]:587, delay=0.28, delays=0.02/0.02/0.16/0.08, dsn=2.0.0, status=sent (250 Great success)

郵件客戶端收到的電子郵件標頭:

Delivered-To: me@DomainB.name
Return-Path: <bounce+0a2943.d031c-me=DomainB.name@DomainA.com>
[snip]
Sender: post=DomainB.name@DomainA.com
[snip]
From: Primary Root <post@DomainB.name>
To: me@DomainB.name
Subject: test mail #5

有兩件事在我看來是非常錯誤的:

  1. 為什麼發件人地址設置為 post=DomainB.name@DomainA.com 即使 Postfix 已設置為:

append_at_myorigin = 沒有 append_dot_mydomain = 沒有 2. 由於發件人地址附加了 DomainA.com,看來 Postfix 選擇使用 DomainA 的 SASL 詳細資訊中繼郵件 - 通過查看 MailGun 儀表板上的日誌確認。這導致退回地址也設置為 DomainA。

嘗試 #2 的 canoncial_maps -僅以DomainB.com結尾的電子郵件地址被重新寫入 email@DomainB.com

/@DomainB.name/ email@DomainB.name

.muttrc 文件設置以強制從電子郵件地址為 DomainB.com

set from="mutt@DomainB.name"
set use_from=yes
set use_envelope_from = yes

mail.log 的輸出:

Aug 18 03:40:49 DomainA postfix/qmgr[8809]: 2BEB92A00D3: from=<mutt@DomainB.name>, size=441, nrcpt=1 (queue active)
Aug 18 03:40:49 DomainA postfix/smtp[8824]: 2BEB92A00D3: to=<me@DomainB.name>, relay=smtp.mailgun.org[104.130.177.23]:587, delay=0.58, delays=0.01/0.02/0.37/0.17, dsn=2.0.0, status=sent (250 Great success)

郵件客戶端收到的電子郵件標頭:

Delivered-To: me@DomainB.name
[snip]
Return-Path: <bounce+0a2943.d031c-me=DomainB.name@DomainA.com>
[snip]
Sender: email=DomainB.name@DomainA.com
[snip]
From: Primary Root <email@DomainB.name>
To: me@DomainB.name
Subject: test mail hdr #7
  1. 從這個測試中,我可以看到規範映射不是問題。重寫發生正確。但是,Postfix 似乎無法將輸出辨識為有效的電子郵件地址,並附加了導致中繼中斷的 FQDN。

非常歡迎任何有關如何解決此問題的建議/想法!

為了對這個問題有新的認識,我開始在另一台伺服器上配置類似的中繼主機設置,正是在這個過程中,我終於找到了問題的根源。結果在我的 sasl_passwd 文件中我遺漏了一個關鍵字元。

修復前的 sasl_passwd 文件:

DomainB.name        relay@DomainB.name:somepassword
#Fallback
[smtp.mailgun.org]:587  relay@DomainA.com:anotherpasswd

修復後的 sasl_passwd 文件:

@DomainB.name        relay@DomainB.name:somepassword
#Fallback
[smtp.mailgun.org]:587  relay@DomainA.com:anotherpasswd

問題是虛擬域B 之前缺少一個“@”字元。備份條目是為什麼當 Postfix 無法匹配任何其他條目時,所有郵件都通過此路由傳遞時,調試此問題如此困難的原因。

因為它可能被證明是有用的,所以一旦我的中繼主機配置開始正常工作,我還包括我的規範地圖文件的設置:

/(.*@)DomainB.name/ ${1}DomainB.name
/(.*@)DomainA.com/ ${1}DomainA.com

上面的正則表達式確保信封發件人更新以匹配發件人,避免在我的電子郵件客戶端中出現任何“通過 DomainA”。

作為後記,事實證明,在 Ubuntu 14.04 中,僅在 main.cf 中包含以下行是不夠的:

canonical_maps = regexp:/etc/postfix/canonical
canonical_classes = envelope_sender, header_sender

還必須包括以下行:

sender_canonical_maps = regexp:/etc/postfix/canonical_sender

第二個文件的內容可以與第一個相同,但它必須存在以避免在 Ubuntu 中中繼電子郵件時出現“通過域”標題。

引用自:https://serverfault.com/questions/714936