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

wp_mail重复自定义标头丢失:如何无需修改原函数解决?

解决wp_mail()重复自定义标头被覆盖的问题

嘿,这个坑我之前踩过!确实,wp_mail()在处理自定义标头时,会把它们转换成关联数组来处理——这就导致如果多次传递相同名称的标头,后面的会直接覆盖前面的,最后只留下最后一个实例。不过完全不用修改核心的pluggable.php文件,咱们有几个灵活的解决方案:

方法1:直接用PHPMailer的addCustomHeader方法(最推荐)

WordPress的wp_mail底层是用PHPMailer实现的,我们可以通过phpmailer_init动作钩子,在邮件发送前直接操作PHPMailer实例,手动添加多个相同的标头,完全绕开wp_mail的关联数组限制。

举个实际的例子:

// 先定义一个全局变量用来临时存储要添加的标头(如果需要多次收集的话)
$pending_custom_headers = [];

// 自定义函数,用来收集要添加的标头
function add_multi_mail_header($header_name, $header_value) {
    global $pending_custom_headers;
    $pending_custom_headers[] = [$header_name, $header_value];
}

// 绑定phpmailer_init钩子,在邮件发送前批量添加标头
add_action('phpmailer_init', function($phpmailer) {
    global $pending_custom_headers;
    foreach ($pending_custom_headers as $header) {
        list($name, $value) = $header;
        // PHPMailer的addCustomHeader支持重复添加同名标头
        $phpmailer->addCustomHeader($name, $value);
    }
    // 清空临时变量,避免影响下一次邮件发送
    $pending_custom_headers = [];
});

// 现在你可以自由添加多个同名标头,然后发送邮件
add_multi_mail_header('X-Tracking-ID', 'user_123');
add_multi_mail_header('X-Tracking-ID', 'campaign_456');
wp_mail('user@example.com', '测试邮件', '这是一封带多个自定义标头的邮件');

这样发送出去的邮件里,就会同时存在两个X-Tracking-ID标头,不会被覆盖。

如果是单次发送邮件需要添加多个标头,也可以直接在调用wp_mail前临时绑定钩子:

// 定义添加标头的命名函数(方便后续移除)
function add_specific_headers($phpmailer) {
    $phpmailer->addCustomHeader('X-Custom-1', 'ValueA');
    $phpmailer->addCustomHeader('X-Custom-1', 'ValueB');
}

// 绑定钩子
add_action('phpmailer_init', 'add_specific_headers');
// 发送邮件
wp_mail('user@example.com', '单次测试', '内容');
// 移除钩子,避免影响其他邮件
remove_action('phpmailer_init', 'add_specific_headers');

方法2:通过wp_mail过滤器修改标头处理逻辑

如果你更习惯用wp_mail自带的$headers参数传递标头,可以通过wp_mail过滤器,把重复的标头从关联数组转成可重复的字符串格式:

add_filter('wp_mail', function($mail_atts) {
    $headers = $mail_atts['headers'];
    $processed = [];

    // 先把字符串格式的标头转成数组
    if (is_string($headers)) {
        $headers = explode("\n", str_replace("\r\n", "\n", $headers));
    }

    if (is_array($headers)) {
        foreach ($headers as $key => $val) {
            // 处理数字索引的标头行(比如"X-Header: 值")
            if (is_numeric($key)) {
                list($header_name, $header_value) = explode(':', $val, 2);
                $header_name = trim($header_name);
                $header_value = trim($header_value);
                $processed[$header_name][] = $header_value;
            } else {
                // 处理关联数组格式的标头
                $processed[$key][] = $val;
            }
        }

        // 把处理后的标头转成多个独立的标头行
        $new_headers = [];
        foreach ($processed as $name => $values) {
            foreach ($values as $v) {
                $new_headers[] = "$name: $v";
            }
        }

        $mail_atts['headers'] = $new_headers;
    }

    return $mail_atts;
});

使用的时候,要注意不要用关联数组传递重复标头(因为PHP本身会覆盖关联数组的重复键),而是用字符串格式的标头行:

$headers = [
    'X-Custom-Header: 第一个值',
    'X-Custom-Header: 第二个值',
];
wp_mail('user@example.com', '测试过滤后的标头', '内容', $headers);

这样过滤器会把这两个标头都保留下来,不会被wp_mail的关联数组逻辑覆盖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:35:31