Skip to Content

PHP 和 Drupal 使用 SMTP 發信

事情的開始

前陣子突然發現承租的主機好像沒有發信給自己。不管是 Drupal 系統的留言通知,或是自己寫的一些 PHP 程式,都沒有寄各種通知信給我,上站一測,果然如此,這可不得了,立刻通知主機商,請他們處理。過去也有類似的經驗,他們通常很快就處理好了。

主機商不久來信,信中說是 GMail 擋了我的信,系統本身並沒有問題,還要我參考這一篇:

https://support.google.com/mail/answer/81126#authentication

我再上站測試,果然寄信到 outlook.com 的信箱沒有問題,寄到 gmail.com 就石沈大海,心中隱隱覺得不妙。

上面那個網址,我看了半天,也不知是怎麼回事。上網查了一些資料,猜想大概是站上的註冊信與廣告信太多,gmail 可能懷疑我的主機有問題,因此要求進一步的認證,否則就不接受這個主機寄出來的信。

於是上網向各方求助,也請主機商再指導一番。他們來信說,我使用的都是 php mail(),建議我改用 smtp 的方式寄信,另外也要我啟用 SPF 和 DKIM,一些朋友也是如此建議,雖然不太懂,但至少有進一步研究的方向了。

 

SPF 和 DKIM 的設定

 

這二個東西還是第一次聽到,又上網去查,大概得知主要的目的是要驗證一封信的來源是不是可靠的,細節請大家自行去找囉。

因為一般在寄 email 時,可以很容易設定寄件者,例如我可以設定寄件者是 xxx@gmail.com,但實際上是由其他非 gmail 的主機寄出的。現在為了避免這種有可能假冒別人寄信的情況,因此用這些設定可以來判斷。

這二個的設定細節我也沒有深入了解,只知道主機的 cPanel 控制台可以設定,我就依要求逐一處理,很快就設定完成了。

這個網址可以用來測試是否設定成功

https://www.mail-tester.com/spf-dkim-check

不過我在設定完成之後,也過了好幾天了,依然偵測不到,不知為什麼?

 

php mail() 和其用法

 

php mail() 就是一般我在 php 上寄信的程式,原本都用的很開心,現在才知道因為 mail() 程式是透過程式直接寄信,收信端無法反向查詢驗證,所以經常會有被阻擋當成垃圾信件的情況,很多主機已經不接收這類的信了,要改成使用 smtp 才行。

在此先記錄一下自己過去是如何使用 mail 來寄信。

 

<?php

if (! utf8mail("寄信者@gmail.com", "收信者@gmail.com", "主旨內容", "信件內容\n這是第二行"))

{

//.... error

}

 

function utf8mail($from, $to, $subject, $message)

{

$headers  = "MIME-Version: 1.0\r\n";

$headers .= "Content-Type: text/plain;charset=utf-8\r\n";

$headers .= "From: $from\nReply-To: $from\n";

$headers .= "X-Mailer: PHP/".phpversion();

$bool = mail($to, $subject, $message, $headers);

return $bool;

}

?>

 

使用 PHPMailer 用 smtp 寄信

 

SMTP 是簡單郵件傳輸協定(Simple Mail Transfer Protocol) ,這是在 Internet 上傳送 email 的一個協定,意思就是可以用它來寄信。

再度上網查詢,得知可以安裝一個套件 PHPMailer 就可以在 PHP 使用 smtp 寄信。問題來了,我不是主機的擁有者,無法直接安裝此套件。所幸後來找到有人有類似的問題,找到了只要複製幾個重要的檔案,就可以執行的方法了。

 

下載 PHPMailer

 

PHPMailer 可在此下載

https://github.com/PHPMailer/PHPMailer/releases

因為我使用的是 PHP 5.3 ,所以選 PHPMailer 5.2.27 版。(當時以為 PHPMailer 6.X 是給 PHP 6.X 使用的)

解壓縮後,取出這四個檔案:

class.phpmailer.php
class.pop3.php
class.smtp.php
PHPMailerAutoload.php

在 php 程式碼的目錄中建一個子目錄,取名為 phpmailer,將這四個檔案放進去。

 

