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

PHP MIME 編碼字串解碼函數:RFC 2047 標準實作

     編輯:PHP 相關知識

解析郵件主題與標頭中 =?charset?encoding?text?= 格式的完整函數

電子郵件標頭 (Subject、From 等) 常包含 MIME 編碼文字以支援非 ASCII 字元。本文提供完整的 PHP 解碼函數,支援 Q (Quoted-Printable) 與 B (Base64) 兩種編碼,並處理 Big5/GB2312 等中文編碼轉換。

完整解碼函數實作

<?php
function decode_mime_string(string $string): string {
    // 尋找 MIME 編碼標記開頭 =? 
    $pos = strpos($string, '=?');
    if ($pos === false) return $string; // 無編碼段落

    $preceding = substr($string, 0, $pos); // 前綴純文字
    $search = substr($string, $pos + 2);   // 剩餘部分

    // 解析 charset (最長 75 字元依 RFC 2047)
    $d1 = strpos($search, '?');
    if ($d1 === false) return $string;
    $charset = substr($search, 0, $d1);
    $search = substr($search, $d1 + 1);

    // 解析 encoding (Q 或 B)
    $d2 = strpos($search, '?');
    if ($d2 === false) return $string;
    $encoding = strtoupper(substr($search, 0, $d2));
    $search = substr($search, $d2 + 1);

    // 解析編碼文字 (以 ?= 結尾)
    $end = strpos($search, '?=');
    if ($end === false) return $string;
    $encoded_text = substr($search, 0, $end);
    $rest = substr($string, $pos + 2 + strlen($charset) + 1 + strlen($encoding) + 1 + $end + 2);

    // 解碼處理
    switch ($encoding) {
        case 'Q': // Quoted-Printable
            $encoded_text = str_replace('_', ' ', $encoded_text); // _ 代表空格
            $encoded_text = str_replace('=', '%', $encoded_text); // =XX -> %XX
            $decoded = urldecode($encoded_text);
            break;

        case 'B': // Base64
            $decoded = base64_decode($encoded_text);
            break;

        default:
            // 未知編碼保持原樣
            return $preceding . '=?' . $charset . '?' . $encoding . '?' . $encoded_text . '?=' . decode_mime_string($rest);
    }

    // 中文編碼轉換 (舊系統相容)
    if (strtolower($charset) === 'big5' || strtolower($charset) === 'gb2312') {
        // PHP 7.3+ 使用 mb_convert_encoding 替代已移除的 convert_cyr_string
        if (function_exists('mb_convert_encoding')) {
            $decoded = mb_convert_encoding($decoded, 'UTF-8', strtoupper($charset));
        }
    }

    // 遞歸處理剩餘部分 (一個標頭可能包含多個編碼段落)
    return $preceding . $decoded . decode_mime_string($rest);
}

// 使用範例
$subject = '=?UTF-8?B?5bCP56uL5LqO?= =?UTF-8?Q?=E6=B5=8B=E8=AF=95?=';
echo decode_mime_string($subject); // 輸出: 測試 測試
?>

RFC 2047 編碼格式規格

Encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
charset      = 註冊字集名稱 (UTF-8, Big5, GB2312, ISO-8859-1...)
encoding     = "Q" / "B" (不分大小寫)
encoded-text = 編碼後文字 (Q: =XX 格式, B: Base64)
最大長度     = 75 字元 (含 =? ?= 標記)

編碼模式差異對比

特性Q 編碼 (Quoted-Printable)B 編碼 (Base64)
適用場景以 ASCII 為主、少量非 ASCII 字元大量非 ASCII 字元 (中文、日文等)
空格表示底線 _Base64 標準編碼
特殊字元=XX (十六進位)Base64 字元集 (A-Z,a-z,0-9,+,/)
長度膨脹~1-3 倍~1.33 倍
可讀性部分可讀完全不可讀

現代 PHP 內建替代方案

PHP 5.3+ 提供 iconv_mime_decode() 與 mb_decode_mimeheader() 內建函數,強烈建議優先使用:

<?php
// 完整標頭行解碼
$header = "Subject: =?UTF-8?B?5bCP56uL?= =?UTF-8?Q?=E6=B5=8B=E8=AF=95?=";
echo iconv_mime_decode($header, 0, 'UTF-8');
// 輸出: Subject: 測試 測試

// 僅解碼 MIME 編碼字串
$encoded = '=?UTF-8?B?5bCP56uL?=';
echo mb_decode_mimeheader($encoded); // 輸出: 測試
?>

優勢**:標準庫實作、自動處理多段落、支援所有 IANA 字集、效能優化、無維護負擔。

郵件解析完整流程建議

<?php
// 使用成熟庫而非手工解析
require 'vendor/autoload.php';
use MimeMailParser\Parser;

$parser = new Parser();
$parser->setText($rawEmail);

$subject = $parser->getHeader('subject'); // 自動解碼
$from = $parser->getHeader('from');
$bodyText = $parser->getMessageBody('text');
$bodyHtml = $parser->getMessageBody('html');
$attachments = $parser->getAttachments();
?>
  • 推薦庫:php-mime-mail-parser/php-mime-mail-parser (Composer 安裝)
  • 支援 RFC 822/2822/5322 完整郵件格式
  • 自動處理多部分 (multipart/alternative, multipart/mixed)
  • 附件串流處理、大郵件記憶體優化
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved