我們已經準備好了身分證 (DNS/Hostname)、通行證 (SSL) 和大腦 (MariaDB)。現在,我們要請出負責收發信件的郵差——Postfix,並給它三張「藏寶圖」,讓它知道去資料庫的哪裡找人。
1. 安裝 Postfix 與 MySQL 驅動
首先,安裝 Postfix 主程式以及讓它能跟資料庫溝通的套件。
sudo apt update
sudo apt install postfix postfix-mysql -y
在安裝過程中,您會看到一個藍底灰字的設定畫面,請依序輸入:
- General type of mail configuration: 選擇
Internet Site。
- System mail name: 輸入您的主網域
mydomain.com (注意:這裡填您信箱 @ 後面的名字,不要填 mail.mydomain.com)。
2. 製作三張「藏寶圖」 (SQL 連接設定)
Postfix 本身看不懂資料庫(SQL)結構,我們需要建立三個設定檔,告訴它 SQL 語句該怎麼寫。
先建立一個專用資料夾來存放這些機密檔案:
sudo mkdir -p /etc/postfix/mysql
接下來建立三個檔案(請記得將下方的 password 換成您在第二章設定的 mailserver 資料庫密碼):
地圖 A:查詢「我們負責哪些網域?」
sudo nano /etc/postfix/mysql/mysql-virtual-mailbox-domains.cf
貼上內容:
user = mailserver
password = password
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'
地圖 B:查詢「這個使用者存在嗎?」
sudo nano /etc/postfix/mysql/mysql-virtual-mailbox-maps.cf
貼上內容:
user = mailserver
password = password
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'
地圖 C:查詢「這封信要轉寄嗎?」
sudo nano /etc/postfix/mysql/mysql-virtual-alias-maps.cf
貼上內容:
user = mailuser
password = password
hosts = 127.0.0.1
dbname = servermail
query = SELECT destination FROM virtual_aliases WHERE source='%s'
3. 保護檔案並測試連接 (關鍵步驟!)
因為檔案裡有密碼,我們必須鎖定權限。
sudo chmod 640 /etc/postfix/mysql/*
sudo chgrp postfix /etc/postfix/mysql/*
立即測試! 不要等到全部設完才測。我們用 postmap 指令測試 Postfix 能不能連上資料庫(假設您在第二章有寫入 example.com 的測試資料):
# 在這請用你剛剛在第二章測試資料庫時設定的網域和使用者
# 測試網域,example.com
# (應回傳 1,如果什麼都沒回傳就是在資料庫沒查到example.com這筆資料,下面同理)
sudo postmap -q example.com mysql:/etc/postfix/mysql/mysql-virtual-mailbox-domains.cf
# 測試使用者 (應回傳 1)
sudo postmap -q user@example.com mysql:/etc/postfix/mysql/mysql-virtual-mailbox-maps.cf
如果這裡報錯(例如 Login failed),則是在連線到資料庫時出錯了,請回頭檢查在第二步中創建的 .cf檔案裡的帳號密碼是否正確。
4. 編輯主設定檔 main.cf
請跟著我一步步修改。為了避免混亂,我會將設定檔拆解成幾個模組來解釋。
備份舊設定:
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.bak
請打開設定檔:
sudo nano /etc/postfix/main.cf
這個檔案裡應該已經有一些預設內容。建議您註解掉(在前面加 #)或是直接刪除舊的內容,然後依照下面的區塊,將設定一塊一塊貼上或修改。
A. 身分識別 (Identity) —— 最容易錯的地方
# ==============================
# Postfix Main Configuration
# ==============================
# --- A. Identity (身分識別:郵差 vs. 收件人) ---
# 1. [郵差的名牌]:這台伺服器自己的名字
# 當它跟別的伺服器打招呼時,會說:「你好,我是郵差,我的名字是 mail.mydomain.com」
myhostname = mail.mydomain.com
# 2. [寄件來源]:從這台機器發出的信,信封上要蓋什麼章?
# 例如:系統排程通知信,會顯示來自 root@mydomain.com
# (看起來像公司發的),而不是 root@mail...
myorigin = mydomain.com
# 3. 哪些信是「寄給郵差自己」的?(本機帳號的系統信件,如cron排程執行結果等等)
# 這是最關鍵的設定!
# 我們只留 localhost 與 mail.mydomain.com ($myhostname),
# 讓 Postfix 知道其他的都要去查 MySQL。
# 千萬「不能」把 mydomain.com 寫在這裡!
# 因為客戶的信 (user@mydomain.com) 不該留在郵差口袋,而是要放入「客戶信箱 (MySQL)」(下面的 Virtual 設定)。
mydestination = $myhostname, localhost.mydomain.com, localhost
!!教學的第二章中Hostname 設定正確的重要性
如果把 Mail Server 比喻成一位「國際外交官」,那 Hostname 就是他的「護照名字」。
為什麼它這麼重要?主要有以下三個致命原因:
1. 為了不被當成騙子 (HELO/EHLO 與 rDNS 檢查)
這是最直接影響「信寄不寄得出去」的原因。
當您的伺服器 (Postfix) 連線到對方的伺服器 (例如 Gmail) 時,第一句話會進行自我介紹:
Postfix: “HELO/EHLO,我是 mail.mydomain.com“
這時候,Gmail 不會輕易相信你,它會做一個 「雙重查核 (FCrDNS)」:
- 查 IP:Gmail 會去查這個連線 IP 的 Reverse DNS (PTR 紀錄),看看這個 IP 註冊的名字是不是真的叫
mail.mydomain.com。(自家的網路要設定反查要找ISP 幫你設定,但是ISP通常不會幫你弄,所以這時AWS的優勢又體現出來了,你可以請AWS幫你設定IP反查)
- 比對:如果你的 Hostname 設成
localhost 或是 ubuntu-server,但 PTR 紀錄卻是 mail.mydomain.com。
- 結果:名字對不上!Gmail 會判定你在說謊(可能是殭屍電腦),直接拒收或丟垃圾桶。
結論: Hostname 必須跟你在 DNS (PTR) 上登記的名字一模一樣,才能取信於人。
2. 為了避免「精神分裂」 (Loop Prevention)
Postfix 需要清楚區分 「我」 和 「我的客戶」:
- Hostname (我):例如
mail.mydomain.com。這是伺服器本身的名字(第二章設定的hostname以及/etc/hosts這個檔案),用來收系統通知(如 root@mail…)。
- Virtual Domain (客戶):例如
mydomain.com。這是我們要服務的郵件網域。
如果 Hostname 設錯(設成跟網域一樣 mydestination = mydomain.com): 當有人寄信給 user@mydomain.com 時,Postfix 會看著自己的 Hostname 說:「咦?這不是寄給我自己的嗎?」 於是它不去查 MySQL(客戶名單),而是去查 Linux 本機帳號 (/etc/passwd)。 結果當然查不到 user 這個帳號,最後導致 “User unknown in local recipient table” 的錯誤。
結論: Hostname 必須是 Sub-domain (子網域),絕對不能跟 Email 主網域重疊,以確保路由邏輯清晰。
3. 為了產生合法的 Message-ID
每一封寄出去的信,都會有一個全球獨一無二的身分證號碼,叫做 Message-ID。這個號碼通常長這樣: 20251020.A1B2C3D4@mail.mydomain.com
注意到了嗎? @ 後面的部分就是由 Hostname 產生的。
- 如果你 Hostname 沒設好(例如叫
localhost.localdomain),Message-ID 就會變成 @localhost。
- 這在嚴格的垃圾郵件過濾器(如 SpamAssassin)眼中,是一個非常大的扣分項目(Malformated Message-ID)。
總結
Hostname 對於 Mail Server 來說,不僅僅是一個代號,它是:
- 對外的誠信憑證(跟 IP 反解必須一致)。
- 對內的導航座標(區分本機與虛擬網域)。
- 信件的合格標章(產生正確的 Message-ID)。
所以,永遠記得把主機名稱設為 FQDN (完整網域名稱,如 mail.example.com),而不要只用 mail 或 server1 這種簡稱。Hostname的重要性介紹到這,接下來我們繼續postfix的設定教學。
B. 網路與連線 (Network)
這裡設定誰可以連線,以及我們監聽的介面。
# --- Network Settings ---
# 監聽所有介面 (包含外部連線)
inet_interfaces = all
# 只使用 IPv4 (為了避免 IPv6 設定不全導致的怪問題,建議新手先鎖定 IPv4)
inet_protocols = ipv4
# 信任的網路 (通常維持預設,只允許本機)
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
C. 虛擬使用者設定 (Virtual Settings) —— 連接 MySQL
這是讓 Postfix 去讀取我們上一節建立的那三個檔案。
# --- Virtual User Settings (MySQL) ---
# 1. 告訴 Postfix,這些網域是歸我們管的 (查 virtual_domains 表)
virtual_mailbox_domains = mysql:/etc/postfix/mysql/mysql-virtual-mailbox-domains.cf
# 2. 告訴 Postfix,這些使用者是存在的 (查 virtual_users 表)
virtual_mailbox_maps = mysql:/etc/postfix/mysql/mysql-virtual-mailbox-maps.cf
# 3. 告訴 Postfix,這些別名要轉寄 (查 virtual_aliases 表)
virtual_alias_maps = mysql:/etc/postfix/mysql/mysql-virtual-alias-maps.cf
# 4. 告訴 Postfix,信件收下來後,透過 LMTP 協定丟給 Dovecot 處理
# (注意:這一步需要等下一章安裝 Dovecot 後才會真正通,現在先設好)
virtual_transport = lmtp:unix:private/dovecot-lmtp
D. 安全性與加密 (TLS/SSL) —— 使用 Let’s Encrypt
請將路徑換成您在第二章申請到的實際路徑。
# --- TLS/SSL Settings ---
# 啟用 TLS
smtpd_tls_security_level = may
smtp_tls_security_level = may
# 指定憑證路徑 (請將 mail.mydomain.com 換成您的真實路徑)
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.mydomain.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.mydomain.com/privkey.pem
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# 強化安全性 (禁止匿名加密協定)
smtpd_tls_auth_only = yes
E. SASL 認證 (整合 Dovecot) —— 寄信驗證
這就是你收信/看信流程圖中,Postfix 轉身問 Dovecot「密碼對不對」的設定。
# --- SASL Authentication (Dovecot) ---
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
F. 基礎防護規則 (Restrictions) —— 第一層擋信
這裡設定誰可以透過我們寄信,以及我們要擋掉誰。
# --- Restrictions ---
smtpd_recipient_restrictions =
permit_mynetworks, # 允許本機 (127.0.0.1)
permit_sasl_authenticated, # 允許通過密碼驗證的使用者 (你)
reject_unauth_destination # 拒絕未經授權的轉寄 (防止變成 Open Relay)
存檔離開
5. 編輯 master.cf 開啟 Submission Port (587)
預設 Postfix 只開 Port 25。但現代的 Email Client (Outlook, iPhone Mail) 寄信時,標準是走 Port 587 (Submission)。我們需要把它打開。
sudo nano /etc/postfix/master
找到開頭是 submission 的那幾行(通常是被註解掉的),將前面的 # 拿掉,改成如下(注意縮排):
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
(重點是開啟它,並強制 TLS 加密與 SASL 認證)
存檔離開。
6. 檢查與重啟
在重啟之前,我們先檢查設定檔語法有沒有寫錯:
sudo postfix check
如果不回傳任何訊息,代表語法正確。
接著重啟 Postfix 讓設定生效:
sudo systemctl restart postfix
4. 驗證成果:我們現在完成了什麼?
現在,您的 Postfix 已經具備了以下能力:
- 知道自己是誰 (
mail.mydomain.com)。
- 知道要去哪裡查資料 (連接 MySQL)。
- 打開了收發信的大門 (Port 25 和 587)。
但是!現在還不能寄信,也不能收信。 為什麼?
- 因為 Dovecot 還沒裝!
- Postfix 設定檔裡的
private/auth (驗證密碼) 和 private/dovecot-lmtp (存信) 都是要連線給 Dovecot 的。現在這兩條線是斷的。
查看 Log 確認: 如果您現在去查看 Log:
Bash
tail -f /var/log/mail.log
您可能會看到類似 warning: connect to private/dovecot-lmtp: No such file or directory 的警告,這是完全正常的,因為我們還沒安裝 Dovecot。
這就是第三章的內容。我們已經把「郵差 (Postfix)」武裝好了,但他現在還缺一個「管家 (Dovecot)」來幫他管倉庫和查戶口。
第一章:架構規劃與環境準備
第二章:基礎建設篇——DNS、SSL 與資料庫
第三章:郵差的武裝——安裝 Postfix 並連接資料庫
第四章:安裝與設定 Dovecot (最後一塊拼圖)。
第五章:驗收時刻——全流程測試
第六章:設定 AWS SES Relay (讓信件使命必達)