garson
By:
garson

Very slow smtp.gmail.com connection

January 14, 2015 6.3k views

I am trying to figure out why my Gmail PHPMailer sends are soooo slow (more than a minute for a tiny email). I tried the following:

telnet smtp.gmail.com 587

...I get a message saying that the server is (I added the etc's)

Trying 2607:f8b0:etc:etc::6c..."

Then, 4 minutes later, this output appeared:

Trying 64.233.etc.etc
Connected to smtp.gmail.com
Escape character is '^]'.
220 mx.google.com etc..

I believe that I have everything configured to send mail. I do receive the emails, but not for several minutes.

Can anyone shed some light on this situation? Could this be why PHPMailer is so slow? Thanks!

3 Answers

It looks like you're timing out on IPv6 connections which is why it's taking so long.

If you have netfilter rules for IPv6 you may want to consider revising them, or if it's DO blocking you you will want to contact support.

How do I check if I have netfilter rules? I don't remember setting any up...

I have the same issue.... I'm not sure how to interpret my iptables rules (lots of output), but I only setup basic Uncomplicated FireWall rules:

root@eqt:~# ufw status
Status: active

To                         Action      From
--                         ------      ----
22                         ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
25/tcp                     ALLOW       Anywhere
22 (v6)                    ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)
25/tcp (v6)                ALLOW       Anywhere (v6)

(I also am running apparmor, but I don't think that is involved)

Dig returns instantly

dig +short smtp.gmail.com
gmail-smtp-msa.l.google.com.
64.233.171.108
64.233.171.109

Ping is equally quick

ping smtp.gmail.com
PING gmail-smtp-msa.l.google.com (64.233.171.108) 56(84) bytes of data.
64 bytes from qd-in-f108.1e100.net (64.233.171.108): icmp_seq=1 ttl=50 time=15.2 ms
64 bytes from qd-in-f108.1e100.net (64.233.171.108): icmp_seq=2 ttl=50 time=15.4 ms

But telnet takes like 4 minutes

time telnet smtp.gmail.com 587
Trying 2607:f8b0:400d:c03::6d...
Trying 64.233.171.108...
Connected to smtp.gmail.com.
Escape character is '^]'.
220 smtp.gmail.com ESMTP g19sm5242291qkh.18 - gsmtp
^]
telnet> quit
Connection closed.

real    4m0.443s
user    0m0.000s
sys     0m0.004s

And, my PHP web application ( https://freephile.org/wikireport ), which is using PHPMailer, takes about 130 seconds when sending a simple email message but only 1 second when I turn off the email. (Mail does get delivered... I figured this must be due to some negotiation in the application to find and use port 25 when 587 times out.)

Then I thought I solved it by opening port 587 with ufw (/smacks forehead duh!) but that actually didn't change anything.

I tried ufw allow 587 (no qualifier about UDP/TCP protocol)
I tried ufw allow out 587 (specifically allow outgoing traffic only)
neither had an effect on the mail time.

root@eqt:~# ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22                         ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
443/tcp                    ALLOW IN    Anywhere
25/tcp                     ALLOW IN    Anywhere
587                        ALLOW IN    Anywhere
465                        ALLOW IN    Anywhere
22 (v6)                    ALLOW IN    Anywhere (v6)
80/tcp (v6)                ALLOW IN    Anywhere (v6)
443/tcp (v6)               ALLOW IN    Anywhere (v6)
25/tcp (v6)                ALLOW IN    Anywhere (v6)
587 (v6)                   ALLOW IN    Anywhere (v6)
465 (v6)                   ALLOW IN    Anywhere (v6)

587                        ALLOW OUT   Anywhere
465                        ALLOW OUT   Anywhere
587 (v6)                   ALLOW OUT   Anywhere (v6)
465 (v6)                   ALLOW OUT   Anywhere (v6)

I've scanned the dmesg output and /var/log/syslog and also looked at iptables -L -n but there isn't anything that looks wrong.

Heading over to open a support ticket and will update when solved.

  • This problem is due to Digital Ocean's network not supporting IPV6 for smtp. There doesn't appear to be a way to configure this on/off in PHPMailer, and I don't want to turn off ipv6 for my entire host, so the easiest solution is to use an IPv4 address for Google's smtp server. And you don't have to hard-code some ip address (which could change or be unreliable over time).

    PHP's gethostbyname() function returns an IPv4 address. So use that when setting the $host for PHPMailer.

    instead of

    $host = 'smtp.gmail.com';
    

    use

    $host = gethostbyname('smtp.gmail.com');
    

    As a side-note: dig is not faster than gethostbyname(). Although "dig" is a bit faster on the command line; in a PHP script it's slower because you have to exec() out to dig.

    greg@eqt:~$ time dig smtp.gmail.com A +short
    gmail-smtp-msa.l.google.com.
    64.233.171.108
    64.233.171.109
    
    real    0m0.079s
    user    0m0.011s
    sys     0m0.005s
    
    
    greg@eqt:~$ time php -r 'echo gethostbyname("smtp.gmail.com");'
    64.233.171.108
    real    0m0.062s
    user    0m0.017s
    sys     0m0.030s
    
    • I have the same issue as others with PHPMailer in my droplet.

      The above (adding gethostbyname ) solves the issue with speed but I guess it introduces another problem.

      When I use this, I notice that the certificate issued by smtp.gmail.com does not more get approved. So when I add this, PHPMailer can no more send emails successfully.

      Here is the warning message :

      PHP Warning: streamsocketenable_crypto(): Peer certificate CN=smtp.gmail.com' did not match expected CN=64.233.171.108'

      which causes a QUIT by the PHPMailer.

      Now the workaround is of course to disable the certificate check inside PHPMailer.

    • Where / how do I edit $host?

Have another answer? Share your knowledge.