Postfix
Postfix 是一種電子郵件伺服器，它是由任職於IBM華生研究中心（T.J. Watson Research Center）的荷蘭籍研究員Wietse Venema為了改良sendmail郵件伺服器而產生的。最早在1990年代晚期出現，是一個開放原始碼的軟體。

Postfix: Tips
postfix 服務 
 服務啟動/停止/重新載入 
 postfix check
postfix start
postfix stop
postfix reload
postfix flush 
 postconf - 不用編輯 main.cf 的設定方法 
 列出設定參數 
 postconf -n 
 修改參數 *不需要重啟服務* 
 postconf -e "relayhost = [192.168.10.10]:587" \
"smtp_sasl_auth_enable = yes" \
"smtp_sasl_security_options = noanonymous" \
"smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd" \
"smtp_use_tls = yes" \
"smtp_tls_security_level = encrypt" \
"smtp_tls_note_starttls_offer = yes" 
 移除參數 
 postconf -# smtp_use_tls 
 No main.cf 
 postconf: fatal: open /etc/postfix/main.cf: No such file or directory 
 Solution: 
 dpkg-reconfigure postfix 
   
 Test SMTP 
 Swaks is a featureful, flexible, scriptable, transaction-oriented SMTP test tool written and maintained by John Jetmore. It is free to use and licensed under the GNU GPLv2. 
 外部網站 
 
 How to configure AWS SES with Postfix MTA

Postfix Installation
With Docker 
 
 Github: docker-mailserver 
 Docker: Running a Postfix container for testing mail during development

Mailu
Mailu is a simple yet full-featured mail server as a set of Docker images. It is free software (both as in free beer and as in free speech), open to suggestions and external contributions. The project aims at providing people with an easily setup, easily maintained and full-featured mail server while not shipping proprietary software nor unrelated features often found in popular groupware. 
 Installation 
 Setting up the DNS 
 加一筆 A 與 MX 紀錄指向郵件主機 
 mail.mydomain.com. IN A a.b.c.d 
 mydomain.com. IN MX 10 mail.mydomain.com. 
 DKIM/SPF & DMARC Entries 
 
 DKIM 的 key 要從 Admin 管理介面 > Mail domains > Details > Generate keys。 
 
 Create the configuration file 
 透過這個網站產生 Docker 需要設定檔 docker-compose.yml , mailu.env 。 
 前往 https://setup.mailu.io/   
 必要的資訊如下： 
 Step 1 - pick a flavor 
 
 Compose 
 
 Step 2 - Initial configuration 
 
 Mailu storage path: /mailu 
 Main mail domain and server display name: mydomain.com 
 Postmaster local part: admin 
 Choose how you wish to handle security: letsencrypt 
 Website name: Webmail - mailu 
 Linked Website URL: https://mail.mydomain.com 
 Enable the admin UI (and path to the admin UI): unCheck

 不啟用 admin UI 的外部網路存取 
 
 
 Step 3 - pick some features 
 
 Enable Web email client (and path to the Web email client): roundcube , /webmail 
 
 Step 4 - expose Mailu to the world 
 
 IPv4 listen address: <the public address of the server> 
 Subnet of the docker network: 192.168.203.0/24

 這裡的子網路是指 docker 的 br-XXXX 介面。 
 
 Public hostnames: mail.mydomain.com 
 
 Database preferences 
 
 Which database back end would you like to use: sqlite 
 
 Download the configuration file 
 mkdir /mailu
cd /mailu
wget http://setup.mailu.io/1.7/file/64c4e566-dda9-4e09-abcb-9b8732dc873b/docker-compose.yml
wget http://setup.mailu.io/1.7/file/64c4e566-dda9-4e09-abcb-9b8732dc873b/mailu.env 
 Start the Compose project 
 cd /mailu
docker-compose -p mailu up -d 
 create the primary administrator user account 
 docker-compose -p mailu exec admin flask mailu admin myadmin mydomain.com THISISPASSWORD 
 Login as admin to verify 
 open the URL: http://127.0.0.1:8080/ui login with the account that you just created. 
 
 Mail Management 
 Webmail 
 https://mail.mydomain.com/webmail 
 
 user 
 docker-compose exec admin flask mailu user myuser mydomain.com 'password123' 
 user-delete 
 docker-compose exec admin flask mailu user-delete foo@mydomain.com

