web-dev-qa-db-ja.com

PHP-STARTTLSと自己署名証明書を使用したSwiftmailer

STARTTLSを使用して、phpとswiftmailerでメールを送信しようとしていますが、証明書エラーが発生します。 SMTPサーバーへのルートアクセス権があり、使用される証明書は自己署名されています。両方のマシン(WebサーバーとSMTPサーバー)でDebianを使用しています

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

自分の証明書をどこかに追加して承認を受ける必要がありますか?または、これはOpenSSL構成エラーですか?

15
David Ventura

Swiftmailerが更新され、このオプションが含まれるようになりました。 Swiftクラスを編集するのではなく、Swift_SmtpTransportインスタンスのsetStreamOptionsメソッドを使用して解決できるようになりました。

$transport = Swift_SmtpTransport::newInstance('smtp.server.com', 123, 'tls')
    ->setUsername('username')
    ->setPassword('password')
    ->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false)));
14
Dave Kennard

LaravelでSwiftmailerを使用しても同じ問題が発生しました。

Swiftmailerにはこのオプションがないようです。クリーンなソリューションは、独自の ルートCA をサーバーに追加し、このCAでメールサーバー証明書に署名することです。この後、証明書は有効になります。たとえば このチュートリアル を参照してください。

とにかく、使用してはいけない簡単なハックは、_swiftmailer\swiftmailer\lib\classes\Swift\Transport\StreamBuffer.php_を編集することです。 _establishSocketConnection() 253行目で以下を置き換えます。

_$options = array();
_

このようなもので:

_$options = array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false));
_

stream_context_create()sslオプション が変更されます(_$options_の下の数行):

_$this->_stream = @stream_socket_client($Host.':'.$this->_params['port'], $errno, 
    $errstr, $timeout, STREAM_CLIENT_CONNECT, stream_context_create($options));
_
13
PiTheNumber

/vendorファイルを編集する必要はありません。 config/mail.phpファイルで(ドキュメント化されていない)オプションを指定できます。

'stream' => [
    'ssl' => [
        'allow_self_signed' => true,
        'verify_peer' => false,
        'verify_peer_name' => false,
    ],
],

vendor/laravel/framework/src/Illuminate/Mail/TransportManager.phpの50行目で自分で確認できます。

...
if (isset($config['stream'])) {
    $transport->setStreamOptions($config['stream']);
}
...
7
Alex

私にとっては、Mailer.phpファイルに$transport->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false, 'verify_peer_name' => false)));を追加する必要がありました。以下を参照してください:

    /**
     * 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;
    }

これは別のリンクから取得しましたが、今は見つかりません。

私が他の答えに追加したと思う人は、'verify_peer_name' => false

0
Tudor