I want to add an additional header to outgoing emails on my sites, so I can easily determine which site sent a given email. (I put a standard functionality plugin on all of my sites, so this is easy enough to do, and configuring my email client to filter and otherwise act on this header would be an amazing time-saver.)

I thought this would be a simple matter of plugging into the wp_mail function, but evidently it isn’t.

First, I tried this:

add_filter('wp_mail', 'ws_add_site_header');
function ws_add_site_header() {
    return array('headers' => 'X-WU-Site: ' . parse_url(get_site_url(), PHP_URL_HOST));
}

Here, my array took precedence over anything else that modified the mail settings (say, Gravity Forms), so HTML emails started showing up as bare HTML and not nicely-formatted. Makes sense, since the Content-type: header that GF added was scrubbed. But my header was added to the email. Since others also depend on receiving pretty emails (all my sites’ content developers and end-users, among others I’m sure), that isn’t acceptable.

One of my colleagues then suggested routing my stuff through wp_parse_args(), thus:

add_filter('wp_mail', 'ws_add_site_header');
function ws_add_site_header($args) {
    $new_header = array('headers' => 'X-WU-Site: ' . parse_url(get_site_url(), PHP_URL_HOST));
    return wp_parse_args($args, $new_header);
}

With that, it’s as if my function doesn’t exist — my header isn’t added, but neither are others’ headers and mail settings stripped.

What’s the correct way to add a header to an outgoing email, without scrambling up any other filters that might exist?

3 s
3

Thanks to the above, I’ve realized my central mistake — I didn’t quite realize that the arguments being passed in were a multi-dimensional array.

For now, I’ve re-implemented the function thus:

function ws_add_site_header($email) {
    $email['headers'][] = 'X-WU-Site: ' . parse_url(get_site_url(), PHP_URL_HOST) ;
    return $email;               
}

My reading of the wp_mail() source (see: https://core.trac.wordpress.org/browser/tags/4.4.2/src/wp-includes/pluggable.php#L235) leads me to believe that the headers component can be an array, or a big string, or possibly some horrific mish-mash of the two, but that using an array is probably the safer/more correct option.

I do like the various phpmailer answers, but it just seems a bit cleaner to try to do things using WordPress’ built-ins.

Leave a Reply

Your email address will not be published. Required fields are marked *