設定 postfix 為寄信主機
情境說明 
 需求：需要一部 SMTP 寄信主機可供論壇網站寄信，免費的 Gmail 或 ISP 提供的 SMTP 主機都會有寄送數量的限制，而其他提供可大量寄信的雲端服務商，例如 Mailchimp、Sendgrid 等收費都不便宜。 
 目的：使用 postfix 架設一部自有的 SMTP 寄信主機。 
 說明： 
 
 採用 docker 佈署方式 
 為了降低寄出的郵件被其他郵件平台視為垃圾郵件而遭阻擋，主機在寄信時所提供的「寄件者」郵件位址的網域，需要包含一些安全設定： NOTE：建議至少要完成最簡單的 SPF Record；不然透過主機寄信到 Gmail 會收不到。 
 
 
 
 
 SPF Record 
 DKIM 
 DMARC 
 
 
 為了要完成上述設定，必須擁有網域的控制權。 
 網域內至少需有一個有效的郵件信箱，作為論壇系統管理後台認証與主機設定過程驗證用。 
 
 關鍵參數定義： 
 
 網域內的有效信箱：alang@mydomain.com 
 網域：mydomain.com 
 寄信主機的 FQDN：smtp.mydomain.com 
 透過主機發信時的「寄件者」郵件位址：alang@mydomain.com 
 
 安裝設定 container 
 git clone https://github.com/a-lang/docker-postfix-smtp.git 
docker pull alangtw/postfix-smtp:trusty 
 修改啟動參數 
 run.sh： 
 
 maildomain: 你的網域名 
 smtp_user: 外寄郵件的連線帳號與密碼，中間用：隔開 
 
 -e maildomain=mydomain.com -e smtp_user=alang@mydomain.com:thispassword \ 
 建立 SSL 自我簽署憑證 
 為了要新增 SSL 憑證，必須先將 container 啟動。 
 注意：此時 container 雖然啟動，但缺少一些需要的憑證與金鑰檔，所以系統還無法正常運作。 
 啟動 container 
 chmod 0755 *.sh
./run.sh 
 建立 SSL 憑證檔 NOTE: 在 Host 執行以下指令 
 docker exec -it postfix openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /etc/postfix/certs/smtp-mydomain-com.key \
-out /etc/postfix/certs/smtp-mydomain-com.crt 
 
 Tip: 
 憑證檔 .crt 與 .key 會儲存在以下路徑： - Host OS: data/certs - Container OS: /etc/postfix/certs 
 SSL 憑證是用在 SMTP 主機與發信電腦或發信系統加密連線。 
 
 建立 DKIM 金鑰 
 在 Host 執行以下指令 
 docker exec -it postfix sh -c "cd /etc/opendkim/domainkeys && opendkim-genkey -t -s mail -d mydomain.com" 
 
 Tip: 
 私鑰檔 .private 與公鑰檔 .txt 會儲存在以下路徑： - Host OS: data/domainkeys - Container OS: /etc/postfix/domainkeys 
 .txt 內有公鑰字串，這要設定在 DNS Zone。 
 
 重啟 container 
 有了 SSL 憑證與 DKIM 金鑰，需重啟 container 以套用這些設定。 
 ./stop.sh
./run.sh 
 到這裡，主機設定都已完成。 
 檢查幾個 container 的服務 postfix: 
 #> docker exec -it postfix ps -ef | grep postfix
root 54 51 0 07:11 ? 00:00:00 /bin/bash /opt/postfix.sh
root 125 1 0 07:11 ? 00:00:00 /usr/lib/postfix/master
postfix 127 125 0 07:11 ? 00:00:00 pickup -l -t unix -u
postfix 128 125 0 07:11 ? 00:00:00 qmgr -l -t unix -u 
 opendkim: 
 #> docker exec -it postfix ps -ef | grep opendkim
opendkim 55 51 0 07:11 ? 00:00:00 /usr/sbin/opendkim -f
opendkim 66 55 0 07:11 ? 00:00:00 /usr/sbin/opendkim -f 
 /var/log/mail.log: 
 #> docker exec -it postfix tail -20 /var/log/mail.log
Jan 2 07:11:14 a037fd779eaa opendkim[66]: OpenDKIM Filter v2.9.1 starting (args: -f)
Jan 2 07:11:15 a037fd779eaa postfix/master[125]: daemon started -- version 2.11.0, configuration /etc/postfix 
 雖然系統會用 sasl 作郵件認証，不過 saslauthd 服務可以不用啟動。 
 
 Tip: mail.log 如果服務正常運作，不應該出現錯誤訊息；用戶端在寄信後，這裡如果顯示 ... doesn't resolve to XXX.XXX.XXX.XXX 的錯誤，這是正常的，原因是主機所在的網路無法反查用戶端的FQDN，這不會影響寄信功能。 
 
 防止寄出信件成為垃圾信而遭阻擋 
 
 避免外寄郵件遭到假冒 
 降低外寄郵件被辨識為垃圾郵件 
 避免有心人士以郵件工具作為釣魚攻擊 
 
 關於 SPF、DKIM 與 DMARC 的運作原理，以及如何保護郵件被假冒或竄改，參閱下述連結 
 
 全球網絡聯盟展示DMARC電子郵件安全協議採納情況 
 最佳電子郵件安全要靠這三大協議：DMARC、SPF和DKIM 
 使用 Gmail 驗證防範垃圾郵件、假冒郵件和網路詐騙郵件 
 
 新增 SPF 記錄 
 SPF 記錄的工作原理是，在「寄件者」郵件位址所在的網域設定裡，新增一筆 SMTP 主機 IP，用途是允許該 IP 使用這網域作為發信時的「寄件者」。 
 在 DNS Zone 新增一筆 TXT 記錄，內容為： 
 
 Type: TXT 
 Name: mydomain.com 或者 @ 
 Value: v=spf1 a mx ip4:123.123.123.123 ~all 
 
 
 Tip: 
 123.123.123.123 是 SMTP 主機位址 
 如果有多個 IP 位址，要用空格隔開，例如 ip4:123.123.123.123 ip4:111.111.111.111 
 關於 SPF 更多的說明，請參閱 Google: 使用 SPF 對電子郵件寄件者進行授權 
 
 新增 DKIM 記錄 
 採用 DomainKeys Identified Mail (DKIM) 標準有助於防止外寄電子郵件遭到假冒。 
 「假冒電子郵件」意指變更電子郵件內容，讓郵件顯示非真實寄件來源的寄件者或寄件地址。假冒是在未經授權的情況下使用電子郵件，這種情形十分常見，因此部分電子郵件伺服器會要求設定 DKIM，以免電子郵件遭到假冒。 
 DKIM 會在所有外寄郵件的標頭加上加密簽名，收到這些郵件的電子郵件伺服器則會使用 DKIM 來解密郵件標頭，並將它與 DNS 上的公鑰做匹配，以確認郵件寄出後並未遭人竄改。 
 DKIM 有一組配對的公、私鑰，私鑰設定在 SMTP 主機上，公鑰則設定在公開的 DNS Zone 上。 
 在 DNS Zone 新增一筆 TXT 記錄，內容為： 
 
 Type: TXT 
 Name: mail._domainkey 
 Value: v=DKIM1; k=rsa; t=y; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAraC3pqvqTkAfXhUn7Kn3JUNMwDkZ65ftwXH58anno/bElnTDAd/idk8kWpslrQIMsvVKAe+mvmBEnpXzJL+0LgTNVTQctUujyilWvcONRd/z37I34y6WUIbFn4ytkzkdoVmeTt32f5LxegfYP4P/w7QGN1mOcnE2Qd5SKIZv3Ia1p9d6uCaVGI8brE/7zM5c 
 
 
 Tip: 
 Value 的值與 p=公鑰，內容都在建立金鑰步驟時產生的檔案 mail.txt 裡。 
 關於 DKIM 更多的說明，請參閱 Google: 使用 DKIM 驗證電子郵件 
 
 新增 DMARC 記錄 
 垃圾郵件發佈者可能會假造電子郵件的「寄件者」地址，讓人誤以為這些郵件是您網域中某位使用者所寄送。如果這類發佈者冒用您網域的名義傳送垃圾郵件，不僅會損害網域的聲譽，收件者也可能將假造郵件連同真正從您網域寄出的郵件一併標示為垃圾內容。 
 為了防堵這種濫發垃圾郵件的情形，許多郵件系統例如Gmail 現在支援「網域型郵件驗證、報告與一致性」(DMARC) 機制。您可以使用 DMARC 定義政策，決定 Gmail 如何處理以您網域名義寄出的垃圾電子郵件。 
 注意：必須先完成 SPF 與 DKIM 設定，才能再設置 DMARC。 
 在 DNS Zone 新增一筆 TXT 記錄，內容為： 
 
 Type: TXT 
 Name: _dmarc 
 Value: v=DMARC1; p=none; rua=mailto:alang@mydomain.com 
 
 
 Tip: 
 p=none，對於可疑郵件，不採取任何處置 rua，回報 DMARC 的活動報告至該郵件位址 
 關於 DMARC 更多的說明，請參閱 Google: 使用 DMARC 管理可疑電子郵件 
 
 驗證與測試寄信 
 如何驗證寄信功能與每個安全協議是否生效，大概是文章中最困難以及最花時間的步驟。 
 驗證寄信功能 
 1. 用 openssl 測試 SMTP 帳號認證，將帳號密碼轉換成 base64 編碼 
 user: alang@mydomain.com pass: yourpass 
 $> echo -ne '\000alang@mydomain.com\000yourpass' | openssl base64
