How to send emails from your website in PHP using PHPMailer
  John Mwaniki /   19 Aug 2021

How to send emails from your website in PHP using PHPMailer

As a web developer, you will most likely at some point need to send out emails from your website or web application.

Below is a list of such very common scenarios:

  • Contact form submission
  • User registration verification
  • User accounts password recovery
  • Sending of order/invoice details
  • Sending email newsletters to subscribers
  • Sending of reports
  • etc

In PHP, this can be achieved using php mail() function or through the use of libraries such as PHPMailer or SwiftMailer.

In this tutorial, you will learn what PHPMailer is, how to download and install it in your PHP project, and how to send emails using it.

What is PHPMailer?

PHPMailer is one of the most popular open-source PHP libraries for sending emails in the world. It is used by many open-source projects(eg. WordPress, Drupal, 1CRM, SugarCRM, Yii, Joomla etc).

It is integrated with SMTP support and so it doesn’t need a local mail server to work.

Advantages of PHPMailer over mail() function

  • PHPMailer provides an object-oriented interface, whereas mail() is not object-oriented.
  • A developer does not require to make $headers string which can be a headache. This also protects against header injection attacks.
  • Sending attachments is much much easier with PHPMailer.
  • PHPMailer can send alternative plaintext version of email for those email viewers which are not HTML compatible.
  • PHPMailer can use a non-local mail server (SMTP) if the developer has authentication whereas a local server is required in mail() function.
  • Send emails with multiple To, CC, BCC and Reply-to addresses
  • Support for UTF-8 content and 8bit, base64, binary, and quoted-printable encodings
  • SMTP authentication with LOGIN, PLAIN, CRAM-MD5 and XOAUTH2 mechanisms over SSL and SMTP+STARTTLS transports
  • Validates email addresses automatically

PHPMailer Installation

Starting from version 6, there are two available methods in which you can install PHPMailer into your project:
  1). Using Composer to download PHPMailer which automatically create an autoloader file.
  2). Manually downloading the PHPMailer source code and including the required files yourself.

The official documentation recommends the first option because Composer takes care of all the download, update, and dependency check steps.
However, the second option may be useful if you have not installed Composer and you don’t want to install it for some reason.

 

Installation on Windows via Composer

You need to prepare the directory in which you will install the PHPMailer. For this tutorial, let’s say the installation will take place in the same directory as your project your which is located within the XAMMP’s htdocs directory(C:xampp/htdocs/myproject). Follow these steps:

1). Open the Command prompt

2). Change to the project directory by typing

cd c:\xampp\htdocs\myproject

3). Type and execute composer installation command:

composer require phpmailer/phpmailer

PHPMailer will be installed and ready for use.

Composer will generate an “autoload.php” file you can use to import the PHPMailer library into your project that is located under the “vendor” directory by default, although you can configure Composer to use a different directory name.

So in our case, this file will be found under “C:xampp/htdocs/myproject/vendor/autoload.php

Copy and paste the following code into your php file that you will be sending the email from:

<?php
use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; require 'vendor/autoload.php';

$mail = new PHPMailer(TRUE); /* .php script to send email. */

Installation via Composer on Linux

Just like in Windows, you need to know where to install the PHPMailer library. I suggest you install it in the same directory as your project. Let’s say your project is called “myproject” located within the XAMMP’s htdocs directory(/opt/lampp/htdocs/myproject/). Follow these steps:

1). Open the terminal

2). Change to the project directory:

cd /opt/lampp/htdocs/myproject

3). Install PHPMailer with this command:

composer require phpmailer/phpmailer

When PHPMailer is installed, the composer generates an “autoload.php” file within the “vendor” directory “/opt/lampp/htdocs/myproject/vendor/autoload.php

Copy and paste the following code into your PHP file that you will be sending the email from:

<?php
use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; require 'vendor/autoload.php'; // You can put the path as either relative or absolute
$mail = new PHPMailer(TRUE); /* .php script to send email. */

