web-dev-qa-db-fra.com

PHP - Swiftmailer utilisant STARTTLS et des certificats auto-signés

J'essaie d'envoyer un e-mail avec php et swiftmailer, en utilisant STARTTLS, mais je reçois une erreur de certificat. J'ai un accès root au serveur SMTP et le certificat utilisé est auto-signé. J'utilise Debian sur les deux machines (serveur web et serveur smtp)

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

Dois-je ajouter mon propre certificat quelque part pour le faire accepter? Ou s'agit-il d'une erreur de configuration OpenSSL?

15
David Ventura

Swiftmailer a maintenant été mis à jour pour inclure une option pour cela. Il peut maintenant être résolu en utilisant la méthode setStreamOptions de votre Swift_SmtpTransport plutôt que de modifier la classe Swift.

$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

J'ai eu le même problème en utilisant Swiftmailer dans Laravel.

Il semble qu'il n'y ait aucune option pour cela dans Swiftmailer. Une solution propre serait d'ajouter votre propre autorité de certification racine à votre serveur et de signer votre certificat de serveur de messagerie avec cette autorité de certification. Le certificat serait valide après cela. Voir par exemple ce tutoriel .

Quoi qu'il en soit, un hack sale rapide que vous ne devriez pas utiliser serait de modifier swiftmailer\swiftmailer\lib\classes\Swift\Transport\StreamBuffer.php. Dans _establishSocketConnection() ligne 253, remplacez:

$options = array();

avec quelque chose comme ça:

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

Cela changera les options ssl de stream_context_create () (quelques lignes en dessous de $options)):

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

Vous n'avez pas besoin de modifier /vendor des dossiers. Vous pouvez spécifier des options (non documentées) dans votre config/mail.php fichier:

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

Vous pouvez le vérifier vous-même dans vendor/laravel/framework/src/Illuminate/Mail/TransportManager.php en ligne ~ 50:

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

Pour moi, j'ai dû ajouter $transport->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false, 'verify_peer_name' => false))); au fichier Mailer.php, voir:

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

Je l'ai obtenu d'un autre lien, je ne le trouve pas maintenant.

On pense que j'ai fait un supplément aux autres réponses était de spécifier le 'verify_peer_name' => false

0
Tudor