Do you need to send emails from your PHP application?
This complete guide will teach you how to setup and run the most used PHP email library: PHPMailer.
Learning how to send emails will take your PHP code to the next level. You will be able to write an alert daemon, receive an email when someone tries to log in and much more.
This tutorial covers all you need to know: the installation steps, the class functions, how to use SMTP authentication (including Gmail), how to handle errors and more. You will also find many code examples.
(You probably want to add this page to your Bookmarks to come back here for reference.)
Table of contents
- why use PHPMailer instead of mail() or other libraries?
- how to install PHPMailer on Windows and Linux (updated in 2018, with and without Composer)
- how to send your first email
- how to use the PHPMailer class
- how to use a custom SMTP server
- debugging and error handling
- how to use PHPMailer with Google (Gmail) SMTP
- conclusion

WHY USE PHPMAILER?
PHPMailer offers many functionalities over the PHP core function mail(), including SMTP SSL encryption and authentication, HTML messages, file attachments and more.
On top of that, PHPMailer is much easier to use than mail() and provides a clean, readable object-oriented syntax.
Let’s see in more detail why you should use PHPMailer instead of mail() or other third-party libraries.
WHY USE PHPMAILER INSTEAD OF mail()?
For at least two good reasons.
The first is that mail() relies on the server email subsystem to work. This means that if you want to change some settings like the SMTP server or the authentication parameters, you need to do it system wide.
That is usually a quite difficult operation, and unless you have a dedicated server or you are using a local PHP development environment, you are probably not even allowed to do it.
This also makes almost impossible to use different configurations at the same time, for example using multiple SMTP accounts and switching between them programmatically.
As you will see in a minute, with PHPMailer is very easy to change any parameter dynamically right in your PHP script.
The second reason is that mail() doesn’t offer any advanced functionality.
mail() is fine for sending simple, plain text emails, but it’s very limiting if you need to do anything more than that. Adding attachments or sending HTML emails, for example, is very difficult with mail(), while with PHPMailer it’s just a matter of a single line of code.

ARE THERE PHPMAILER ALTERNATIVES?
Yes, there are other libraries like Zend Mail, SwiftMailer and Zeta Components Mail, but PHPMailer is usually the first choice because of its popularity.
Of course, if you are already familiar with another mail extension and it works fine for you, you can just stick with it.
But if you want to start using one of them and you need to choose which one to go with, PHPMailer is probably the best choice because it’s the most used one.
Other extensions like Zend Mail, SwiftMailer or Zeta Components Mail are probably as good as PHPMailer, but look at the Google search results for “php mail library”:

And these are the results on YouTube:

As you can clearly see, PHPMailer dominates the first results. That doesn’t necessarily mean PHPMailer is better than other extensions, but it does mean it’s the most popular.
The main reason you want to go with the most used library is support: the more widely used a piece of software is, the easier is to find help and examples online.
I should also mention that I have been using PHPMailer for work for a few years now, sending up to 100 emails per day with it. I use it to send alerts using PHP daemons, to monitor my scripts’ memory usage and to receive warnings if SQL injection attacks are detected.
As far as I remember, I never had any trouble with it, so chances are you won’t either.
If you want to learn more about how to use the PHP mail() function, the Pear Mail extension or Swift Mailer, you can take a look at this detailed tutorial from Mailtrap.
HOW TO INSTALL PHPMAILER? (UPDATED IN 2018)
Older versions of PHPMailer (up to version 5) used to provide a “PHPMailerAutoload.php” file, and all you needed to do was to include it in your script.
Starting from version 6, however, this file is no longer provided. Now, to make the PHPMailer class available in your script you have two options:
- use Composer to download PHPMailer and automatically create an autoloader file;
- manually download the PHPMailer source code and include the required files yourself.
The first option is the recommended one, because Composer takes care of all the download, update and dependency check steps. This is especially useful if you need to install other libraries as well, like the one needed for XOAUTH2 Google authentication (I will tell you how to use XOAUTH2 with Google later in this post).
However, the second option may be useful if you don’t want to install Composer for some reason, for example if you are using PHPMailer on a testing environment.
Let’s see both installation options, starting with the one with Composer.
Installing Composer and PHPMailer on Windows (if you use XAMPP, WAMP etc.)
Composer is a dependency manager for PHP. It helps you download, install and keep up to date PHP extensions and libraries.
Installing Composer requires just a couple of minutes:
- first, make sure you have a web development environment already installed (XAMPP, WAMP, EasyPHP etc.) as Composer needs a PHP executable to work;
- download the Composer installation file from here (under “Windows Installer”) and run it;
- follow the installation instructions, and make sure you can select a PHP executable:

- once the installation is complete, you will be able to use the Composer command line tools to install PHPMailer.
Now you need to open a terminal (by executing “cmd.exe” or looking for “Command prompt” in the Start menu) and navigate to the directory where you want to install the Composer packages including PHPMailer (if you need help using the terminal just leave me a comment below).
For example, let’s use “C:\xampp\composer” as installation directory. First create the directory, then go back to the terminal and move into the directory by typing “cd C:\xampp\composer”.
Then, simply execute the command: “composer require phpmailer/phpmailer” as shown in the following image:

