Email with Attachments PHP

Sending plain email with PHP is easy. The mail function handles all the messy protocol details behind the scenes. But if you want to send attachments, you will need to dig into an RFC, specifically RFC 1341. This RFC describes MIME, Multipurpose Internet Mail Extensions.

Sending a Tab-Delimited Excel File

There are several example implementations to be found on the Web. Check out David Sklar's networking section. html?section_id=10>. Most of these put functionality into a class and attempt to incorporate every aspect of the standard. Its contains code that sends email with multiple attachments using two simple functions. Use this example as a basis for learning the process, and expand its functionality if necessary

Sending Attachments

<?
/*
** Function: makeAttachment
** Input: ARRAY attachment
** Output: STRING
** Description: Returns headers and data for one
** attachment. It expects an array with elements
** type, name, and content. Attachments are naively
** base64 encoded, even when unnecessary.
*/
function makeAttachment($attachment) { //send content type$headers = "Content-Type: " . $attachment["type"]; if($attachment["name"] != "")
{
$headers .= "; name= "{$attachment["name"]}"";
}
$headers .= " ";$headers .= "Content-Transfer-Encoding:
base64 ";
$headers .= " ";$headers .=
chunk_split(base64_encode($attachment["content"]));$headers .= " ";
return($headers); } /* ** Function: mailAttachment ** Input: STRING to, STRING from, STRING subject, ARRAY attachment ** Output: none ** Description: Sends attachments via email. The attachment ** array is a 2D array. Each element is an associative array ** containing elements type, name and content. */ function mailAttachment($to, $from,$subject,
$attachment) { //add from header$headers = "From: $from "; //specify MIME version 1.0$headers .= "MIME-Version: 1.0 ";
//multiple parts require special treatment
if(count($attachment) > 1) { //multiple attachments require special handling$boundary = uniqid("COREPHP");
$headers .= "Content-Type: multipart/mixed";$headers .= "; boundary =
$boundary ";$headers .= "This is a MIME encoded
message. ";
$headers .= "--$boundary";
foreach($attachment as$a)
{
$headers .= " ";$headers .= makeAttachment($a);$headers .= "--$boundary"; }$headers .= "-- ";
}
else
{
$headers .= makeAttachment($attachment[0]);
}
//send message
mail($to,$subject, " ", $headers); } //add text explaining message$attach[] = array("content"=>"This is Listing",
"type"=>"text/plain");
//add script to list of attachments
$fp = fopen(__FILE__, "r");$attach[] = array("name"=>basename(__FILE__),
"content"=>fread($fp, filesize(__FILE__)), "type"=>"application/octet-stream"); fclose($fp);
//send mail to root
mailAttachment("root@localhost",
"httpd@localhost",
"Listing 18.6",
\$attach);
print("Mail sent!<BR> ");
?>

The mailAttachment function assembles the parts that make up a MIME message. These parts are sent in the fourth argument of the mail function, which is generally used for headers. In the case of a MIME message, this area is used for both headers and attachments. After sending the customary From headers, a MIME-Version header is sent. Unless there's onlyone attachment, a boundary string must be created. This is used to divide attachments from one another. We want to avoid using a boundary value that might appear in the message itself, so we use the uniqid function.

Each attachment is surrounded by the boundaries that always start with two dashes. The attachment itself is prepared by the makeAttachment function. Each attachment requires Content-Type and Content-Transfer-Encoding headers. The type of content depends on the attachment itself. If an image file is being sent, it might be image/jpg. These are the same codes discussed above with regard to the HTTP protocol. For the sake of simplicity, this function always encodes attachments using base64, which can turn binary files into 7-bit ASCII. This prevents them from being corrupted as they travel through the network. As you might imagine, text files don't require encoding, and complete implementations encode attachments based on content type.

It may be instructive to see the assembled message in full. Try sending yourself a message. On a UNIX operating system, you should be able to peek at the file itself inside /var/spool/mail before reading it, or perhaps inside ~/Mail/received afterward.