Swiftmailer Gmail Connection timed out #110

2019-06-23 17:55发布

问题:

I want to send emails using gmail's smtp with the PHP script posted below using Swiftmailer. Now this works fine on my own webserver. But when I used it on the webserver of the people I'm creating this for, I get an exception:

    Fatal error: Uncaught exception 'Swift_TransportException' with message 'Connection could not be established with host smtp.gmail.com [Connection timed out #110]' in ...

What could be the problem? I'm assuming its got to do with the difference in server settings, because the code works on my own webserver. I've checked with phpinfo() the following:

- Registered Stream Socket Transports   tcp, udp, unix, udg, ssl, sslv3, sslv2, tls
- OpenSSL support   enabled 
- OpenSSL Library Version   OpenSSL 1.0.1e-fips 11 Feb 2013 

This is my PHP code:

    $emailname = MY_GMAIL_ACCOUNT_USERNAME;
    $emailpass = MY_GMAIL_ACCOUNT_PASSWORD;

    $transport = Swift_SmtpTransport::newInstance('smtp.gmail.com', 465, "ssl")
      ->setUsername($emailname)
      ->setPassword($emailpass);

    $mailer = Swift_Mailer::newInstance($transport);

    $message = Swift_Message::newInstance($emailtitle)
      ->setFrom(array($emailname.'@gmail.com' => $emailsender))
      ->setTo(array($emailrecp))
      ->setBody($emailbody,'text/html');

    $result = $mailer->send($message);

回答1:

I had the same issue on a Digital Ocean server. Turns out they're blocking SMTP by default on IPv6. Here's the fix:

nano /etc/gai.conf precedence ::ffff:0:0/96 100

as per: https://www.digitalocean.com/community/questions/outgoing-connections-on-port-25-587-143-blocked-over-ipv6



回答2:

My easy solution to avoid the problem of dynamic IP (every time i ping smtp.gmail.com I see a slight difference in the last 3digit chunk), is to simply use php built-in gethostbyname() to read the IP in real-time.

 $smtp_host_ip = gethostbyname('smtp.gmail.com');
 $transport = Swift_SmtpTransport::newInstance($smtp_host_ip,465,'ssl')
   ->setUsername('username')->setPassword('pwd');


回答3:

Im not advanced in php and streams but it seems that IPv6 DNS resolution depends on the router and/or ISPs. I changed my provider, got a new router and the smtp connection always timed out.

To use IPv6 you should either add your own IPv6 or force stream_context_create to use IPv4. You can call setSourceIp() on a swiftmailer object or directly change the Swift_SmtpTransport class (i.e. in the constructor).

Use IPv6:

// replace IP with your own IPv6
$this->setSourceIp('2aaa:8a8:fc0:230:fds:4fd:faa:24ae');

Use IPv4 (mentioned at https://github.com/phergie/phergie/issues/195):

$this->setSourceIp('0.0.0.0');


回答4:

I've just been doing battle with exactly the same problem. Mine worked locally too, but as soon as it got on a real server ... no. It just would not work even though all the settings were the same.

After many hours, I've think I've found out why.

What seems to happen is that on a server with IPv4 and IPv6 support, IPv6 takes precedence. Which makes sense, given that it's newer. But in the case of smtp.gmail.com, it appears to only listen on IPv4. So when the server resolved smtp.gmail.com, it got its IPv6 address back and so PHP tried to connect to it. That eventually gives up with a "Connection timed out" exception. Now you would think that fsockopen, presumably, would detect the connection wasn't working and so try IPv4, but seemingly it doesn't.

If you find out what smtp.gmail.com's IPv4 address is (ping smtp.gmail.com) and simply put that IP in place of the hostname in the code - it works :)

It's not ideal coding in an IP address - given that Google could change it at any minute - but at least you will get some emails sent



回答5:

just add

74.125.130.108 smtp.gmail.com

to server's hosts file



回答6:

The answer for me was that my server was blocking the outbound connection. It could be your firewall or your host.

The way to test this is to try connecting yourself. I used telnet on two different machines to compare and it became obvious that this was my issue. There may be a way to test this with curl directly.