Installation without composer

If you prefer not to use Composer, you can just download the PHPMailer source files and import the required classes manually.

Follow these steps:

1). Download the ZIP file with the source code from this Github link: https://github.com/PHPMailer/PHPMailer. Click on the green “Clone or download” button (on the right) and then select “Download ZIP

phpmailer installation without composer

2). Extract the zip file inside your project directory eg. (/opt/lampp/htdocs/myproject/)

3). Import the needed classes(PHPMailer.php, Exception.php, SMTP.php) files in your PHP script as shown below.

<?php
use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; /* Exception class */ require 'PHPMailer/src/Exception.php'; /* The main PHPMailer class */ require 'PHPMailer/src/PHPMailer.php'; /* SMTP class, needed if you want to use SMTP. */ require 'PHPMailer/src/SMTP.php';
$mail = new PHPMailer(TRUE); /* .php script to send email. */

To send an email with PHPMailer you need to create a PHPMailer object, set some parameters using its methods and attributes and finally call the send() method.

Let’s see with the help of a basic example how this library works

In our example, let us say you have installed PHPMailer in the same directory as the PHP script you will use to send emails. If your case is different, just replace the “vendor/autoload.php” with your correct autoload.php path.

<?php
/* Import PHPMailer classes into the global namespace
These must be at the top of your script, not inside a function */
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

// Load Composer's autoloader
require 'vendor/autoload.php';

/* If you installed PHPMailer manually(without Composer) do this instead: */
/*
require 'PHPMailer/src/Exception.php';
require 'PHPMailer/src/PHPMailer.php';
require 'PHPMailer/src/SMTP.php';
*/

// Instantiation and passing `true` enables exceptions
$mail = new PHPMailer(TRUE);

try {
    /*Server settings */ 
    $mail->SMTPDebug = 2; 
    $mail->isSMTP(); 
    $mail->Host       = 'smtp.server.com';
    $mail->SMTPAuth   = true;
    $mail->Username   = 'user@example.com';
    $mail->Password   = 'secret';
    $mail->SMTPSecure = 'tls';
    $mail->Port       = 587;

    /* Recipients */
    $mail->setFrom('from@example.com', 'Mailer');
    $mail->addAddress('joe@example.net', 'Joe User');
    $mail->addReplyTo('info@example.com', 'Information');
    $mail->addCC('cc@example.com');
    $mail->addBCC('bcc@example.com');

    /* Attachments */
    $mail->addAttachment('http://example.com/attachments/file1.pdf');         

    /* Content */
    $mail->isHTML(true); 
    $mail->Subject = 'Here is the subject';
    $mail->Body    = '<p>This is the html message body <b>in bold!</b></p>';
    $mail->AltBody = 'This is the body in plain text for non-html mail clients';

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

Breaking it Down

Namespace aliases

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

This is used to import PHPMailer classes into the global namespace. This must be placed at the very top of the PHP code.

If you don’t want to use exceptions, you don’t have to add “use PHPMailer\PHPMailer\Exception”.

 

Importing PHPMailer classes

// If you used composer to install PHPMailer, link to the autoloader file
require 'vendor/autoload.php';

/* Else, if you installed PHPMailer manually(without Composer) link to these files instead: */
require 'PHPMailer/src/Exception.php';
require 'PHPMailer/src/PHPMailer.php';
require 'PHPMailer/src/SMTP.php';
/*If you don’t want to use exceptions, you don’t have to include 'PHPMailer/src/Exception.php'
  If you don’t want to use SMTP, you dont have to include 'PHPMailer/src/SMTP.php'
*/

 

Creating a new PHPMailer object

$mail = new PHPMailer(TRUE);

The class’ constructor argument is set to TRUE to make PHPMailer use exceptions for error reporting.
If you prefer not to use exceptions, just omit the argument (or set it to FALSE). In this case you need to check the send() method return value and look for the error message in the $ErrorInfo attribute:

 

SMTP server settings

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

You use this code when you want to use your SMTP server to send the emails.
If you don’t want to use SMTP, just don’t include the above code. In this case PHPMailer uses the server email subsystem, just like mail() does

However, I would encourage you to use SMTP server to send emails if you already have a registered domain.

Below are some simple steps to get your SMTP details. I will show how to do it in cPanel though its just the same the other hosting control panels.

1). Log in to cPanel.
2). Navigate to the EMAIL section

