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

PHP 郵件發送完整指南:JMail 組件、SMTP 類別與現代最佳實踐

     編輯:PHP 相關知識

郵件發送架構選擇

方案優點缺點適用場景
PHP mail()零依賴、內建功能弱、易進垃圾箱、無 SMTP 驗證簡單通知、開發測試
SMTP 類別 (自寫/PEAR)可控性高、支援驗證、SSL/TLS需自行處理 MIME、編碼、附件學習、輕量專案
PHPMailer / Symfony Mailer功能完整、安全、支援異步、模板需 Composer 安裝生產環境首選
API 服務送達率高、統計分析、免維護成本、資料外洩風險行銷郵件、交易郵件大量發送

經典 JMail (ASP/COM) 參考

原文提供的 JMail 為 ASP/COM 組件,PHP 環境無法直接使用。此處保留參考,實務請改用 PHP 原生方案。

自訂 SMTP 類別核心實作(教學用)

<?php
class SmtpMailer {
    private $host;
    private $port;
    private $username;
    private $password;
    private $timeout = 30;
    private $socket;

    public function __construct(string $host, int $port = 587, string $username = '', string $password = '') {
        $this->host = $host;
        $this->port = $port;
        $this->username = $username;
        $this->password = $password;
    }

    public function send(string $to, string $from, string $subject, string $body, bool $isHtml = true, array $options = []): bool {
        if (!$this->connect()) return false;
        if (!$this->auth()) { $this->close(); return false; }
        if (!$this->mailFrom($from)) { $this->close(); return false; }
        if (!$this->rcptTo($to)) { $this->close(); return false; }
        if (!$this->data($from, $to, $subject, $body, $isHtml)) { $this->close(); return false; }
        $this->close();
        return true;
    }

    private function connect(): bool {
        $this->socket = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
        if (!$this->socket) return false;
        return $this->readResponse(220);
    }

    private function auth(): bool {
        if (!$this->username) return true; // 無驗證模式
        fwrite($this->socket, "AUTH LOGIN\r\n");
        if (!$this->readResponse(334)) return false;
        fwrite($this->socket, base64_encode($this->username) . "\r\n");
        if (!$this->readResponse(334)) return false;
        fwrite($this->socket, base64_encode($this->password) . "\r\n");
        return $this->readResponse(235);
    }

    private function mailFrom(string $from): bool {
        fwrite($this->socket, "MAIL FROM:<$from>\r\n");
        return $this->readResponse(250);
    }

    private function rcptTo(string $to): bool {
        fwrite($this->socket, "RCPT TO:<$to>\r\n");
        return $this->readResponse(250);
    }

    private function data(string $from, string $to, string $subject, string $body, bool $isHtml): bool {
        fwrite($this->socket, "DATA\r\n");
        if (!$this->readResponse(354)) return false;

        $headers = [
            "From: $from",
            "To: $to",
            "Subject: $subject",
            "Date: " . date('r'),
            "MIME-Version: 1.0",
            "Content-Type: " . ($isHtml ? 'text/html' : 'text/plain') . "; charset=UTF-8",
            "X-Mailer: PHP/" . phpversion(),
        ];
        if (!empty($options['cc'])) $headers[] = "Cc: " . implode(', ', $options['cc']);
        if (!empty($options['bcc'])) $headers[] = "Bcc: " . implode(', ', $options['bcc']);

        $message = implode("\r\n", $headers) . "\r\n\r\n" . $body . "\r\n.\r\n";
        fwrite($this->socket, $message);
        return $this->readResponse(250);
    }

    private function readResponse(int $expectedCode): bool {
        $response = fgets($this->socket, 512);
        return (int)substr($response, 0, 3) === $expectedCode;
    }

    private function close(): void {
        if ($this->socket) {
            @fwrite($this->socket, "QUIT\r\n");
            @fclose($this->socket);
            $this->socket = null;
        }
    }
}

// 使用範例
$mailer = new SmtpMailer('smtp.gmail.com', 587, 'user@gmail.com', 'app_password');
$ok = $mailer->send(
    'recipient@example.com',
    'sender@example.com',
    '測試主旨',
    '

HTML 內容

支援中文

', true ); echo $ok ? '發送成功' : '發送失敗'; ?>

生產環境首選:PHPMailer

<?php
// composer require phpmailer/phpmailer
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require 'vendor/autoload.php';

$mail = new PHPMailer(true);
try {
    $mail->isSMTP();
    $mail->Host = 'smtp.gmail.com';
    $mail->SMTPAuth = true;
    $mail->Username = 'user@gmail.com';
    $mail->Password = 'app_password';
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // 或 ENCRYPTION_SMTPS (465)
    $mail->Port = 587;

    $mail->setFrom('sender@example.com', '寄件者名稱');
    $mail->addAddress('recipient@example.com', '收件者名稱');
    $mail->addReplyTo('reply@example.com');
    $mail->addCC('cc@example.com');
    $mail->addBCC('bcc@example.com');
    $mail->addAttachment('/path/to/file.pdf');

    $mail->isHTML(true);
    $mail->Subject = 'PHPMailer 測試';
    $mail->Body    = '

HTML 內容

支援中文、附件、內嵌圖片

'; $mail->AltBody = '純文字備用內容'; $mail->send(); echo '發送成功'; } catch (Exception $e) { echo "發送失敗:{$mail->ErrorInfo}"; } ?>

送達率優化關鍵清單

  • SPF/DKIM/DMARC:網域 DNS 正確設定三大認證,核心防偽造。
  • 專用 IP / 信譽:大量發送申請專用 IP,預熱信譽。
  • 退訂機制:List-Unsubscribe 標頭、一鍵退訂連結,法規遵循 (GDPR、CAN-SPAM)。
  • 內容品質:避免垃圾郵件關鍵字、圖文比例平衡、純文字版本完整。
  • 退信處理:監控 Bounce、Complaint,自動移除無效地址。
  • 加密傳輸:強制 STARTTLS 或 SMTPS (465),拒絕明文傳輸。

非同步發送架構

// 生產者:寫入佇列
$redis->lpush('mail_queue', json_encode([
    'to' => 'user@example.com',
    'subject' => '歡迎註冊',
    'template' => 'welcome',
    'data' => ['name' => 'John']
]));

// 消費者:背景工作處理
while (true) {
    $job = $redis->brpop('mail_queue', 5);
    if ($job) {
        $data = json_decode($job[1], true);
        // 渲染模板 -> PHPMailer 發送
    }
}
?>

總結

PHP 發送郵件已從早期 mail()、自寫 SMTP 類別演進至 PHPMailer/Symfony Mailer 等成熟函式庫。生產環境務必配合 SPF/DKIM/DMARC、非同步佇列、退信處理、內容優化,才能獲得高送達率與可維護的郵件系統。

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