You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP管道邮件转发故障:含MIME头、原正文转为HTML附件求助

管道邮件转发PHP脚本问题修复

存在的问题

  • 转发后的邮件正文中包含原邮件的MIME头信息
  • 原邮件的正文文本被转为HTML附件,未显示在转发邮件的正文中

问题原因

  1. 直接将完整的原邮件内容(包含MIME头和编码后的正文/附件)拼接到转发邮件的正文里,导致MIME头被当成普通文本显示
  2. 未正确提取原邮件的正文内容,仅处理了附件部分,原正文未被单独提取并整合到转发邮件的正文区域

修复后的代码

#!/usr/bin/php -q
<?php
// 读取STDIN中的邮件内容
$fd = fopen("php://stdin", "r");
$email_content = stream_get_contents($fd);
fclose($fd);

// 分割邮件头和邮件体(头和体之间是\r\n\r\n)
list($email_headers, $email_body) = explode("\r\n\r\n", $email_content, 2);

// 提取原邮件主题
preg_match('/^Subject: (.+)$/m', $email_headers, $matches);
$subject = isset($matches[1]) ? $matches[1] : '转发邮件';

// 目标邮箱
$to_email = "example@example.com";

// 生成新的MIME边界(避免和原邮件边界冲突)
$new_boundary = '----ForwardBoundary_' . md5(time());

// 解析原邮件的正文内容
$original_body = '';
// 匹配text/plain类型的正文
if (preg_match('/Content-Type: text\/plain;.*?\r\n\r\n(.+?)\r\n--/sm', $email_body, $text_matches)) {
    // 检查编码并解码
    if (preg_match('/Content-Transfer-Encoding: (base64|quoted-printable)/i', $email_body, $encoding_match)) {
        switch(strtolower($encoding_match[1])) {
            case 'base64':
                $original_body = base64_decode($text_matches[1]);
                break;
            case 'quoted-printable':
                $original_body = quoted_printable_decode($text_matches[1]);
                break;
            default:
                $original_body = $text_matches[1];
        }
    } else {
        $original_body = $text_matches[1];
    }
}
// 如果没有纯文本正文,尝试提取HTML正文
elseif (preg_match('/Content-Type: text\/html;.*?\r\n\r\n(.+?)\r\n--/sm', $email_body, $html_matches)) {
    if (preg_match('/Content-Transfer-Encoding: (base64|quoted-printable)/i', $email_body, $encoding_match)) {
        switch(strtolower($encoding_match[1])) {
            case 'base64':
                $original_body = base64_decode($html_matches[1]);
                break;
            case 'quoted-printable':
                $original_body = quoted_printable_decode($html_matches[1]);
                break;
            default:
                $original_body = $html_matches[1];
        }
    } else {
        $original_body = $html_matches[1];
    }
}

// 构建转发邮件的正文内容
$forward_message = "此邮件由PHP脚本转发。\n\n原邮件内容:\n\n{$original_body}";

// 解析原邮件的附件
$attachments = [];
// 匹配附件部分
preg_match_all('/Content-Disposition: attachment; filename="(.+)"\s*Content-Type: (.+);\s*name=".+"\s*Content-Transfer-Encoding: (base64|quoted-printable|7bit|8bit|binary)\s*\r\n\r\n(.+?)\r\n--/sm', $email_body, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
    $attachment_data = $match[4];
    switch(strtolower($match[3])) {
        case 'base64':
            $attachment_data = base64_decode($attachment_data);
            break;
        case 'quoted-printable':
            $attachment_data = quoted_printable_decode($attachment_data);
            break;
    }
    $attachments[] = [
        'name' => $match[1],
        'type' => $match[2],
        'data' => $attachment_data
    ];
}

// 构建带附件的多部分邮件内容
$multipart_content = '';

// 添加转发邮件的正文部分
$multipart_content .= "--{$new_boundary}\r\n";
$multipart_content .= "Content-Type: text/plain; charset=UTF-8\r\n";
$multipart_content .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
$multipart_content .= "{$forward_message}\r\n";

// 添加附件部分
foreach ($attachments as $attachment) {
    $multipart_content .= "--{$new_boundary}\r\n";
    $multipart_content .= "Content-Type: {$attachment['type']}; name=\"{$attachment['name']}\"\r\n";
    $multipart_content .= "Content-Disposition: attachment; filename=\"{$attachment['name']}\"\r\n";
    $multipart_content .= "Content-Transfer-Encoding: base64\r\n\r\n";
    $multipart_content .= chunk_split(base64_encode($attachment['data']));
}

// 结束边界
$multipart_content .= "--{$new_boundary}--\r\n";

// 设置邮件头
$headers = "From: example@example.com\r\n";
$headers .= "Reply-To: example@example.com\r\n";
$headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"{$new_boundary}\"\r\n";

// 发送邮件
mail($to_email, $subject, $multipart_content, $headers, "-fexample@example.com");

exit;
?>

修复说明

  1. 分离邮件头和体:通过\r\n\r\n分割原邮件的头和体,避免将头信息混入正文
  2. 提取原邮件正文:分别匹配纯文本和HTML类型的正文内容,根据编码格式解码后整合到转发邮件的正文中
  3. 自定义MIME边界:生成新的边界字符串,避免和原邮件的边界冲突,防止邮件解析混乱
  4. 重构邮件内容结构:先添加转发提示和原正文,再添加附件,确保正文正常显示,附件也能正确识别

内容的提问来源于stack exchange,提问作者uk_nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 09:25:05