AGFsYW5nQG15ZG9tYWluLmNvbQB5b3VycGFzcw==

# 另一個 perl 的方法
# 帳密如有包含 @ 字元，必須加上 \
$> perl -MMIME::Base64 -e \ 'print encode_base64("\0alang\@mydomain.com\0yourpass");' 
AGFsYW5nQG15ZG9tYWluLmNvbQB5b3VycGFzcw== 
 連線 smtp 主機 
 
 SMTP 主機位址：smtp.mydomain.com 
 submission 服務：587 
 
 $> openssl s_client -quiet -starttls smtp -connect smtp.mydomain.com:587
depth=0 C = TW, ST = TY, L = TaoYuan, O = RAIDA, OU = Admin, CN = smtp.osslab.tw
verify error:num=18:self signed certificate
verify return:1
depth=0 C = TW, ST = TY, L = TaoYuan, O = RAIDA, OU = Admin, CN = smtp.osslab.tw
verify return:1
250 DSN 
 輸入帳號密碼的 base64編碼 
 AUTH PLAIN AGFsYW5nQG15ZG9tYWluLmNvbQB5b3VycGFzcw== 
 如果通過認証，會出現 
 
 235 2.7.0 Authentication successful 
 
 離開，輸入 quit。 
 2. 寄測試信到 Gmail 信箱 
 為何要用 Gmail 作測試信的收信位址？因為 Gmail 郵件系統已經整合了 SPF/DKIM/DMARC 郵件安全協議檢查，而且很容易得知檢查的結果。 
 
 郵件用戶端軟體：必須使用有支援 STARTTLS 加密連線的郵件用戶端軟體，本例使用 Mozilla Thunderbird。 
 Gmail 信箱一個 
 網域的有效信箱一個：設定郵件用戶端軟體時，需要提供一個「寄件者」的信箱，本例使用 alang@mydomain.com NOTE：如果是無效信箱位址，可能無法順利設定 Thunderbird 軟體。 
 
 Thunderbird SMTP 設定： 
 
 Port: 587 
 SMTP 主機：smtp.mydomain.com 
 連線安全性：STARTTLS 
 使用者名稱：這裡必須與 container 啟動參數裡的帳號相同，本例是 alang@mydomain.com 
 
 
 Tip: 
 連線安全性若使用 SSL/TLS，會無法成功連線主機。 
 如果連線成功，Thunderbird 會彈出密碼輸入的視窗，密碼必須與 container 啟動參數裡的相同。 
 因為使用 self-signed 憑證，所以必須檢驗憑證時，需要加入例外名單，參閱附圖 thunderbird-smtp.png 。 
 
 驗證 DNS 記錄 
 從 DNS 管理控制台新增完 TXT 記錄後，要驗證是否生效很簡單。 
 找一部可以上網的 Linux 桌機，分別執行 
 # SPF record
$> dig +short TXT mydomain.com

# DKIM key
$> dig +short TXT mail._domainkey.mydomain.com

# DMARC
$> dig +short TXT _dmarc.mydomain.com

外部轉信主機設定
GoDaddy SMTP 
 GoDaddy Setup: Office 365 Email: Enable SMTP Authentication 
 Sign in Email & Office Dashboard > Select one email account created (your@domain.name) > Advanced Settings > SMTP Authentication: ON 
 main.cf: 
 ## for GoDaddy SMTP with Office 365