撰寫由 GMail SMTP 寄信的程式

 

在 PHPMailer 的套件中就有不少例子,底下則是我抄自網路,修改後測試成功的程式碼。

 

<?php

require_once("phpmailer/PHPMailerAutoload.php");

 

// 產生 Mailer 實體

$mail = new PHPMailer();

// 設定為 SMTP 方式寄信

$mail->IsSMTP();

// SMTP 伺服器的設定,以及驗證資訊

$mail->Host = "smtp.gmail.com";

$mail->Port = 465;

$mail->SMTPAuth = true;

$mail->SMTPSecure = 'ssl';

// 信件內容的編碼方式       

$mail->CharSet = "utf-8";

// 信件處理的編碼方式

$mail->Encoding = "base64";

// SMTP 驗證的使用者資訊

$mail->Username = "myemail@gmail.com";  //mail的帳號(需要完整的mail帳號,含@後都要填寫)

$mail->Password = "password";  //密碼

// 信件內容設定  

$mail->From = "myemail@gmail.com"; //需要與上述的使用者資訊相同mail

$mail->FromName = "myemail"; //此顯示寄件者名稱

$mail->Subject = "信件標題"; //信件主旨

$mail->Body = "這是一封測是信!";   //信件內容

$mail->IsHTML(true);

// 收件人

$mail->AddAddress("someone@gmail.com", "someone"); //此為收件者的電子信箱及顯示名稱

// 顯示訊息

if(!$mail->Send()) {

echo "Mail error: " . $mail->ErrorInfo;     

} else {

echo "Mail sent";     

}

?>

 

執行後就可以用 gmail 的 smtp 主機寄信了。

有一點要注意,若是要用 gmail 的主機寄信,則 gmail 要設定成「低安全性應用程式存取權」,可在登錄 Google 帳號後,瀏覽此頁說明。

https://myaccount.google.com/lesssecureapps

 

撰寫由網站主機寄信的程式

 

上面是由 gmail smtp 寄信的測試,不過實際上還是希望由租用主機的 smtp 寄出,因此要修改一些資料。

首先要在租用的主機上建立一個信箱帳號,我以前都沒有建,因為我都直接把信件轉到 gmail,這次為了要使用主機的 smtp,因此建了帳號,設了密碼,再把上面測試的 php 程式碼修改相關的部份,所幸也測試成功了。

以上就是自行撰寫的 PHP 程式可以使用 smtp 寄信了。

 

在 Drupal 系統中使用 smtp 寄信

 

前面是介紹直接用 php 撰寫用 smtp 寄信的程式,目前遇到的問題,還有一個是需要讓 Drupal 系統使用 smtp 寄信。

在查詢的過程中,找到二個模組可以做到,分別是 SMTP Authentication Support 和 phpmailer。

 

模組 SMTP Authentication Support

 

SMTP Authentication Support 可在這裡下載。

https://www.drupal.org/project/smtp

依一般模組的安裝方式處理後,還要下載 PHPMailer 的程式,在此模組的 INSTALL.txt 有詳細說明,它是建議放在這裡

sites/all/libraries/phpmailer

我一切處理好之後,測試是失敗的。主要是出現這個訊息:

PHP Fatal error: Class 'SMTP' not found in ….class.phpmailer.php on line ….

後來也發現模組中有補丁要處理,因為懶得再深入,就打算試另一個模組。

 

模組 phpmailer

 

phpmailer 可在這裡下載。

https://www.drupal.org/project/phpmailer

我用的是 Drupal 6,所以選擇 phpmailer-6.x-3.1 版。後來發現它需要依靠 Libraries API 模組,所以我就選了不需要 Libraries 的 phpmailer-6.x-2.2 版。

這一版的 README.txt 裡面有說明,同樣要下載 PHPMailer for PHP5/6 套件,解開後將其中這二個檔案

class.phpmailer.php
class.smtp.php

放在模組本身的 phpmailer 子目錄裡面,這個子目錄在安裝模組時已經先有預先準備好了。

不過在測試時,同樣有問題,訊息也是

