My struggle with phpmailer, wamp, xampp, and gmail smtp.

So far I have been coding for a little over two months, in training with BeCode in the hope of getting a job in web development.
Things have become progressively more complex and for the last couple of weeks we have been dealing with PHP.

The creation of a to-do list was a somewhat difficult challenge simply due to the number of possibilities to take into account, with the use of javascript greatly simplifying the problem. All in all, I found all the work rather easy.
And so it was with a great sense of confidence that I set to the task of creating a simple mailing function.

The only good DC movies in recent years are the animated one.

Needless to say that with the universe great love for irony, I was in for a very rough ride.

Part one: the easy part.

Step one: installing composer.
This step was of no great problem. Working with windows does have its advantages. Simplicity of installation being one of them.

Step two: installing phpmailer as a dependency with composer.
This step was, as well, not a problem. The documentation for phpmailer is rather well written and following the basic instruction was relatively easy.

Using the terminal you simply need to ensure you are currently in the folder with your project (Using cd) and then entering the following command:

composer require phpmailer/phpmailer

This would create the composer.json file that is required for the following work. In essence the composer.json tells the app which files are required for the app to work. In this case the phpmailer files.

Step three: using the correct mailer code.
Going back to the github of phpmailer, you will be able to find a folder named examples. This folder contains, surprisingly enough, multiple examples of how to use the phpmailer code.

For the purpose of using an SMTP it is necessary to use a working SMTP server. 
Perhaps it might be useful to spend a minute explaining what an SMTP server is. An SMTP server (standing for simple mail transport protocol) is quite literally what it says on the tin, a server dedicated to transferring mail. Much like other types of server it is possible to run one locally on your machine. In fact XAMPP comes pre-installed with such a service in the form of mercury.

So for the purpose of this exercise I decided to use the gmail SMTP server since it is readily available to the public.

After copying the relevant code, most of the work was already done for me. The exemple code given in the gmail.phps file was already configured to access the gmail server.

In fact, only a small part of the code needed to be modified for actual use.

step four: modifying the code

//Username to use for SMTP authentication — use full email address for gmail
$mail->Username = “username@gmail.com”;
/Password to use for SMTP authentication
$mail->Password = “yourpassword”;
//Set who the message is to be sent from
$mail->setFrom(‘from@example.com’, ‘First Last’);
//Set an alternative reply-to address
$mail->addReplyTo(‘replyto@example.com’, ‘First Last’);
//Set who the message is to be sent to
$mail->addAddress(‘whoto@example.com’, ‘John Doe’);
//Set the subject line
$mail->Subject = ‘PHPMailer GMail SMTP test’;
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents(‘contents.html’), __DIR__);
//Replace the plain text body with one created manually
$mail->AltBody = ‘This is a plain-text message body’;
//Attach an image file
$mail->addAttachment(‘images/phpmailer_mini.png’);

These represent the part of the code that needs to be modified to create a fully functioning email. This code can be slightly modified to exclude parts that aren’t useful to you.

//Username to use for SMTP authentication — use full email address for gmail
$mail->Username = “username@gmail.com”;
//Password to use for SMTP authentication
$mail->Password = “yourpassword”;

These two lines of code are used to identify yourself to the gmail SMTP server. While you could simply enter your password directly into the code I highly discourage you from doing this, this will make you exceedingly vulnerable to hacking. Anyone who can see your code will be able to obtain your password.

Rather than modify the code directly I recommend you create a form from which you will get the information you need.

In the end your code should more probably look something like this:

$password = $_POST[‘password’];
$mail->Password = $password;
unset($password);

Of course this is the most basic of precautions, it would be a good idea to sanitize and validate your entire form before you even use the result into the mail code but I will assume here that you already know how to do this.
The unset line of code is putting the $password variable back to null which means it exists only long enough to be passed to the mail object and no longer.

//Set who the message is to be sent from
$mail->setFrom(‘from@example.com’, ‘First Last’);
//Set an alternative reply-to address
$mail->addReplyTo(‘replyto@example.com’, ‘First Last’);
//Set who the message is to be sent to
$mail->addAddress(‘whoto@example.com’, ‘John Doe’);

This part of the code is used to set both the recipient and the sender, as well as define an alternative adress to be used to receive replies. This particular line of code for alternatives can be safely edited out of the code. 
Also note that only valid adresses are required, the ‘First Last’ and ‘John Doe’ parameter can also be entirely omitted if you so wish.

