在测试环境中使用Hotmail工程收发邮件,需要程序对加密连接邮件服务器做工作。
一、smtp 发送邮件
如果用户设置了邮件服务器是加密(安全)连接方式,则PHP程序在与邮件服务器连接成功,第一次发送“HELO”后,将链接管道设置为加密方式,下面是SMTP测试连接的代码。
if($svrparam['secureconn']=='1'){
fputs($smtpConnect, "STARTTLS". $newLine);
$smtpResponse = fgets($smtpConnect, 4096);
if( substr($smtpResponse,0,3) == '220' )
$ret .= '<p class="success" title="'.$smtpResponse.'"><i></i>STARTTLS 成功</p>';
else{
$ret .= '<p class="err" title="'.$smtpResponse.'"><i></i>STARTTLS 失败</p>';
echo $ret;exit;
}
// 将通讯管道设置为加密模式
if(!stream_socket_enable_crypto($smtpConnect, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
$ret .= '<p class="err"><i></i>加密管道失败</p>';
echo $ret;exit;
}
// you have to say HELO again after TLS is started
fputs($smtpConnect, "HELO $localhost". $newLine);
$smtpResponse = fgets($smtpConnect, 4096);
if( substr($smtpResponse,0,3) == '250' )
$ret .= '<p class="success" title="'.$smtpResponse.'"><i></i>与服务器二次握手成功</p>';
else{
$ret .= '<p class="err" title="'.$smtpResponse.'"><i></i>与服务器二次握手失败</p>';
echo $ret;exit;
}
}
二、POP3 接收邮件
imap_open使用非加密方式连接POP3服务器时的连接字符串:
$imapopenstr="{".$svrparam['rcvsvr']."/pop3:".$svrparam['rcvport']."}inbox";
使用加密方式链接POP3服务器时的连接字符串:
$imapopenstr="{".$svrparam['rcvsvr']."/pop3:".$svrparam['rcvport']."/ssl}inbox";
option中增加了ssl。
《二》
pop3加密
在smtp发送时ssl加密时可能遇到的问题,连接过程同博客”PHP 加密收发邮件“
一、基本流程
//1.打开sock通道
$smtp = fsockopen('smtp.live.com', 25, $errno, $errstr, $timeout);
//2.发送 ehlo
cmd( "EHLO {$_POST['DomainName']}" );
//3.启动tls加密
cmd( "STARTTLS" );
//4.将通道设为加密模式
stream_socket_enable_crypto( $smtp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT );
//5.再次 ehlo
cmd( "EHLO {$_POST['DomainName']}" );
//6.登录命令
cmd( "AUTH LOGIN" );
//输入用户名
cmd(
//输入密码
cmd(
二、用smtp发送邮件时,如果你所用的邮箱服务器没有限制要加密收发邮件,那么只要有第 1,2,6步骤,就可以成功发送了
三、但当 服务器要求加密时,就一定要有3,4步,否则当然是连接不上啦。这里第5步不是必须的,不写也不会报错。
四、可能出现的问题
问题一:
报错:Warning:
意思是不支持ssl,输出phpinfo,发现自己的php环境没有安装ssl扩展,有些默认安装了,有些没有安装
这里写下windows下的安装方法
1、拷贝PHP 目录中的libeay32.dll, ssleay32.dll, php5ts.dll, php ext 目录下 php_curl.dll 文件到
system32 目录。(一定要拷贝全啊,不要丢掉哪个,不然会报错的)
2、修改php.ini:配置好extension_dir ,去掉extension = php_curl.dll
3、重起apache。
再次输出phpinfo,看到如下内容就安装成功了
cURL Information
Registered Stream Socket Transports tcp, udp, ssl, sslv3, sslv2, tls
问题二:
AUTH LOGIN的时候,从网上找,发现都写着 base64_encode("USERNAME_HERE" ),base64_encode("PASSWORD_HERE");自己也这样写了,报错了AUTH command failed: 5.0.0 Authentication Failed,去掉之后正常发送邮件
还有一点要注意的就是,发送邮件加密的这种感官上比平时的要慢三四秒钟
stream_socket_enable_crypto
(PHP 5 >= 5.1.0)
stream_socket_enable_crypto — Turns encryption on/off on an already connected socket
说明
$stream
,
bool $enable
[,
int $crypto_type
[,
resource $session_stream
]] )
Enable or disable encryption on the stream.
Once the crypto settings are established, cryptography can be turned on and off dynamically by passing TRUE
or FALSE
in the enable
parameter.
参数
-
The stream resource.
-
Enable/disable cryptography on the stream.
-
Setup encryption on the stream. Valid methods are
-
STREAM_CRYPTO_METHOD_SSLv2_CLIENT
-
STREAM_CRYPTO_METHOD_SSLv3_CLIENT
-
STREAM_CRYPTO_METHOD_SSLv23_CLIENT
-
STREAM_CRYPTO_METHOD_TLS_CLIENT
-
STREAM_CRYPTO_METHOD_SSLv2_SERVER
-
STREAM_CRYPTO_METHOD_SSLv3_SERVER
-
STREAM_CRYPTO_METHOD_SSLv23_SERVER
-
STREAM_CRYPTO_METHOD_TLS_SERVER
-
-
Seed the stream with settings from
session_stream
.
stream
enable
crypto_type
session_stream
返回值
Returns TRUE
on success, FALSE
if negotiation has failed or 0 if there isn't enough data and you should try again (only for non-blocking sockets).
范例
Example #1 stream_socket_enable_crypto() example
<?php
$fp = stream_socket_client("tcp://myproto.example.com:31337", $errno, $errstr, 30);
if (!$fp) {
die("Unable to connect: $errstr ($errno)");
}
/* Turn on encryption for login phase */
stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
fwrite($fp, "USER god\r\n");
fwrite($fp, "PASS secret\r\n");
/* Turn off encryption for the rest */
stream_socket_enable_crypto($fp, false);
while ($motd = fgets($fp)) {
echo $motd;
}
fclose($fp);
?>
以上例程的输出类似于: