Sending Emails with PHP

Share this article

We know why you’re here… you want to write a script to send emails to your friends with funny return addresses. I’m here to tell you you’re better than that. There’s so much more you could be doing with your life! But, what other reasons could you possibly have? Well, maybe you have a cron job that you want to inform you of issues, have a user-initiated script you’d like to be notified when run, have a “Contact Us” form that forwards messages to you, want to flex your PHP muscles and write your own web-based mail client, need to set up a confirmation-by-email script – there are plenty of other reasons to send email with PHP. Plus, it’s so easy! In most cases your installation of PHP will be capable of sending emails. If you are using a shared host, or if you installed PHP using a package management system like apt-get, more than likely you’re all set. You’ll really only need to worry about extra configuration if you’re compiling PHP from source or if you’re running it on Windows. In either case, there are plenty of resources available online to help you out. Because that’s all beyond the scope of this article, I’ll assume you’re set. If not, Google will be your friend.

The Super-Basic Example

To send just a really simple email, the code is:
<?php
mail($address, $subject, $message);
Really, that’s all there is to sending basic plain-text emails (if it doesn’t work for you, again check with Google to see how to configure PHP correctly). Now let’s see how this would look in a script. Let’s say, for example, you want the script to email you every time a query fails:
<?php
$query = "SELECT left_arm AS arm_in, right_leg AS leg_in, front_head AS head_in FROM hokey_pokey WHERE its_about = 'all'";
try {
    $result = $db->query($query);
    // ...
}
catch (PDOException $e) {
    mail("bad_things@my_database.com", "Error in " . $_SERVER["SCRIPT_NAME"], $e->getMessage());
}
If there’s some unforeseen error that happens with the execution of your query then you’ll get an email informing you what script had an error and what that error was.

A Full-Blown HTML Mail Example

Now, let’s check out a full-blown multipart mail() example that has an HTML body with a plain text alternative and a file attachment:
<?php
$emailList = array("first_sucker@wazoo.com",
                   "nextSucker@hemail.com",
                   "othersucker32@clotmail.com",
                   "sckrfnl@mayohell.com");

$headers = "From: "Fluffy Mumsy" <sincere@dumsing.com>rn" .
   "Reply-To: weregonnaberich@shhhsecret.comrn" .
   "MIME-Version: 1.0rn" .
   "Content-Type: multipart/mixed; boundary="YaGottaKeepEmSeparated"rn";
$subject = "Please donate all your moneys to us";
$goodAttachment = chunk_split(base64_encode(file_get_contents( "novyrus.zip")));
$body = "--YaGottaKeepEmSeparatedrn" .
    "Content-Type: multipart/alternative; boundary="EachEmailAlternative"rn" .
     "--EachEmailAlternativern" .
      "Content-Type: text/plain; charset="iso-8859-1"rn" .
      "Content-Transfer-Encoding: 7bitrn" .
      "You have cheap text email you have no money. Please ignore.rn" .
     "--EachEmailAlternativern" .
      "Content-Type: text/html; charset="iso-8859-1"rn" .
       "<html>
 <head>
  <title>We need money to give you</title>
 </head>
 <body>
  <p>We found some <span style='color:green'>money</span>. And we need you give us money to give some you. We is good people. You can trust. Please install contact information attachment</p>
 </body>
</html>rn" .
    "--YaGottaKeepEmSeparatedrn" .
     "Content-Type: application/zip; name="novyrus.zip"rn" .
     "Content-Transfer-Encoding: base64rn" .
     "Content-Disposition: attachmentrn" .
     $goodAttachment . "rn" .
    "--YaGottaKeepEmSeparated--";

