PHPMailer is a code library to send (transport) emails safely and easily via PHP code from a web server (mail user agent to the mail submission server). Sending emails directly by PHP code requires a high-level familiarity with Simple Mail Transfer Protocol (SMTP) standard protocol and related issues (such as Carriage return) and vulnerabilities about Email Injection for spamming.
Features of PHPMailer
Some of the features of the PHPMailer we would tap into are further listed below:
- Plain text, HTML and multipart batched files
- SSL and TSL (Secure Sockets Layer and Transport Layer Security) but in this tutorial we would be making use of TSL
- SMTP, POP3
- Debugging system
- PHP send mail and mail methods
Terminologies
· PHP
PHP is a popular general-purpose scripting language that is especially suited to web development. Fast, flexible and pragmatic, PHP powers everything from your blog to the most popular websites in the world.
· POP3
In computing, the Post Office Protocol (POP) is an application-layer Internet standard protocol used by e-mail clients to retrieve e-mail from a mail server.
· SMTP
The Simple Mail Transfer Protocol (SMTP) is a communication protocol for electronic mail transmission. User-level email clients typically use SMTP only for sending messages to a mail server for relaying, typically submit outgoing email to the mail server.
· SSL & TLS
Transport Layer Security (TLS), and its now-deprecated predecessor, Secure Sockets Layer (SSL) are cryptographic protocols designed to provide communications security over a computer network. The TLS protocol aims primarily to provide privacy and data integrity between two or more communicating computer applications.
Resources
· Composer – Dependency Manager for PHP
· PHPMailer – Email Sending Library for PHP
· Bootstrap & jQuery CDN
· Active Gmail account
Setup
Composer
To get started with this tutorial we need to install Composer on our machine and a way to get to do this is by running PHP Composer Install or download it.
PHPMailer
Once we have Composer installed on our local machine, we can proceed to install PHPMailer via the description below:
Bootstrap & jQuery CDN
To make use of modern CSS design patterns we adopt the use of Bootstrap and jQuery in this tutorial, hence we will be connecting to their various CDN links available here.
Let’s Start Coding
First, we need to create a file and save as a .php extension. This would enable files processed across the server and thus enable mail delivery. Then we should proceed to structure our tags, connect to our CDN to activate Bootstrap styles and also add a bit of JavaScript to validate input fields, this allows us ensure that fields will not be left empty.
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Sending Feedback PHPMailer</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> </head> <body> <!-- Button trigger modal --> <button type="button" class="btn btn-primary mt-3 ml-4" data-toggle="modal" data-target="#exampleModal"> Feedback form </button> <!-- Modal --> <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <form method="POST" enctype="multipart/form-data" class="container" id="needs-validation" novalidate> <div class="modal-header"> <h5 class="modal-title" id="exampleModalLabel">Modal title</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <div class="row"> <div class="col-md-12"> <div class="form-group"> <input type="text" class="form-control" name="username" placeholder="username"> <div class="invalid-feedback"> Please provide username. </div> </div> </div> <div class="col-md-12"> <div class="form-group"> <input type="email" class="form-control" name="email" placeholder="email"> <div class="invalid-feedback"> Please provide valid email. </div> </div> </div> <div class="col-md-12"> <div class="form-group"> <select name="to" class="form-control"> <option value="sales">Sales</option> <option value="support" selected="selected">Support</option> </select> </div> </div> <div class="col-md-12"> <div class="form-group"> <textarea class="form-control" name="reason" rows="2" required=""></textarea> <div class="invalid-feedback"> Please provide feedback information. </div> </div> </div> <div class="col-md-12"> <div class="form-group"> <input type="file" name="attachment"> <div class="invalid-feedback"> Please attach file </div> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> <button type="submit" class="btn btn-primary" name="feedback">Send Feedback</button> </div> </form> </div> </div> </div> </body> </html>
Here we have been able to structure our hypertext markup tag, Next is adding to our script tag to enable us add form validation and form submisson
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script> (function() { 'use strict'; window.addEventListener('load', function() { var form = document.getElementById('needs-validation'); form.addEventListener('submit', function(event) { if (form.checkValidity() === false) { event.preventDefault(); event.stopPropagation(); } form.classList.add('was-validated'); }, false); }, false); })(); </script>
Next we can put it all together to enable us have a well structured code
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Sending Feedback PHPMailer</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> </head> <body> <!-- Button trigger modal --> <button type="button" class="btn btn-primary mt-3 ml-4" data-toggle="modal" data-target="#exampleModal"> Feedback form </button> <!-- Modal --> <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <form method="POST" enctype="multipart/form-data" class="container" id="needs-validation" novalidate> <div class="modal-header"> <h5 class="modal-title" id="exampleModalLabel">Modal title</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <div class="row"> <div class="col-md-12"> <div class="form-group"> <input type="text" class="form-control" name="username" placeholder="username"> <div class="invalid-feedback"> Please provide username. </div> </div> </div> <div class="col-md-12"> <div class="form-group"> <input type="email" class="form-control" name="email" placeholder="email"> <div class="invalid-feedback"> Please provide valid email. </div> </div> </div> <div class="col-md-12"> <div class="form-group"> <select name="to" class="form-control"> <option value="sales">Sales</option> <option value="support" selected="selected">Support</option> </select> </div> </div> <div class="col-md-12"> <div class="form-group"> <textarea class="form-control" name="reason" rows="2" required=""></textarea> <div class="invalid-feedback"> Please provide feedback information. </div> </div> </div> <div class="col-md-12"> <div class="form-group"> <input type="file" name="attachment"> <div class="invalid-feedback"> Please attach file </div> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> <button type="submit" class="btn btn-primary" name="feedback">Send Feedback</button> </div> </form> </div> </div> </div> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script> (function () { 'use strict'; window.addEventListener('load', function () { var form = document.getElementById('needs-validation'); form.addEventListener('submit', function (event) { if (form.checkValidity() === false) { event.preventDefault(); event.stopPropagation(); } form.classList.add('was-validated'); }, false); }, false); })(); </script> </body> </html>
<?php // use the phpmailer we installed via composer use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; require 'vendor/autoload.php'; require 'vendor/phpmailer/phpmailer/src/Exception.php'; require 'vendor/phpmailer/phpmailer/src/PHPMailer.php'; require 'vendor/phpmailer/phpmailer/src/SMTP.php'; if (array_key_exists('to', $_POST)) { $err = false; $msg = ''; $email = ''; //Apply some basic validation and filtering to the query if (array_key_exists('reason', $_POST)) { //Limit length and strip HTML tags $reason = substr(strip_tags($_POST['reason']), 0, 16384); } else { $reason = ''; $msg = 'No feedback provided!'; $err = true; } //Apply some basic validation and filtering to the name if (array_key_exists('username', $_POST)) { //Limit length and strip HTML tags $username = substr(strip_tags($_POST['username']), 0, 255); } else { $username = ''; } //Validate to address //Never allow arbitrary input for the 'to' address as it will turn your form into a spam gateway! //Substitute appropriate addresses from your own domain, or simply use a single, fixed address if (array_key_exists('to', $_POST)) { $to = 'suleabimbola@gmail.com'; } else { $to = 'larry56@gmail.com'; } //Make sure the address they provided is valid before trying to use it if (array_key_exists('email', $_POST) and PHPMailer::validateAddress($_POST['email'])) { $email = $_POST['email']; } else { $msg .= "Error: invalid email address provided"; $err = true; } if (array_key_exists('attachment', $_FILES)) { $img_name = $_FILES['attachment']['name']; $upload = tempnam(sys_get_temp_dir(), hash('sha256', $_FILES['attachment']['name'])); //to sure image upload goes to root directory add a link in my own case my project folder is Mail $uploadfile = $_SERVER['DOCUMENT_ROOT'].'/Mail/assets/img/'.$img_name; if (move_uploaded_file($_FILES['attachment']['tmp_name'], $uploadfile)) { if (!$err) { $mail = new PHPMailer(true); $mail->isSMTP(); // SMTPDebug turns on error display mssg // $mail->SMTPDebug = 3; $mail->SMTPSecure = 'tls'; $mail->Host = 'smtp.gmail.com'; // set a port $mail->Port = 587; $mail->SMTPAuth = true; // set login detail for gmail account $mail->Username = 'Your_emailaddress'; $mail->Password = 'Your_password'; $mail->CharSet = 'utf-8'; // set subject $mail->setFrom($email, $username); $mail->addAddress($to); $mail->addReplyTo($email, $username); $mail->addAttachment($uploadfile, 'My uploaded image'); $mail->IsHTML(true); $mail->Subject = 'Contact form: Feedback form'; $mail->Body = $reason; if (!$mail->send()) { $msg .= "Mailer Error: " . $mail->ErrorInfo; } else { $msg .= "Message sent!"; } } } else { $msg .= 'Failed to move file to ' . $uploadfile; } } } ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Sending Feedback Phpmailer</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> </head> <body> <!-- Button trigger modal --> <button type="button" class="btn btn-primary mt-3 ml-4" data-toggle="modal" data-target="#exampleModal"> Feedback form </button> <!-- Modal --> <?php if(empty($msg)){ ?> <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <form method="POST" enctype="multipart/form-data" class="container" id="needs-validation" novalidate> <div class="modal-header"> <h5 class="modal-title" id="exampleModalLabel">Modal title</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <div class="row"> <div class="col-md-12"> <div class="form-group"> <input type="text" class="form-control" name="username" placeholder="username"> <div class="invalid-feedback"> Please provide username. </div> </div> </div> <div class="col-md-12"> <div class="form-group"> <input type="email" class="form-control" name="email" placeholder="email"> <div class="invalid-feedback"> Please provide valid email. </div> </div> </div> <div class="col-md-12"> <div class="form-group"> <select name="to" class="form-control"> <option value="sales">Sales</option> <option value="support" selected="selected">Support</option> </select> </div> </div> <div class="col-md-12"> <div class="form-group"> <textarea class="form-control" name="reason" rows="2" required=""></textarea> <div class="invalid-feedback"> Please provide feedback information. </div> </div> </div> <div class="col-md-12"> <div class="form-group"> <input type="file" name="attachment"> <div class="invalid-feedback"> Please attach file </div> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> <button type="submit" class="btn btn-primary" name="feedback">Send Feedback</button> </div> </form> </div> </div> </div> <?php }else{ echo $msg; } ?> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script> (function() { 'use strict'; window.addEventListener('load', function() { var form = document.getElementById('needs-validation'); form.addEventListener('submit', function(event) { if (form.checkValidity() === false) { event.preventDefault(); event.stopPropagation(); } form.classList.add('was-validated'); }, false); }, false); })(); </script> </body> </html>
Screenshot
After mail has been sent, the PHPMailer would return an error in this format.
To resolve this problem click here login then click on security then click to switch “Allow less secure apps: ON“.
Fixed the problem of could not be authenticated and boom email get sent to user address.
Email delivery to my Google account shows mail was successfully sent ! Yippee!
Conclusion
What inspired me to write this was due to the fact that I found it challenging while trying to send mails with attachment, but on successful completion of the task I was happy and decided to help so many others who might face this same challenge in the future.
The complete source code is here.
Happy coding!