Website Magazine

HowTo: Sending Attachments with PHP Mail

Writen By Tyler Ingram on Aug 22, 2007

Recently I have been looking to automate a few of the processes I do manually here at work, mainly when reports are created I wanted a way to drop them into a CSV (comma separated values) file and have them emailed to their respective locations.

The basic way to send an email with PHP is utilizing the mail() function like so:

[code]
<?php

if (mail($to, $subject, $message)) {

  echo "Mail Sent Successfully";

} else {

  echo "Error: Mail could not be sent";

}
?>

[/code]

Now that seems fairly basic right? What if you want to get a little more advanced by added multiple people or even attachments in your email? Well you need to use the optional, additional headers that the mail() function can accept. This also allows you to send plain text, html based emails, or even both. The following is how to set up an email in PHP for a single file attachment.

First off we need to create a boundary. The boundary is a separator that tells the email program that the message should be handled differently for a particular section: text, html, inline image or an attachment.

Using MD5 for its hash with the date as a seed we can generate a somewhat random string of characters for use in the boundary. The boundary needs to be something that will not have a chance of showing up in any part of the email message.

[code]
<?php

$semi_rand = md5(date('r'));

$mime_boundary = "x{$semi_rand}x";

?>
[/code]

Now we set up the email’s headers first by specifying the MIME version and then telling the client that it is a mixed message so it should handle it differently. What is MIME? Multipurpose Internet Mail Extensions – allows for more than just plain text emails.

[code]
<?php

$headers = "MIME-Version: 1.0\\r\\n ";

$headers .= "Content-Type: multipart/mixed; boundary=\"{$mime_boundary}\"\\r\\n";

$headers .= "To: Me <me@me.com>\\r\\n";

$headers .= "From: You <you@you.com>\\r\\n";

?>
[/code]

So you want to add a message body to this email prior to attaching the file right? This is the easiest way to do it.

[code]
<?php
$BODY = "–{$mime_boundary}\\r\\n".

        "Content-Type: text/plain; charset=\"iso-8859-1\"\\n".

        "Content-Transfer-Encoding: 7bit\\r\\n". 

        "You can put whatever you want here as long as it is plain text\\r\\n";
?>
[/code]

Notice how there are 2 dashes before the $mime_boundary, this is needed so that the client knows the string of characters after it is a boundary and parse it correctly.

Now it is time to read in the file you wish to attach to the email.

[code]
<?php

$FILE = fopen('path/to/file.txt', 'rb');

$FILETYPE  = mime_content_type('path/to/file.txt');

$DATA = fread($FILE, filesize('path/to/file.txt');

fclose($FILE);
?>

[/code]

The file is opened and the contents are read into the $DATA variable for later usage. Next we need to encode the data into a binary format that can go along with the email.

[code]
<?php

$DATA = chunk_split(base64_encode($DATA));

?>
[/code]

Now we attach the file to the body of the email

[code]
<?php

$BODY .= "–{$mime_boundary}\\r\\n".

       "Content-Transfer-Encoding: base64\\r\\n".

       "Content-Disposition: attachment; filename=\"MyFileName\"\\r\\n".

       "{$DATA}\\r\\n".

       "–{$mime_boundary}–\\r\\n";

?>
[/code]

So far so good? We tell the email client that the next set of data has been encoded in base64 and that it is to be an attachment by the filename we specified. Then we close the email message with the boundary with 2 dashes at the end as well.

Then we just send the email

[code]
<?php

if (!mail('toMyFriend@someplace.com', 'Your File', $BODY, $HEADERS)) {

    echo "Error in sending email";

} else {

   echo "Mail was sent successfully!";

}

?>
[/code]

And there we have it, a somewhat easy and hopefully understandable way of sending an email with some text and include an attachment. The above code can also be slightly modified for adding multiple attachments; you would just need to add in a loop to do so.

One thing I noticed while I was doing this was that when you are creating your headers you MUST make sure you do not leave ANY whitespace between the right margin and the text. If the headers do have whitespace before them, the email client will not read them properly and the email will be send all inline. Meaning that you will see the base64 encoding of the file attachment in the body of the email message!

I hope this has been helpful for those who are curious about how to get PHP’s mail function to send file attachments.

Posted in: Uncategorized | 1,159 views

 3 Comments

  • Thanks Tyler.
    This would be a great way for my comment script to send the entire file containing new entries. Rather than me having to download it using FTP after I recieve the comment notification email.

    Now I just need some time to incorporate it into my script which should happen around MArch. LOL!

    Brennan the Vyper

  • Are you saying that with comments you want them emailed to you so you know when someone has made a comment? If so why not just create an RSS feed and subscribe to that? :)

  • No, no I get an email already with the comments from users. I just want the comment file sent to my desktop so I can update the backup files with out having to download use the FTP to download the new files.

    Brennan

What do you think? Join the discussion...






How do I change my avatar?

Go to gravatar.com and upload your preferred avatar.