relayhost = [smtp.office365.com]:587
# SASL
smtp_sasl_auth_enable=yes
smtp_sasl_password_maps = hash:/etc/postfix/saslpasswd_godaddy
smtp_sasl_security_options = noanonymous
# TLS
smtpd_tls_key_file = /etc/postfix/tls/godaddy.key
smtpd_tls_cert_file = /etc/postfix/tls/godaddy.crt
smtpd_use_tls = yes
smtp_use_tls = yes
smtpd_tls_auth_only = no
smtp_tls_note_starttls_offer = yes
smtpd_tls_loglevel = 2
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_randome_source = dev:/dev/urandom
# Fix for MAIL-FROM
smtp_generic_maps = hash:/etc/postfix/generic 
 測試 TLS 連線 
 openssl s_client -quiet -starttls smtp -connect smtp.office365.com:587 
 depth=2 /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
verify return:1
depth=1 /C=US/O=DigiCert Inc/CN=DigiCert Cloud Services CA-1
verify return:1
depth=0 /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=outlook.com
verify return:1
250 SMTPUTF8 
 Ctrl + c 離開。 
 建立密碼檔 saslpasswd_godaddy，內容格式如下: 
 smtp.office365.com your@domain.name:thisispass 
 chmod 0600 saslpasswd_godaddy
postmap hash:/etc/postfix/saslpasswd_godaddy 
 建立憑證檔 
 cd /etc/postfix
mkdir tls
cd tls
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout godaddy.key -out godaddy.crt 
 指定 MAIL-FROM 位址 
 編輯 /etc/postfix/generic 
 root@freepbx.sangoma.local your@sender.email.address
root your@sender.email.address
asterisk your@sender.email.address 
 轉換 generic 
 cd /etc/postfix
postmap generic 
 Google Mail 
 
 How to Configure a Postfix Server to Send Email through Gmail | Linode Docs 
 
 Domino Notes SMTP 
 測試 TLS 連線 
 openssl s_client -quiet -starttls smtp -connect 10.14.26.18:587 
 depth=0 C = TW, ST = Taiwan, L = Taoyuan, O = WIN Semiconductors Corp., OU = IT, CN = tpemissp01.winfoundry.com, emailAddress = dominooa@winfoundry.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = TW, ST = Taiwan, L = Taoyuan, O = WIN Semiconductors Corp., OU = IT, CN = tpemissp01.winfoundry.com, emailAddress = dominooa@winfoundry.com
verify error:num=21:unable to verify the first certificate
verify return:1
250 PIPELINING 
 SMTP 不需要帳密認證 
 postconf -e "relayhost = [10.14.26.18]:587"
postconf -e "smtp_use_tls = yes" 
 
 Q & A 
 STARTTLS is required to send mail 
 Jul 27 02:41:51 freepbx postfix/smtp[20403]: B56021017FB13: to=<alang.hsu@gmail.com>, relay=smtp.office365.com[52.96.165.34]:587, delay=10, delays=0.02/0.01/5.3/5.1, dsn=4.0.0, status=deferr
ed (host smtp.office365.com[52.96.165.34] said: 451 5.7.3 STARTTLS is required to send mail [BN9PR03CA0153.namprd03.prod.outlook.com] (in reply to MAIL FROM command)) 
 Solution: 
 
 檢查 main.cf 的 TLS 參數 
 憑證檔成功建立 
 
 XXX not allowed to send as asterisk@freepbx.sangoma.local 
 Jul 27 04:11:53 freepbx postfix/smtp[31670]: warning: smtp.office365.com[52.96.28.178]:587: response longer than 2048: 554 5.2.252 SendAsDenied; info...
