首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP mail() 函式完整配置指南(Windows SMTP、Linux sendmail、編碼處理、常見失敗排查)

     編輯:PHP 相關知識

php.ini 核心設定

指令Windows (SMTP)Linux (sendmail)說明
SMTPsmtp.example.com(無效)SMTP 伺服器主機名/IP
smtp_port25 / 587 / 465(無效)SMTP 埠號
sendmail_fromnoreply@example.com(無效)預設寄件人(Windows 必填)
sendmail_path(無效)/usr/sbin/sendmail -t -isendmail 執行檔路徑與參數

Windows 環境完整範例


; php.ini
[mail function]
SMTP = smtp.gmail.com
smtp_port = 587
sendmail_from = noreply@example.com
; 注意:Windows 內建 mail() 不支援 SMTP 驗證(AUTH LOGIN)、SSL/TLS
; 實務上 Windows 生產環境**強烈建議改用 PHPMailer/Symfony Mailer** 直連 SMTP

Linux 環境完整範例


; php.ini
[mail function]
sendmail_path = "/usr/sbin/sendmail -t -i -f noreply@example.com"
; -t 從訊息標頭解析收件人、-i 單獨處理點號行、-f 設定信封寄件人(影響 SPF/DKIM)

確保系統已安裝並啟用 Postfix/Exim/Sendmail:systemctl enable --now postfix。

發送郵件完整程式碼(含編碼、HTML、附件基礎)


function sendMail(
    string $to,
    string $subject,
    string $htmlBody,
    string $fromEmail = 'noreply@example.com',
    string $fromName  = '系統通知',
    array  $attachments = [] // ['path' => '/path/file.pdf', 'name' => 'file.pdf', 'mime' => 'application/pdf']
): bool {
    // 1. 標頭編碼:Subject、From 需 MIME encoded-word
    $subject = '=?UTF-8?B?' . base64_encode($subject) . '?=';
    $from    = '=?UTF-8?B?' . base64_encode($fromName) . '?= <' . $fromEmail . '>';

    // 2. 邊界字串(混合 HTML + 附件)
    $boundary = '==MULTIPART_BOUNDARY_' . md5(uniqid(microtime(true), true)) . '==';

    // 3. 標頭
    $headers = [
        "From: $from",
        "Reply-To: $fromEmail",
        "MIME-Version: 1.0",
        "Content-Type: multipart/mixed; boundary=\"$boundary\"",
        "X-Mailer: PHP/" . PHP_VERSION,
    ];

    // 4. 訊息主體
    $message = "--$boundary\r\n";
    $message .= "Content-Type: text/html; charset=UTF-8\r\n";
    $message .= "Content-Transfer-Encoding: base64\r\n\r\n";
    $message .= base64_encode($htmlBody) . "\r\n";

    // 5. 附件
    foreach ($attachments as $att) {
        if (!file_exists($att['path'])) continue;
        $content = base64_encode(file_get_contents($att['path']));
        $message .= "--$boundary\r\n";
        $message .= "Content-Type: " . ($att['mime'] ?? 'application/octet-stream') . '; name="' . $att['name'] . "\"\r\n";
        $message .= "Content-Transfer-Encoding: base64\r\n";
        $message .= 'Content-Disposition: attachment; filename="' . $att['name'] . "\"\r\n\r\n";
        $message .= chunk_split($content) . "\r\n";
    }
    $message .= "--$boundary--\r\n";

    // 6. 發送
    $result = @mail($to, $subject, $message, implode("\r\n", $headers));
    if (!$result) {
        error_log("mail() failed: to=$to, subject=$subject");
    }
    return $result;
}

為什麼生產環境不建議直接用 mail()?

  • 無 SMTP 驗證支援(Windows)、無 SSL/TLS、無重試機制、無異步佇列、易被判定垃圾郵件(缺乏 DKIM/SPF/DMARC 簽署支援)。
  • 替代方案(必選):
    • PHPMailer:功能完整、SMTP AUTH、SSL/TLS、DKIM 簽署、多語言、附件、內嵌圖片。
    • Symfony Mailer:現代元件化、DSN 設定、Transport 抽象、非同步發送、Twig 整合。
    • Swift Mailer(維護模式,建議遷移 Symfony Mailer)。

常見失敗排查表

現象可能原因排查步驟
mail() 回傳 true 但未收到信進入垃圾箱、對方伺服器靜默丟棄、SPF/DKIM 失敗檢查垃圾箱、查看郵件原始碼 Authentication-Results、設定 SPF/DKIM/DMARC
mail() 回傳 falsesendmail_path 錯誤、SMTP 連線失敗、埠號被防火牆阻擋CLI 測試 echo "test" | sendmail -t、telnet SMTP 埠、查看 mail.log
中文亂碼Subject/From 未 MIME 編碼、Body 未指定 charsetSubject 用 =?UTF-8?B?...?=、Body Content-Type: text/html; charset=UTF-8
附件損壞/無法開啟Base64 編碼未分行、邊界字串衝突、二進位讀取錯誤用 chunk_split(base64_encode($data))、唯一邊界、file_get_contents 讀取
大量發送極慢mail() 同步阻塞、每封建立新 SMTP 連線改用 PHPMailer + SMTP keep-alive、或佇列異步發送

結語

PHP mail() 適合簡單測試、低頻通知、無法安裝擴展的受限環境。**任何正式專案請直接使用 PHPMailer 或 Symfony Mailer**,配合專業郵件服務商(SendGrid、Mailgun、Amazon SES、Postmark、自建 Postfix + OpenDKIM),確保送達率、安全性、可觀測性與維護性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved