Send email via SMTP

Hi guys

I have some php code which submits an email to the user (and CC’s me) using php’s mail() function. This was inconsistent in getting to the user’s inbox, unsurprisingly because it was sometimes being marked as spam, and other times not even getting as far as the user’s spam box!

The emails are handled by o365. I did try specifying in php to send the email via smtp, but I just couldnt get it working. That was about 6 months ago, so cant remember what I tried.

I really need to get this sending via smtp but I need a bit of hand-holding. I have the mailbox’s username/password etc… so its just a case of getting the ‘smtp bit’ working.

I suppose I could use an SMTP service like SendGrid, but Id rather not if I can help it. (because I think that the contents of the email needs to reside on SendGrids platform, yet some of the email’s content is dynamically generated depending on what the user has entered on the form, so I dont know how I could get that working with SendGrid).

If I can just get a ''hello world" example of sending email via smtp using my mailbox settings, then I can do the rest.

Thanks

I would use PHPMailer. PHP’s mail() function is inherently unreliable. To quote from the PHPMailer readme:

Please don’t be tempted to do it yourself – if you don’t use PHPMailer, there are many other excellent libraries that you should look at before rolling your own. Try SwiftMailer, Laminas/Mail, ZetaComponents etc.

Of course, there is still a chance that emails end up in spam depending on the recipient’s spam settings.

Thanks @Gandalf. So PHPMailer sends email via SMTP?

Ive just had a look at my code, and it looks like I already tried using PHPMailer, without success. :frowning:

I have this commented out in my code (Ive obviously hashed-out the mailbox details):

/*
require_once DIR.’/…/calendar/config/class-phpmailer.php’;
$mailer = new PHPMailer();
$mailer->IsSMTP();
$mailer->Host = “smtp.office365.com”;
$mailer->SMTPAuth = true;
$mailer->Username = “###@###.com”;
$mailer->Password = “###”;
$mailer->setFrom(’###@###.com’, ‘###’);
$mailer->AltBody = “To view the message, please use an HTML compatible email viewer.”;
$mailer->addAddress($requestData[‘email’]);
$mailer->msgHTML($message);
$mailer->Subject = $subject;
$mailer->send();
//$mailer->clearAllRecipients();
*/

Is there anything obviously wrong with the above?

It looks as though that might be an old version of PHPMailer you were using.

You’ll want a new directory named PHPMailer with the library code in there and

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

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

followed by the rest of the code. I don’t have time to check what you have line by line right now. You’ll find the latest version on GitHub.

Lovely - thanks @Gandalf. I will take a look at this later/tomorrow and let you know how I get on. :slight_smile:

While I haven’t used PHPMailer, or Outlook365, keep in mind that some of these public mail services require additional settings. I have used Gmail to send emails, and they require TLS and alternate ports, for example. But there’s information on their web site about it, as I am sure there will be for O365.

Doesn’t everything send email via SMTP? From what I can see, the isSMTP() option in PHPMailer just switches between PHPMailer using the inbuilt mail() function and talking directly to the SMTP server.

1 Like

I recently read of some emails not being sent because the host did not have a HTTPS server.

I’ve seen it written that to reduce the chances of emails being rejected as spam you should send with the ‘from’ email address (within additional headers) being on the same server as the website. This means that if you have a contact form requesting an email address, you should not use that as the ‘from’ email address. I don’t know how true this is.

I am using mail() for many clients without any trouble but recently emails to one recipient would get rejected. The way a got around that was to give the recipient an email address on the website’s server and to set that email address to forward emails to my client’s personal email address.

I don’t think so. To quote again from the PHPMailer readme:

Many PHP developers need to send email from their code. The only PHP function that supports this directly is mail(). However, it does not provide any assistance for making use of popular features such as encryption, authentication, HTML messages, and attachments.

