Sending Emails With Attachments Using PHP and SMTP

In a recent website I was working on the client wanted an email to be sent from a form that contained all the data from that form in the email, including a photo and a video. This meant that the photo and video would need to be attached to the email. After searching Google to find out how it would be best to go about doing it I came to the conclusion that the best solution would be to use SMTP. The reason that I am writing this tutorial is that while there are a few tutorials around the web about how to do this, not all of them a very clear and I ended up having to combine a couple of them in order to get a working piece of code.

Don’t get me wrong, this is a pretty simple thing to do but for those of you that don’t know and want to know how to do it, lets get started!

Firstly, I will go through each part of the code individual and explain what each line does. Now…lets get into the code!

The first thing we need to do is include the required files for using SMTP:

require_once "Mail.php";
require_once "Mail/mime.php";

The first file we have included (Mail.php) is basically the class that we will use to send the email using SMTP. This file is usually already available to you and does not usually need anything to be done by you. The second file that we include (Mail/mime.php) adds the ability to add attachments to your emails when sending them using SMTP. Without this file included you could still use SMTP to send emails, you just wouldn’t be able to attach any files to those emails. Just like the Mail.php file this file is usually already available to you and doesn’t usually need any action from yourself.

The next thing we need to do is define some variables that will hold the SMTP server details and then connect to the SMTP server:

$host = 'mail.example.com';
$username = 'username';
$password = 'password';

$smtp = Mail::factory('smtp', array('host'=>$host, 'auth'=>true, 'username'=>$username, 'password'=>$password));

The first three lines you should probably be able to work out that they just assign values to the $host, $username and $password variables that will be used to connect to the SMTP server. The following line of code is used to actually connect to the SMTP server, the first parameter define the name of the backend that is being used. There are three options to choose from and they are: ‘smtp’, ‘mail’ and ‘sendmail’ but for this we obviously will want to use ‘smtp’. The second parameter is basically a list of different options for the connection, the bare minimum you will need to use are the ones that I have used here (‘host’, ‘auth’, ‘username’ and ‘password’) although you may choose you use more options which can be found here.

Next we need to setup some quite standard headers for sending email:

$to = "address@domain.com";
$from = "address2@domain.com";
$subject = "Attachments Test";

$headers = array(
  'To' => $to,
  'From' => $from,
  'Subject' => $subject
);

As you will have probably worked out, the first three lines assign three different variables (the recipient email address, the sender email address and the subject text respectively). The next part of the code basically sets up an array of header details for the email and sets the ‘To’, ‘From’ and ‘Subject’ keys in the array to their respective variables ($to, $from and $subject).

After setting up the headers array we need to define some content for the email:

$text = "Plain Text Email Content";
$html = "HTML Email Content\n";

The first line defines a variable that contains the plain text version of the email, this is the version of the email that would be displayed to email clients that either do not support HTML emails or have HTML emails turned off. The second line obviously defines a variable that contains the HTML version of the email that would be displayed to email clients that have the ability to display HTML emails.

At the end of the HTML email content you may have noticed that I have put ‘\n’, what this does is creates a new line at the end of the emails content. If you attach an image to the email you will find that it will be displayed at the bottom of the email at the end of the last line of content, resulting in the emails layout being a bit messy. Putting ‘\n’ at the end of the content pushes the image down onto a new line to ensure that the layout of the email is retained.

Please note that you dont need to provide both plain text and HTML versions of the email, you can provide either just one of them or both of them depending on your requirements. Although if you choose to use HTML email it is recommended that you provide a plain text version as well for people with email clients that do not support HTML emails.

Now, we are going to add our first attachment to the email:

$attachment = "image.jpg";

All this does is points to where the file is located, if you are doing this straight from an uploaded file you could use $FILES[‘fileinputname’][‘tmpname’] to get the uploaded files temporary file location. Please note that it is always best to have some kind of validation for files that users upload for example you could check the files size and type as well as many other things.

Now we are going to actually build up the email that will be sent:

$mime = new Mail_mime();
$mime -> setTXTBody($text);
$mime -> setHTMLBody($html);
$mime -> addAttachment($attachment, 'image/jpeg');

The first line of this code sets up a new instance of the Mail_mime object which is basically allows you to use the functions that follow that line to setup the email that you want to send.

The next line sets up the plain text version of the email that email clients that don’t support HTML emails will see, this function has one required parameter and one optional parameter, the first parameter is required and is the content for the plain text email in this case $text. The second parameter (the optional one) is used to tell the function if the content you have specified is a file or not, if the specified content is a file then the required value of the second parameter is true (this parameter is false by default).

The next line does exactly the same job as the previous one apart from this time it sets up the content for the HTML version of the email. The parameters for this function are exactly the same the same as the previous line, it has one required parameter and one optional parameter. The required one (the first one) is used to specify the content for the HTML email, the optional parameter (the second one) just like the previous line is used to tell the function if the specified content is a file or not. This parameter is false by default.

Moving onto the next line, this line attaches the file you assigned to $attachment earlier to the email. The first parameter is the location of the file you wish to be attached to the email (in this case the location was stored in $attachment). The second parameter specifies the files type that you are attaching to the email. If you are using a file that has been uploaded by a user then you can get this information using something like $_FILES[‘fileinputname’][‘type’] but make sure you have validated any files that a user has uploaded before processing them and sending them in an email.

So now we have setup an email, we just need to push everything together to create the email that will be sent and then attach the headers that we also setup earlier:

$body = $mime -> get();
$headers = $mime -> headers($headers);

The first line takes everything we did in the last step and puts it all together to build an email, after we have built the email it needs the have the headers added to it so that it know information like where it needs to go, who sent it and what the subject of the email should be, that is what the next line does. Remember setting up the $headers array in the second step? Well this is where we actually use it!

Now that we have built the email and added the header information to it, all that is left to do is send it!

$mail = $smtp -> send($to, $headers, $body);

All this line of code does is send the email. The first parameter is the recipient(s) of the email, the second parameter is the $headers variable that was setup in the previous step and the third parameter just like the second is the $body variable that was setup in the previous step.

This next step is optional but probably recommended for most tasks, all it does it checks to see if the message was sent correctly or if it failed. If the message failed to send it outputs an error to try and help you correct the problem:

if(PEAR::isError($mail)) {
  echo $mail->getMessage();
} else {
  echo 'Message sent';
}
?>

This is just a basic if statement that basically checks to see if PEAR::isError($mail) returns true or false. If it returns false then that means there were no errors and the message has probably been successfully sent and the message ‘Message sent’ will be displayed, if it returns true on the other hand then that means there is an error present and the message was probably not sent. In this case the error will be outputted by the line of code that reads
echo $mail->getMessage();.

Ok so to recap the steps are as follows:

  1. Include the required files for SMTP with attachments to work correctly
  2. Connect to the SMTP server
  3. Define header information and body content
  4. Define attachments
  5. Setup email ready to be build
  6. Build email
  7. Send email
  8. Check for errors sending the email

Well there you have it! Now you know how to send emails with attachments using SMTP. I hope this has helped you out and if not or you have found any bugs/typing errors in my code please do get in touch and I will be sure to do my best to help 🙂

Thanks for reading folks!

Mike.