11/21/2013

Build WordPress Email Wrapper (With Attachments)

WordPress default email sending function wp_mail is way too basic. It uses "Wordpress" as sender name and doesn't allow you send HTML and plain text mail at the same time. If you are writing a plugin that sends emails this is going to be a problem.

In this quick tutorial I will show you how plugins like BroadFast for Wordpress manage to overwrite the default sender and to send emails with plain text and HTML versions. You simply need a small wrapper function. See the full code first and I will explain it below:

  1. function send($sender$receiver$subject$message$ctype = 'text/html'$attachments = NULL) {  
  2.     $plain_text = strip_tags(str_replace("<br>""\n"$message));  
  3.       
  4.     // handle text-only and "both" mail types  
  5.     if($ctype=='text/plain'$message = $plain_text;  
  6.     else $message=wpautop($message);  
  7.               
  8.     if($ctype=='both') {  
  9.         // thanks to http://www.tek-tips.com/faqs.cfm?fid=2681                    
  10.         $semi_rand = md5(time());  
  11.         $mime_boundary = "==MULTIPART_BOUNDARY_$semi_rand";  
  12.         $mime_boundary_header = chr(34) . $mime_boundary . chr(34);  
  13.           
  14.         // construct the body  
  15.         $body = "This is a multi-part message in MIME format. 
  16.  
  17.         --$mime_boundary 
  18.         Content-Type: text/plain; charset=\"UTF-8\" 
  19.         Content-Transfer-Encoding: 8bit 
  20.          
  21.         $plain_text 
  22.          
  23.         --$mime_boundary 
  24.         Content-Type: text/html; charset=utf8 
  25.         Content-Transfer-Encoding: 8bit 
  26.          
  27.         $message 
  28.          
  29.         --$mime_boundary--";  
  30.           
  31.         $body = str_replace("\t""" ,$body);  
  32.           
  33.         // now replace the vars  
  34.         $message = $body;  
  35.         $ctype = "multipart/alternative;\n" .   
  36.    "     boundary=" . $mime_boundary_header;              
  37.     }  
  38.       
  39.     $headers=array();  
  40.     $headers[] = "Content-Type: $ctype";  
  41.     $headers[] = 'From: '.$sender;  
  42.     $headers[] = 'sendmail_from: '.$sender;  
  43.       
  44.     // prepare attachments if any     
  45.     if($attachments and is_array($attachments)) {  
  46.         $atts = array();  
  47.         foreach($attachments as $attachment$atts[] = $attachment->file_path;  
  48.         $attachments = $atts;  
  49.     }  
  50.        
  51.     $message = do_shortcode($message);        
  52.     $result = wp_mail($receiver$subject$message$headers$attachments);                 
  53.     return $result;  
  54. }  

Now, let's have a look at this code:

Line 1. The function definition: The function accepts sender's email address that can contain just email address or a string like My Name <myemail@dot.com>. This allows you to send emails with different name than "Wordpress" (how exactly this happens is explained later below. Then $receiver is the receiver email address and $subject and $message are obvious parameters.

The parameter $ctype is the email content type - it can be either "text/html", "text/plain" or "both". Using "both" will generate email with two alternative parts so the email client program can choose the best one. Note that "both" doesn't work together with attachments. This is currently unsolvable - so if you want to send attachments, choose text/html or text/plain.

Now, let's go on with the code.

Line 2. Create a plain text version of the message to be used when sending the email as plain text.

Lines 4 - 5 take care to further prepare the message depending on the selected content type.


We have more work to do when sending both HTML and plain text version. It starts after line 8. First we generate the mime boundary by preparing a pseudo random number. Then from line 15 we start constructing the body of the message. First add the intro text, then the boundary, and then the two headers:

Content-Type: text/plain; charset=\"UTF-8\"
Content-Transfer-Encoding: 8bit


before the plain text version (lines 17 - 21) and:

Content-Type: text/html; charset=utf8
Content-Transfer-Encoding: 8bit


Before the HTML version (lines 23 - 27). Then closing the mime boundary.

Please pay attention to all the formatting and new lines, they are very important.

Then we have to remove any tabulators which come from our code indentation so we do it on line 31.

Lines 34 - 36 replace the proper content type for the email header.

Then we need to construct the headers to pass to wp_mail() function in WordPress.

The headers "from" and "sendmail_from" (lines 41 and 42) are very important. They are the lines that ensure when you set "John <email@dot.com>" as email sender, the email will be sent from "John" and not from "WordPress".

The next lines simply add the attachments (assuming you have the object coming from database or so).

Process shortcodes. I prefer to do this (line 51) because this enables the email author to include shortcodes from other plugins in the email contents. Be careful with this if you are letting end users send emails.

Then line 52 calls wp_mail and the function returns the result. Simple, isn't it?