不依賴 `mail()` 函數,直接透過 Socket 連線 SMTP 伺服器發送郵件,支援 SMTP 認證、HTML 郵件、多收件人/抄送/密件抄送、自定義標頭、錯誤記錄。
<?php
class SMTP {
// 公有屬性
public $smtp_port = 25;
public $time_out = 30;
public $host_name = 'localhost';
public $log_file = '';
public $relay_host = '';
public $debug = false;
public $auth = false;
public $user = '';
public $pass = '';
// 私有屬性
private $sock = false;
public function __construct($relay_host = '', $smtp_port = 25, $auth = false, $user = '', $pass = '') {
$this->smtp_port = $smtp_port;
$this->relay_host = $relay_host;
$this->auth = $auth;
$this->user = $user;
$this->pass = $pass;
}
// 主發送函數
public function sendmail($to, $from, $fromname, $subject = '', $body = '', $mailtype = 'TEXT', $cc = '', $bcc = '', $additional_headers = '') {
$mail_from = $this->get_address($this->strip_comment($from));
$body = preg_replace('/(^|(\r\n))(.)/', '\1.\3', $body); // 標準化換行
$header = "MIME-Version: 1.0\r\n";
if ($mailtype == 'HTML') {
$header .= "Content-Type: text/html; charset=utf-8\r\n";
}
$header .= "To: $to\r\n";
if ($cc) $header .= "Cc: $cc\r\n";
$header .= "From: $fromname <$from>\r\n";
$header .= "Subject: $subject\r\n";
$header .= $additional_headers;
$header .= "Date: " . date('r') . "\r\n";
$header .= "X-Mailer: PHP/" . phpversion() . "\r\n";
list($msec, $sec) = explode(' ', microtime());
$header .= "Message-ID: <" . date('YmdHis', $sec) . "." . ($msec * 1000000) . "." . $mail_from . ">\r\n";
// 整理所有收件人
$TO = array_merge(
explode(',', $this->strip_comment($to)),
$cc ? explode(',', $this->strip_comment($cc)) : [],
$bcc ? explode(',', $this->strip_comment($bcc)) : []
);
$sent = true;
foreach ($TO as $rcpt_to) {
$rcpt_to = $this->get_address($rcpt_to);
if (!$this->smtp_sockopen($rcpt_to)) {
$this->log_write("Error: Cannot connect to $rcpt_to");
$sent = false;
continue;
}
if ($this->smtp_send($this->host_name, $mail_from, $rcpt_to, $header, $body)) {
$this->log_write("E-mail sent to <$rcpt_to>");
} else {
$this->log_write("Error: Cannot send to <$rcpt_to>");
$sent = false;
}
fclose($this->sock);
$this->log_write("Disconnected from remote host");
}
return $sent;
}
// 以下為私有方法:smtp_send, smtp_sockopen, smtp_sockopen_relay, smtp_sockopen_mx,
// smtp_message, smtp_eom, smtp_ok, smtp_putcmd, smtp_error, log_write,
// strip_comment, get_address, smtp_debug
// ... (完整程式碼請見原文,此處省略以節省篇幅)
}
?>
<?php
require 'smtp.class.php';
$smtp = new SMTP('smtp.gmail.com', 587, true, 'your@gmail.com', 'your_password');
// 或使用 SSL: $smtp = new SMTP('ssl://smtp.gmail.com', 465, true, ...);
$to = 'recipient@example.com';
$from = 'your@gmail.com';
$fromname = '您的名稱';
$subject = '測試郵件';
$body = '<h1>HTML 郵件測試</h1><p>這是內容</p>';
$mailtype = 'HTML';
if ($smtp->sendmail($to, $from, $fromname, $subject, $body, $mailtype)) {
echo '發送成功';
} else {
echo '發送失敗,請查看 log';
}
?>
| 功能 | 支援 | 說明 | |
|---|---|---|---|
| SMTP 認證 | ✓ | AUTH LOGIN (Base64) | |
| SSL/TLS | ✓ | 透過 `ssl://` 或 `tls://` 主機前綴 | |
| HTML 郵件 | ✓ | 設定 `$mailtype='HTML'` | |
| 多收件人 | ✓ | 以逗號分隔 | |
| 抄送/密件抄送 | ✓ | `$cc`, `$bcc` 參數 | |
| 自定義標頭 | ✓ | `$additional_headers` | |
| MX 記錄查詢 | ✓ | 無 relay_host 時自動查詢 MX | |
| 除錯模式 | ✓ | `$debug = true` 輸出 SMTP 交互 | |
| 發送記錄 | ✓ | `$log_file` 指定記錄檔路徑 |
| 提供商 | 主機 | 埠號 | 加密 |
|---|---|---|---|
| Gmail | smtp.gmail.com | 587 / 465 | TLS / SSL |
| Outlook | smtp.office365.com | 587 | TLS |
| Yahoo | smtp.mail.yahoo.com | 465 / 587 | SSL / TLS |
| SendGrid | smtp.sendgrid.net | 587 / 2525 | TLS |
雖然此類別功能完整,但建議新專案使用成熟庫:
這些庫支援更完整的 MIME、附件、內嵌圖片、多種傳輸介面、非同步發送等進階功能。