Jul 27 04:11:53 freepbx postfix/smtp[31670]: E0E4010176933: to=<info@mediasystemsfl.com>, relay=smtp.office365.com[52.96.28.178]:587, delay=313418, delays=313416/0.01/1.1/0.26, dsn=5.2.252, 
status=bounced (host smtp.office365.com[52.96.28.178] said: 554 5.2.252 SendAsDenied; info@mediasystemsfl.com not allowed to send as asterisk@freepbx.sangoma.local; STOREDRV.Submission.Excep
tion:SendAsDeniedException.MapiExceptionSendAsDenied; Failed to process message due to a permanent exception with message [BeginDiagnosticData]Cannot submit message. 0.35250:14350000, 1.3667
4:0A000000, 1.61250:00000000, 1.45378:02000000, 1.44866:EC2D0000, 1.36674:0E000000, 1.61250:00000000, 1.45378:F12D0000, 1.44866:CA010000, 16.55847:9A120000, 17.43559:000000002402000000000000
0000000000000000, 20.52176:140F52951900103100000000, 20.50032:140F52958917000000000000, 0.35180:140F5295, 255.23226:0A000000, 255.27962:0A000000, 255.27962:0E000000, 255.31418:19000000, 0.35
250:1F001336, 1.36674:0A000000, 1.61250:00000000, 1.45378:02000000, 1.44866:58000000, 1.36674:32000000, 1.61250:00000000, 1.45378:5D000000, 1.44866:01000000, 16.55847:D3000000, 17.43559:0000
000098030000000000000F00000000000000, 20.52176:140F52951900101062000000, 20.50032:140F5295891700001F001A00, 0.35180:67000000, 255.23226:0A001380, 255.27962:0A000000, 255.27962:32000000, 255.
17082:DC040000, 0.27745:0B002900, 4.21921:DC040000, 255.27962:FA000000, 255.1494:03003600, 0.38698:0F010480, 1.41134:46000000, 7.36354:010000000000010B01000000, 0.37692:01000000, 0.37948:860
00000, 5.33852:00000000534D545000000000, 7.36354:010000000000010907000000, 4.56248:DC040000, 7.40748:010000000000010B0A000000, 7.57132:000000000000000003000000, 4.39640:DC040000, 1.63016:320
00000, 8.45434:EAFEADFEA5E644438592F8B9E718580F00000000, 1.46798:04000000, 5.10786:0000000031352E32302E353435382E3032353A424C30505231364D42323333383A39333261363135642D616239372D346165312D623
030362D3234323361383536363439313A3332323631360093001000000000, 7.51330:2A6B5D23866FDA0800000000, 0.39570:07000000, 1.55954:0A000000, 0.49266:0200
Jul 27 04:11:53 freepbx postfix/cleanup[31676]: AC9D41016F023: message-id=<20220727041153.AC9D41016F023@freepbx.sangoma.local>
Jul 27 04:11:53 freepbx postfix/bounce[31675]: E0E4010176933: sender non-delivery notification: AC9D41016F023
Jul 27 04:11:53 freepbx postfix/qmgr[27367]: AC9D41016F023: from=<>, size=8634, nrcpt=1 (queue active)
Jul 27 04:11:53 freepbx postfix/qmgr[27367]: E0E4010176933: removed
Jul 27 04:11:53 freepbx postfix/local[31678]: AC9D41016F023: to=<asterisk@freepbx.sangoma.local>, relay=local, delay=0.02, delays=0.01/0.01/0/0, dsn=2.0.0, status=sent (delivered to mailbox)
Jul 27 04:11:53 freepbx postfix/qmgr[27367]: AC9D41016F023: removed 
 Solution: 
 GoDaddy SMTP 服務會檢查 sender 的地址是否有效。讓 postfix 將特定無效的地址轉換成其他指定的有效地址。使用檔案 generic 編輯要對應的郵件地址。 
 openssl 測試連線不成功 
 執行測試連線時，如果只有見到以下 1 ~ 2 行輸出，表示 TLS 連線失敗 
 write:errno=104 
 連線成功的訊息如下 
 depth=2 /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
verify return:1
depth=1 /C=US/O=DigiCert Inc/CN=DigiCert Cloud Services CA-1
verify return:1
depth=0 /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=outlook.com
verify return:1
250 SMTPUTF8 
 certificate verification failed 
 
 postfix/smtp[17989]: certificate verification failed for 10.14.26.18[10.14.26.18]:587: untrusted issuer /DC=com/DC=winfoundry/CN=win-root 
 
 要連線的 SMTP Server，可能使用了自簽的憑證，這個不會影響信件的寄送，可直接忽略。 
 如果不想讓這訊息出現，必須取的遠端 SMTP Server 所用憑證的 CA 根憑證檔，然後設定 postfix 讀取這個 CA 檔。 
 TLS handshake failed 
 STARTTLS=client, error: connect failed=-1, SSL_error=5, errno=104, retry=-1
ruleset=tls_server, arg1=SOFTWARE, relay=tpemissp01.winfoundry.com, reject=403 4.7.0 TLS handshake failed.
...relay=tpemissp01.winfoundry.com. [10.14.26.18], dsn=4.0.0, stat=Deferred: 403 4.7.0 TLS handshake failed. 
 使用 openssl 測試與 SMTP 主機的 TLS 連線是否成功。 
 relay=none & status=bounced 
 to=<alang.hsu@gmail.com>, relay=none, delay=0.03, delays=0.02/0/0/0.01, dsn=5.0.0, status=bounced ([smtp.office365.com]:587) 
 Solution: Re-create the main.cf 
 dpkg-reconfigure postfix
# Select "Internet Site"

sSMTP
sSMTP - Simple SMTP 
 sSMTP is a simple MTA to deliver mail from a computer to a mail hub (SMTP server). sSMTP is simple and lightweight, there are no daemons or anything hogging up CPU; Just sSMTP. Unlike Exim4, sSMTP does not receive mail, expand aliases, or manage a queue. 
 Setting up 
 /etc/ssmtp/ssmtp.conf 
 # For My SMTP relay server AuthUser=alang@domain.com AuthPass=ThisIsPassword FromLineOverride=YES mailhub=smtp.domain.com:587 UseSTARTTLS=YES 
 如何自訂 sender 的位址 
 修改 /etc/ssmtp/ssmtp.conf 
 FromLineOverride=NO root=win.mis03 
 修改 /etc/ssmtp/revaliases 
 root:win.mis03@msa.hinet.net 
 發信測試 
 方法一: 使用 ssmtp 
 $> ssmtp alang.hsu@gmail.com To: alang.hsu@gmail.com From: sender@domain.com Subject: Test Mail Hello, World <Ctrl-D to Exit> 
 方法二: 使用 mail 
 echo "Hello, World" | mail -s "Test Mail" 
 
 NOTE: 
 使用方法一時，From 必須輸入一個有效的郵件地址。 
 使用方法二有可能會寄不出去，原因是 sender 的郵件地址不是一個有效的位址。參考自訂 sender 位址的步驟。

Procmail
Configuration 
 ~/.forward 
 john@example.com, benny@example.com, "|exec /usr/bin/procmail -f- || exit 75" 
 ~/.procmailrc 
 MAILDIR=/var/spool/mail
SHELL=/bin/sh
LOGFILE=$HOME/temp/procmail.log
LINEBUF=8192
VERBOSE=yes
SUBJECT=`formail -xSubject:`

SMS_SUBJECT="Alert: $SUBJECT, something went wrong with the DS storage, pls check your mail box ASAP!!"
SMS_SUBJECT_1="Alert: $SUBJECT, something went wrong with the IBM xServer, pls check your mailbox ASAP!"
SMS_TO="alert@example.com"
SMS_ID="[SMS_AIX]"

# Phone numbers
# 123123123
SMS_PHONE="123123123 456456456"

:0
# Fetching all email
#* ^From.*
#
# For DS Storage
# Fetch the email that included the word 'tpemismo02'.
#* ^From.*(tpemismo02)

# Sending the SMS via email
#| echo "$SMS_ID" | mail -s "$SMS_SUBJECT" "$SMS_TO" ;
# Sending the SMS via API
#| /usr/local/bin/sendSMS.sh -t "$SMS_SUBJECT" -n "$SMS_PHONE";

:0
# For ServerRaid/MegaRaid
* ^From.*(tpecimvm02|tpecimvm04|tpecimvm05|tpecimvm08|tpecimvm09|pms2|adb1-a|tomahawk06|tpecimvm07|tpecimvm10|tpecimvm12|tycitpvm02|tycitpvm81|tycitpvm82|tycitpvm83)
| /usr/local/bin/sendSMS.sh -t "$SMS_SUBJECT_1" -n "$SMS_PHONE"; 
 /usr/local/sendSMS.sh 
 #!/bin/bash
# File: sendSMS.sh
# Author: A.Lang
# Purpose: Sendind the SMS thru FareaStone carrier
# Created: 2014/01/13
#

API_SYSID="WINSEMIP"
API_SRCADD="0191680002117540000000"
API_URL="http://61.20.32.60:6600/mpushapi/smssubmit"

Usage() {
 echo "Usage: $0 [-t <TEXT-Message>] [-n <phone-number>]";
 echo "For example: $0 -t \"Hello, SuperMan\" -n \"085713 457199\" "
}

while getopts ":t:n:" o; do
 case "$o" in
 t)
 t=$OPTARG
 ;;
 n)
 n=$OPTARG
 ;;
 \?)
 echo "Invalid option: -$OPTARG"
 Usage
 exit 1
 ;;
 :)
 echo "Option -$OPTARG requires an argument !"
 Usage
 exit 1
 ;;
 esac