foreach ($emailList AS $addy) {
   $success = mail($addy, $subject, $body, $headers);
   if (!$success) {
       echo "Mail to " . $addy . " is fail.";
   }
}
Certain aspects of more typical email scripts had been simplified to make the general concept easier to grasp, though I will touch on those in this breakdown. First, the $emailList array is populated with some email addresses I’d like to share my message with. The array is iterated through at the end of the script and each address will be sent a copy of my email. Next, the $headers string is built with various mail headers. Each header in the string is separated with a CRLF (rn) per RFC 2822, the standard that defines the format of email messages. "From: "Fluffy Mumsy" <sincere@dumsing.com>rn" The From header specifies the email address the recipient will see the message as having come from. "Reply-To: weregonnaberich@shhhsecret.comrn" The Reply-To header is the email address to which an email reply should be sent. By making it different than the “From:” header, the chances of this email being identified as spam increases (though if this were the only thing that caused an email client to raise a red flag this message is spam then it would probably get through). "MIME-Version: 1.0rn" The MIME-Version header tells the server to expect Multipurpose Internet Mail Extensions
in the body, which allows you to have a more advanced email than simple text. "Content-Type: multipart/mixed; boundary="YaGottaKeepEmSeparated"rn" The “Content-Type” header actually does two things: it indicates that there will be multiple parts in the body of various kinds, and it specifies what string is used to divide each part. This boundary string needs cannot appear anywhere else in the email or the mail client will not be able to parse the message correctly. You could use “12” as your boundary for example, though chances are that it will show up elsewhere in the message. I chose “YaGottaKeepEmSeparated”. Most people assign a randomly generated hash to serve as the boundary, like $boundary = md5(time()), since the chance of collision is very low. The contents of novyrus.zip, which here happens to be located in the same directory as the script, is base64-encoded and broken into “chunks” for easier digestion by the mail client. The result is stored in $goodAttachment which will make an appearance later. Finally, the body of the email message is composed… "--YaGottaKeepEmSeparatedrn" This is the first instance of using the boundary defined earlier and says to the mail client, “hey, here’s the start of the first section of the email message.”, and it always starts with the double-dash in front of your chosen boundary string. "Content-Type: multipart/alternative; boundary="EachEmailAlternative"rn" Besides “multipart/mixed” given in the email’s headers, you can also use a Content-Type header with “multipart/alternative” within the body and with a different boundary specific to this breakdown to provide alternate formats for the message. "--EachEmailAlternativern" This is the first instance of the nested boundary and starts the first alternate version of the message. "Content-Type: text/plain; charset="iso-8859-1"rn" This Content-Type header tells the mail client this alternative is plain text. If the client isn’t capable of displaying more complex formats, such as HTML, then it will use this version of the message. "Content-Transfer-Encoding: 7bitrn" The Content-Transfer-Encoding header specifies the encoding scheme used in the message. For historical reasons, “7bit” is the default value and so this could be omitted. I included it so just so you’ll be aware of it. "You have cheap text email you have no money. Please ignore.rn" This is the text-only version of the message which people using non-HTML-capable readers will see. "--EachEmailAlternativern" The end of the first alternative has been reached, and you’re ready to start the next alternate version. "Content-Type: text/html; charset="iso-8859-1"rn" This Content-Type header informs the client this version is formatted as HTML, and the set of characters that is used. "<html> ... </html>rn" Notice that this version, besides the inclusion of HTML tags, has content that is considerably different than the plain text version. Some spam filters may view this as one more reason to block me message from getting to the inbox. "--YaGottaKeepEmSeparatedrn"
This is the multipart/mixed boundary, indicating that you’ve reached the end of the message body section with all its alternatives. "Content-Type: application/zip; name="novyrus.zip"rn" The Content-Type header signals the next part of the email is an attachment (the novyrus.zip file), and that it is ZIP file. "Content-Transfer-Encoding: base64rn" 7bit encoding restricts characters to seven bits and might not be able to faithfully represent all the necessary binary characters for the ZIP file, which was why the file was base64-encoded and chunked. The Content-Transfer-Encoding header here lets the client know how to decode the attachment file. "Content-Disposition: attachmentrn" The Content-Disposition header details how content should be presented; there are two possible values: attachment and inline. While it would hardly make sense to display a ZIP file inline element in a message, it comes in handy to embed images. $goodAttachment . "rn" The contents of the attached file is simply dumped into the mix. "--YaGottaKeepEmSeparated--" This is the final boundary declaring that nothing more shall follow by ending with one last set of double-dashes.

Summary

There you have it! You’ve seen how to send super-basic text email message, and full-fledge HTML emails with attachments. Simple emails are just a matter of calling the mail() function. For HTML messages, you need to break your email into segments using the MIME standards, divided by a boundary of your choosing. Then, you define what the content is, how it’s encoded, possibly the disposition, and then the content itself. Depending to whom you plan on sending emails, you will want to be conscientious about factors that may cause your message to be more likely flagged as spam, just in case you want to actually want to send something serious. Image via Photosani / Shutterstock

Frequently Asked Questions about Sending Emails with PHP

How can I send an email using PHP with an SMTP server?

To send an email using PHP with an SMTP server, you need to use the PHPMailer library. This library allows you to connect to your SMTP server and send emails using PHP. First, you need to download and include the PHPMailer library in your script. Then, you can create a new instance of PHPMailer, set the SMTP server details, and send the email. Here is a basic example:

require 'PHPMailerAutoload.php';

$mail = new PHPMailer;

$mail->isSMTP();
$mail->Host = 'smtp.example.com';
$mail->SMTPAuth = true;
$mail->Username = 'user@example.com';
$mail->Password = 'secret';
$mail->SMTPSecure = 'tls';

$mail->From = 'from@example.com';
$mail->addAddress('to@example.com');

$mail->Subject = 'Hello';
$mail->Body = 'Hello, this is a test email.';

if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message has been sent';
}

How can I send an HTML email using PHP?

