This one should be easy, but I can't figure it out. I want to send an email that is HTML formatted, but also has an attachment. The attachment is being sent correctly, but the message is delivered as plaintext, like this:

<p>Some text.</p>
<p>Best wishes,</p>

If it was an email without attachment, I would force it to send html by changing the header as described here. But now I need the content type to be multipart / mixed (right?). So my question is: how do I convince wp_mail() to send my messages as html, and include the attachment?

  • 3
    what is the result when you do set the content type to text/html via the provided filter? developer.wordpress.org/reference/hooks/wp_mail_content_type
    – majick
    May 23, 2016 at 12:41
  • You've will upon a bug of sort that is yet to be fixed officially on core. There is luckily a patch that you can add and basically you are about to step into a serious headache (huvudvärk) but luckily I've decreased the pain for you in my explanation on how multipart messages works with wp_mail() in my question: wordpress.stackexchange.com/questions/191923/… -- Best of luck!
    – Christine Cooper
    May 23, 2016 at 14:11
  • @majick : it is a multipart / mixed message. It can't have content type 'text/html'. May 23, 2016 at 15:32
  • @ChristineCooper : yeah, I read that thread, was just hoping that there is a better way to solve this by now. Urgh. :( I think I will use plaintext for content for now. May 23, 2016 at 15:32
  • that bug should not affect you being able to do what you are asking though, see answer (and one added to the other thread identifying the cause.)
    – majick
    May 25, 2016 at 7:22

3 Answers 3


Reference link click here.

Using below code you can send the mail with html format.

$to = '[email protected]';
$subject = 'The subject';
$body = 'The email body content';
$headers = array('Content-Type: text/html; charset=UTF-8');

wp_mail( $to, $subject, $body, $headers );

// For attachment 

$attachments = array( WP_CONTENT_DIR . '/uploads/file_to_attach.zip' );
$headers = 'From: My Name <[email protected]>' . "\r\n";

wp_mail( '[email protected]', 'subject', 'message', $headers, $attachments );
  • 3
    If you read carefully, you will see that this is not an answer to my question. May 23, 2016 at 15:30

I believe the answer in your particular case does not involve the bug that is mentioned in the linked thread. There is no need to set custom headers to achieve what you state you want to do.

Instead you simply set the alternative body as text using $phpmailer->AltBody. This automatically sets the to content type multipart/alternative (not multipart/mixed) and you allow the phpmailer class to take care of the rest without needing to set custom headers manually.

function wp_mail_set_text_body($phpmailer) {
     $phpmailer->AltBody = strip_tags($phpmailer->Body);

$to = '[email protected]';
$headers = array();
$attachments = array(dirname(__FILE__).'/test.txt');

If you add attachments, the overall content type will automatically become multipart/mixed with multipart/alternative inside of that wchi contains text/plain and text/html parts, then followed by the attachments.

You can also add multipart/related (inline) attachments such as images by passing them to wp_mail via $attachements (with the 5th parameter as 'inline') - or even declaring them within the HTML body itself. These will not be accessible to the text version as far as I know.


as stated in the link you posted:

The default content type is ‘text/plain’ which does not allow using HTML. However, you can set the content type of the email by using the 'wp_mail_content_type’ filter.

Adding this to functions.php, as stated in wp_mail_content_type:

add_filter( 'wp_mail_content_type', 'set_content_type' );
function set_content_type( $content_type ) {
    return 'text/html';

Should do the trick.

  • Not what I was asking. May 23, 2016 at 15:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.