Article

Advanced email in PHP

Page: 1 2 3 4 5 6 Next

File Attachments

File attachments work just like mixed email, except that a different content type is used for the message as a whole (multipart/mixed instead of multipart/alternative), and there's a new Content-Disposition header that tells the email client how to handle each part of the message.

Let's write a PHP script that processes a form submission that contains an email message to be sent, possibly with a file attachment, and sends it out. I'll talk you through it line by line so that by the end you'll not only have a useful snippet of PHP code, but also an understanding of how file attachments work. You can download the script (and the form for it) if you want to try it out for yourself.

First, we grab the submitted values and place them in PHP variables. Most people have their servers set up to create global variables for submitted values automatically, but as of PHP 4.1 this is no longer the default, so we do it by hand just in case. Since we want to accept file attachments, it's safe to assume that the form will be submitted with a POST request:

<?php    
// Read POST request params into global vars    
$to      = $_POST['to'];    
$from    = $_POST['from'];    
$subject = $_POST['subject'];    
$message = $_POST['message'];

File uploads in PHP 4.1 are placed in a special $_FILES array, so we fetch the values we need out of it:

// Obtain file upload vars    
$fileatt      = $_FILES['fileatt']['tmp_name'];    
$fileatt_type = $_FILES['fileatt']['type'];    
$fileatt_name = $_FILES['fileatt']['name'];

For the sake of brevity, we'll assume that the required parameters ($to and $from) now have valid values (email addresses) in them. Normally we would check their format with regular expressions.

Next, we use the $from value to begin building the extra headers for the email:

$headers = "From: $from";

Next we check the $fileatt variable, which may or may not contain the path and filename to an uploaded file attachment. We use PHP's is_uploaded_file function to find out:

if (is_uploaded_file($fileatt)) {    
 // Read the file to be attached ('rb' = read binary)    
 $file = fopen($fileatt,'rb');    
 $data = fread($file,filesize($fileatt));    
 fclose($file);

Having read in the data for the file attachment, we need to set up the message headers to send a multipart/mixed message:

 // Generate a boundary string    
 $semi_rand = md5(time());    
 $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";    
     
 // Add the headers for a file attachment    
 $headers .= "\nMIME-Version: 1.0\n" .    
             "Content-Type: multipart/mixed;\n" .    
             " boundary=\"{$mime_boundary}\"";

Now for the message body itself. This works just as we saw for the text part of a mixed message in the previous section:

 // Add a multipart boundary above the plain message    
 $message = "This is a multi-part message in MIME format.\n\n" .    
            "--{$mime_boundary}\n" .    
            "Content-Type: text/plain; charset=\"iso-8859-1\"\n" .    
            "Content-Transfer-Encoding: 7bit\n\n" .    
            $message . "\n\n";

Now, to allow for binary file types, we need to use Base64 encoding to convert the (possibly binary) file attachment data to a text-only format suitable for sending by email. All email programs in popular use support Base64 encoding of file attachments, so this is the best way to go. Fortunately, PHP provides a function for Base64 encoding:

 // Base64 encode the file data    
 $data = chunk_split(base64_encode($data));

We now have everything we need to write the portion of the message that contains the file attachment. Here's the code:

 // Add file attachment to the message    
 $message .= "--{$mime_boundary}\n" .    
             "Content-Type: {$fileatt_type};\n" .    
             " name=\"{$fileatt_name}\"\n" .    
             "Content-Disposition: attachment;\n" .    
             " filename=\"{$fileatt_name}\"\n" .    
             "Content-Transfer-Encoding: base64\n\n" .    
             $data . "\n\n" .    
             "--{$mime_boundary}--\n";    
}

That completes the modifications necessary to accommodate a file attachment. We can now send the message with a quick call to mail:

// Send the message    
$ok = @mail($to, $subject, $message, $headers);    
if ($ok) {    
 echo "<p>Mail sent! Yay PHP!</p>";    
} else {    
 echo "<p>Mail could not be sent. Sorry!</p>";    
}    
?>

And that's how we send emails with file attachments in PHP!

If you liked this article, share the love:
Print-Friendly Version Suggest an Article

Sponsored Links