摘要:隨著云服務器的盛行,幾乎無法以指向本機的域名向外發送郵件,除了在本機內發送提醒郵件,用處已然不大。發送效率低非面向對象的調用方式,配置麻煩以及云服務器廠商的封鎖,是使用函數的最大阻礙。
轉載請注明文章出處: https://tlanyan.me/php-review...PHP回顧系列目錄
PHP基礎
web請求
cookie
web響應
session
數據庫操作
加解密
Composer
創建自己的Composer包
發送郵件是網站的常用功能,用戶激活、找回密碼等場景常需要發送郵件到用戶郵箱。本文先回顧發送郵件的相關概念,再給出使用PHP發送郵件的示例代碼。
發送短信從功能上看,短信和郵件類似,用途常是通知和安全校驗。發送短信(基本上)需要向供應商付費,所以短信供應商有動力提供清晰的文檔,易用的接口方便用戶接入。一般而言,發送短信的是:
尋找供應商,例如阿里大魚、聚合數據等;
注冊賬戶,獲取appid和appkey;
申請模板;
查看接口文檔,集成到應用中;
調用API發送短信。
流程簡單易懂,接入和使用也十分便捷,基本上一兩小時內就能對接和測試好。用戶無需考慮訊息在通訊過程中的編碼、尋址下發等細節,缺點是要付費。
郵件一般是免費服務,相關支持沒那么到位,這也要理解。各種編程語言發送郵件的類庫不少,從信源角度看基本可以分成兩類:從本機發送和從第三方郵件服務商發送。為了理解郵件發送的流程,先介紹一些相關概念。
相關概念大部分接觸到互聯網的人都有使用郵件的經驗,但基本上限于郵件客戶端、網頁端和提供商這幾個概念。作為一個開發,理解本節中的以下概念能更好的幫你掌握郵件通訊中的細節。
MUA : Mail User Agent,郵件用戶代理。用戶代理是開發中經常接觸到的詞,主要指 理解人的意圖并代表用戶向資源方請求的工具。例如瀏覽器是最常用的用戶代理,以HTTP/HTTPS協議格式向web服務器發送請求,并解析響應,渲染后呈現給用戶。郵件用戶代理,常見的是Foxmail、Outlook這類工具,人們寫好郵件后,按格式封裝郵件內容與郵件服務器通訊。
MTA : Mail Transfer Agent,郵件傳輸代理,幫用戶收發郵件的程序。常說的郵件服務器指的就是MTA,開源的程序有sendmail,postfix,QMail等。
MRA : Mail Retrieval Agent,郵件收取代理,將用戶的郵件從郵件服務器取回本地。郵件客戶端是常見的MRA。
SMTP : Simple Mail Transfer Protocol,簡單郵件傳輸協議。用戶與郵件服務器、郵件服務器互相傳遞郵件均使用該協議(默認明文,可使用SSLTLS加密)。
POP3/IMAP : Post Office Protocol version 3/Internet Message Access Protocol,郵局協議版本3或網絡信息獲取協議,客戶端從服務端獲取郵件時使用的協議。
用戶A(163郵箱)向用戶B(Gmail郵箱)發信,用戶B獲取信件的過程涉及到上述的概念。流程和概念關系可用如下簡圖表示:
用戶A --發送郵件--> 用戶B M|S M|I U|M R|M A|T A|A |P |P v v MTA(163)--轉發(SMTP)->MTA(gmail)
注:上圖給出的是郵件發送的大體流程,其他MSA、MDA、ESMTP、SMTPS等可能會出現在整個流程中,但不影響郵件收發的理解。下文中會提到的縮寫和概念會注明,其他請自行查詢。
postfixLinux下發送郵件的軟件主要是sendmail和postfix,它們在系統中充當上文概念中的MTA/MDA(Mail Delivery Agent,郵件投遞代理)角色。它幫助用戶向外發送郵件,接收郵件投遞到用戶信箱(默認位置/var/spool/mail/用戶名)。
sendmail是老牌的郵件軟件,知名度非常高。但是Wietse(Wietse Zweitze Venema)用的不爽,于是有了postfix。postfix命令(幾乎)兼容于sendmail,但更高效和安全(后綴fix的由來),是目前大部分Linux發行版的默認郵件收發軟件,推薦使用postfix而非sendmail(本博客多年前有篇文章寫如何配置sendmail,那時年少無知見識少,打算抽空把那篇文章改一下)。
postfix的主要配置文件是/etc/postfix/main.cf,配置文件的注釋非常全,選項基本是自解釋的。最重要的幾個配置是:myhostname、myorigin、inet_interfaces、inet_protocols以及mydestination(如果你打算收外網來信的話)。需要注意inet_interfaces配置為localhost時,inet_protocols的值應為ipv4,否則可能會出現類似postfix: fatal: parameter inet_interfaces: no local interface found for ::1的錯誤提示。
與郵件相關的幾個常用postfix命令是:
postquque,查看郵件發送隊列。postqueue -p可取代sendmail中的mailq命令,postqueue -f刷新隊列(強制嘗試發送隊列中的郵件)。
postcat,查看未發送郵件的信息。例如postcat -q xxxx(xxxx是postqueue或者mailq顯示的未發送隊列ID)可查看郵件的詳細信息,postcat -b -q xxxxx只查看郵件正文。
postsuper,超級用戶才可使用的郵件管理程序。postsuper -d xxxx,刪除隊列ID為xxxxx的郵件;postsuper -h xxxxx,暫停隊列ID為xxxx的郵件發送,等。
以上介紹對于發送郵件基本已足夠。注意,mail命令發送的郵件能投遞的前提是postfix正在運行(ps aux | grep postfix | grep -v grep輸出不為空)。
有了postfix,配置好后可以對外發送郵件,也能收取外網發送過來的郵件,但限于命令行操作。想用foxmail等客戶端收發郵件,需要讓服務器支持POP3/IMAP協議。開源的dovecot可以實現這個功能。dovecot服務于收郵件而非發送,了解其對開發中的幫助不大。如果想搭建一套完整的郵件系統(包括網頁端支持、垃圾郵件過濾、病毒查殺、傳輸加密等),建議參考或使用國產開源的 EwoMail。
了解postfix對開發中發送郵件幫助有多大?說實話,幾乎沒有幫助。原因是為了防止垃圾郵件泛濫,各大云服務器廠商屏蔽了25端口(Google Cloud連465都干掉了)。亞馬遜云通過申請還有放行的可能(但有速率和每日額度限制),其他廠商幾乎不會讓你使用自己的域名從本機直接發送郵件。封禁25端口,必須使用第三方的郵件服務,幾乎是業界的標準做法。
聰明的人可能想到,使用465加密端口(基于SMTPS,SMTP over SSL協議)或587端口(SMTP over STARTTLS協議)發送郵件,是不是就能繞開限制了?阿里云/騰訊云等廠商并不封禁465端口,發送郵件可以使用該端口而無需申請。但注意465和587端口是客戶端和郵件服務器通訊使用的端口,郵件服務器之間通訊使用25端口。你可以通過465端口連接到Gmail郵箱對外發送郵件,但無法讓postfix使用465端口投遞郵件到hotmail郵件服務器。
總結來說,sendmail/postfix作為垃圾和欺詐郵件泛濫前的郵件服務器軟件,對業界貢獻很大。隨著云服務器的盛行,幾乎無法以指向本機的域名向外發送郵件,sendmail/postfix除了在本機內發送提醒郵件,用處已然不大。要對外發送郵件,要么自建機房,要么使用第三方郵件系統。
PHP的mail函數作為PHP開發中,了解sendmail/postfix還是有點用處。mail函數默認使用sendmail/postfix發送郵件,了解相關配置,就能知道為啥能工作/為啥不能工作。
簡單來說,要讓PHP自帶的mail函數正常工作,需要做以下事情:
申請域名,在DNS解析中設置MX記錄,指向本機(非合法主機(FQDN, Fully Qualified Domain Name)發送的郵件都會被當做垃圾郵件直接丟棄);
安裝sendmail/postfix,配置軟件并運行;
配置防火墻、安全組,放行端口。
發送效率低、非面向對象的調用方式,配置麻煩以及云服務器廠商的封鎖,是使用mail函數的最大阻礙。所以做PHP以來,本人并未直接用過mail函數。
PHP發送郵件發個郵件要了解這么多,會讓人覺得很心累。說好的PHP是最好的語言呢?
PHP發送郵件也可以很簡單,推薦方式就是使用Swift Mailer或PHPMailer等類庫。引入這些類庫后,注冊第三方郵箱(比如Gmail、QQ等),填好用戶名密碼,配置好STMP地址和端口,就能像發送短信一樣輕松發送郵件。當然這些類庫也支持使用sendmail/postfix發送郵件,但我想你不會再這樣做了。
以Swift Mailer為例,直接上代碼說明使用PHP發送郵件也是一個非常簡單的事情!
首先,在項目中引入Swift Mailer:
composer require "swiftmailer/swiftmailer:^6.0"
然后準備好郵件內容(以文本文件為例,不帶附件):
$message = (new Swift_Message("Test Message")) ->setFrom(["tlanyan@tlanyan.me" => "tlanyan"]) ->setTo(["tlanyan1@tlanyan.me"]) ->setBody("Hello, this is a test mail from Swift Mailer!");
接著,設置好郵件傳輸方式(使用Gmail郵箱):
$transport = (new Swift_SmtpTransport("smtp.gmail.com", 465, "ssl")) ->setUsername("username") ->setPassword("password");
或者使用sendmail/postfix的方式(不推薦):
$transport = (new Swift_SendmailTransport());
最后,使用transport構造mailer實例,發送郵件:
$mailer = new Swift_Mailer($transport); $result = $mailer->send($message);
老板再也不用擔心發送郵件收不到了,So easy!
總結本文先回顧了發送郵件的相關概念,說明不推薦使用內置的mail函數原因,最后給出了使用第三方類庫發送郵件的代碼示例。
感謝閱讀,歡迎評論指正!
參考http://cn.linux.vbird.org/lin...
http://doc.ewomail.com/ewomai...
http://php.net/manual/en/func...
https://swiftmailer.symfony.com
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28596.html
摘要:如果你想體驗原味編程,用開頭的比較適合否則建議使用流函數。有關流的知識,請參考本人之前的博文回顧之流。接下來我們用流函數實現一個簡單的客戶端和服務端。流函數中的和兩個函數是我們想要的。本文目的是簡要介紹中的編程,行文到此已經達到目的。 轉載請注明文章出處: https://tlanyan.me/php-review... PHP回顧系列目錄 PHP基礎 web請求 cookie w...
摘要:通過,腳本層無需過多考慮執行的具體環境,而本身則可以讓針對自己的特點給出特有實現。模式下,也只執行一次。這幾個概念的關系如下網關協議,與語言無關,所以與關系也不大。總結本文簡要回顧了程序的架構和執行流程,并對幾個容易混淆概念做了介紹。 轉載請注明文章出處:https://tlanyan.me/php-review... PHP回顧系列目錄 PHP基礎 web請求 cookie we...
摘要:多進程中與多進程相關的兩個重要拓展是和。函數執行期間,主進程除了等待無法處理其他任務,所以一般不認為這是多進程編程。回收子進程有兩種方式,一種是主進程調用函數等待子進程結束另外一種是處理信號。 轉載請注明文章出處: https://tlanyan.me/php-review... PHP回顧系列目錄 PHP基礎 web請求 cookie web響應 session 數據庫操作 加解...
說明 原文發表在我的個人網站:利用 Composer 完善自己的 PHP 框架(二)——發送郵件 本教程示例代碼見 https://github.com/johnlui/My-First-Framework-based-on-Composer 回顧 上一篇文章中,我們手工建造了一個簡易的視圖加載器,順便引入了錯誤處理包,讓我們的 MFFC 框架在 M、V、C 三個方面都達到了好用的水平。V...
閱讀 2461·2023-04-26 02:18
閱讀 1261·2021-10-14 09:43
閱讀 3822·2021-09-26 10:00
閱讀 6944·2021-09-22 15:28
閱讀 2535·2019-08-30 15:54
閱讀 2599·2019-08-30 15:52
閱讀 473·2019-08-29 11:30
閱讀 3464·2019-08-29 11:05