我正在尝试验证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