cPanel Email Accounts

3). Click on the Email Accounts. You will see a list of all emails registered with your domain. If you don’t have an email address yet, click on the “Create” button and create one.

Custom domain emails in cPanel


4). Click on the “ Connect Devices” on the email address inwhich you want to see it's SMTP configurations. You will be directed to a page with the table as below:

Email SMTP configurations

What you are most interested in here is the outgoing server hostname(eg. mail.example.com) and SMTP port(eg. 465) because you already have your email/username(email1@example.com) and its password.

$mail->SMTPDebug = 2; // Change to 0 in production
$mail->isSMTP();  //Tells PHPMailer to use SMTP
$mail->Host       = 'mail.example.com';  //Outgoing Server
$mail->SMTPAuth   = true;   //Use SMTP authentication
$mail->Username   = 'email1@example.com'; //SMTP authentication username
$mail->Password   = 'email1 password';  //Password to your email
$mail->SMTPSecure = 'ssl'; //Use value either as 'ssl' or 'tls'
$mail->Port       = 465; //SMTP port

 

Setting recipients details

$mail->setFrom('email1@example.com', 'Your Name');
$mail->addAddress('johndoe@gmail.com', 'John Doe');
$mail->addReplyTo('email1@example.com', 'Your Name');
$mail->addCC('obama@yahoo.com');
$mail->addBCC('trump@aol.com');

setFrom() - This method takes the sender address as the first parameter, while the second parameter is optional and sets the sender name as will be seen by the recipients.

addAddress() - This method, just like setFrom() takes the recipient address as the first parameter and the second parameter as the recipient name which is also optional.

addReplyTo() - This method takes the address to which emails get delivered if the recipients send a reply to the email. It too takes two parameters, first the reply-to address and the second(optional) the name of the reply recipient. If this method is not included, the sender email is treated as the reply-to email by default.

If you are sending the emails to more than one recipient, you can as well add the addCC() - CC (carbon-copy) and addBCC() - BCC (blind carbon-copy) with the recipient's email addresses. The differences between the two are that BCC addresses will be invisible to other email recipients.

 

Adding attachments to the email

$mail->addAttachment('pathtofile/filename.pdf');

You can attach files of different types (eg. images, pdfs, word documents etc) to your email using the addAttachment() method.

This function takes two parameters: the first is the file path, and the second (optional) is the file name that the recipient will see. If not set, the same file name of the local file will be used.

 

Setting email content

$mail->isHTML(true); 
$mail->Subject = 'Here is the subject';
$mail->Body    = '<p>This is the html message body <b>in bold!</b></p>';
$mail->AltBody = 'This is the body in plain text for non-html mail clients';

The message body can include plain text and HTML content.

If you don’t specify isHTML() as true, the message will be pain-text by default.

The isHTML() method sets the email body content type to HTML. You can also include an alternative, plain text body for those email clients that do not support HTML or that are configured not to display HTML messages by using a plain text version to AltBody() method.

It’s a good idea to always include a plain text alternative body to be sure everyone will be able to read your emails.

Examples

Below are multiple working examples that you can copy and use in your projects to do tests.

You need to have installed the PHPMailer within the same directory as your PHP script that you will copy this code into. If you decide to place the file in a different directory please make sure you change the file path to PHPMailer accordingly.

NOTE: If you installed PHPMailer without composer, please make the change below to all the sample codes.
Replace this line:

require 'vendor/autoload.php';

with:

 require 'PHPMailer/src/Exception.php';
 require 'PHPMailer/src/PHPMailer.php';
 require 'PHPMailer/src/SMTP.php';

 

Sending email without SMTP

<?php
use PHPMailer\PHPMailer\PHPMailer;
require 'vendor/autoload.php';
$mail = new PHPMailer();
$mail->setFrom('email1@example.com', 'Your Name');
$mail->addAddress('johndoe@gmail.com', 'John Doe');

$mail->isHTML(true); 
$mail->Subject = "Sending email without SMTP";
$mail->Body = "<h1>Hello <b>John!</b></h1> <p>I just wanted to check on you</p>";
   
if($mail->send()){
 echo "<span style='color:green'> Message sent successfully</span>";
}else {
 echo "<span style='color:red'> Message could not be sent. $mail->ErrorInfo.</span>";
}
?>

 

Sending email with SMTP

<?php
use PHPMailer\PHPMailer\PHPMailer;
require 'vendor/autoload.php';
$mail = new PHPMailer();

$mail->SMTPDebug = 0;
$mail->isSMTP();
$mail->Host = 'mail.example.com';
$mail->SMTPAuth = true;
$mail->Username = 'email1@example.com';
$mail->Password = 'email1 password';
$mail->SMTPSecure = 'ssl';
$mail->Port = 465;

$mail->setFrom('email1@example.com', 'Your Name');
$mail->addAddress('johndoe@gmail.com', 'John Doe');

$mail->isHTML(true); 
$mail->Subject = "Sending email without SMTP";
$mail->Body = "<h1>Hello <b>John!</b></h1> <p>I just wanted to check on you</p>";
   
if($mail->send()){
 echo "<span style='color:green'> Message sent successfully</span>";
}else {
 echo "<span style='color:red'> Message could not be sent. $mail->ErrorInfo.</span>";
}
?>

 

Sending email from contact form

<?php
$msg = "";

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'vendor/autoload.php';
$mail = new PHPMailer(TRUE);

