PHPMailer: The robust email-sending library for PHP apps with SMTP & attachment support. Install via Composer for efficient functionality.
The PHPMailer plain text class is the best choice for including email functionality in your PHP application. It works with the majority of PHP frameworks (Laravel or Symfony are based on the SwiftMailer library, though, but it is still possible to use PHPMailer as well.) Using SMTP or a local web server, PHPMailer offers the robust capability for creating HTML emails with attachments and sending them to numerous recipients.
What is PHPMailer?
The traditional email-sending library from PHP is called PHPMailer. Direct dispatch to SMTP servers, mail(), Sendmail, and other methods of delivering email are also supported. It also lists several sophisticated features:
- authentication for SMTP.
- MIME safe encryption.
- TLS and SSL protocol support.
- combined with plain text and HTML.
- several binaries, textual, and fs attachments.
- support for embedded images.
PHPMailer and SMTP Email Sending
You must first install PHPMailer and set up your SMTP settings before you can send emails using SMTP and PHPMailer.
Installing PHPMailer: Steps
Up until version 5, all that was required to start a PHPMailer instance was to include the "PHPMailerAutoload.php" file in your script. Since PHPMailer 6.0 was released in August 2017, you must install it, ideally via Composer, a PHP dependency management (this method is advised by the developers of PHPMailer on Github). Add this line to your composer after installing the Composer.json file :
"phpmailer/phpmailer": "~6.1"
Or
composer require phpmailer/phpmailer
You can manually add PHPMailer if, for instance, you're working in a testing environment and don't want to install Composer. Copy the contents of the PHPMailer plain text folder to one of the included path directories listed in your PHP settings, then manually load each class file:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'path/to/PHPMailer/src/Exception.php';
require 'path/to/PHPMailer/src/PHPMailer.php';
require 'path/to/PHPMailer/src/SMTP.php'
Alternative: Download the PHPMailer source code files.
You can manage issues and troubleshoot them with the addition of the Exception class. Like other programming languages, PHP operates similarly. Therefore, without it, if there is a problem with your email sending code, all you will get is a notice that says, "Exception class is not found," without any information on how to troubleshoot it. Debugging will be covered separately in this post.
Configuring SMTP
How can I use PHPMailer to send test messages?
We will utilize MailSlurp, a fake SMTP server, to test PHP mail capabilities so as not to overburden our inboxes or, worse still, the inboxes of our clients. Once you make sure that everything works properly and your email messages look right, you will be able to quickly swap the SMTP settings in our samples with your real servers.
Create a free account with MailSlurp if you haven't already, then go to your Inbox and copy the values from the SMTP settings tab into your PHPMailer script
-
server host (
$mail->Host = 'mx.mailslurp.com'
) -
username (
$mail->Username = '23489drj'
(example, generated by MailSlurp)) -
password (
$mail->Password = 'dfshsdfj'
(example, generated by MailSlurp))
and:
- port (
$mail->Port = 25
, or 465, or 2525)
SMTP vs POP3
POP-before-SMTP for authentication is the last aspect of SMTP to be discussed. Although SMTP authentication has nearly completely supplanted this mechanism, it is still occasionally applicable. The transparency of the user sending an email is its key benefit. To see an example of using POP before SMTP with PHPMailer plain text, visit this Github page.
Making use of PHPMailer to send HTML email via SMTP
Most likely, you'll build your email notice using HTML. So let's go over some actual uses for HTML properties and functions.
Message in HTML basics
Include the autoload.php file produced by Composer if you used it for installation:
require 'path/to/composer/vendor/autoload.php';
If you manually installed PHPMailer, initialize it as follows:
require path/to/PHPMailer/src/PHPMailer.php';
require path/to/PHPMailer/src/SMTP.php';
require path/to/PHPMailer/src/Exception.php';
Afterward, develop the PHPMailer class:
<?php
use PHPMailer\PHPMailer\PHPMailer;
The following action is to make a fresh PHPMailer object:
$mail = new PHPMailer();
Let's proceed to set up SMTP:
$mail->isSMTP();
$mail->Host = 'mx.mailslurp.com';
$mail->SMTPAuth = true;
$mail->Username = '1a2b3c4d5e6f7g'; //paste one generated by
MailSlurp
$mail->Password = '1a2b3c4d5e6f7g' //paste one generated by
MailSlurp
$mail->SMTPSecure = 'tls';
$mail->Port = 2525;
Indicate the PHPMailer headers:
$mail->setFrom('info@MailSlurp.com', 'MailSlurp');
$mail->addReplyTo('info@MailSlurp.com', 'MailSlurp');
$mail->addAddress('recipient1@MailSlurp.com', 'James');
$mail->addCC('cc1@example.com', 'Jack');
$mail->addBCC('bcc1@example.com', 'Wus');
If you want to add many addresses, create a separate command for each one:
$mail->AddBCC('bcc2@example.com', 'Anna');
$mail->AddBCC('bcc3@example.com', 'Mark');
Set a subject:
$mail->Subject = 'Test Email via MailSlurp SMTP using PHPMailer';
Then, using the isHTML(true) property, set the email format to HTML:
$mail->isHTML(true);
The desired material can now be entered:
$mailContent = "<h1>Send HTML Email using SMTP in PHP</h1>
<p>This is a test email I'm sending using SMTP mail server with
PHPMailer.</p>";
$mail->Body = $mailContent;
Reading and sending
You can send your message in a loop to numerous recipients using PHPMailer. You can read a list from the table, in particular. In a later section of this essay, we'll go over some of these examples again, but for now, let's focus on the core idea.
You can create beautiful HTML emails with PHPMailer plain text as well as send emails that have attachments and custom formatting. For your convenience, PHPMailer plain text can convert referenced images to embedded images, read an HTML message body from an external file, and convert HTML into a simple plain-text alternative body. In this manner, you can update your HTML template independently and avoid overburdening your message-sending code with HTML. Add the following properties to incorporate a different HTML file:
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
Finally, list the characteristics of email sending:
if($mail->send()){
echo 'Message has been sent;
}else{
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
}
You know that your code has been executed properly when you see the message "Message has been sent." Visit your MailSlurp inbox to view the delivery status and other details; your messages will arrive there in a matter of seconds.
PHP Mailer with MailSlurp
With MailSlurp, you can check your HTML code, and raw data, test your email client and ensure that neither your message nor your sending domain will be flagged as spam.
All test emails should be recorded and examined in one location.
Attachments in HTML emails
Two possibilities exist for including files in your message:
-
Include a file from your filesystem, just like you would in an email. Your files should be saved in the same directory as the script in this situation.
-
Additionally, you can inline a file within your message; this works for photos.
-
Add a string attached to the message, which will attach the data contained in the variable. You don't actually need to store it as a file because it may be pulled from a database, for instance.
Just enter a file's path to attach it. Additionally, but optionally, supply a filename; the script will use it instead:
$mail->addAttachment('path/to/invoice1.pdf', 'invoice1.pdf');
Repeat the command to add an additional file:
$mail->addAttachment('path/to/calculation1.xlsx',
'calculation1.xlsx');
Use the addStringAttachment()
command to add an attachment from a
string. The filename and the content should be passed:
$mysql_data = $mysql_row['blob_data'];
$mail->addStringAttachment($mysql_data, 'db_data.db');
This is an illustration of adding data from a MySQL database that is stored as a BLOB (Binary Large OBject).
You can also use a remote URL, like the one below:
$mail->addStringAttachment(file_get_contents($url),
'file.pdf');
Here, we employ CID attachments to embed images:
$mail->addEmbeddedImage('path/to/image_file.jpg', 'image_cid');
$mail->isHTML(true);
$mail->Body = '<img src="cid:image_cid">';
Complete message example
Let's explore an example of a complete message that includes an internal HTML body and an inlined image.
<?php
use PHPMailer\PHPMailer\PHPMailer;
require 'path/to/composer/vendor/autoload.php';
$mail->isSMTP();
$mail->Host = 'mx.mailslurp.com';
$mail->SMTPAuth = true;
$mail->Username = 'paste one generated by MailSlurp';
$mail->Password = 'paste one generated by MailSlurp'
$mail->SMTPSecure = 'tls';
$mail->Port = 2525;
$mail->setFrom('from@example.com', 'First Last');
$mail->addReplyTo('towho@example.com', 'John Doe';
$mail->isHTML(true);
$mail->Subject = "PHPMailer SMTP test";
$mail->addEmbeddedImage('path/to/image_file.jpg', 'image_cid');
$mail->Body = '<img src="cid:image_cid"> Mail body in HTML';
$mail->AltBody = 'This is the plain text version of the email
content';
if(!$mail->send()){
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
}else{
echo 'Message has been sent';
}
You know that your code is running properly when you see the message "Message has been sent" as a result. Visit your MailSlurp inbox to view the delivery status and other details; your messages will arrive there in a matter of seconds.
Testing sending
With MailSlurp, you can check your HTML code, and raw data, test your email client and ensure that neither your message nor your sending domain will be flagged as spam.
You can switch to standard email sending using any desired SMTP server once you have confirmed that the PHPMailer sending result meets your expectations.
Distributing emails to numerous people
In the section above, we looked at how to send the same email to several recipients while also using the CC and BCC functions. For transactional emails, it's common to need to send an updated message to a list of recipients. What then? These usage cases are also supported by PHPMailer's features!
<?php
use PHPMailer\PHPMailer\PHPMailer;
require 'path/to/composer/vendor/autoload.php';
$mail = new PHPMailer;
$body = file_get_contents('contents.html');
$mail->isSMTP();
$mail->Host = 'mx.mailslurp.com';
$mail->SMTPAuth = true;
$mail->Username = '1a2b3c4d5e6f7g'; //generated by MailSlurp
$mail->Password = '1a2b3c4d5e6f7g'; //generated by MailSlurp
$mail->SMTPSecure = 'tls';
$mail->Port = 2525;
$mail->SMTPKeepAlive = true; // add it to keep SMTP connection open
after each email sent
$mail->setFrom('list@example.com', 'List manager');
$mail->Subject = "New MailSlurp mailing list";
$users = [
['email' => 'john@example.com', 'name' => 'John'],
['email' => 'dave@example.com', 'name' => 'Dave']
];
foreach ($users as $user) {
$mail->addAddress($user['email'], $user['name']);
$mail->Body = "<h2>Hello, {$user['name']}!</h2> <p>How
are you?</p>";
$mail->AltBody = "Hello, {$user['name']}! \n How are you?";
try {
$mail->send();
echo "Message sent to: ({$user['email']})
{$mail->ErrorInfo}\n";
} catch (Exception $e) {
echo "Mailer Error ({$user['email']}) {$mail->ErrorInfo}\n";
}
$mail->clearAddresses();
}
$mail->smtpClose();
Gmail usage instructions for PHPMailer
One of the most widely used SMTP servers that enable free email sending is Gmail. However, some fiddling with the login settings is necessary.
Encryption
The standard Gmail SMTP credentials are as follows:
$mail->SMTPSecure = 'tls';
$mail->Host = 'smtp.gmail.com';
$mail->Port = 587;
Or
$mail->SMTPSecure = 'ssl';
$mail->Host = 'smtp.gmail.com';
$mail->Port = 465;
Utilize your Gmail address and password to access your Gmail account if you don't use two-step verification for your account.
In your account settings, you should permit less secure applications. Please be aware that this setting may not take effect for a few hours. You can occasionally need to adjust anything on the unlock CAPTCHA page.
In the event that something goes wrong, you will get the error "5.7.14." Try again after logging in using your web browser, or "Username and Password not accepted." Instructions on how to remedy it ought to be included.
Verification in Two Steps
You must generate an App password if 2-step verification is set for your Gmail account and you want to utilize it with PHPMailer. The 16-digit passcode should be entered as the value for $mail->Password. Following these Google guidelines will make it simple to generate one.
XOAuth2
Despite being the most challenging, OAuth2 is still the suggested approach. Thank goodness for oauth2-google. It is a package to facilitate the PHP League's OAuth 2.0 Client's use of Google OAuth 2.0. It supports PHP versions 7.0 through 7.3. You must first obtain a Google client ID and client secret in order to utilize it. To set things up, adhere to this Google manual. Once finished, use composer to install the package, then add the authorization information as follows:
composer require league/oauth2-google
use League\OAuth2\Client\Provider\Google;
$provider = new Google([
'clientId' => '{google-client-id}',
'clientSecret' => '{google-client-secret}',
'redirectUri' => 'https://example.com/callback-url',
]);
Without using an SMTP server, send an email to PHPMailer.
The most common and useful transport option with PHPMailer is SMTP. But as we just explained, it also supports various approaches.
Use the normal Sendmail software for localhost:
// Set mailer with this method
$mailer->isSendmail();
// And send mail as usual
$mailer->send();
Use qmail if you prefer Unix:
// Set mailer with this method
$mailer->isQmail();
// And send mail as usual
$mailer->send();
Debugging PHP Mailer
The SMTPDebug command will assist you in investigating any issues you have when sending emails using an SMTP server and determining what needs to be resolved.
Enable SMTP debugging and modify your script's debug level as follows:
$mail->SMTPDebug = 2;
Debug levels
-
Level 1 (client) displays messages that the client has sent.
-
Level 2 is the suggested setting; it means client and server and will add server messages.
-
Level 3 (client, server, and connection) adds details to the first data and may be helpful in identifying STARTTLS errors.
-
Low-level information is level 4.
If level 2 doesn't work at all, try level 3 or level 4. Debugging can be turned off by setting level 0; this setting is often used for production.
More PHP Mailer examples
Let's go over a few examples to gain a better grasp of how debugging in PHPMailer functions.
1. An incorrect SMTP hostname
2018-12-12 14:51:32 Connection: opening to mailslurp.com:2525,
timeout=10, options=array()
2018-12-12 14:51:42 Connection failed. Error #2:
stream_socket_client(): unable to connect to mailslurp.com:2525 (Operation
timed out) [/Users/xxxx/Downloads/PHPMailer/src/SMTP.php line 326]
2018-12-12 14:51:42 SMTP ERROR: Failed to connect to server: Operation
timed out (60)
2018-12-12 14:51:42 SMTP connect() failed.
Mailer Error: SMTP connect() failed.
In this illustration, we typed mailslurp.com instead of mx.mailslurp.com as the hostname, which is incorrect, and we immediately got a notice saying that there was a problem with the server's initial communication.
Example 2. False identification
2018-12-12 14:49:26 Connection: opening to mx.mailslurp.com:2525,
timeout=300, options=array()
2018-12-12 14:49:26 Connection: opened
2018-12-12 14:49:26 SMTP INBOUND: "220 mailslurp.com ESMTP ready"
2018-12-12 14:49:26 SERVER -> CLIENT: 220 mailslurp.com ESMTP ready
...
2018-12-12 14:49:30 SMTP INBOUND: "535 5.7.0 Invalid login or
password"
2018-12-12 14:49:30 SERVER -> CLIENT: 535 5.7.0 Invalid login or
password
2018-12-12 14:49:30 SMTP ERROR: Username command failed: 535 5.7.0
Invalid login or password
2018-12-12 14:49:30 SMTP Error: Could not authenticate.
2018-12-12 14:49:30 CLIENT -> SERVER: QUIT
2018-12-12 14:49:30 SMTP INBOUND: "221 2.0.0 Bye"
2018-12-12 14:49:30 SERVER -> CLIENT: 221 2.0.0 Bye
2018-12-12 14:49:30 Connection: closed
2018-12-12 14:49:30 SMTP connect() failed.
Mailer Error: SMTP connect() failed.
The SMTP, its hostname, and port are now correct, but a login and password combination was not identified, illustrating where the mistake occurs. As a result, you should double-check and adjust your credentials.
When you need to delve deeper into debugging and troubleshooting, look to the aforementioned in-depth articles on GitHub.
Additional information on PHPMailer
The most typical PHPMailer use cases have been covered in this article, including producing HTML emails with graphics and attachments, delivering them through SMTP or localhost to various recipient types, and providing debugging options.
Check the "examples" subdirectory in the PHPMailer docs on Github if you require more detailed examples.