done

if [ $OPTIND -ne 5 ]; then
 echo "Invalid options entered !"
 Usage
 exit 1
fi

IN_TXT="$t"
IN_PHONE="$n"

function parseXML() {
 elemList=( $(echo $xmlFile | tr '\n' ' ' | XMLLINT_INDENT="" xmllint --format - | /bin/grep -e "</.*>$" | while read line; do \
 echo $line | sed -e 's/^.*<\///' | cut -d '>' -f 1; \
 done) )

 totalNoOfTags=${#elemList[@]}; ((totalNoOfTags--))
 suffix=$(echo ${elemList[$totalNoOfTags]} | tr -d '</>')
 suffix="${suffix}_"

 for (( i = 0 ; i < ${#elemList[@]} ; i++ )); do
 elem=${elemList[$i]}
 elemLine=$(echo $xmlFile | tr '\n' ' ' | XMLLINT_INDENT="" xmllint --format - | /bin/grep "</$elem>")
 echo $elemLine | grep -e "^</[^ ]*>$" 1>/dev/null 2>&1
 if [ "0" = "$?" ]; then
 continue
 fi
 elemVal=$(echo $elemLine | tr '\011' '\040'| sed -e 's/^[ ]*//' -e 's/^<.*>\([^<].*\)<.*>$/\1/' | sed -e 's/^[ ]*//' | sed -e 's/[ ]*$//')
 xmlElem="${suffix}$(echo $elem | sed 's/-/_/g')"
 eval ${xmlElem}=`echo -ne \""${elemVal}"\"`
 attrList=($(echo $xmlFile | tr '\n' ' ' | XMLLINT_INDENT="" xmllint --format - | /bin/grep "</$elem>" | tr '\011' '\040' | sed -e 's/^[ ]*//' | cut -d '>' -f 1 | sed -e 's/^<[^ ]*//' | tr "'" '"' | tr '"' '\n' | tr '=' '\n' | sed -e 's/^[ ]*//' | sed '/^$/d' | tr '\011' '\040' | tr ' ' '>'))
 for (( j = 0 ; j < ${#attrList[@]} ; j++ )); do
 attr=${attrList[$j]}
 ((j++))
 attrVal=$(echo ${attrList[$j]} | tr '>' ' ')
 attrName=`echo -ne ${xmlElem}_${attr}`
 eval ${attrName}=`echo -ne \""${attrVal}"\"`
 done
done
}

function Process_PhoneNumbers(){
 if [ -n "$@" ]; then
 API_DEST=""
 for no in $@
 do
 API_DEST="${API_DEST}<DestAddress>${no}</DestAddress>"
 done
 fi
}

function PreCheck(){
 NOT_OK=0
 ## Check the command curl
 if ! which curl > /dev/null 2>&1; then
 NOT_OK=1
 echo "The Command curl NOT Found!"
 fi

 ## Check the command base64
 if ! which base64 > /dev/null 2>&1; then
 NOT_OK=1
 echo "The Command base64 NOT Found !"
 fi

 ## Check the internet to FareaStone
 if ! curl -m 6 --silent --head $API_URL |egrep "200 OK" >/dev/null
 then
 NOT_OK=1
 echo "It seems the internet is down !"
 fi

 if [ $NOT_OK -eq 1 ]; then
 return 0
 else
 return 1
 fi
}

function SendSMS(){
 XML_STR='xml=<?xml version="1.0" encoding="UTF-8"?><SmsSubmitReq><SysId>'${API_SYSID}'</SysId><SrcAddress>'${API_SRCADD}'</SrcAddress>'${API_DEST}'<SmsBody>'${API_TXT}'</SmsBody><DrFlag>true</DrFlag><FirstFailFlag>false</FirstFailFlag></SmsSubmitReq>'

 RE=$(echo $XML_STR | curl -d @- $API_URL)

}

API_TXT=$(echo "$IN_TXT" | base64)

if PreCheck; then
 echo "Aborted."
 exit 1
fi

Process_PhoneNumbers "$IN_PHONE"
SendSMS

xmlFile=$RE
parseXML
echo "ResultCode: $SubmitRes_ResultCode" #Variables for each XML ELement
echo "ResultText: $SubmitRes_ResultText" #Variables for each XML ELement
echo ""