if(isset($_POST["submit"])){
 $name = $_POST["name"];
 $email = $_POST["email"];
 $phone = $_POST["phone"];
 $subject = $_POST["subject"];
 $message = $_POST["message"];

$body = <<<EOD
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>$subject</title>
</head>
<body>
<div style="background-color: #f9f9f9; padding-top: 30px; padding-bottom: 25px;">
<div style="max-width: 640px; margin: 0 auto; box-shadow: 0px 1px 5px rgba(0,0,0,0.1); overflow: hidden; border-top: 4px solid #139401; background: #fff;padding-bottom:25px;">
<table style="width: 640px;" role="presentation" border="0" width="640" cellspacing="0" cellpadding="0" align="center">
<tbody>
<tr>
<td style="padding: 20px;"><span style="font-size: 14pt;"><strong><span style="color: #333232;">Hi Admin!</span></strong></span>
<p><span style="font-family: &rsquo;proxima_nova_rgregular&rsquo;, Helvetica; font-weight: normal; font-size: 12pt; color: #424242;">The message below was sent through contact form:<br /></span></p>
<p><span style="font-family: &rsquo;proxima_nova_rgregular&rsquo;, Helvetica; font-weight: normal; font-size: 12pt; color: #424242;"><span style="color: #52b505;"><strong>Sender Details:</strong></span><br /><span style="color: #262626;">Name</span>: <strong>$name</strong><br /><span style="color: #333232;">Email</span>: <strong>$email</strong> <br />Phone: <strong>$phone</strong></span></p>
<p><span style="font-family: &rsquo;proxima_nova_rgregular&rsquo;, Helvetica; font-weight: normal; font-size: 12pt; color: #424242;"><span style="color: #52b505;"><strong>Subject:</strong></span> <strong>$subject</strong></span></p>
<p><span style="font-family: &rsquo;proxima_nova_rgregular&rsquo;, Helvetica; font-weight: normal; font-size: 12pt; color: #424242;"><span style="color: #52b505;"><strong>Message:</strong></span><br />$message</span></p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
EOD;

try{
   $mail->SMTPDebug = 0;
   $mail->isSMTP();
   $mail->Host = 'mail.example.com';
   $mail->SMTPAuth = true;
   $mail->Username = 'email1@example.com';
   $mail->Password = 'email1 password';
   $mail->SMTPSecure = 'ssl';
   $mail->Port = 465;

   $mail->setFrom('email1@example.com', 'Your Name');
   $mail->addAddress('johndoe@gmail.com', 'John Doe');

   $mail->isHTML(true); 
   $mail->Subject = $subject;
   $mail->Body = $body;
   
   $mail->send();
   $msg = "<span style='color:green'> Message sent successfully</span>";
   } catch (Exception $e) {
    $msg = "<span style='color:red'> Message could not be sent. Mailer Error: {$mail->ErrorInfo}.</span>";
  }
}
?>
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Contact Us</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style type="text/css">
*{
  padding: 0;
  margin: 0;
}
.contact{
  width: 40%;
  display: block;
  margin: auto;
  margin-top: 20px;
  padding: 10px;
  box-shadow: 1px 1px 2px;
  border-radius: 7px;
  background: #f9fcfc;
}
.contact h1{
  color: #06062a;
  font-size: 28px;
  margin: 0px;
  padding: 0px;
  border-bottom: 1px dashed #ddd;
}
.contact p{
  padding: 5px;
}
form{
  padding-bottom: 35px;
}
input{
  width: 47%;
  position: relative;
  float: left;
  margin-bottom: 10px;
  height: 25px;
}
input:nth-child(1),input:nth-child(3){
  margin-right: 5px;
}
textarea{
  width: 98%;
  margin-bottom: 10px;
}
input,textarea{
  background: #fff;
  border:1px solid #eee;
  border-radius: 5px;
  padding: 5px;
}
input[type="submit"]{
  background: #5ca830;
  height: 35px;
  color: #fff;
  font-size: 16px;
  font-weight: 650;
  border: none;
  border-radius: 8px;
  cursor: pointer;
}
#msg{
  width: 100%;
}
@media screen and (max-width: 960px){
 .contact{
  width: 60%;
 }
}
@media screen and (max-width: 767px){
 .contact{
  width: 90%;
 }
}
@media screen and (max-width: 640px){
 input{
  width: 98%;
 }
 textarea{
  width: 98%;
 }
}
</style>
</head>
<body>
<div class="contact">
<h1>Contact Form</h1>
<p>All the fields are required</p>
<form action="<?php echo $_SERVER['PHP_SELF']?>" method="post">
<input type="text" name="name" placeholder="Name" required>
<input type="tel" name="phone" placeholder="Phone Number" required>
<input type="email" name="email" placeholder="Email Address" required>
<input type="text" name="subject" placeholder="Message Subject" required>
<textarea name="message" rows="4" placeholder="Write your message here..." required></textarea>
<input type="submit" name="submit" value="Send Message">
<p id="msg"><?php echo $msg;?></p>
</form>
</div>
</body>
</html>

 

Sending email with details and file attachments from HTML form

This code first uploads the two files into a folder within your project on clicking the “Submit Details” button, then attaches it into the email.

Create a folder in your project(within the same directory as your php script) and name it attachments”.

<?php
$msg = "";

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'vendor/autoload.php';
$mail = new PHPMailer(TRUE);

