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

PHP 郵件類別:HTML 郵件、附件、內嵌圖片完整實作 (html_mime_mail)

     編輯:PHP 相關知識

多重替代內容郵件:text/plain + text/html + 內嵌圖片 + 附件

標準郵件格式 multipart/mixed 包含 multipart/alternative (純文字/HTML 版本) 與 multipart/related (HTML 內嵌圖片) 及附件。html_mime_mail 類別封裝此複雜結構。

類別核心結構

<?php
class html_mime_mail {
    var $headers = [];
    var $body = '';
    var $multipart = '';
    var $mime = '';
    var $html = '';
    var $html_text = '';
    var $html_images = []; // ['name'=>'logo.png', 'cid'=>'...', 'path'=>'/path/logo.png']
    var $cids = [];
    var $do_html = false;
    var $parts = []; // 附件

    function __construct($headers = '') {
        $this->headers = $headers;
    }

    // 新增 HTML 版本與純文字備選
    function add_html($html, $text) {
        $this->do_html = 1;
        $this->html = $html;
        $this->html_text = $text;
        // 將 HTML 中的圖片 src 替換為 cid:
        if (is_array($this->html_images) && count($this->html_images) > 0) {
            foreach ($this->html_images as $img) {
                $this->html = str_replace($img['name'], 'cid:'.$img['cid'], $this->html);
            }
        }
    }

    // 新增內嵌圖片
    function add_html_image($path, $name, $cid = '') {
        $cid = $cid ?: md5(uniqid(time()));
        $this->html_images[] = ['path'=>$path, 'name'=>$name, 'cid'=>$cid];
        $this->cids[$name] = $cid;
    }

    // 新增附件
    function add_attachment($path, $name, $ctype = 'application/octet-stream', $disposition = 'attachment') {
        $this->parts[] = ['path'=>$path, 'name'=>$name, 'ctype'=>$ctype, 'disposition'=>$disposition];
    }

    // 建構完整郵件本體
    function build_message() {
        $boundary = '=_'.md5(uniqid(time()));
        $this->mime = "This is a MIME encoded message.\n";
        $this->mime .= "--$boundary\n";

        if ($this->do_html) {
            $this->build_html($boundary);
        } else {
            $this->mime .= "Content-Type: text/plain; charset=utf-8\n";
            $this->mime .= "Content-Transfer-Encoding: 7bit\n\n";
            $this->mime .= $this->body . "\n";
        }

        // 附件
        foreach ($this->parts as $part) {
            $this->mime .= "--$boundary\n";
            $this->mime .= "Content-Type: {$part['ctype']}; name=\"{$part['name']}\"\n";
            $this->mime .= "Content-Transfer-Encoding: base64\n";
            $this->mime .= "Content-Disposition: {$part['disposition']}; filename=\"{$part['name']}\"\n\n";
            $this->mime .= chunk_split(base64_encode(file_get_contents($part['path']))) . "\n";
        }
        $this->mime .= "--$boundary--\n";

        // 標頭加入 MIME 版本與邊界
        $this->headers[] = "MIME-Version: 1.0";
        $this->headers[] = "Content-Type: multipart/mixed; boundary=\"$boundary\"";
    }

    // 建構 HTML 部分 (alternative + related)
    function build_html($outerBoundary) {
        $altBoundary = '=_'.md5(uniqid(time()));
        $relBoundary = '=_'.md5(uniqid(time()));

        // outer -> alternative
        $this->mime .= "Content-Type: multipart/alternative; boundary=\"$altBoundary\"\n\n";

        // alternative -> text/plain
        $this->mime .= "--$altBoundary\n";
        $this->mime .= "Content-Type: text/plain; charset=utf-8\n";
        $this->mime .= "Content-Transfer-Encoding: 7bit\n\n";
        $this->mime .= $this->html_text . "\n";

        // alternative -> related (html + images)
        $this->mime .= "--$altBoundary\n";
        $this->mime .= "Content-Type: multipart/related; boundary=\"$relBoundary\"\n\n";

        // related -> text/html
        $this->mime .= "--$relBoundary\n";
        $this->mime .= "Content-Type: text/html; charset=utf-8\n";
        $this->mime .= "Content-Transfer-Encoding: 7bit\n\n";
        $this->mime .= $this->html . "\n";

        // related -> 內嵌圖片
        foreach ($this->html_images as $img) {
            $this->mime .= "--$relBoundary\n";
            $this->mime .= "Content-Type: " . $this->get_mime_type($img['name']) . "\n";
            $this->mime .= "Content-Transfer-Encoding: base64\n";
            $this->mime .= "Content-ID: <{$img['cid']}>\n";
            $this->mime .= "Content-Disposition: inline; filename=\"{$img['name']}\"\n\n";
            $this->mime .= chunk_split(base64_encode(file_get_contents($img['path']))) . "\n";
        }
        $this->mime .= "--$relBoundary--\n";
        $this->mime .= "--$altBoundary--\n";
    }

    function get_mime_type($filename) {
        $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
        $types = ['png'=>'image/png','jpg'=>'image/jpeg','jpeg'=>'image/jpeg','gif'=>'image/gif','pdf'=>'application/pdf'];
        return $types[$ext] ?? 'application/octet-stream';
    }

    // 發送
    function send($to, $subject, $from) {
        $this->build_message();
        $headers = implode("\r\n", $this->headers);
        return mail($to, $subject, $this->mime, $headers, "-f$from");
    }
}
?>

使用範例

<?php
require 'html_mime_mail.php';

$mail = new html_mime_mail();
$mail->add_html(
    '<h1>歡迎</h1><p>這是 <img src="logo.png"> 內嵌圖片</p>',
    '歡迎\n這是純文字備選版本'
);
$mail->add_html_image('/var/www/images/logo.png', 'logo.png');
$mail->add_attachment('/var/www/files/report.pdf', 'report.pdf', 'application/pdf');

$sent = $mail->send('user@example.com', '測試 HTML 郵件', 'system@example.com');
echo $sent ? '發送成功' : '發送失敗';
?>

現代替代方案:PHPMailer / Symfony Mailer

特性html_mime_mailPHPMailerSymfony Mailer
SMTP 驗證不支援 (僅 mail())完整支援 (SSL/TLS/STARTTLS)完整支援
多重收件人/CC/BCC手動處理內建內建
DKIM 簽名無支援支援
異步佇列無需自行實作整合 Messenger
模板引擎無無 (可整合 Twig/Blade)原生 Twig 整合
維護狀態停止更新活躍活躍

遷移建議

<?php
// PHPMailer 範例
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;

$mail = new PHPMailer(true);
try {
    $mail->isSMTP();
    $mail->Host = 'smtp.example.com';
    $mail->SMTPAuth = true;
    $mail->Username = 'user';
    $mail->Password = 'pass';
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
    $mail->Port = 587;

    $mail->setFrom('system@example.com', '系統');
    $mail->addAddress('user@example.com');
    $mail->Subject = '測試';
    $mail->isHTML(true);
    $mail->Body = '<h1>HTML 內容</h1>';
    $mail->AltBody = '純文字備選';
    $mail->addEmbeddedImage('/path/logo.png', 'logo_cid');
    $mail->addAttachment('/path/report.pdf');

    $mail->send();
    echo '發送成功';
} catch (Exception $e) {
    echo "發送失敗: {$mail->ErrorInfo}";
}
?>

html_mime_mail 展示了 MIME 多重替代結構的手工構建邏輯,理解其原理有助於除錯現代郵件庫的發送問題。生產環境請直接使用 PHPMailer 或 Symfony Mailer。

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