Sending html mails with attachment using PHP mail

For sending a simple mail, PHP provides the mail function

mail("someone@example.com", "Email Subject", "A text message");

The mail function has the optional parameter $additional_header which can be used to set the From, Cc, Bcc fields. It can also be used to set the content-type to html for sending html mails

Sending html mails with PHP

$headers  = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

// Additional headers
$headers .= 'From: Abc ' . "\r\n";
$headers .= 'Cc: xyz@example.com' . "\r\n";
$headers .= 'Bcc: lmn@example.com' . "\r\n";

// Mail it
mail("someone@example.com", "Email Subject", "

HTML message

" $headers);

Sending html mails with attachment

However in many situations you may wish to send a file as an attachment with some html message. Say your website has an form with resume upload for Job application. When someone fills the form you may want to send the applicant a thank you email with his uploaded resume as attachment.

For sending mails with attachment we can use the same mail function of PHP with little modification in the headers and the message body.

Below is the function for sending mails with attachment using PHP mail function

function send_mail($mailer_arr){
	
	$mailer_arr = array_merge( array( 'to'=>'', 'from'=>'', 'subject'=>'', 'message'=>'', 'cc'=>'', 'bcc'=>'', 'file_name'=>'', 'file_path'=>'' ), $mailer_arr );

	$EmailTo = strip_tags($mailer_arr['to']);
	$EmailFrom = strip_tags($mailer_arr['from']);
	$EmailSubject = $mailer_arr['subject'];
	$EmailMessage = stripslashes($mailer_arr['message']);
	$EmailCc = strip_tags($mailer_arr['cc']);
	$EmailBcc = strip_tags($mailer_arr['bcc']);
	$filepath = $mailer_arr['file_path'];
	//if file_name is set explicitly use it else use the name of the uploaded file
	$filename = $mailer_arr['file_name'] ? $mailer_arr['file_name'] : end(explode("/",$filepath));
	
	// carriage return type (we use a PHP end of line constant)
	$eol = PHP_EOL;

	$headers = "";

	// main header
	if( !empty($EmailFrom) )
	$headers  .= "From: ".$EmailFrom.$eol;	
	
	if( !empty($EmailFrom) )
	$headers .= "Reply-To: ". $EmailFrom .$eol;

	if( !empty($EmailCc) )
	$headers .= "CC: ".$EmailCc.$eol;

	if( !empty($EmailBcc) )
	$headers .= "BCC: ".$EmailBcc.$eol;

	$headers .= "MIME-Version: 1.0".$eol; 

	/** in case file path is not set then send html mail with no attachment **/
	if( !isset( $mailer_arr['file_path'] ) || $mailer_arr['file_path'] == '' ){		
		 
		$headers .= "Content-type: text/html".$eol;
		if(mail($EmailTo, $EmailSubject, $EmailMessage, $headers))			
		return true;
                else 
                return false;
		
	}
	
	$attachment = chunk_split( base64_encode(file_get_contents($filepath)) );
  
	//a unique seperator
	$separator = md5(time());  

	$headers .= "Content-Type: multipart/mixed; boundary=\"".$separator."\"";
  
	// message
	$body = "";
	$body .= "--".$separator.$eol;
	$body .= "Content-Type: text/html; charset=\"iso-8859-1\"".$eol;
	$body .= "Content-Transfer-Encoding: 7bit".$eol.$eol;//optional defaults to 7bit
	$body .= $EmailMessage.$eol;
  
	// attachment
	$body .= "--".$separator.$eol;
	$body .= "Content-Type: application/octet-stream; name=\"".$filename."\"".$eol; 
	$body .= "Content-Transfer-Encoding: base64".$eol;
	$body .= "Content-Disposition: attachment".$eol.$eol;
	$body .= $attachment.$eol;
	$body .= "--".$separator."--";
  
	// send message
	if (mail($EmailTo, $EmailSubject, $body, $headers)) {
		return true;
	}
	else {
		return false;
	}
}

The above functions accepts an associative array as params. You can call this function as below

$mail_array = array(
				'to'		=>	'someone@example.com',
				'from'		=>	'info@perials.com',
				'subject'	=>	'Welcome',
				'message'	=>	'

Welcome Sanket

First nameSanket
First nameSanket
', 'file_path' => 'temp.jpg', 'file_name' => 'Awesome.jpg' ); send_mail($mail_array);

If you take a look at the send_mail() function you will notice that in the header we have declared the content type as multipart/mixed

$headers .= "Content-Type: multipart/mixed; boundary=\"".$separator."\"";

The above header indicates that the message body will contain multiple parts and each will be separated by the $separator which is a unique key. For our case we have generated it using md5( time() ).

Then in the first part we send the html message

	$body = "";
	$body .= "--".$separator.$eol;
	$body .= "Content-Type: text/html; charset=\"iso-8859-1\"".$eol;
	$body .= "Content-Transfer-Encoding: 7bit".$eol;//optional defaults to 7bit
	$body .= $EmailMessage.$eol;

Notice the use of ‘–‘ before $separator and $eol as CRLF. Here $eol is nothing but PHP_EOL which is analogous to \r\n.

After appending the html message we now the append the attachment

	$body .= "--".$separator.$eol;
	$body .= "Content-Type: application/octet-stream; name=\"".$filename."\"".$eol; 
	$body .= "Content-Transfer-Encoding: base64".$eol;
	$body .= "Content-Disposition: attachment".$eol.$eol;
	$body .= $attachment.$eol;
	$body .= "--".$separator."--";

The double slashes ‘–‘ appended to separator at the end marks the end of the message.

Join the discussion

  1. Avatar
    daniel alor says:

    Thanks for your help! I have not used PHP for many years! this is the solution for me!

  2. Avatar
    Sam says:

    Helped me a lot thank you !
    Is it possible to add multiple attachment files ?

  3. Avatar

    Awesome, helped me debug legacy code.

  4. Avatar
    Srinivas says:

    sir, my requirement is attachment image display in html content of the body please give me suggestion.

  5. Avatar
    devesh pandya says:

    Its help me so much .Thanks for tutorial.

  6. Avatar
    Arun says:

    i need send email with table layout and also attachment? Did you know that?can you suggest me?

Leave a Reply

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