18

Facts

I am using PEAR Mail, I want to use gmail SMTP to send a mail. I have Apache/2.4.27 (Win64) PHP/7.2.0beta3, PEAR 1.10.15, Mail 1.4.1, Net_SMTP 1.8.0, Net_Socket 1.2.2.

I went to php.ini and added extension = php_openssl.dll. The error.log gives no ssl-related errors.

Here is the code

require_once "Mail.php";

$from = '<slevin@gmail.com>';
$to = '<slevinkelevra@gmal.com>';
$subject = 'Hi!';
$body = "Hi,\n\nHow are you?";

$headers = array(
    'From' => $from,
    'To' => $to,
    'Subject' => $subject
);

$smtp = Mail::factory('smtp', array(
        'host' => 'ssl://smtp.gmail.com',
        'port' => '465',
        'auth' => true,
        'username' => 'slevinmail@gmail.com',
        'password' => 'mypassword'
    ));

$mail = $smtp->send($to, $headers, $body);

if (PEAR::isError($mail)) {
    echo('<p>' . $mail->getMessage() . '</p>');
} else {
    echo('<p>Message successfully sent!</p>');
}

The problem

I get this error

Failed to connect to ssl://smtp.gmail.com:465 [SMTP: Failed to connect socket: fsockopen(): unable to connect to ssl://smtp.gmail.com:465 (Unknown error) (code: -1, response: )]

and I have no clue what to do, I Googled but I got more confused.

Please advice on how to fix this. Thank you

Update

Following symcbean's instructions I got the following results :

bool(true) 

array(5) { 
[0]=> string(31) "alt3.gmail-smtp-in.l.google.com" 
[1]=> string(26) "gmail-smtp-in.l.google.com" 
[2]=> string(31) "alt4.gmail-smtp-in.l.google.com" 
[3]=> string(31) "alt1.gmail-smtp-in.l.google.com" 
[4]=> string(31) "alt2.gmail-smtp-in.l.google.com" } 
IPV4 address = 64.233.188.27

If you've got this far without errors then problem is with your SSL config

Check you've got your cacerts deployed in one of the following locations
default_cert_file = C:\Program Files\Common Files\SSL/cert.pem
default_cert_file_env = SSL_CERT_FILE
default_cert_dir = C:\Program Files\Common Files\SSL/certs
default_cert_dir_env = SSL_CERT_DIR
default_private_dir = C:\Program Files\Common Files\SSL/private
default_default_cert_area = C:\Program Files\Common Files\SSL
ini_cafile = 
ini_capath = 

