PHPMailer woes and documentation feedback


#1

First, I want to say that whoever wrote the UserFrosting documentation did a great job. I’ve been out of the web development world for many years and have used PHP just enough in the meantime to keep an osCommerce site running (which is not a trivial amount but it’s also not building sites from scratch) and I really appreciate the clear presentation of the various tools used and their rationale. It’s sorely missing from many projects. Laravel doesn’t even bother to tell you what it is, beyond a “PHP framework for web artisans”. UserFrosting’s documentation has been the only thing keeping me from having an aneurysm today.

My install (vagrant + homestead) went fairly smoothly, up until the mail setup. I use Dreamhost for SMTP and I’ve had TLS problems in the past, so when I couldn’t connect the first thing I tried was disabling TLS. It wasn’t clear what the valid options were - from what I’ve gathered since, they’re false, ‘ssl’, and ‘tls’. Setting it to false and changing the port to 25 didn’t fix it, and it still gave the same STARTTLS messages. More on that in a minute.

Finding the relevant config file took me a bit. If I’m understanding the docs right, at some point I’ll just create my own Sprinkle with its own default.php and I can put everything in there, but my goal was to get the default app working before muddying the waters with my own code. For the sake of testing I edited app/sprinkles/core/config/default.php. This is probably not the thing to do, but again, I wanted to make the bare minimum changes required to demonstrate basic functionality.

And since that section of the docs is aimed at clueless noobs and senile relics like myself, it might be worth adding a reminder about how to get it to take new settings. If it parses everything every time, then I was doing something else wrong. I used ‘/etc/init.d/php7.2-fpm restart’ to kick it, but that took me a bit to figure out since I didn’t know what FPM was, what was hosting PHP, or which version (out of four installed with homestead) it was using. Not a UF problem, of course, I’m just offering this up as feedback on where my sticking points were.

Now, back to the PHPMailer issue. All of my searches pointed toward the PHPMailer troubleshooting wiki, which came up as a blank entry. I had to use archive.org to get a copy from last month.

It turns out PHPMailer uses opportunistic TLS and will start TLS regardless of your settings, if the server says it’s capable. There were some additional settings to be added to smtp_options to disable certificate verification, but those didn’t help. (And it might be nice to have the docs explicitly show the mapping between UF’s mail properties and PHPMailers’.) I needed the SMTPAutoTLS option. I found /app/sprinkles/core/src/Mailer.php and the section where PHPMailer is set up, and added $this->phpMailer->SMTPAutoTLS = false;. That did the trick and the confirmation email went out that time… and straight into my spam folder, but that’s another problem.

I don’t know why PHPMailer doesn’t want to speak TLS with Dreamhost, and one of the open issues is better log output for TLS negotiation, but it might be nice to have the SMTPAutoTLS option accessible from the UF config.

I’ve had enough for today. It’s up and running, at least in my local VM. I’ll tackle git deployment later.

Thanks,

Scott


#2

Thanks for the kind words - UserFrosting has been a team effort by multiple contributors :slight_smile:

Also, thanks for the feedback!

A few things:

  • You don’t need to directly modify Mailer.php to modify PHPMailer’s settings. You can actually set any of PHPMailer’s options via the Mailer::setOptions method! So, you could extend the mailer service in your Sprinkle’s service provider class to set these kinds of custom settings. We can also consider exposing this directly in the UF config file in a future version.
  • If you need to troubleshoot the conversation between your application and the mail server itself, you can enable mail debugging by setting debug.smtp to true. This will dump response of the mail server, at various levels of verbosity, to app/logs/userfrosting.log.

Join us in chat some time; we’re glad to welcome you to our little community!


#3

Hi Alex,

I figured the mailer options could be overridden elsewhere, but it wasn’t immediately obvious if adding my own Sprinkle and setting mail options there would affect the account confirmation emails or if that portion would have its own mailer instance. And again, I just wanted to make sure I could get the default app to work before adding to it.

I did get email debugging working, but it didn’t tell me much. This is one example:

>[2018-04-24 19:32:44] mail.DEBUG: SERVER -> CLIENT: 250-homiemail-a102.g.dreamhost.com
>250-PIPELINING
>250-SIZE 40960000
>250-ETRN
>250-STARTTLS
>250-AUTH PLAIN LOGIN
>250-AUTH=PLAIN LOGIN
>250-ENHANCEDSTATUSCODES
>250 8BITMIME
> [] []
>[2018-04-24 19:32:44] mail.DEBUG: CLIENT -> SERVER: STARTTLS
> [] []
>[2018-04-24 19:32:44] mail.DEBUG: SMTP -> get_lines(): $data was "" [] []
>[2018-04-24 19:32:44] mail.DEBUG: SMTP -> get_lines(): $str is "220 2.0.0 Ready to start TLS
>" [] []
>[2018-04-24 19:32:44] mail.DEBUG: SMTP -> get_lines(): $data is "220 2.0.0 Ready to start TLS
>" [] []
>[2018-04-24 19:32:44] mail.DEBUG: SERVER -> CLIENT: 220 2.0.0 Ready to start TLS
> [] []
>[2018-04-24 19:32:44] mail.DEBUG: SMTP Error: Could not connect to SMTP host. [] []
>[2018-04-24 19:32:44] mail.DEBUG: CLIENT -> SERVER: QUIT
> [] []
> [2018-04-24 19:32:44] mail.DEBUG: SMTP -> get_lines(): $data was "" [] []
> [2018-04-24 19:32:44] mail.DEBUG: SMTP -> get_lines(): $str is "" [] []
> [2018-04-24 19:32:44] mail.DEBUG: SMTP -> get_lines(): $data is "" [] []
> [2018-04-24 19:32:44] mail.DEBUG: SERVER -> CLIENT:  [] []
> [2018-04-24 19:32:44] mail.DEBUG: SMTP ERROR: QUIT command failed:  [] []
> [2018-04-24 19:32:44] mail.DEBUG: Connection: closed [] []
> [2018-04-24 19:32:44] mail.DEBUG: SMTP Error: Could not connect to SMTP host. [] []

I checked with WireShark as well, and whatever was going wrong, was going wrong in the encrypted portion.

I’ve got too many other battles to fight right now, I’ll worry about TLS on PHPMailer later.

Thanks,

Scott


#4

If you extend the existing mailer service, it will be the same instance across the entire application (including account confirmation emails).

Good luck!


#6

Do you have an example of extending the mail service? I’m running into the same issue.


#7

First, you’ll need to set up a service provider class in your Sprinkle if you haven’t already.

Then, you can add this in the register method:

        /**
         * Extends the 'mailer' service to set custom PHPMailer settings.
         */
        $container->extend('mailer', function ($mailer, $c) {
            $mailer->getPhpMailer()->SMTPAutoTLS = false;

            return $mailer;
        };