PHPMailer will be installed and you’ll be ready to use it.
Composer will generate an “autoload.php” file you can use to include the installed libraries, in this case PHPMailer. This file is located under the “vendor” directory by default, although you can configure Composer to use a different directory name.
So, assuming your installation directory is “C:\xampp\composer”, you need to include the “C:\xampp\composer\vendor\autoload.php” file.
Also, because now PHPMailer defines its classes under the PHPMailer\PHPMailer namespace, it’s a good idea to make use of the use directive at the beginning of your script, aliasing the PHPMailer\PHPMailer\PHPMailer and PHPMailer\PHPMailer\Exception classes:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'C:\xampp\composer\vendor\autoload.php';
$email = new PHPMailer(TRUE);
/* ... */
Installing Composer and PHPMailer on Linux
Many GNU/Linux distributions include the Composer package in their repositories.
On Debian-like systems (including Ubuntu), for example, you can simply use the “apt-get” command to install Composer (installing Composer from the source code is outside the scope of this guide, but if you need help with it feel free to ask me).
Once Composer is installed, you can use the Composer command line executable to install PHPMailer inside a directory of your choice, just like we already saw for the Windows installation (you can use the very same command):

Now PHPMailer is installed.
You can include the “autoload.php” file and set the namespace aliases just like for the Windows installation (changing the file path, of course).
Installing PHPMailer without Composer
If you prefer not to use Composer, you can just download the PHPMailer source files and include the required files manually.
You can download the ZIP file with the source code from the PHPMailer homepage, clicking on the “Clone or download” green button (on the right) and then selecting “Download ZIP”. Unzip the package inside the directory where you want to save the source files.
Then you just need to include the needed classes files in your PHP script.
As a minimum, you want to include the main PHPMailer class, the Exception class (for error handling) and probably the SMTP class too, if you are going to connect to an SMTP server for mail delivery.
You should also set the namespace aliases just like you saw before for the Composer installation.
Assuming your source code directory is “C:\PHPMailer”, this is how your PHP script will look like:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
/* Exception class. */
require 'C:\PHPMailer\src\Exception.php';
/* The main PHPMailer class. */
require 'C:\PHPMailer\src\PHPMailer.php';
/* SMTP class, needed if you want to use SMTP. */
require 'C:\PHPMailer\src\SMTP.php';
$email = new PHPMailer(TRUE);
/* ... */
Keeping PHPMailer up to date
If you choose the Composer installation method, you can keep your PHPMailer installation up to date by executing the “update” Composer command.
The syntax is the same on both Windows and Linux. Just go to the installation directory (where you issued the installation command) and execute the update:
composer update
If you choose not to use Composer, then you will need to manually download the new ZIP file from the PHPMailer homepage and overwrite the previous installation (following the same steps).
In either case, before updating your installation is a good idea to look at the changelog file and the update notes, just to be sure that your PHP applications are compatible with the new PHPMailer version.
HOW TO SEND YOUR FIRST EMAIL WITH PHPMAILER
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 a basic example so you can understand how this class works (don’t worry about the details for now, we will cover them in the next chapter).
In all the examples I will use the Windows installation path, because I am working on my local XAMPP development environment. If you are using Linux just change the include paths accordingly.
<?php
/* Namespace alias. */
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
/* Include the Composer generated autoload.php file. */
require 'C:\xampp\composer\vendor\autoload.php';
/* If you installed PHPMailer without Composer do this instead: */
/*
require 'C:\PHPMailer\src\Exception.php';
require 'C:\PHPMailer\src\PHPMailer.php';
require 'C:\PHPMailer\src\SMTP.php';
*/
/* Create a new PHPMailer object. Passing TRUE to the constructor enables exceptions. */
$mail = new PHPMailer(TRUE);
/* Open the try/catch block. */
try {
/* Set the mail sender. */
$mail->setFrom('darth@empire.com', 'Darth Vader');
/* Add a recipient. */
$mail->addAddress('palpatine@empire.com', 'Emperor');
/* Set the subject. */
$mail->Subject = 'Force';
/* Set the mail message body. */
$mail->Body = 'There is a great disturbance in the Force.';
/* Finally send the mail. */
$mail->send();
}
catch (Exception $e)
{
/* PHPMailer exception. */
echo $e->errorMessage();
}
catch (\Exception $e)
{
/* PHP exception (note the backslash to select the global namespace Exception class). */
echo $e->getMessage();
}
See how PHPMailer uses a nice and easy OOP syntax?
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:
<?php
/* Namespace alias (don't need Exception this time). */
use PHPMailer\PHPMailer\PHPMailer;
/* Include the Composer generated autoload.php file. */
require 'C:\xampp\composer\vendor\autoload.php';
/* Create a new PHPMailer object. */
$mail = new PHPMailer();
/* Set the mail sender. */
$mail->setFrom('darth@empire.com', 'Darth Vader');
/* Add a recipient. */
$mail->addAddress('palpatine@empire.com', 'Emperor');
/* Set the subject. */
$mail->Subject = 'Force';
/* Set the mail message body. */
$mail->Body = 'There is a great disturbance in the Force.';
/* Finally send the mail. */
if (!$mail->send())
{
/* PHPMailer error. */
echo $mail->ErrorInfo;
}
It’s interesting to see how this script would look like if you were using the mail() function:
<?php
$from = 'Darth Vader <darth@empire.com>';
$to = 'Emperor <palpatine@empire.com>';
$subject = 'Force';
$message = 'There is a great disturbance in the Force.';
$headers = 'From: ' . $from;
if (!mail($to, $subject, $message, $headers))
{
echo "Error.";
}
else
{
echo "Message sent.";
}
Yes, the syntax is much worse 🙂
In the previous basic example, we did not tell PHPMailer to use a specific SMTP server. In this case PHPMailer uses the server email subsystem, just like mail() does.
Of course, you want to use your own SMTP connection parameters instead. Don’t worry: we’ll cover this in a minute.
Now let’s see how to use all the PHPMailer class functionalities.
Would you like to talk with me and other developers about PHPMailer, PHP and web development? Join my Facebook Group now: Alex PHP café
See you there 🙂
HOW TO USE THE PHPMAILER CLASS
Once you have created a PHPMailer object as seen in the previous examples, you can use the extensive PHPMailer class functionalities to set all the email parameters and attributes you need.
Let’s see the most useful PHPMailer methods.
- Set the sender (“From:”) address
This is probably the first thing you want to do. This method takes the sender address as first parameter, while the second parameter is optional and sets the sender name as will be seen by the recipients.
$mail->setFrom('darth@empire.com', 'Darth Vader');
- Add a recipient (“To:”) address
This is the second thing you want to do 🙂
Like for the sender, the second parameter is optional and specifies the name of the recipient.
$mail->addAddress('palpatine@empire.com', 'Emperor');
- Set the email subject
$mail->Subject = 'Force';
- Set the email body (the actual message)
The message body can include plain text and HTML code. If you want your email to be parsed as HTML, be sure to read the next point.
$mail->Body = 'There is a great disturbance in the Force.';
- Create an HTML email message
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.
It’s a good idea to always include a plain text alternative body to be sure everyone will be able to read your emails.
$mail->isHTML(TRUE);
$mail->Body = '<html>There is a great disturbance in the <strong>Force</strong>.</html>';
$mail->AltBody = 'There is a great disturbance in the Force.';
- Add an attachment
You can attach files to your email using the addAttachment() function.
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.
Note that the file must be readable by the user running the PHP script (this is especially important under Linux systems).
$mail->addAttachment('/home/darth/star_wars.mp3', 'Star_Wars_music.mp3');
- Set a different reply-to address
You can specify which address the recipient will reply to when replying to your email. The default is the sender (“From:”) address, but you can change it.
$mail->addReplyTo('vader@empire.com', 'Lord Vader');
- Add CC and BCC recipients
$mail->addCC('admiral@empire.com', 'Fleet Admiral');
$mail->addBCC('luke@rebels.com', 'Luke Skywalker');
- Create an attachment from binary data
With PHPMailer you can create a “virtual” attachment from a binary stream, like a database binary field or a network stream. This means that you don’t have to save the data to a local file before sending it as an attachment.In the example below, we attach two files: the first contains the data from a “blob” (binary) SQL field and is named “db_data.db”, the second is created from a network stream (a PDF file) and is named “file.pdf”.
/* Binary stream from a database blob field */
$mysql_data = $mysql_row['blob_data'];
$mail->addStringAttachment($mysql_data, 'db_data.db');
/* Binary network stream */
$pdf_url = 'http://remote-server.com/file.pdf';
$mail->addStringAttachment(file_get_contents($pdf_url), 'file.pdf');
- Create an HTML message from a string
The msgHTML() method automatically reads an HTML string (or a local file, using file_get_contents() to read it) into an embedded HTML message. The second parameter tells the function where to look for images, so that they can be included inline in the message.
Note that this function will override both Body and AltBody attributes.
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
HOW TO USE A CUSTOM SMTP SERVER
PHPMailer lets you configure the SMTP connection parameters directly from your PHP script, using the PHPMailer class methods and attributes.
This is incredibly useful compared to mail(), which relies on the underlying system configuration instead.
The following example shows how you can use a specific SMTP server using SSL and authentication:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'C:\xampp\composer\vendor\autoload.php';
$mail = new PHPMailer(TRUE);
try {
$mail->setFrom('darth@empire.com', 'Darth Vader');
$mail->addAddress('palpatine@empire.com', 'Emperor');
$mail->Subject = 'Force';
$mail->Body = 'There is a great disturbance in the Force.';
/* SMTP parameters. */
/* Tells PHPMailer to use SMTP. */
$mail->isSMTP();
/* SMTP server address. */
$mail->Host = 'smtp.empire.com';
/* Use SMTP authentication. */
$mail->SMTPAuth = TRUE;
/* Set the encryption system. */
$mail->SMTPSecure = 'tls';
/* SMTP authentication username. */
$mail->Username = 'smtp@empire.com';
/* SMTP authentication password. */
$mail->Password = 'iamyourfather';
/* Set the SMTP port. */
$mail->Port = 587;
/* Finally send the mail. */
$mail->send();
}
catch (Exception $e)
{
echo $e->errorMessage();
}
catch (\Exception $e)
{
echo $e->getMessage();
}
Of course, you need to use the correct connection parameters, including the server encryption capabilities and the TCP port it listens to.
A more advanced SMTP related attribute is the SMTPOptions array. If you are using SMTP encryption, PHPMailer passes this array to the underlying PHP stream_context_create() function.
You can use the SMTPOptions attribute to set advanced SSL context options. While you won’t need to use it most of the time, in some cases it can be really useful.
For example, if you have your own SMTP server which uses a self-signed certificate, the SMTP connection will probably fail for the lack of a valid certification authority signature. This is a quite common scenario in work environments.
In these cases, you can use the SMTPOptions attribute to tell PHPMailer (and the PHP SSL subsystem) to ignore this issue.
In the following example we set the verify_peer and verify_peer_name parameters to FALSE and the allow_self_signed parameter to TRUE in order to disable some security checks:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'C:\xampp\composer\vendor\autoload.php';
$mail = new PHPMailer(TRUE);
try {
$mail->setFrom('darth@empire.com', 'Darth Vader');
$mail->addAddress('palpatine@empire.com', 'Emperor');
$mail->Subject = 'Force';
$mail->Body = 'There is a great disturbance in the Force.';
/* SMTP parameters. */
$mail->isSMTP();
$mail->Host = 'smtp.empire.com';
$mail->SMTPAuth = TRUE;
$mail->SMTPSecure = 'tls';
$mail->Username = 'smtp@empire.com';
$mail->Password = 'iamyourfather';
$mail->Port = 587;
/* Disable some SSL checks. */
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
/* Finally send the mail. */
$mail->send();
}
catch (Exception $e)
{
echo $e->errorMessage();
}
catch (\Exception $e)
{
echo $e->getMessage();
}
A PRACTICAL VIDEO EXAMPLE
Why don’t you look at a practical video example? This nice video from Mr. Digital shows how to create a PHPMailer script:
DEBUGGING AND ERROR HANDLING
If something goes wrong while trying to send the message, the PHPMailer object throws and exception (if TRUE is passed to the constructor) and saves the error information inside the $ErrorInfo attribute.
The best way to handle errors is to use a try/catch block to catch the exception, as shown in the previous examples. The PHPMailer/Exception class provides the errorMessage() method to retrieve the error message directly from the exception object.
SMTP DEBUG
You can set the SMTPDebug attribute to enable on screen SMTP connection debugging.
This kind of debugging output can be extremely useful in the development phase, because it lets you see if something goes wrong with the SMTP connection.
Note that the SMTPDebug output should be used for debugging purposes only, because it can expose sensitive data to remote clients.
The SMTPDebug argument can be set to an integer value between 0 (the default, no output is generated) and 4 (low-level info output is displayed). If your emails are not being sent, I suggest you set this value to 4 and see what happens:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'C:\xampp\composer\vendor\autoload.php';
$mail = new PHPMailer(TRUE);
try {
$mail->setFrom('darth@empire.com', 'Darth Vader');
$mail->addAddress('palpatine@empire.com', 'Emperor');
$mail->Subject = 'Force';
$mail->Body = 'There is a great disturbance in the Force.';
$mail->isSMTP();
$mail->Host = 'smtp.empire.com';
$mail->SMTPAuth = TRUE;
$mail->SMTPSecure = 'tls';
$mail->Username = 'smtp@empire.com';
$mail->Password = 'iamyourfather';
$mail->Port = 587;
/* Enable SMTP debug output. */
$mail->SMTPDebug = 4;
$mail->send();
}
catch (Exception $e)
{
echo $e->errorMessage();
}
catch (\Exception $e)
{
echo $e->getMessage();
}
ERROR MESSAGES LOCALIZATION
PHPMailer supports error messages localization. You can use one of the many (48 at the moment of writing) already available translations (you can find the list here) or even create a customized language set by yourself.
To set the language, just call the setLanguage() method:
/* Set language to Italian using a default translation set. */
$mail->setLanguage('it');
/* Or use your own translation set
(in this case you need to specify the translation file path). */
$mail->setLanguage('klingon', 'C:\PHPMailer\myLanguages\');
If you want to use your own translation set, then you need to pass the translation file path to the function as second parameter (with a trailing directory separator). If you are using one of the default ones, then leave the second parameter empty.
HOW TO USE PHPMAILER WITH GOOGLE (GMAIL) SMTP
The Google SMTP server is smtp.gmail.com. It uses TLS-encrypted connections and listens to port 587.
The PHPMailer SMTP configuration should therefore use those settings:
/* Use SMTP. */
$mail->isSMTP();
/* Google (Gmail) SMTP server. */
$mail->Host = 'smtp.gmail.com';
/* SMTP port. */
$mail->Port = 587;
/* Set authentication. */
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
SMTP servers usually require clients to authenticate themselves with username and password before they are allowed to send messages. Google’s SMTP does too, but you may need to take additional steps to make it work.
Google’s SMTP authentication steps with PHPMailer depend on whether you have Google two-step verification enabled or not.
GMAIL AUTHENTICATION WITH 2-STEP VERIFICATION DISABLED
If you don’t have Google two-step verification enabled, you can try using your own username (in this case, your email address) and password to login:
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->Port = 587;
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
/* Username (email address). */
$mail->Username = 'myusername@gmail.com';
/* Google account password. */
$mail->Password = 'mypassword';
That *may* work, however Google is very suspicious about unusual log in attempts and may refuse to authorize your PHPMailer script authentication process. This is also explained in this PHPMailer’s Troubleshooting document.
Google’s SMTP may ask the “client” (in this case, the PHPMailer script) to log in with the web browser first, or to follow this page‘s instructions.
If you don’t want to enable 2-step verification, you probably must tell Google to “Allow less secure apps” login attempts for the PHPMailer’s authentication to be accepted.
To do that you can follow these instructions, or just go here while logged in with the Google account you want to use.
After you have authorized “less secure apps” connections, you can try again and see if it works (you may need to wait for a couple of hours for the change to take effect).
If it still doesn’t work, you are left with two options: enable the 2-step verification and follow the instructions below or use the XOAUTH2 authentication process as described later in this tutorial.
Your choice 🙂
GMAIL AUTHENTICATION WITH 2-STEP VERIFICATION ENABLED
If you enabled two-step verification then you need to create an “App password” and use it to log in with PHP, because you won’t be able to use the second authentication factor with PHPMailer (which involves using an authentication app or authorizing the access with your smartphone).
An “app password” is a string you can use to login without the second authentication factor. To create one, just follow Google’s instructions at this page or just open this link.
From there, choose a name for your app (for example, “PHPMailer”) and press the “Generate” button as seen in this image:

After pressing the button, you will obtain a 16-chars string you can use to log in. Be sure to copy it right away, because you won’t be able to retrieve it later (if you lose it, you will need to create a new app password from scratch):

Now all you need to do is use this new string as password in your PHPMailer configuration (without spaces, those are there just for readability):
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->Port = 587;
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
$mail->Username = 'myusername@gmail.com';
/* App password. */
$mail->Password = 'eqwvrwlbbizcsdcz';
USING GMAIL WITH XOAUTH2 AUTHENTICATION
XOAUTH2 is Google’s recommended authentication method. While it’s a quite complex protocol, thanks to PHPMailer is possible to use it without much difficulty.
PHPMailer’s XOAUTH2 implementation relies on the league/oauth2-client library, that must therefore be installed on your system. Specifically, you need to install the league/oauth2-google package.
The easiest way to install it is to use Composer. If you chose to install PHPMailer with Composer, then you can do the same with the league/oauth2-google library: just go to the Composer installation directory and type “composer require league/oauth2-google”:

You can also install this library inside another directory, but in this case you will need to include two autoloader.php files. If you didn’t use Composer to install PHPMailer, just install the OAUTH2 library in a new directory.
Unfortunately, installing league/oauth2-google without Composer is a bit difficult, because it requires a few libraries to be installed as well. If you really hate Composer and don’t want to use it, you will need to download them all manually and include them in your scripts.
Once you have league/oauth2-google installed, you will need to perform some steps with the Google account you are going to use.
All these steps are explained in detail in this PHPMailer XOAUTH2 tutorial. Follow all the steps but stop before the last “Configure your email script” paragraph, because it’s outdated and the example code there no longer works.
Keep in mind that you will need to have a working development environment, because you will need to edit a PHPMailer file (get_oauth_token.php) and run it with a web browser.
After you have completed all the required steps, you will have three authentication strings:
- the Client ID
- the Client Secret
- and the Refresh Token
You need to use them in your PHPMailer XAUTH2 authentication process.
Next you need to configure the PHPMailer script, include the OAUTH2 library and set the authentication parameters. The required steps are:
- set namespace aliases for the PHPMailer OAuth and league Google classes;
- include the league library (if you used the same Composer installation directory then the autoloader.php file will take care of that);
- set the script time zone to UTC; this is needed for proper time synchronization with the Google server;
- set the PHPMailer class AuthType attribute to “XOAUTH2”;
- create a league/Google object and a PHPMailer/OAuth object with the authentication strings you got in the previous steps and use them for the authentication process.
In this final example you can see how this is done:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
/* New aliases. */
use PHPMailer\PHPMailer\OAuth;
use League\OAuth2\Client\Provider\Google;
/* Composer autoload.php file includes all installed libraries. */
require 'C:\xampp\composer\vendor\autoload.php';
/* If you installed league/oauth2-google in a different directory, include its autoloader.php file as well. */
// require 'C:\xampp\league-oauth2\vendor\autoload.php';
/* Set the script time zone to UTC. */
date_default_timezone_set('Etc/UTC');
/* Information from the XOAUTH2 configuration. */
$google_email = 'myaddress@gmail.com';
$oauth2_clientId = 'CliendIdString';
$oauth2_clientSecret = 'ClientSecret';
$oauth2_refreshToken = 'RefreshToken';
$mail = new PHPMailer(TRUE);
try {
$mail->setFrom($google_email, 'Darth Vader');
$mail->addAddress('palpatine@empire.com', 'Emperor');
$mail->Subject = 'Force';
$mail->Body = 'There is a great disturbance in the Force.';
$mail->isSMTP();
$mail->Port = 587;
$mail->SMTPAuth = TRUE;
$mail->SMTPSecure = 'tls';
/* Google's SMTP */
$mail->Host = 'smtp.gmail.com';
/* Set AuthType to XOAUTH2. */
$mail->AuthType = 'XOAUTH2';
/* Create a new OAuth2 provider instance. */
$provider = new Google(
[
'clientId' => $oauth2_clientId,
'clientSecret' => $oauth2_clientSecret,
]
);
/* Pass the OAuth provider instance to PHPMailer. */
$mail->setOAuth(
new OAuth(
[
'provider' => $provider,
'clientId' => $oauth2_clientId,
'clientSecret' => $oauth2_clientSecret,
'refreshToken' => $oauth2_refreshToken,
'userName' => $google_email,
]
)
);
/* Finally send the mail. */
$mail->send();
}
catch (Exception $e)
{
echo $e->errorMessage();
}
catch (\Exception $e)
{
echo $e->getMessage();
}
CONCLUSION
Mastering PHP email handling is a big advantage.
With this tutorial, you have learned all you need to know to use PHPMailer at its full potential: how to install it, how to use its functionalities, how to configure SMTPS connections (including Gmail’s), error handling and more.
Feel free to bookmark this page and return here for reference as needed.
If you have any issue, check the PHPMailer Troubleshooting guide or just leave me a comment below. You are also invited to join my Facebook Group (Alex PHP café) where me and my community will be very glad to help you!
Now, I’m curious: how do YOU use email in your web applications? I’m looking forward to hearing from you!
P.s. If this guide has been helpful to you, please spend a second of your time to share it… thanks!
Alex
This may not be the place that I need to post this, but it is a start. I am trying to set up PHPMailer to use gmail and xoauth2. I have created the app in Google Developer, and got the clientID and clientSecret. However, when I entered it into the get_oauth_token.php program and ran the php script, Chrome came back with a HTTP 500 error. I’m not sure how to fix this. Any help or direction to look is appreciated.
Hello Dan,
A 500 error is usually caused by a syntax error or a runtime error. You should be able to check the exact error from the PHP/Apache logs or by enabling error reporting.
Can you check that and share here the error message?
I looked at all of the Apache logs and didn’t see anything. I even tried to delete the logs to check if an entry went into a log that I didn’t see at first. There were no entries. Where would I find the PHP log?
I thought that it might be a firewall problem and tried turning that off. It didn’t change anything. I still got the 500 error again. Suggestions on how to get to these errors?
Hi Dan,
The PHP logs usually go into the Apache logs, unless a different file has been configured in the php.ini file (you can check that just to be sure).
Unfortunately it is no use to debug the PHP code itself, because when a 500 error occurs PHP is not even executed (it stops before that, usually because of a syntax error).
Where are you executing the script? On a remote server or on a local development environment?
P.S.
As this issue may be harder to fix than expected, if you want you can join my Facebook group where it’s easier to talk: https://www.facebook.com/groups/289777711557686
Dear Alex,
I shifted the discussion to your Facebook account as you suggested.
Sincerely,
Dan
Hi Alex – thank you for the thorough presentation. Not understanding composer and how to make it work on GoDaddy, I was able to use your code examples to manually get phpmailer to work. It took a little bit of piecing some of the things together. But, with the many examples you provided, I was able to make it happen. Could not get the regular php mail() to work with GoDaddy/Plesk, but this worked great! Thanks again, you saved me a couple days worth of work!!
Thank you for leaving your comment, Steve. I’m happy to help!
Good day alex, Please I need a step by step guide/instruction on how to build/create a webpage Php mailer, I mean how to create a webmailer from the scratch, Please help me because I read your article and wasn’t able to get anything from it, I can possibly send you a sample of the kind of mailer I want, and also i have many questions, too, Anyway contact me via my email below;
Freddy,
Thanks so much
Hi Freddy,
This tutorial is about how to use the PHPMailer library, not about how to build a webmailer app from scratch.
I cannot build it for you, but if you have questions related to PHPMailer itself you can ask them here.
(P.S. I removed your email address from the comment to protect your privacy).
Hi, I’m trying to validate google recaptcha or let me say I’m trying to enable google recaptcha within the PHPMailer Library but it doesn’t seems to validate.
here is the problem I’m having
1. I can’t seems to find where I would paste my google secret key for validation.
2. form still submits successfully without recaptcha passed.
can you just do a tutorial around that or refer me to an article or video that explains the process
I don’t know of any complete tutorial unfortunately.
However, the PHPMailer part and the reCaptcha part are distinct. Can you share the program logic are you implementing?
We can also talk on my Facebook group: https://www.facebook.com/groups/289777711557686
When I try to send message with new line, the line does not break and |n characters are appear.
The function nl2br, create a new line but the characters \n appear in the start of the new line.
How should I solve the problem?
Thanks in advance
Hi, are you sending an HTML message or a plain-text message?
I was struggling with a file where it appeared as 1 line in the mail ignoring carriage returns in the text file. I saw this and wrapped it around n2lbr and it solved my issue. Great tutorial and I’ve learnt a lot. If it’s Html the n2lbr defo sorts it.
Thank you for sharing your solution, Steve!
Very nice tutorial! Congrats Alex.
Thank you Rafael, I’m glad you liked it.
Hie alex, am having problems in understanding some of the concepts which you have gave. But I have hope that I will pick up soon. I have a question, how can you use the phpmailer in case you would want to sent an email upon a specific condition in php?
Hi,
You can execute the send() command only when specific conditions are met.
You can use “standard” PHP logic (such as IFs, comparisons, etc.) and execute the send() method only inside the desired case.
You can also move the whole PHPMailer object instantiation inside the condition to make the code more efficient (avoiding its instantiation if it’s not needed).
hi dude, I have build the system regarding to the certificate expired date and now I am using this code to receive an automatic email if the certificate date will expired in one month. do you have an idea on how to receive the email one month before for everyday triggering until the certificate being update to new date?
while($row = sqlsrv_fetch_array($result))
{
$dateJoin = $row[‘DateJoin’]-> format(‘Y-m-d ‘);
$Name = $row[‘EmpName’];
$EmpNum = $row[‘EmpNo’];
$status = $row[‘Status’];
$MonthAfter = date(‘Y-m-d’, strtotime($dateJoin. ‘+29 days’));
$today = date(“Y-m-d”);
if ($today == $MonthAfter)
{
$html .= ”;
$html .= ” . $Name . ”;
$html .= ” . $EmpNum . ”;
$html .= ” . $dateJoin . ”;
$html .= ”;
$countResult = count($Name);
}
else
{
echo “Not today”;
}
Hi Mira,
Instead of sending the email if the current day is exactly 29 days before the expiration day, you send the email if the expiration day is less than 29 days ahead.
You can use Unix Timestamps to make it easier to calculate the time difference.
You also probably want to avoid sending more than one email per day. You can do this by keeping a flag on the database, whith the current day and a “sent” flag.
thanks Alex. btw, did I use the right expression for the expiration day is less than 29 days. I bit confusing.
$MonthAfter = date(‘Y-m-d’ < strtotime($dateJoin. '+29 days'));
$MonthAfter = date(‘Y-m-d’, strtotime($dateJoin) < strtotime('+30 days'));
like this right?
The idea is correct, but you can do that more easily if you use Unix Timestamps.
For example, if you get the Unix Timestamp for the expiration date into $monthAfterUts, then the check becomes like this:
if (($monthAfterUts – time()) < (86400 * 29)) {.....} Which means: if the time between the expiration date ($monthAfterUts) and now (time()) is less than 29 days (each day has 86400 seconds), then send the email.
J’ai tester le code et j’ai enfin pu réussir a envoyer des mail je te remercie très fort !!!!
🙂
Great topic , Thanks .
but I’m building a project using WordPress and I need to send emails , I’ve followed all your steps but how to test with WordPress plugin ?
Hi Yolla,
Are you developing a plugin or you would like to use an existing plugin?
In the first case, I did a very quick search on Google and found this: https://artisansweb.net/how-to-send-wordpress-email-using-smtp-server/
Maybe it can be useful.
If you are just looking for a plugin, you can start here: https://it.wordpress.org/plugins/tags/phpmailer/
Great article. Thanks!
Thank you, Martin!
What should the code look like on the site (html) with the form?
You can use any kind of HTML form, even with Captchas or similar controls.
The back-end code works as long as it receives the email data (subject, message body).
I installed the PHPMailer at the subfolder PHPMailer62 in my webspace.
Then I wrote this: (before the code I show the lines).
2 use PHPMailer62\PHPMailer\PHPMailer;
3 use PHPMailer62\PHPMailer\Exception;
4 require ‘./PHPMailer62/src/Exception.php’;
5 require ‘./PHPMailer62/src/PHPMailer.php’;
6 require ‘./PHPMailer62/src/SMTP.php’;
7 $mail = new PHPMailer(TRUE);
And I get the message:
Class ‘PHPMailer62\PHPMailer\PHPMailer’ not found in /…/kontaktmail.php:47 Stack trace: #0 {main} thrown in /…/kontaktmail.php on line 47
And that message is the same, if I use
7 $mail = new PHPMailer();
or
7 $mail = new PHPMailer;
Any idea what´s wrong?
Thanks for any help!
Hello Stephan,
In the “use” directives you need to use PHPMailer instead of PHPMailer62, because that is the Namespace and not the file path.
The requires, on the other hand, are correct.
Hello Alex,
I am trying to build my own form using this tutorial, but I get the error 500. The code is here: https://pastebin.com/4HSYZXFw
Can you please tell me why this code causes error 500?
Thanks
Hello Abe,
There are a couple of errors in the code.
First, you forgot to create the $mail PHPMailer object. You cat do that before the try block.
Second, if you include the Composer autoload then you don’t need to manually include the PHPMailer classes.
Here is the fixed Pastebin: https://pastebin.com/SzdMC7dw
Let me know if it works now.
Followed your directions but now PHPMailer hangs and throws an error message Fatal error: Maximum execution time of 30 seconds exceeded in C:\PHP\PHPMailer\src\SMTP.php on line 1225. Don’t know how to correct this.
Doing this from a localhost web site and using comcast.net.
Hello Rose,
It may be a timeout on the connection to the SMTP server. Try connecting to the SMTP server manually to check if it works.
On Linux you can use telnet, on Windows you can use Putty.
Hi Alex,
I’m a PHP programmer since 2008, I always avoided using the composer.
Your instructions helped me to understand how to use it. I updated and installed successfuly a package. I’m happy !!!
THANKS A LOT !!!
Zeke from Argentina
I’m glad you made it, Zeke!
hy alex
i followed your guide and achieved what i wan.thank you so much for this guide.
and one thing i wanted to ask is how to include template file in the body of phpmailer as i need to send templates and often pass data to these templates too.
can you guide me?
Hi Mary,
Do you mean using an HTML template for the email itself?
If so, you can keep the HTML template in a PHP string variable, customize the template for each email recipient, and then set the email HTML body.
I made a small example here: https://pastebin.com/NFRjcgJN
Let me know if you have any questions about it.
I have a working contactform on my website, but still a bit confused about sender and receiver.
Now I have:
setFrom($user, ‘websitename’);
addReplyTo($email, $name);
addAddress($user, ‘websiteownername’);
In which:
$user is the smtp-user
$email and $name come from the filled-in form
I think I have a security issue here, and the form is vunerable for hacking and/or spam
How do I get it the save way?
Hi Johanna,
Yes there can be some security issues. The solution here is mostly about validation.
First, I kindly ask you if you can share the code on Pastebin, because the comments here cut some code characters.
Just create a Pastebin “paste” and share the URL here.
If you prefer, we can also continue on my Facebook group: https://www.facebook.com/groups/289777711557686/
Thank you Alex.
I’ve created a pastebin:
https://pastebin.com/P2mRSMFE
I do not doubt about the security of my input data validation. But I think i’ve massed up the sender and receiver in the send-email function.
Sorry, I see that I forgot to delete the ‘ signs around host and port when I made it more anonymous. So don’t count that as a mistake please.
Hello,
Thank you for sharing the code.
Setting the reply-to address to the client’s address can be problematic:
$mail->addReplyTo($_POST[’email’], $_POST[‘name’]);
The SMTP server may block your email for this. But it depends on how it’s configured. If it works for you, then it’s ok.
Also, be sure to validate all $_POST variables even if you think they are safe. An attacker can easily mess with them.
Next, you should sanitize the variables used in the email body.
For example, this:
$body = ‘Name: ‘.$_POST[‘name’];
must become this:
$body = ‘Name: ‘. htmlentities($_POST[‘name’]);
Hi Alex,
I’ve implemented phpmailer version 6.3.0 (via Composer/packgist) for a contact page. The web server is apache 2.4 on ubuntu 20.04. It’s all working fine. Today while doing final testing and checks I noticed directory/file permissions and ownership don’t seem quite right.
vendor directory is 775
composer directory is 775
phpmailer directory is 775
phpmailer php files are 664
What are the minimum permissions required ?
I’ve searched github, stackoverflow, and googled but I don’t see any definitive guide. I’d appreciate your insights.
Hello,
These permissions seem just fine.
775 is the standard permission mask for public directories, and 664 is the standard mask for public files.
The difference is about “execution”. For directories, the execution permission actually means traversal permission, so it must be set if you want users to enter the directory. Files do not need the execution permission if they are not executables.
Hi Alex, I need help. It is for a website made with Adobe Muse hosted on hosting. I have downloaded the 3 essential files and placed them in the PHPMailer folder, inside the Scripts folder. To make the web stop sending two forms that exist, in php mail (), I must fix it and connect with PHPMailer. Do I have to make a new file with custom shipping settings? How do I link it to PHPMailer? and how do I link it to the web? I’m going crazy, help please.
Hello Miriam,
To use PHPMailer in any of your PHP scripts, you simply need to include the PHPMailer files (like in the tutorial examples).
If you are moving from the mail() function, simply replace every mail() instance with PHPMailer.
If you can share your code maybe I can give you more help. We can also talk on my Facebook group: https://www.facebook.com/groups/289777711557686/
I’m sorry but I don’t have rrss, I don’t like them. I put the code of the form_process.php file that is on the web. I have tried several options but I can not get it to work, if you want and it is possible you can write me to my email and I will give you more information if you need it or you think it is better, it is that I am doing a favor to a friend with the adobe web muse and I no longer know how to get it to receive the forms, the hosting says that it is the mail () format, they do not authorize it and they demand that it be SMTP with TLS. If this is not the code you are asking me, you will tell me, I also made a new file called send.php but it doesn’t work for me either. Thank you very much Alex, is that so much reading about how to use PHPMailer has made my head a mess, sorry.
It won’t let me put the code for you, I get a warning about something wrong, I guess it’s too long. Tell me at least how to communicate please, please, please. Thanks again Alex.
I’m only sending you a few pieces because it won’t let me include it, I don’t know how I can put the complete code for you to help me.
IsSMTP();
$mail->SMTPDebug = off;
$mail->Port = 587;
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Host = ‘smtp.nameserver.com’;
$mail->SMTPAuth = true;
$mail->Username = ‘info@domain.com’;
$mail->Password = ‘Secret’;
$mail->FromName = ‘webdo’;
$mail->From = ‘info@domain.com’;
$mail->AddAddress($to);
$mail->Subject = $subject;
$mail->Body = $message;
//Send the message, check for errors
if (!$mail->send()) {
echo ‘Mailer Error: ‘ . $mail->ErrorInfo;
} else {
echo ‘Message sent!’;
}
//Final del script*******
on top of that this is missing:
IsSMTP();
up is this:
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
and
this up to first text :
require(‘public/scripts/PHPMailer/src/phpmailer.php’);
require ‘public/scripts/PHPMailer/src/SMTP.php’;
require ‘public/scripts/PHPMailer/src/Exception.php’;
$mail = new PHPMailer();
$mail->IsSMTP();
Hello Miriam,
I’ll get in touch with you via email tomorrow.