if(isset($_POST["submit"])){
 $name = $_POST["name"];
 $email = $_POST["email"];
 $phone = $_POST["phone"];
 $subject = $_POST["subject"];
 $message = $_POST["message"];

 if(is_uploaded_file($_FILES["file1"]["tmp_name"])){
  $file1 = $_FILES["file1"]["name"];
  $file_tmp1 =$_FILES["file1"]["tmp_name"];
  move_uploaded_file($file_tmp1,"attachments/".$file1);
 }
 if(is_uploaded_file($_FILES["file2"]["tmp_name"])){
  $file2 = $_FILES["file2"]["name"];
  $file_tmp2 =$_FILES["file2"]["tmp_name"];
  move_uploaded_file($file_tmp2,"attachments/".$file2);
 }

$body = <<<EOD
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Contact form submission</title>
</head>
<body>
<p>Hi Admin,<br>
Please find attached some files I have sent you.<br>
My email address is <b>$email</b><br>
Regards,<br>
$name.
</p>
</body>
</html>
EOD;

try{
   $mail->SMTPDebug = 0;
   $mail->isSMTP();
   $mail->Host = 'mail.example.com';
   $mail->SMTPAuth = true;
   $mail->Username = 'email1@example.com';
   $mail->Password = 'email1 password';
   $mail->SMTPSecure = 'ssl';
   $mail->Port = 465;

   $mail->setFrom('email1@example.com', 'Your Name');
   $mail->addAddress('johndoe@gmail.com', 'John Doe');

   $mail->isHTML(true); 
   $mail->Subject = "You have received file attachments";
   $mail->Body = $body;

   $mail->addAttachment("attachments/".$file1);
   $mail->addAttachment("attachments/".$file2);
 
   $mail->send();
   $msg = "<span style='color:green'> Email sent successfully</span>";
   } catch (Exception $e) {
    $msg = "<span style='color:red'> Email could not be sent. Mailer Error: {$mail->ErrorInfo}.</span>";
  }
}
?>
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Attachments Form</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style type="text/css">
*{
  padding: 0;
  margin: 0;
}
.contact{
  width: 40%;
  display: block;
  margin: auto;
  margin-top: 20px;
  padding: 10px;
  box-shadow: 1px 1px 2px;
  border-radius: 7px;
  background: #f9fcfc;
  min-height: 200px;
}
.contact h1{
  color: #06062a;
  font-size: 28px;
  margin: 0px;
  padding: 0px;
  border-bottom: 1px dashed #ddd;
}
.contact p{
  padding: 5px;
}
input{
  width: 47%;
  position: relative;
  float: left;
  margin-bottom: 10px;
  height: 25px;
}
input:nth-child(1),input:nth-child(3){
  margin-right: 5px;
}
input{
  background: #fff;
  border:1px solid #eee;
  border-radius: 5px;
  padding: 5px;
}
input[type="submit"]{
  background: #5ca830;
  height: 35px;
  color: #fff;
  font-size: 16px;
  font-weight: 650;
  border: none;
  border-radius: 8px;
  cursor: pointer;
}
#msg{
  width: 100%;
}
@media screen and (max-width: 960px){
 .contact{
  width: 60%;
 }
}
@media screen and (max-width: 767px){
 .contact{
  width: 90%;
 }
}
@media screen and (max-width: 640px){
 input{
  width: 98%;
 }
 textarea{
  width: 98%;
 }
}
</style>
</head>
<body>
<div class="contact">
<h1>Attachments Form</h1>
<p>All the fields are required</p>
<form action="<?php echo $_SERVER['PHP_SELF']?>" method="post"  enctype="multipart/form-data">
<input type="text" name="name" placeholder="Name" required>
<input type="email" name="email" placeholder="Email Address" required>
<input type="file" name="file1" accept=".jpg,.png,.pdf,.docx,.jpeg" required>
<input type="file" name="file2" accept=".jpg,.png,.pdf,.docx,.jpeg" required>
<input type="submit" name="submit" value="Submit Details">
<p id="msg"><?php echo $msg;?></p>
</form>
</div>
</body>
</html>


Conclusion

In this tutorial, you learned what PHPMailer is, how to install it in your PHP project, and how you can use it to send emails with or without SMTP. You also learned how to send emails to multiple recipients, with or without attachments as well as how to collect and send HTML form information via email using PHPMailer.