Formatting email correctly is surprisingly difficult. There are myriad overlapping (and conflicting) standards, requiring tight adherence to horribly complicated formatting and encoding rules – the vast majority of code that you’ll find online that uses the mail() function directly is just plain wrong, if not unsafe!

The PHP mail() function usually sends via a local mail server, typically fronted by a sendmail binary on Linux, BSD, and macOS platforms, however, Windows usually doesn’t include a local mail server; PHPMailer’s integrated SMTP client allows email sending on all platforms without needing a local mail server. Be aware though, that the mail() function should be avoided when possible; it’s both faster and safer to use SMTP to localhost.

Cheers. I’m not sure how sendmail works, though I was really thinking that most internet email would be sent by connecting to a suitable SMTP server to send it, whether that’s done via mail() using sendmail, or via some other local mail server, and however that happens “under the bonnet”. I imagine there are some other ways of doing it, somewhere.

I’d say that was very true, but also it might have been me that made the comment in the first place as I do tend to jump on that when I see it in people’s form-processing code. If I try to send an email using your email address as my “from” address, and my mail server allows it, isn’t that what they call “open relay”, and a very bad way to set up a mail server? I believe legitimate mail servers that allow open relay are a thing of the past, they should all only send emails from an address that they’re configured for.

Obviously there are open relay mail servers all around the place, but not usually for a good reason. When you get a load of email “bounce” messages relating to emails you didn’t send in the first place, that’s because someone is using an open relay to pretend to send messages from your address, usually for nefarious purposes.

OK, Ive manually downloaded PHPMailer (I dont know how Composer works) and uploaded to the server.

My code so far:

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

require 'https://www.###.com/calendar/config/PHPMailer/src/Exception.php';
die();

This is returning a 500 error. I went into the logs and it says

[Mon Nov 22 09:03:42 2021] [error] [client 217.32.33.106:0] PHP Fatal error: require(): Failed opening required ‘https://www.####.com/calendar/config/PHPMailer/src/Exception.php’ (include_path=’.:/usr/share/pear73:/usr/share/php’) in /home/sites/####.com/public_html/calendar/public/contact-form-DEV.php on line 9

So it cant find the PHPMailer files?! (the path is correct). Ive contacted my hosting’s support and they said “Everything required for a mailing form has been enabled, and we haven’t had any issues with PHPMailer being configured, except that most mail servers flag emails sent through it as spam. These error logs all indicate an issue with the configuration of the script.”

So it seems Ive failed at the first hurdle!! :face_with_head_bandage:

Is it normal to specify a complete URL like that in a ‘require’? I haven’t done much with stuff on live servers, so I genuinely don’t know, but it seems to me that you would put the relative path instead.

I can confirm (having just tried it) that ‘require’ needs a relative path, not absolute.

I did initially try

require __DIR__.'/../calendar/config/PHPMailer/src/Exception.php';

but that resulted in the same. :frowning: . Hmm, Ill have another look with fresh eyes later.

I am a rank beginner here compared to others but have to ask - have you tried putting in the top of exception.php file something like

echo "Got here";
die;

just to check that the require bit is correctly pointing?

That is a good idea! I added your code, but it still returns a 500. Ive tried tweaking the path and whatever I do doesnt work. Its obviously something simple Im missing here (hopefully!)

Heres the directory structure:

I want contact-form-DEV.php to pull in Exception.php

My code is

require __DIR__.'/../calendar/config/PHPMailer/src/Exception.php';
1 Like

Have you tried echoing

__DIR__.'/../calendar/config/PHPMailer/src/Exception.php'

to see if it’s what you expect?

1 Like

Hmm, interesting. I get:
/home/sites/###.com/public_html/calendar/public/../calendar/config/PHPMailer/src/Exception.php

Would it be easier to put the PHPMailer in the root directory for the website?

Shouldn’t it be

require __DIR__.'/../config/PHPMailer/src/Exception.php';

to make it

/home/sites/###.com/public_html/calendar/public/../config/PHPMailer/src/Exception.php

?