PHP Fatal error: Class 'SMTP' not found in ….class.phpmailer.php on line ….

查了一些資料,我猜測可能當時的 phpmailer 套件是可以用的,但我下載比較新的版本,裡面還有

PHPMailerAutoload.php

有人說這是比較好的載入點,要改成這個。

不過我也不知怎麼改,明明也有 class.smtp.php,裡面就有 'SMTP' 類別,不知為何沒有捉到?

於是我用暴力解決法,把 class.smtp.php 的內容全部複製到 class.phpmailer.php 裡面,我就不信它還找不到。

這一次果然就成功了,順利寄出測試信了。 :)

我想之前使用 SMTP Authentication Support 也是類似的問題,但已經不想回頭去測試了。

 

設定模組 phpmailer

 

我把 Drupal 設定的畫面也記錄下來。同時啟用翻譯,看起來比較親切。

這是最基本的主機設定。

 

 

這是要使用 gmail 的帳號和密碼。

 

 

設定寄件者

 

 

測試寄件

 

 

PHP 錯誤小插曲

 

這裡再記錄過程中遇到的二個小插曲。

 

is_a() 的錯誤

 

第一個是在測試 PHPMailer 時就發生了。錯誤訊息如下:

Strict Standards: is_a(): Deprecated. Please use the instanceof operator in ......

問題發生在這一行:

if (is_a($this->smtp, 'SMTP')) {

查到資料說,is_a 這個函數在 PHP 5.2.x 是不能用的,可以用 instanceof 來取代,也就是改成如下,注意這個用法中的 SMTP 沒有使用引號。

if ($this->smtp instanceof SMTP)) {

 

改過之後就可以使用了。

有人說 is_a() 有點危險,所以不再使用,但在 PHP 5.3.x 又可以用了。

 

goto() 的錯誤

 

我原本系統的 PHP 也是使用 5.2,後來想改成 5.3,但有一個新的錯誤訊息如下。

Parse error: syntax error, unexpected T_GOTO, expecting T_STRING in …

查詢後得知,在 PHP 5.3.x ,goto 這個名稱變成保留字,所以要把程式中用到使用 goto 名稱的自訂函數要改掉,這樣問題就解決了。

 

至此,PHP + SMTP 的技能終於解鎖成功。 ^_^

 

回應

發表新回應

這個欄位的內容會保密,不會公開顯示。
  • 自動將網址與電子郵件地址轉變為連結。
  • 自動斷行和分段。
  • 可使用的 HTML 標籤:<a> <address> <b> <blockquote> <br> <caption> <center> <cite> <code> <dd> <del> <div> <dl> <dt> <em> <h1> <h2> <h3> <h4> <h5> <h6> <hr> <i> <img> <ins> <li> <ol> <p> <pre> <span> <strike> <strong> <sub> <sup> <table> <tbody> <td> <th> <tr> <u> <ul>
    Allowed Style properties: background, background-attachment, background-color, background-image, background-position, background-repeat, border, border-bottom, border-bottom-color, border-bottom-style, border-bottom-width, border-collapse, border-color, border-left, border-left-color, border-left-style, border-left-width, border-right, border-right-color, border-right-style, border-right-width, border-spacing, border-style, border-top, border-top-color, border-top-style, border-top-width, border-width, bottom, caption-side, clip, color, direction, empty-cells, font, font-family, font-size, font-size-adjust, font-stretch, font-style, font-variant, font-weight, height, left, letter-spacing, line-height, list-style, list-style-image, list-style-position, list-style-type, margin, margin-bottom, margin-left, margin-right, margin-top, max-height, max-width, min-height, min-width, overflow, padding, padding-bottom, padding-left, padding-right, padding-top, right, table-layout, text-align, text-decoration, text-indent, text-transform, top, unicode-bidi, vertical-align, white-space, width, word-spacing, z-index

更多關於格式選項的資訊

CAPTCHA
驗證碼只有阿拉伯數字, 這是躲廣告用的, 麻煩你輸入了.
Image CAPTCHA
Enter the characters shown in the image.


story | about seo