盡管此答案的某些部分僅適用于 mail()
函數(shù)本身的使用,但其中許多故障排除步驟可以應用于任何 PHP 郵件系統(tǒng)。嗯>
您的腳本未發(fā)送電子郵件的原因有多種。除非存在明顯的語法錯誤,否則很難診斷這些事情。如果沒有,您需要仔細檢查下面的清單,以查找您可能遇到的任何潛在陷阱。
錯誤報告對于根除代碼中的錯誤以及 PHP 遇到的一般錯誤至關重要。需要啟用錯誤報告才能接收這些錯誤。將以下代碼放在 PHP 文件的頂部(或主配置文件中)將啟用錯誤報告。
error_reporting(-1); ini_set('display_errors', 'On'); set_error_handler("var_dump");
請參閱如何獲得有用的錯誤PHP 中的消息? — 此答案了解更多詳細信息。
mail()
函數(shù)這可能看起來很愚蠢,但一個常見的錯誤是忘記在代碼中實際放置 mail()
函數(shù)。確保它在那里并且沒有被注釋掉。
mail()
函數(shù)郵件函數(shù)采用三個必需參數(shù),以及可選的第四個和第五個參數(shù)。如果您對 mail()
的調(diào)用沒有至少三個參數(shù),它將失敗。
如果您對 mail()
的調(diào)用沒有按正確順序提供正確的參數(shù),它也會失敗。
您的網(wǎng)絡服務器應該記錄通過它發(fā)送電子郵件的所有嘗試。這些日志的位置會有所不同(您可能需要詢問服務器管理員它們的位置),但通??梢栽谟脩舾夸浀?logs
下找到它們。里面將是服務器報告的與您嘗試發(fā)送電子郵件相關的錯誤消息(如果有)。
端口阻止是大多數(shù)開發(fā)人員在集成代碼以使用 SMTP 發(fā)送電子郵件時面臨的一個非常常見的問題。并且,這可以在服務器郵件日志中輕松追蹤(郵件日志服務器的位置可能因服務器而異,如上所述)。如果您位于共享托管服務器上,則默認情況下端口 25 和 587 仍處于阻止狀態(tài)。此阻止是由您的托管提供商故意完成的。即使對于某些專用服務器也是如此。當這些端口被阻止時,請嘗試使用端口 2525 進行連接。如果您發(fā)現(xiàn)該端口也被阻止,那么唯一的解決方案就是聯(lián)系您的托管提供商以解除對這些端口的阻止。
大多數(shù)托管提供商都會阻止這些電子郵件端口,以保護其網(wǎng)絡免于發(fā)送任何垃圾郵件。
使用端口 25 或 587 進行普通/TLS 連接,使用端口 465 進行 SSL 連接。對于大多數(shù)用戶,建議使用端口 587 以避免某些托管提供商設置的速率限制。
當錯誤抑制運算符 @
被添加到 PHP 中的表達式之前,該表達式可能生成的任何錯誤消息都將被忽略。在某些情況下,需要使用此運算符,但發(fā)送郵件不是其中之一。
如果您的代碼包含@mail(...)
,那么您可能隱藏了有助于您調(diào)試的重要錯誤消息。刪除@
并查看是否報告任何錯誤。
僅當您使用error_get_last()
緊接著具體失敗。
mail()
返回值mail()
函數(shù):
這一點值得注意,因為:
FALSE
返回值,您就知道錯誤在于您的服務器接受您的郵件。這可能不是編碼問題,而是服務器配置問題。您需要與系統(tǒng)管理員聯(lián)系以找出發(fā)生這種情況的原因。TRUE
返回值,并不意味著您的電子郵件一定會發(fā)送。這僅意味著電子郵件已通過 PHP 成功發(fā)送到服務器上相應的處理程序。還有更多 PHP 無法控制的故障點可能導致電子郵件無法發(fā)送。因此,FALSE
將幫助您指明正確的方向,而 TRUE
并不一定意味著您的電子郵件已成功發(fā)送。值得注意的是!
許多共享網(wǎng)絡主機,尤其是免費網(wǎng)絡主機提供商,要么不允許從其服務器發(fā)送電子郵件,要么限制在任何給定時間段內(nèi)可以發(fā)送的數(shù)量。這是因為他們努力限制垃圾郵件發(fā)送者利用其更便宜的服務。
如果您認為您的主機有電子郵件限制或阻止發(fā)送電子郵件,請查看他們的常見問題解答,看看他們是否列出了任何此類限制。否則,您可能需要聯(lián)系他們的支持人員,以驗證發(fā)送電子郵件是否存在任何限制。
通常,由于各種原因,通過 PHP(和其他服務器端編程語言)發(fā)送的電子郵件最終會進入收件人的垃圾郵件文件夾。在對代碼進行故障排除之前,請務必檢查那里。
為了避免通過 PHP 發(fā)送的郵件被發(fā)送到收件人的垃圾郵件文件夾,您可以在 PHP 代碼中或其他方面執(zhí)行多種操作,以最大程度地減少電子郵件被標記為垃圾郵件的機會。 Michiel de Mare 提供的好建議包括:
有關此主題的詳細信息,請參閱如何確保以編程方式發(fā)送的電子郵件不會自動標記為垃圾郵件?。
如果郵件缺少“發(fā)件人”和“回復”等通用標頭,某些垃圾郵件軟件將拒絕郵件:
$headers = array("From: from@example.com", "Reply-To: replyto@example.com", "X-Mailer: PHP/" . PHP_VERSION ); $headers = implode("\r\n", $headers); mail($to, $subject, $message, $headers);
無效的標頭與沒有標頭一樣糟糕。一個不正確的字符就可能導致您的電子郵件脫軌。請仔細檢查以確保您的語法正確,因為 PHP 不會為您捕獲這些錯誤。
$headers = array("From from@example.com", // missing colon "Reply To: replyto@example.com", // missing hyphen "X-Mailer: "PHP"/" . PHP_VERSION // bad quotes );
發(fā)件人:
發(fā)件人雖然郵件必須有發(fā)件人:發(fā)件人,但您不能只使用任何值。特別是用戶提供的發(fā)件人地址是阻止郵件的可靠方法:
$headers = array("From: $_POST[contactform_sender_email]"); // No!
原因:您的網(wǎng)絡或發(fā)送郵件服務器未列入 SPF/DKIM 白名單,無法假裝對 @hotmail 或 @gmail 地址負責。它甚至可能會默默地丟棄帶有未配置的 From:
發(fā)件人域的郵件。
有時,問題就像電子郵件收件人的值不正確一樣簡單。這可能是由于使用了不正確的變量。
$to = 'user@example.com'; // other variables .... mail($recipient, $subject, $message, $headers); // $recipient should be $to
測試此問題的另一種方法是將收件人值硬編碼到 mail()
函數(shù)調(diào)用中:
mail('user@example.com', $subject, $message, $headers);
這可以應用于所有 mail()
參數(shù)。
為了幫助排除電子郵件帳戶問題,請將您的電子郵件發(fā)送到不同電子郵件提供商的多個電子郵件帳戶。。如果您的電子郵件未到達用戶的 Gmail 帳戶,請將相同的電子郵件發(fā)送到 Yahoo 帳戶、Hotmail 帳戶和常規(guī) POP3 帳戶(例如您的 ISP 提供的電子郵件帳戶)。
如果電子郵件到達所有或部分其他電子郵件帳戶,則您知道您的代碼正在發(fā)送電子郵件,但電子郵件帳戶提供商可能出于某種原因阻止了它們。如果電子郵件未到達任何電子郵件帳戶,則問題很可能與您的代碼有關。
如果您已將表單方法設置為 POST
,請確保使用 $_POST
查找表單值。如果您已將其設置為 GET
或根本沒有設置,請確保使用 $_GET
查找表單值。
action
值指向正確的位置確保您的表單 action
屬性包含指向您的 PHP 郵件代碼的值。
<form action="send_email.php" method="POST">
某些網(wǎng)絡托管提供商不允許或啟用通過其服務器發(fā)送電子郵件。造成這種情況的原因可能有所不同,但如果他們禁止發(fā)送郵件,您將需要使用替代方法,即使用第三方為您發(fā)送這些電子郵件。
發(fā)送給他們的技術支持的電子郵件(在訪問他們的在線支持或常見問題解答之后)應該澄清您的服務器上是否可以使用電子郵件功能。
localhost
郵件服務器如果您使用 WAMP、MAMP 或 XAMPP 在本地工作站上進行開發(fā),則您的工作站上可能未安裝電子郵件服務器。如果沒有,PHP 默認無法發(fā)送郵件。
您可以通過安裝基本的郵件服務器來克服這個問題。對于 Windows,您可以使用免費的 Mercury Mail。
您還可以使用 SMTP 發(fā)送電子郵件。請參閱來自 這個很棒的答案 >Vikas Dwivedi 了解如何執(zhí)行此操作。
mail.log
除了 MTA 和 PHP 的日志文件之外,您還可以啟用 專門記錄 mail()
函數(shù)。它不記錄完整的SMTP交互,但至少記錄了函數(shù)調(diào)用參數(shù)和調(diào)用腳本。
ini_set("mail.log", "/tmp/mail.log"); ini_set("mail.add_x_header", TRUE);
參見http://php.net/manual/en/mail.configuration.php 了解詳細信息。 (最好在 php.ini
或 .user.ini
或 .htaccess
中啟用這些選項。)
您可以使用各種傳送和垃圾郵件檢查服務來測試您的 MTA/網(wǎng)絡服務器設置。通常,您將郵件探測發(fā)送到:他們的地址,然后獲取遞送報告和更具體的故障或稍后分析:
PHP 的內(nèi)置 mail()
函數(shù)很方便,通??梢酝瓿晒ぷ?,但它 有其缺點。幸運的是,有一些替代方案可以提供更強大的功能和靈活性,包括處理上述許多問題:
所有這些都可以與專業(yè)的 SMTP 服務器/服務提供商結合使用。 (因為典型的 08/15 共享虛擬主機計劃在電子郵件設置/可配置性方面時好時壞。)