Функция stream_socket_enable_cryp для возврата SSL23_GET_SERVER_HELLO: неизвестный протокол - PullRequest
0 голосов
/ 23 декабря 2018

Я пытаюсь проверить правильность данных соединения для SMTP-сервера (сервер, порт, STARTTLS, если выбран, пользователь и пароль).Я пробовал эти же данные соединения с Thunderbird, поэтому они действительны, потому что я могу отправлять электронные письма.

Но мой PHP-код не работает, поэтому я предполагаю, что это не сервер.Ошибки возникают при вызове stream_socket_enable_crypto()

Я пытался переключаться между различными значениями параметра crypto_type (STREAM_CRYPTO_METHOD_SSLv23_CLIENT или STREAM_CRYPTO_METHOD_TLS_CLIENT), но безуспешно.

function smtpconnect($server, $port, $user, $password, $tls = false)
{
    $errno = ''; // error number and messages
    $errstr = '';
    $response = [ 'connected' => false, 'message' => '' ];

    // connect to the host on the specified port
    $socket = fsockopen($server, $port, $errno, $errstr, 30);
    if (is_resource($socket)) {
        $hello = smtpcommand($socket, 'EHLO ' . $_SERVER['SERVER_ADDR']);

        if (substr($hello, 0, 3) != '220') {
            $response['message'] = "This does not look like a SMTP server";
            return $response;
        }

        if ($tls) {
            $tls = smtpcommand($socket, 'STARTTLS');

            if (substr($tls, 0, 3) != '250') {
                $response['message'] = 'TLS connection could not be established';
                return $response;
            }

            $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;

            if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
                $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
                $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
            }

            stream_set_blocking($socket, true);
            $crypto = stream_socket_enable_crypto($socket, true, $crypto_method);
            stream_set_blocking($socket, false);

            if (!$crypto) {
                $response['message'] = 'Encrypted connection could not be started';
                return $response;
            }

            $hello = smtpcommand($socket, 'EHLO ' . $_SERVER['SERVER_ADDR']);
        }

        smtpcommand($socket, 'AUTH LOGIN');
        smtpcommand($socket, base64_encode($user));
        $pass = smtpcommand($socket, base64_encode($password));
        if (substr($pass, 0, 3) != '235') {
            $response['message'] = 'Invalid SMTP user or password';
            return $response;
        }
        $response['connected'] = true;
        return $response;
    }
}

function smtpcommand($socket, $command)
{
    try {
        fwrite($socket, $command . "\r\n");
    } catch (Exception $e) {
        return $e->getMessage();
    }
    return smtpresponse($socket, 30);
}

function smtpresponse($socket, $timeout)
{
    stream_set_timeout($socket, $timeout);
    $response = '';
    while (($line = fgets($socket, 515)) != false) {
        $response .= trim($line) . "\n";
        if (substr($line, 3, 1) == ' ') {
            break;
        }
    }
    return trim($response);
}

Несмотря на то, что STARTTLS возвращает 220, функция stream_socket_enable_crypto() не выполняется, возвращает сообщение 'TLS-соединение не может быть установлено' , и ошибка отправляется в файл журнала.Я ожидаю, что эта функция вернет TRUE

...