给phpMailer类加上使用socks5代理发邮件功能
使用sock5代理发邮件参考前一篇帖子https://blog.csdn.net/rty426/article/details/88899069
在使用代码前请先确保socks代理服务器/smtp服务器是正常工作的
chrome可以直接设置代理,然后通过访问测ip的工具可以比较方便的验证代理是否正常工作。
smtp服务器验证则可以直接通过不前一篇帖子的telnet来测试。
主要工作
原理和上一篇帖子类似,关于socks5协议和smtp协议上一篇都有说明,而在上一篇自己封装的类中,对异常的处理还不完善,以及没有用到ssl或tls加密,使用【Wireshark】能直接抓到明文信息,因此现在主要的工作就是把使用socks5代理的相关代码添加到phpmailer类中,以及完善一些异常的提示。
phpmailer类中的加密方式
经过对phpmailer类里加密相关的代码的阅读,这里有分2种类型加密ssl和tls。
2者加密的原理都一样,客户端先获取服务器端明文传输过来的公钥,通过使用对应的公钥加密客户端的公钥,并把密文发送到服务器端,服务器端使用自己的私钥解密后获取到客户端的公钥,之后的消息交流都互相使用对方公钥进行加密。
区别在于:tls是在客户端发送STARTTLS
后,服务端回复ready
后客户端才开启加密隧道。而ssl则是全程加密交流。
在phpmailer中,tls在startTLS()中使用了stream_socket_enable_crypto
函数开启加密隧道。而ssl则直接在smtp服务器的域名前加上ssl://
因为fsockopen()
和stream_socket_client()
有对应的协议特殊处理。
和phpmailer的区别
使用socks5代理服务器去进行加密和直接php开启加密隧道有一定区别,这是因为socks5服务器没有对连接的域名或ip前的协议ssl://
进行特殊处理,因此需要把phpmailer中直接加ssl://
也改成和tls一样处理的方式,使用stream_socket_enable_crypto
函数开启加密隧道。其中还存在一个问题是,stream_socket_enable_crypto
将获取证书的要求发送到socks5服务器,服务器直接转发到目标smtp服务器,smtp服务器将证书发到socks5服务器,服务器又原样转发到客户端,当客户端获取了证书后,会对证书和域名进行校验,如果不匹配,返回0。而证书和socks5服务器的域名肯定是不匹配的,这时候应该要让php不校验证书,phpmailer中打开socket连接使用的是fsockopen()
或者stream_socket_client()
,其中fsockopen()
没找到办法不校验证书,而stream_socket_client()
可以通过先构造一个不验证证书的context后传给第六个参数。
$options=['ssl' =>[
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
];
$socket_context = stream_context_create($options);
$this->smtp_conn = stream_socket_client(
$proxy['proxyHost'] . ':' . $proxy['proxyPort'],
$errno,
$errstr,
$timeout,
STREAM_CLIENT_CONNECT,
$socket_context
);
其中在整合后测试发现,phpmailer发的原始邮件中,居然还把当前运行程序的服务器域名给加上去了,分别加到了 EHLO
后面和MessageID
的@之后的部分中,这样和我们要使用socks隐藏发邮件的服务器ip的初衷完全违背了,因此还要把serverHostname()
方法魔改一下。如果代理服务器没连接上smtp服务器,在类的析构函数中有向smtp服务器发送quit
这时候socks服务器不会有反应就会出现一直加载中,卡死的状态。因此需要在连上smtp服务器后加上一个连接状态,在析构函数中加上判断是连上才发送quit
指令。
出现的错误
在进行相关测试时,发现程序经常未响应,经过一行行代码的定位发现fwrite或者fputs一直没有响应,原来是因为fwirte或fputs发送成功后,服务器没有任何返回,所以导致该函数一直在等服务器的返回。出现未响应的情况:1、smtp服务器识别每行的代码是通过判断\r\n
如果没有回车符+换行符,服务器不会有返回值,而是会认为还没完全接收完。(也有因为\r\n
是用单引号而没有解析导致识别不了)2、没连上smtp服务器,析构函数向socks5服务器发送quit
指令socks5服务器识别不了quit
指令也没有返回值导致程序超时。
魔改后的代码(环境参考安装环境帖子,php为7.1版本)
代码太长了,不能直接贴出来,打包一个下载地址
名称 | 链接 | 提取码 |
---|---|---|
魔改后的phpmailer类 | 下载地址 | ywk4 |
原装phpmailer类 | 下载地址 | b8jm |