diff --git a/docs/book/read.md b/docs/book/read.md index c737e3ba..87a17e2e 100644 --- a/docs/book/read.md +++ b/docs/book/read.md @@ -117,6 +117,10 @@ $mail = new Pop3([ ]); ``` +If you are connecting to a mail server with a self-signed certificate and want to +skip the SSL verification, you can also pass an additional argument `novalidatecert` +with the value `true`. + Both constructors throw `Zend\Mail\Exception` or `Zend\Mail\Protocol\Exception` (extends `Zend\Mail\Exception`) for connection errors, depending on the type of error encountered. diff --git a/src/Protocol/Imap.php b/src/Protocol/Imap.php index 0f27995d..1449a106 100644 --- a/src/Protocol/Imap.php +++ b/src/Protocol/Imap.php @@ -18,6 +18,12 @@ class Imap */ const TIMEOUT_CONNECTION = 30; + /** + * If set to true, do not validate the SSL certificate + * @var null|bool + */ + protected $novalidatecert; + /** * socket to imap server * @var resource|null @@ -33,13 +39,16 @@ class Imap /** * Public constructor * - * @param string $host hostname or IP address of IMAP server, if given connect() is called - * @param int|null $port port of IMAP server, null for default (143 or 993 for ssl) - * @param bool $ssl use ssl? 'SSL', 'TLS' or false + * @param string $host hostname or IP address of IMAP server, if given connect() is called + * @param int|null $port port of IMAP server, null for default (143 or 993 for ssl) + * @param bool $ssl use ssl? 'SSL', 'TLS' or false + * @param bool $novalidatecert set to true to skip SSL certificate validation * @throws \Zend\Mail\Protocol\Exception\ExceptionInterface */ - public function __construct($host = '', $port = null, $ssl = false) + public function __construct($host = '', $port = null, $ssl = false, $novalidatecert = false) { + $this->novalidatecert = $novalidatecert; + if ($host) { $this->connect($host, $port, $ssl); } @@ -53,6 +62,14 @@ public function __destruct() $this->logout(); } + public function setNoValidateCert($novalidatecert) + { + + if (is_bool($novalidatecert)) { + $this->novalidatecert = $novalidatecert; + } + } + /** * Open connection to IMAP server * @@ -64,6 +81,7 @@ public function __destruct() */ public function connect($host, $port = null, $ssl = false) { + $isTls = false; if ($ssl) { @@ -86,8 +104,29 @@ public function connect($host, $port = null, $ssl = false) } } + $socket_options = []; + + if ($this->novalidatecert) { + $socket_options = [ + 'ssl' => [ + 'verify_peer_name' => false, + 'verify_peer' => false, + ] + ]; + } + + $socket_context = stream_context_create($socket_options); + ErrorHandler::start(); - $this->socket = fsockopen($host, $port, $errno, $errstr, self::TIMEOUT_CONNECTION); + $this->socket = stream_socket_client( + $host . ":" . $port, + $errno, + $errstr, + self::TIMEOUT_CONNECTION, + STREAM_CLIENT_CONNECT, + $socket_context + ); + $error = ErrorHandler::stop(); if (! $this->socket) { throw new Exception\RuntimeException(sprintf( diff --git a/src/Protocol/Pop3.php b/src/Protocol/Pop3.php index dcc9895a..8a94bb32 100644 --- a/src/Protocol/Pop3.php +++ b/src/Protocol/Pop3.php @@ -24,6 +24,12 @@ class Pop3 */ public $hasTop = null; + /** + * If set to true, do not validate the SSL certificate + * @var null|bool + */ + protected $novalidatecert; + /** * socket to pop3 * @var null|resource @@ -39,12 +45,15 @@ class Pop3 /** * Public constructor * - * @param string $host hostname or IP address of POP3 server, if given connect() is called - * @param int|null $port port of POP3 server, null for default (110 or 995 for ssl) - * @param bool|string $ssl use ssl? 'SSL', 'TLS' or false + * @param string $host hostname or IP address of POP3 server, if given connect() is called + * @param int|null $port port of POP3 server, null for default (110 or 995 for ssl) + * @param bool|string $ssl use ssl? 'SSL', 'TLS' or false + * @param bool $novalidatecert set to true to skip SSL certificate validation */ - public function __construct($host = '', $port = null, $ssl = false) + public function __construct($host = '', $port = null, $ssl = false, $novalidatecert = false) { + $this->novalidatecert = $novalidatecert; + if ($host) { $this->connect($host, $port, $ssl); } @@ -58,6 +67,14 @@ public function __destruct() $this->logout(); } + public function setNoValidateCert($novalidatecert) + { + + if (is_bool($novalidatecert)) { + $this->novalidatecert = $novalidatecert; + } + } + /** * Open connection to POP3 server * @@ -91,8 +108,29 @@ public function connect($host, $port = null, $ssl = false) } } + $socket_options = []; + + if ($this->novalidatecert) { + $socket_options = [ + 'ssl' => [ + 'verify_peer_name' => false, + 'verify_peer' => false, + ] + ]; + } + + $socket_context = stream_context_create($socket_options); + ErrorHandler::start(); - $this->socket = fsockopen($host, $port, $errno, $errstr, self::TIMEOUT_CONNECTION); + $this->socket = stream_socket_client( + $host . ":" . $port, + $errno, + $errstr, + self::TIMEOUT_CONNECTION, + STREAM_CLIENT_CONNECT, + $socket_context + ); + $error = ErrorHandler::stop(); if (! $this->socket) { throw new Exception\RuntimeException(sprintf( diff --git a/src/Storage/Imap.php b/src/Storage/Imap.php index 5324f9d7..cf8aa92d 100644 --- a/src/Storage/Imap.php +++ b/src/Storage/Imap.php @@ -212,6 +212,11 @@ public function __construct($params) $ssl = isset($params->ssl) ? $params->ssl : false; $this->protocol = new Protocol\Imap(); + + if (isset($params->novalidatecert)) { + $this->protocol->setNoValidateCert(true); + } + $this->protocol->connect($host, $port, $ssl); if (! $this->protocol->login($params->user, $password)) { throw new Exception\RuntimeException('cannot login, user or password wrong'); diff --git a/src/Storage/Pop3.php b/src/Storage/Pop3.php index a08b33b2..e1159f7d 100644 --- a/src/Storage/Pop3.php +++ b/src/Storage/Pop3.php @@ -145,6 +145,11 @@ public function __construct($params) $ssl = isset($params->ssl) ? $params->ssl : false; $this->protocol = new Protocol\Pop3(); + + if (isset($params->novalidatecert)) { + $this->protocol->setNoValidateCert($params->novalidatecert); + } + $this->protocol->connect($host, $port, $ssl); $this->protocol->login($params->user, $password); }