If all good so far, then this bit should work....
fsockopen 
Warning: fsockopen(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed in C:\Apache24\htdocs\phptest2.php on line 28

Warning: fsockopen(): Failed to enable crypto in C:\Apache24\htdocs\phptest2.php on line 28

Warning: fsockopen(): unable to connect to ssl://smtp.gmail.com:465 (Unknown error) in C:\Apache24\htdocs\phptest2.php on line 28
bool(false) int(0) string(0) "" 

Line 28 is this line var_dump(fsockopen("ssl://smtp.gmail.com", 465, $errno, $errstr, 3.0));

Thanks again

Update #2

I googled just "fsockopen(): SSL operation failed with code 1." of the first warning.

End up here . I changed the mail port of the AVG, like the answer. symcbean's code run with no errors, but my code replied with mail error : authentication failure [SMTP: Invalid response code received from server (code: 534, response: 5.7.14 Please log in via your web browser and 5.7.14 then try again. 5.7.14 Learn more at 5.7.14 https://support.google.com/mail/answer/78754 c1sm1243434wre.84 - gsmtp)]

So I googled code: 534, response: 5.7.14 and end-up here, followed the instructions of the first answer by emgh3i, enabled less secured connections and allowed access to my google account

And its working perfectly now.

slevin
  • 4,166
  • 20
  • 69
  • 129
  • You'll have to dabble with some commandline tools first. Check `openssl client` on how to establish a test connection. If that fails, some firewall rule might be in place. If it just fails from Apache/PHP, something like SELinux/AppArmor instead. – mario Sep 01 '17 at 23:46
  • What does `phpinfo()` show about openssl? – Don't Panic Sep 02 '17 at 15:06
  • @mario How do I check the `openssl client` on how to establish a test connection? – slevin Sep 04 '17 at 10:08
  • @Don'tPanic The openssl section is there, is enabled, and there are also the library version, the header version, the default config , but no values for the `openssl.cafile` and the `opensll.capath`. – slevin Sep 04 '17 at 10:11
  • 1
    Could it be firewall, do you have anything blocking connections to the internet? – Don't Panic Sep 04 '17 at 10:15
  • @Don'tPanic I turned of the Windows firewall and I get the same error. I also have AVG on my system, but I dont see any settings for blocking connections. So...yeah...at this point I dont know...maybe its my code? No clue... – slevin Sep 05 '17 at 09:56
  • @slevin I came across almost identical code in other places ([eg this question](https://stackoverflow.com/questions/16642346/smtp-failed-to-connect-socket-unable-to-find-the-socket-transport-ssl) when I first looked at your question, so I think your code is probably OK. My guess would be environment - PHP, OS, firewall, but you've already covered those! The ["Use the Gmail SMTP Server" section of this guide](https://support.google.com/a/answer/176600?hl=en) says you need to enable "Less secure apps", [as described here](https://support.google.com/a/answer/6260879?hl=en), have you done that? – Don't Panic Sep 06 '17 at 12:40
  • @slevin if it turns out to be the "Less secure apps" switch I'd be happy to post it as an answer ... :-) – Don't Panic Sep 07 '17 at 08:20
  • this problem can also be caused by selinux; I spent a whole day configuring firewalld by opening ports and adding services to no avail. – Ajowi Jan 11 '21 at 16:12

9 Answers9

6

Your host configuration shouldn't contain the protocol. The reason it's failing is because it's probably trying to perform a DNS Lookup on ssl://smtp.gmail.com and failing.

Change

'host' => 'ssl://smtp.gmail.com',

to

'host' => 'smtp.gmail.com',
Adam Lavin
  • 753
  • 7
  • 15
  • If I edit the `host` as you said, the age wont't load at all, just hangs there and never actually loads. – slevin Sep 04 '17 at 10:07
  • [`ssl://` in hostname is apparently correct](https://stackoverflow.com/questions/37982619/smtp-gmail-com-vs-ssl-smtp-gmail-com-while-sending-email-using-gmail-smtp-serv) – Don't Panic Sep 07 '17 at 18:15
  • @Don't Panic: That's a post about the codeigniter email library you've linked to, not Pear::Mail. – symcbean Sep 07 '17 at 22:06
  • @symcbean Is it? The question links to some CI code, but they don't say they are using it. The accepted answer says it is PHP handling `ssl://` links, not a library or framework. Also, https://stackoverflow.com/questions/16642346/smtp-failed-to-connect-socket-unable-to-find-the-socket-transport-ssl – Don't Panic Sep 07 '17 at 22:19
6

Your code is correct

I tried to test my gmail account. Mail sending was successful.

Check your socket connection

<?php

error_reporting(E_ALL);

var_dump(fsockopen("ssl://smtp.gmail.com", 465, $errno, $errstr));
var_dump($errno);
var_dump($errstr);

resource(4) of type (stream)

int(0)

string(0) ""

Been Kyung-yoon
  • 1,644
  • 12
  • 13
  • Thanks for the amazing code, will help me as a debugging tool. – slevin Sep 08 '17 at 13:28
  • With this I receive $errno as 0 & $errstr as '' (empty) so mails are not working with ssl., Can you guide what can be the wrong? – Dushyant Joshi Dec 22 '20 at 07:46
  • The fsockopen test simply knows that a socket connection from a google server is possible in PHP. If there is no socket error, you should analyze it by referring to the contents mentioned in other comments. – Been Kyung-yoon Dec 23 '20 at 08:14
6

Few debugging steps :

1. check phpinfo

I recommend checking phpinfo() to check whether all modules are enabled. Check for mail, fsocketopen.

2. Enable debug flag

Enable debug flag to check exactly what's the problem. Like below.

$smtp = Mail::factory('smtp', array(
        'host' => 'ssl://smtp.gmail.com',
        'port' => '465',
        'auth' => true,
        'debug' => true,
        'pipelining' => true,
        'username' => 'xxx@gmail.com',
        'password' => 'xxx'
    ));

After running above code on my machine I got follow response. Issue can be different from yours. But debug helped me. As I have 2FA enabled, it gave me error. And I got a mail also, that my login has been blocked.

DEBUG: Recv: 220 smtp.gmail.com ESMTP s65sm4891344pfi.36 - gsmtp DEBUG: Send: EHLO localhost DEBUG: Recv: 250-smtp.gmail.com at your service, [110.227.210.84] DEBUG: Recv: 250-SIZE 35882577 DEBUG: Recv: 250-8BITMIME DEBUG: Recv: 250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH DEBUG: Recv: 250-ENHANCEDSTATUSCODES DEBUG: Recv: 250-PIPELINING DEBUG: Recv: 250-CHUNKING DEBUG: Recv: 250 SMTPUTF8 DEBUG: Send: AUTH LOGIN DEBUG: Recv: 334 VsadfSFcm5hbWU6 DEBUG: Send: cGF0ZWwuZ29wYhkafdaASFnbWFpbC5jb20= DEBUG: Recv: 334 UGFzc3dvcmQ6 DEBUG: Send: OWwzMy5zaHlAbTE4 DEBUG: Recv: 534-5.7.14 Please log in via your web browser and DEBUG: Recv: 534-5.7.14 then try again. DEBUG: Recv: 534-5.7.14 Learn more at DEBUG: Recv: 534 5.7.14 https://support.google.com/mail/answer/78754 s65sm4891344pfi.36 - gsmtp DEBUG: Send: RSET DEBUG: Send: QUIT DEBUG: Recv: 250 2.1.5 Flushed s65sm4891344pfi.36 - gsmtp DEBUG: Recv: 221 2.0.0 closing connection s65sm4891344pfi.36 - gsmtp
authentication failure [SMTP: Invalid response code received from server (code: 534, response: 5.7.14 Please log in via your web browser and 5.7.14 then try again. 5.7.14 Learn more at 5.7.14 https://support.google.com/mail/answer/78754 s65sm4891344pfi.36 - gsmtp)]

Update:

Your issue looks like PHP is not even able to connect to gmail server.

shyammakwana.me
  • 5,562
  • 2
  • 29
  • 50
6

The "Use the Gmail SMTP Server" section of this guide says you need to enable "Less secure apps".

Don't Panic
  • 13,965
  • 5
  • 32
  • 51
  • 1
    In addition to "less secure apps" having nothing to do with sending mail, are you suggesting that it is only possible to send emails to gmail from a gmail account? – symcbean Sep 07 '17 at 22:51
  • @Don't Panic You were right about the "less secure apps", but having from the same as username is not necessary, I checked it and works fine. – slevin Sep 08 '17 at 13:27
  • @slevin Great. Good luck picking the right answer! :-) – Don't Panic Sep 08 '17 at 14:21
  • I want to pick yours, but I think you should edit out the from/username part, because it is irrelevant and it could be misleading to others. – slevin Sep 08 '17 at 15:26
  • @symcbean No I did not suggest that, perhaps you misread. What I said was sending mail "from" a different address than the account you are using is a potential problem. AFAIK Gmail is particularly sensitive to anything that looks like spoofing, though it seems that was not the problem here. – Don't Panic Sep 08 '17 at 16:07
4

When something fail and we don't know the cause we have to do debugging. So here instead of putting an answer I am requesting you to execute some tests

  1. confirm system connectivity with internet: Open cmd terminal and type

    ping smtp.gmail.com
    
  2. confirm firewall: Enter following in cmd terminal

    telnet smtp.gmail.com 465
    
  3. confirm php setup: enter php -a at cmd terminal and on php prompt execute (copy / paste and then press enter) following code.

    $result = fsockopen('ssl://smtp.gmail.com', 465, $error_no, $error_message, 5);
    if ($result === false) {
      echo "error no: $error_no error message: $error_message";
      echo print_r($result, true);
    } else {
      echo 'success';
    }
    
  4. confirm Pear Mail library and Gmail SMTP access: again on cmd and php prompt php -a execute your own code (as you posted in this thread)

And lets know where it breaks, and what is the error. Only after that we can help

Nasir Iqbal
  • 909
  • 7
  • 24
  • check my original post, Update #2. Thanks for your effort.For the record, ping the smtp.gmail worked, but ping telnet replied with `'telnet' is not recognized as an internal or external command, operable program or batch file.` Step 3 replied `success`. Step 4 said : `Warning: Uncaught Error: Class 'PEAR' not found in php shell code:1 Stack trace: #0 {main} thrown in php shell code on line 1` – slevin Sep 08 '17 at 13:21
3

Been Kyung-yoong is the only person to have made a meaningful contribution to solving the problem so far (+1 Been!). I can confirm his result. And I would recommend you try the same. You are currently trying to debug a rather complex stack of components:

Been is doing your job for you - as the person posting the question - should be creating a Minimal, Complete, and Verifiable example

This will hopefully also provide more meaningful diagnostic information.

The most likely reasons for this to be failing are:

  • the host you are running this on cannot route outgoing connections to the internet (but since you seem to be using a desktop PC, I would think you might have noticed this by now)
  • the code is running within a security sandbox (but MSWindows doesn't really have such things)
  • the host is unable to resolve the hostname (see first point about routing)
  • the host is able to connect but unable to verify the certificate

Hence you might consider this more elaborate implementation of a test script:

 <?php

 error_reporting(E_ALL);

 print "DNS\n";
 var_dump(getmxrr('gmail.com',$result));
 var_dump($result);
 $use_ip=gethostbyname($result[0]);
 print "IPV4 address = $use_ip\n";

 print "\nIf you've got this far without errors then problem is with your SSL config\n";
 $calocns=openssl_get_cert_locations();
 if (count($calocns)) {
     print "Check you've got your cacerts deployed in one of the following locations\n";
     foreach ($calocns as $k=>$v) print "$k = $v\n";
 } else {
     print "You've not configured your openssl installation on this host\n";
 }

 print "\nIf all good so far, then this bit should work....\n";
 print "fsockopen\n";
 var_dump(fsockopen("ssl://smtp.gmail.com", 465, $errno, $errstr, 3.0));
 var_dump($errno);
 var_dump($errstr);

Which should give you a response like this:

 DNS
 bool(true)
 array(5) {
   [0]=>
   string(31) "alt1.gmail-smtp-in.l.google.com"
   [1]=>
   string(31) "alt2.gmail-smtp-in.l.google.com"
   [2]=>
   string(31) "alt4.gmail-smtp-in.l.google.com"
   [3]=>
   string(26) "gmail-smtp-in.l.google.com"
   [4]=>
   string(31) "alt3.gmail-smtp-in.l.google.com"
 }
 IPV4 address = 74.125.131.26

 If you've got this far without errors then problem is with your SSL config
 Check you've got your cacerts deployed in one of the following locations
 default_cert_file = /usr/lib/ssl/cert.pem
 default_cert_file_env = SSL_CERT_FILE
 default_cert_dir = /usr/lib/ssl/certs
 default_cert_dir_env = SSL_CERT_DIR
 default_private_dir = /usr/lib/ssl/private
 default_default_cert_area = /usr/lib/ssl
 ini_cafile =
 ini_capath =

 If all good so far, then this bit should work....
 fsockopen
 resource(4) of type (stream)
 int(0)
 string(0) ""

Given that we can't replicate your error we can't give a definitive answer what the problem is - but my guess would be that you haven't configure openSSL.

symcbean
  • 47,736
  • 6
  • 59
  • 94
  • Thanks for the amazing effort. Check my original post for the results, in the Update section. Please keep in mind, I am a "back-end newbie" (if this is even a term), so please advice. I cannot get a hint on how should I proceed or what my next step should be. Thanks again – slevin Sep 08 '17 at 10:45
  • "certificate verify failed" - so either your connection to smtp.gmail.com is being MITMed (unlikely) or your cacerts are not installed / up to date. You can get the current Mozilla curated CACert bundle in the right format here: https://curl.haxx.se/docs/caextract.html – symcbean Sep 08 '17 at 11:20
  • Check my original post, Update #2. So, this was a problem on the gmail part after all? Thanks again – slevin Sep 08 '17 at 13:23
  • Does the error "certificate verify failed" means that my certificates are out of date anyway? Should I install the cacert.pem and try without having less secured apps enabled on google? How do I install it? Do I replace the file here `C:\Program Files\Common Files\SSL/cert.pem` with the file I just downloaded from Mozilla? Thanks – slevin Sep 08 '17 at 13:41
  • If tweaking your Anti-virus changed the outcome then clearly your connection was MITMed and the certificate bundle you currently have is up to date. But you now appear to have exposed an issue with authentication. Since the problem you were encountering is now resolved, you might consider opening a new post about the new error. (you might also consider upgrading to a more sensible platform) – symcbean Sep 08 '17 at 14:17
  • Not trying to put you on the spot, but are you sure this is a MITM? Because a lot of relevant cases have been sold with enabling less secured connections, without anyone mentioning a MITM. Thanks again. Promise I will start another bounty to also give you 100. – slevin Sep 08 '17 at 15:29
  • 1
    I mean that the connection was MITM'd **by your AV product**. It can't read the encrypted stream so it it decrypts it, then re-encrypts it back to your applications. When you installed it, it would have injected its own CAcert into the Microsoft certificate store so any applications using that would think the cert was fine - but it won't have known about the OpenSSL CAcert files. – symcbean Sep 08 '17 at 15:45
  • @ OK, I thought that you were talking about an actual MITM. – slevin Sep 08 '17 at 16:29
  • 1
    @symvbean, 'Been Kyung-yoong is the only person to have made a meaningful contribution'... Your editorializing is insulting to those that gave correct answers, which had nothing to do with what you thought the problem was. – Altimus Prime Sep 08 '17 at 23:48
2

Before I begin, let me preface this that there are many possibly solutions and outcomes between your server and the google server, so these may or may not work for different people.

1) SMTP is not very secure, so Google may be rejecting your request. I had this problem 6 months ago and the solution was enabling insecure apps under 'myaccount.google.com'

enter image description here

2) If that doesn't work for you then you may consider switching protocols.

from

'host' => 'ssl://smtp.gmail.com',

to

'host' => 'tls://smtp.gmail.com:587';

Altimus Prime
  • 2,207
  • 2
  • 27
  • 46
  • "SMTP is not very secure" - its not intended to be secure - thats what AUTH, STARTTLS and SMTPS are about. The configuration option to "Allow less secure apps" merely enables IMAPS connectivity with basic authentication to be enabled on the mailbox - nothing to do with sending mail. – symcbean Sep 07 '17 at 22:10
  • 1
    @symcbean. My answer was the right one. It actually solved the issue for myself and for slevin. – Altimus Prime Sep 08 '17 at 23:43
0

In PHP 5.3, the tip given by others about "less secure apps," that need to be activated when logged into your Google Gmail account, solved all my problems.

In PHP 7.2 I had to do more: setting 'auth' to PLAIN and then add "verify_peer" and verify_peer_name for ssl socket_options like this:

$mail= Mail::factory('smtp', array('host' => 'ssl://smtp.gmail.com',
                                   'port' => '465',
                                   'auth' => 'PLAIN',
                                   'socket_options' => array('ssl' => array('verify_peer' => false,
                                                                            'verify_peer_name' => false)),
                                   'username' => 'someAccount@gmail.com',
                                   'password' => 'myPassword'
));
0

This may not be directly related to the question but for anyone having issues sending email using Pear SMTP via remote server, the real issue my not be firewall configurations but SELINUX. If it is on, which is the default, you can spend days wondering why permission is denied. Just tell selinux to allow apache to send email:

setsebool -P httpd_can_sendmail 1

I hope this saves somebody the trouble.

Ajowi
  • 449
  • 3
  • 12