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