PHPMailer - SSL3_GET_SERVER_CERTIFICATE:certificate verify failed - php

Have encountered an issue where email should be sent from an mail server which has self signed certificate, the error which I get is :
PHP Warning: stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in class.smtp.php on line 327.
Has anyone encountered anything similar?
EDIT:
I have also tried to set the stream_context params (params: SSL context options):
$options['ssl']['verify_peer'] = false;
$options['ssl']['verify_peer_name'] = false;
$options['ssl']['allow_self_signed'] = true;
No luck, it still fails with the same error as pointed above.
Thanks.

PHP 5.6 introduces SSL certificate verification, so if your config is broken, it will fail with this error. You should fix your SSL, but you can revert to the old behaviour by setting the SMTPOptions property to not verify certificates:
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
Editing the library defeats the entire point of libraries - and if you do as Kaf's answer suggests, your code will break when you upgrade. Really, don't do that.
Editor's note: disabling SSL verification has security implications. Without verification of the authenticity of SSL/HTTPS connections, a malicious attacker can impersonate a trusted endpoint (such as GitHub or some other remote Git host), and you'll be vulnerable to a Man-in-the-Middle Attack. Be sure you fully understand the security issues before using this as a solution.

I have the same problem. So i changed the file class.smtp.php in line 238:
public function connect($host, $port = null, $timeout = 30, $options = array()) {
if (count($options) == 0) {
$options['ssl'] = array('verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true);
}
now it works fine!
Editor's note: disabling SSL verification has security implications. Without verification of the authenticity of SSL/HTTPS connections, a malicious attacker can impersonate a trusted endpoint (such as GitHub or some other remote Git host), and you'll be vulnerable to a Man-in-the-Middle Attack. Be sure you fully understand the security issues before using this as a solution.

I had the same problem. It turned out that my Postfix config was missing the intermediates and root certificates setting:
smtpd_tls_CAfile=/etc/ssl/certs/intermediate-root-bundle.crt
Even though this Postfix config has worked for years with Outlook and Thunderbird, PHP was more picky and failed the SSL check.
So even though you might be tempted to hack PHPMailer, please don't, and fix the underlying problem.

Just wanted to put my 2 cents in since I've been looking for a fix for days until I tried Kaf's solution and it worked!! Thanks #Kaf
Anyways... For me, PHPMailer was working fine until I decided to upgrade PHP to PHP5.6
Changes were made to open ssl in PHP 5.6. Here is the official docs:
http://php.net/manual/en/migration56.openssl.php
From the docs it says to set verify_peer and verify_peer_name to false
So just follow Kaf's answer and see if that works for you.
Editor's note: The doc also says this is not recommended! Disabling SSL verification has security implications. Without verification of the authenticity of SSL/HTTPS connections, a malicious attacker can impersonate a trusted endpoint (such as GitHub or some other remote Git host), and you'll be vulnerable to a Man-in-the-Middle Attack. Be sure you fully understand the security issues before using this as a solution.

Related

Trying to connect SSL server using fsockopen()

I'm running the next script from my local host and the production server, and Im getting different outputs. Anyone knows why am I getting that false from my localhost?
<?php
$host = 'ssl://mail.companyname.org';
$port = 993;
$error = 0;
$errorString = "";
var_dump(fsockopen($host, $port, $error, $errorString, 30));
var_dump($errorString);
var_dump($error);
Local host output:
bool(false)
Production server output:
resource(4) of type (stream)
UPDATE: after the comments/answer I have modified the code and now Im getting this output on my local host:
PHP Warning: fsockopen(): SSL operation failed with code 1. OpenSSL
Error messages: error:1416F086:SSL
routines:tls_process_server_certificate:certificate verify failed in
/tmp/test.php on line 7 PHP Warning: fsockopen(): Failed to enable
crypto in /tmp/test.php on line 7 PHP Warning: fsockopen(): unable to
connect to ssl://mail.twmdata.org:993 (Unknown error) in /tmp/test.php
on line 7 bool(false) string(0) "" int(0)
it seems this is problem with server certificate :
first you can check if your server certificate and its chains are valid by this:
https://www.sslshopper.com/ssl-checker.htm
if somethings were wrong in ssl-checker?
you can try to correct SSL certificate configs in companyname.org
if you succeed and error was persists ?
you have to add Certificate files manually.
if you have a self-signed certificate:
you have to add Certificate files manually.
if you dont have certificate nor you dont care about man-in-the-middle attack,
you can still use SSL without Certificate.
turn off php fsock Certificate check (not recommended)
its recommended to have a certificate at least a self-signed. if you have a self-signed try 1 solution.
I have found the Problem
You have exposed your Domain name in your PHP Warning Log, so i have checked your domain SSL.
after i check your company`s domain certificate using this tool:
https://www.sslshopper.com/ssl-checker.html#hostname=twmdata.org
it had 2 errors with your certificates:
This certificate has expired (0 days ago). Renew now.
None of the common names in the certificate match the name that was entered (twmdata.org). You may receive an error when accessing this site in a web browser.
so it seems you have to renew your certificate first
Update:
i have found this answer maybe helpful
https://stackoverflow.com/a/40962061/9287628
it suggested to use
stream_context_create(['ssl' => [
'ciphers' => 'RC4-MD5'
]])
as #ChrisHaas suggested connecting with stream_context_create and stream_socket_client brings you a lot of option if you want to dictate the cert directory or you want to turn off certificate check.
Per the documentation for fsockopen
The function stream_socket_client() is similar but provides a richer set of options, including non-blocking connection and the ability to provide a stream context.
Basically, fsockopen is very low-level but without many options, or, arguably, "sane defaults".
Instead, you can switch to stream_socket_client which will allow you to specify a context as the last parameter, and that object has many options, including a dedicated one with over a dozen options specific to SSL. The object created from this function is compatible with fwrite and other functions, so it should do everything you are hoping for.
$context = stream_context_create([/*Options here*/]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);
Now, what options should you use?
The worst option that might work is probably verify_peer. I say "worst" because you are throwing away the verifiability part of SSL/TLS and only using it for encryption, and doing this will make you susceptible to MitM attacks. However, there's a place and time for this, so you could try it if the other options are too complicated.
$context = stream_context_create(['ssl' => ['verify_peer' => false]]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);
Instead, I'd recommend using either cafile or capath which do the same thing except the former is for a file while the latter is for a directory.
$context = stream_context_create(['ssl' => ['verify_peer' => true, 'cafile' => '/path/to/file']]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);
What certs should you use? We use this library to pull in recent CA files on a periodic basis, very convenient. There's a little bit of setup that's per-project but once you get it it goes pretty fast. See this for pulling in a CA file at a well-known location.
One other last option is local_cert which you can use with a PEM file that holds the certificate and private key from the server, if you have access to that.
EDIT
The cert on mail.twmdata.org:993 is different than the web server's cert that other people are talking about, which is generally a best practice. You can inspect that cert using:
openssl s_client -connect mail.twmdata.org:993 -servername mail.twmdata.org
If you do that, you'll see that the server has a self-signed cert which you can get around by setting the verify_peer option to false.
Remove the # symbol. You are hiding error messages that might tell you what the problem is. You should also set a variable in the errorno argument to fsockopen() and echo it for debugging.
My guess would be that you haven't installed PHP with SSL support on your local server. See here.
Companyname.org might also block requests from your local server that are allowed from the production server.

SSL Error in WAMP/XAMPP: stream_socket_enable_crypto(): SSL operation failed

A week ago I was testing some components in WAMP with PHPMailer and everything worked correctly. The next day it just stopped working. No configuration in WAMP has changed. Using SMTPDebug this is the following error when I try to send an email:
Connection failed. Error #2: stream_socket_enable_crypto(): SSL
operation failed with code 1. OpenSSL Error
messages:error:14090086:SSL
routines:ssl3_get_server_certificate:certificate verify failed
[C:...\SMTP.php line 404]
I did other tests using the x86 version of WAMP and XAMPP (I currently use x64 WAMP) but without success, I get the same error.
All tests were performed with gmail "Allow less secure apps" enabled.
After a quick search in the documentation I discovered that the problem is due to verification of the SSL certificate. And as a workaround I can use the following code to skip this check:
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
But as has been said, this is a workaround. I wanted to know where the source of the problem is, I do not understand why it stopped working. I have already tried replacing the certificates in the WAMP / XAMPP folders but without success. Also did extensive research but no results. Any idea how I can solve the certificate verification problem without any workaround?
possible duplicate: Warning: stream_socket_enable_crypto(): SSL operation failed with code 1
there is lot of configs that makes this error come up. but more often is that your system's configuration is not set properly. to do it correctly follow this: 1- check if have cacert.pem file for OPENSSL or not if you have not, download proper version from of cacert.pem according to your php version and config your php.ini file as "2-"
2- if you have this file then you have to lookup inside of your php.ini file and see if it has been set in it or not. to do so: lookup for line
openssl.cafile ="example address..\cacert.pem"
if you find the line with an specific address, look for cacert.pem file in that address, if you find it, than it is all done with cacert.pem file. else, you should use the correct address.
hope this help you.. good luck..!

PHPMailer 5.2 OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

I'm getting this error with PHPMailer on a PHP 5.6 server.
Warning: stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in class.smtp.php on line 344
The interesting thing is I'm trying to send email through the local SMTP server # localhost, and I'm not using SSL or TLS - it's plain SMTP on port 25.
$mail->SMTPSecure=''
$mail->SMTPPort //not set
The server has a valid SSL Certificate installed for the website domain.
I've read the documentation on GitHub about PHP 5.6 certificate verification failure and it doesn't seem to address this scenario.
I've added this code, but still receive the error:
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
I guess the main question is, what SSL certificate, or lack thereof is it complaining about?
PHPMailer's github page mentions this type of error:
This is covered in the troubleshooting docs. PHP 5.6 verifies SSL certificates by default, and if your cert doesn't match, it will fail with this error. The correct solution is to fix your SSL config - it's not PHP's fault!
I see that you've gone through the trouble of making the PHPMailer settings insecure as is not recommended in the troubleshooting docs. Did you notice that requires PHPMailer 5.2.10?
The correct fix for this is to replace the invalid, misconfigured or self-signed certificate with a good one. Failing that, you can allow insecure connections via the SMTPOptions property introduced in PHPMailer 5.2.10 (it's possible to do this by subclassing the SMTP class in earlier versions), though this is not recommended
There's also suggestions for enabling debug output:
$mail->SMTPDebug = 4;
If you look at the debug output, you may glean more helpful info.
EDIT: this also is not about your website's cert, it's about the cert (if any) being hosted by your SMTP mail server endpoint.

Allowing insecure connections in PHP Mailer

I encountered the same problem mentioned here, and allowing insecure connections solved it, while nothing else did. Can you please inform me about what security issues I might face if i kept allowing these insecure connections?
I suggest this link:
PhpMailer not sending mails - TLS error?
if you have insecure connection troubles, let add this lines:
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
It prevent certifies checking and so on.
TLS fulfils two roles: authenticating who you're connecting to, and protecting data in transit. Disabling verification drops the former, but data is still encrypted in transit in exactly the same way as with a verified cert, so it is still substantially better than having no encryption.
The most obvious problem with disabling verification is that you lose the ability to detect interception of your connection. It's very common for ISPs to have a firewall config that redirects outbound SMTP connections to their own mail servers without telling you. If you don't verify the certificate, your script will not notice that it's connected to the wrong server, and will continue and submit your credentials (which will probably fail, since it's the wrong server) - but you've just submitted your ID and password to a man-in-the-middle, and you can't tell if it's your ISP or someone else intercepting your connection.
A better option if you're having these issues and you know the certificate name that it's being translated to... instead of disabling this checking, you can explicitly add what names are acceptable.
$mail->SMTPOptions = array(
'ssl' => array(
'peer_name' => <acceptable peer name>
));
So looking at the referenced example which through this error:
PHP Warning: stream_socket_enable_crypto(): Peer certificate
CN=*.mail.dreamhost.com' did not match expected
CN=mx1.sub4.homie.mail.dreamhost.com' in
/home/ikbb/domains/dev.ikbb.com/public_html/includes/phpmailer/5.2.10/class.smtp.php
You could set *.mail.dreamhost.com as an allowed name.

PHP - Swiftmailer using STARTTLS and self signed certificates

I'm trying to send an email with php and swiftmailer, using STARTTLS, but I'm getting a certificate error. I have root access to the SMTP server, and the certificate used is self-signed.
I'm using Debian on both machines (web server and smtp server)
PHP message: PHP Warning: stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in [..]/lib/classes/Swift/Transport/StreamBuffer.php on line 97
PHP message: PHP Fatal error: Uncaught exception 'Swift_TransportException' with message 'Unable to connect with TLS encryption' in [..]/lib/classes/Swift/Transport/EsmtpTransport.php:294
Do I need to add my own certificate somewhere to get it accepted? Or is this some OpenSSL configuration error?
Editor's note: disabling SSL verification has security implications. Without verification of the authenticity of SSL/HTTPS connections, a malicious attacker can impersonate a trusted endpoint (such as GitHub or some other remote Git host), and you'll be vulnerable to a Man-in-the-Middle Attack.
Be sure you fully understand the security issues before using this as a solution.
Swiftmailer has now been updated to include an option for this. It can now be solved using the setStreamOptions method from your Swift_SmtpTransport instance rather than editing the swift class.
$transport = Swift_SmtpTransport::newInstance('smtp.server.com', 123, 'tls')
->setUsername('username')
->setPassword('password')
->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false)));
I got the same problem using Swiftmailer in Laravel.
Looks like there is no option for this in Swiftmailer. Clean solution would be to add your own root CA to your server and sign your mail server certificate with this CA. The certificate would be valid after this. See for example this tutorial.
Editor's note: disabling SSL verification has security implications. Without verification of the authenticity of SSL/HTTPS connections, a malicious attacker can impersonate a trusted endpoint (such as GitHub or some other remote Git host), and you'll be vulnerable to a Man-in-the-Middle Attack.
Be sure you fully understand the security issues before using this as a solution.
Anyway, a quick dirty hack you should not use would be to edit swiftmailer\swiftmailer\lib\classes\Swift\Transport\StreamBuffer.php. In _establishSocketConnection() line 253 replace:
$options = array();
with something like this:
$options = array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false));
This will change the ssl options of stream_context_create() (a few lines below $options):
$this->_stream = #stream_socket_client($host.':'.$this->_params['port'], $errno,
$errstr, $timeout, STREAM_CLIENT_CONNECT, stream_context_create($options));
Editor's note: disabling SSL verification has security implications. Without verification of the authenticity of SSL/HTTPS connections, a malicious attacker can impersonate a trusted endpoint (such as GitHub or some other remote Git host), and you'll be vulnerable to a Man-in-the-Middle Attack.
Be sure you fully understand the security issues before using this as a solution.
You do not need to edit /vendor files. You can specify (undocumented) options in your config/mail.php file:
'stream' => [
'ssl' => [
'allow_self_signed' => true,
'verify_peer' => false,
'verify_peer_name' => false,
],
],
You can check it yourself in vendor/laravel/framework/src/Illuminate/Mail/TransportManager.php on line ~50:
...
if (isset($config['stream'])) {
$transport->setStreamOptions($config['stream']);
}
...
Needless to say, circumventing peer verification has huge security implications (read vulnerabilities). I imagine this solution for some dev or local environment, never in production or even in an Internet/Publicly available app.
Editor's note: disabling SSL verification has security implications. Without verification of the authenticity of SSL/HTTPS connections, a malicious attacker can impersonate a trusted endpoint (such as GitHub or some other remote Git host), and you'll be vulnerable to a Man-in-the-Middle Attack.
Be sure you fully understand the security issues before using this as a solution.
For me, I had to add $transport->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false, 'verify_peer_name' => false))); to the Mailer.php file, see:
/**
* Returns the SMTP transport
*
* #return \Swift_SmtpTransport
*/
protected function getSmtpInstance(): \Swift_SmtpTransport {
$transport = new \Swift_SmtpTransport();
$transport->setTimeout($this->config->getSystemValue('mail_smtptimeout', 10));
$transport->setHost($this->config->getSystemValue('mail_smtphost', '127.0.0.1'));
$transport->setPort($this->config->getSystemValue('mail_smtpport', 25));
if ($this->config->getSystemValue('mail_smtpauth', false)) {
$transport->setUsername($this->config->getSystemValue('mail_smtpname', ''));
$transport->setPassword($this->config->getSystemValue('mail_smtppassword', ''));
$transport->setAuthMode($this->config->getSystemValue('mail_smtpauthtype', 'LOGIN'));
}
$smtpSecurity = $this->config->getSystemValue('mail_smtpsecure', '');
if (!empty($smtpSecurity)) {
$transport->setEncryption($smtpSecurity);
}
$streamingOptions = $this->config->getSystemValue('mail_smtpstreamoptions', []);
if (is_array($streamingOptions) && !empty($streamingOptions)) {
$transport->setStreamOptions($streamingOptions);
}
/* EDIT - allow self-signed mail cert */
$transport->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false, 'verify_peer_name' => false)));
/* EDIT end */
return $transport;
}
I got this from another link, can't find it now.
One think that I did extra to the other answers was to specify the 'verify_peer_name' => false

Categories