To send an HTML email using PHP, you need to set the Content-type header to text/html. This tells the email client that the email contains HTML content. Here is an example:

$to = 'somebody@example.com';
$subject = 'My HTML email';
$message = '
<html>
<head>
<title>My HTML email</title>
</head>
<body>
<p>This is an HTML email!
</body>
</html>
';

$headers[] = 'MIME-Version: 1.0';
$headers[] = 'Content-type: text/html; charset=iso-8859-1';

mail($to, $subject, $message, implode("\r\n", $headers));

How can I send an email with an attachment using PHP?

To send an email with an attachment using PHP, you can use the PHPMailer library. This library provides a method called addAttachment() that you can use to attach files to your email. Here is an example:

require 'PHPMailerAutoload.php';

$mail = new PHPMailer;

$mail->isSMTP();
$mail->Host = 'smtp.example.com';
$mail->SMTPAuth = true;
$mail->Username = 'user@example.com';
$mail->Password = 'secret';
$mail->SMTPSecure = 'tls';

$mail->From = 'from@example.com';
$mail->addAddress('to@example.com');

$mail->addAttachment('/var/tmp/file.tar.gz');

$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';

if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message has been sent';
}

How can I handle errors when sending emails with PHP?

When sending emails with PHP, you can handle errors by checking the return value of the mail() function. If the function returns false, it means that the email could not be sent. Here is an example:

$to = 'somebody@example.com';
$subject = 'My subject';
$message = 'Hello, this is a test email.';

if(mail($to, $subject, $message)) {
echo 'Email sent successfully';
} else {
echo 'Email could not be sent';
}

How can I send multiple emails using PHP?

To send multiple emails using PHP, you can use a loop. You can create an array of email addresses and then use a foreach loop to send an email to each address. Here is an example:

$to = array('person1@example.com', 'person2@example.com', 'person3@example.com');
$subject = 'My subject';
$message = 'Hello, this is a test email.';

foreach($to as $email) {
if(mail($email, $subject, $message)) {
echo 'Email sent to ' . $email;
} else {
echo 'Email could not be sent to ' . $email;
}
}

How can I send an email with a custom header using PHP?

To send an email with a custom header using PHP, you can pass the headers as the fourth argument to the mail() function. Here is an example:

$to = 'somebody@example.com';
$subject = 'My subject';
$message = 'Hello, this is a test email.';
$headers = 'From: webmaster@example.com' . "\r\n" .
'Reply-To: webmaster@example.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();

mail($to, $subject, $message, $headers);

How can I send an email with CC and BCC using PHP?

To send an email with CC and BCC using PHP, you can add the CC and BCC headers to the email. Here is an example:

$to = 'somebody@example.com';
$subject = 'My subject';
$message = 'Hello, this is a test email.';
$headers = 'From: webmaster@example.com' . "\r\n" .
'CC: somebodyelse@example.com' . "\r\n" .
'BCC: hidden@example.com';

mail($to, $subject, $message, $headers);

How can I send an email with a reply-to address using PHP?

To send an email with a reply-to address using PHP, you can add the Reply-To header to the email. Here is an example:

$to = 'somebody@example.com';
$subject = 'My subject';
$message = 'Hello, this is a test email.';
$headers = 'From: webmaster@example.com' . "\r\n" .
'Reply-To: replyto@example.com';

mail($to, $subject, $message, $headers);

How can I send an email with a high priority using PHP?

To send an email with a high priority using PHP, you can add the X-Priority header to the email. Here is an example:

$to = 'somebody@example.com';
$subject = 'My subject';
$message = 'Hello, this is a test email.';
$headers = 'From: webmaster@example.com' . "\r\n" .
'X-Priority: 1 (Highest)';

mail($to, $subject, $message, $headers);

How can I send an email with a read receipt using PHP?

To send an email with a read receipt using PHP, you can add the Disposition-Notification-To header to the email. Here is an example:

$to = 'somebody@example.com';
$subject = 'My subject';
$message = 'Hello, this is a test email.';
$headers = 'From: webmaster@example.com' . "\r\n" .
'Disposition-Notification-To: webmaster@example.com';

mail($to, $subject, $message, $headers);

Jason PasnikowskiJason Pasnikowski
View Author

Whether it happened on its own, or if it only occurred because he finally acknowledged it, Jason Pasnikowski decided at the age of date('Y',now())-date('Y',strtotime('1974-07-29'))) to join the ranks of adulthood. This epiphany occurred while lounging about his partners' home in Newark, NY, and one of his missions pursuant to this realization is to share bits and pieces of his accumulated knowledge. Jason brings with him a skill set born of necessity; what he knows of PHP is because he needed it. Jason hopes this makes what he contributes more relevant to newcomers to PHP and others who are looking to learn just what they need to get the task done.

Beginner
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week