//Set the subject line
$mail->Subject = ‘PHPMailer GMail SMTP test’;
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents(‘contents.html’), __DIR__);
//Replace the plain text body with one created manually
$mail->AltBody = ‘This is a plain-text message body’;
//Attach an image file
$mail->addAttachment(‘images/phpmailer_mini.png’);

This is perhaps the part of the code that can be most heavily modified. 
The code under the comment ‘//Attach an image file’ can be discarded as it only concern attachments of external files. This can of course be very useful, but for the sake of a simple test I have ommitted it.

Meanwhile, both of these:

//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents(‘contents.html’), __DIR__);
//Replace the plain text body with one created manually
$mail->AltBody = ‘This is a plain-text message body’;

Are about the message to be sent in and of itself. It is possible to send an entire HTML page with an alt in case this page cannot be displayed; or for very simple text message it is also possible to simply use this line of code, replacing those above entirely:

$mail->Body = ‘your message’;

Once all of this is done, I recommend unseting the entire $_POST for safety sake. This way any data sent via the form you will have created will be entirely removed, existing only into the $mail object.

step five: sending the mail
It’s time to get your Kevin Costner on because we are now ready to send this mail!

Obscure 90s references are cool
//send the message, check for errors
if (!$mail->send()) { echo “Mailer Error: “ . $mail->ErrorInfo;}
else { echo “Message sent!”;
//Section 2: IMAP //Uncomment these to save your message in the ‘Sent Mail’ folder. #
if (save_mail($mail)) { # echo “Message saved!”; #}
}
//Section 2: IMAP//IMAP commands requires the PHP IMAP Extension, found at: https://php.net/manual/en/imap.setup.php
//Function
to call which uses the PHP imap_*() functions to save messages: https://php.net/manual/en/book.imap.php
//You
can use imap_getmailboxes($imapStream, ‘/imap/ssl’) to get a list of available folders or labels, this can
//be useful if you are trying to get this working on a non-Gmail IMAP server.function save_mail($mail){
//You can change ‘Sent Mail’ to any other folder or tag $path = “{imap.gmail.com:993/imap/ssl}[Gmail]/Sent Mail”;
//Tell your server to open an IMAP connection using the same username and password as you used for SMTP
$imapStream = imap_open($path, $mail->Username, $mail->Password); $result = imap_append($imapStream, $path, $mail->getSentMIMEMessage()); imap_close($imapStream); return $result;}

Yes, I know, this looks like a jumbled mess, I blame the text editor. You can blame my lazyness if you want.

In any case, the good news is that the entirety of section exists solely so you can save your sent email somewhere. It is, therefore, optionnal.
After trimming the fat the code will look like this:

//send the message, check for errors
if (!$mail->send()) { echo “Mailer Error: “ . $mail->ErrorInfo;}
else { echo “Message sent!”;
}

And now our code is ready to be sent.

Part two: the nightmare begins

Obscure 80s references are even cooler

Yes, this is where things got rough for me, very very rough.

You see, I made a terrible mistake, I tried to use my code in local. This resulted in me having problems after problems with security certificate.

Connection failed. Error #2: stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages:error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed [C:\xampp\htdocs\php_mail_test\vendor\phpmailer\phpmailer\src\SMTP.php line 404]

The error code that haunts my nightmare, stalking me for days on end. I tried it all to resolve it. I tried to create a dozen security certificate, I tried to modify half a dozen config file, in the process I even switched from wamp to xampp. One of the few things I don’t regret doing during those days by the way.

In the end, nearly reduced to a state of madness I even reverted to using a simple PHP mail() function, just to see if the damn thing would work.

AFter a brief stint in the insane asylum, I was ready to continue working. And, after realising that making the app work in local was essentially impossible, I moved on and put it in heroku. And then, a fantastic thing happened….

It still didn’t work!

I was ready to end it all, throw my computer into the trash and live the life of an hermit deep in the wood, wrapped in the pelt of a bear I strangled to death with my bare hands in pure impotent coding rage. That’s when I realized the error message had changed.

The first thing I had to do was to visit this link to allow my gmail account to accept input from less secure applications. Otherwise I would have required a different code using identifications token issued by google to make everything work; I was not, at this point, willing to go to such length.

Another test, another mistake, but at least there was progress.

After some research I finally found the solution. I had to visit this link to allow the application to not use captcha.

And then, finally, my app was error free. The simplest possible mailer was working and I was ready to face a new, more dangerous and bugged world of PHP.