PHP - Swiftmailer using STARTTLS and self signed certificates

前端 未结 4 509
眼角桃花
眼角桃花 2020-12-05 11:32

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

相关标签:
4条回答
  • 2020-12-05 11:35

    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.

    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));
    
    0 讨论(0)
  • 2020-12-05 11:38

    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']);
    }
    ...
    
    0 讨论(0)
  • 2020-12-05 11:50

    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)));
    
    0 讨论(0)
  • 2020-12-05 11:58

    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

    0 讨论(0)
提交回复
热议问题