PHP使用socks5代理发送邮件

通过socks5代理使用smtp发邮件

起因

因为使用smtp发邮件,点击查看邮件原文能看到发送的服务器ip,而一般使用smtp的服务器为后台服务器,为了防止ip暴露,所以需要通过代理来进行发邮件的动作。
红色框中为连接smtp服务器的服务器ip地址
为了完成这个需求,首先百度、谷歌了一遍没找到有能’参考‘的例子,因此只能自己想办法去实现。

思路1

之前使用过php的curl扩展中添加代理,因此很容易就想到用curl,而curl使用代理的相关例子也是比较容易找到,在curl中设置相关参数就可以。

curl_setopt($curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
curl_setopt($curl, CURLOPT_PROXY, "代理服务器ip");
curl_setopt($curl, CURLOPT_PROXYPORT, "代理端口");
curl_setopt($curl, CURLOPT_PROXYUSERPWD, "账号:密码");

而使用curl去发送smtp邮件的例子我也找到,参考这个帖子的例子php中通过curl smtp发送邮件虽然我不知道他的代码自己是不是能实现的,反正在我的环境PHP Version 7.1.26;cURL Information 7.61.1是报错的,提示curl的url不合法)。然后花了不少时间去查出错的原因(因为在phpinfo中看到cURL支持的协议有smtp、telnet,我觉得还能抢救一下),但是相关的用法没找到文档或例子。百度能搜到的只是刚刚参考的例子,谷歌搜到的使用curl发smtp邮件的完全没有。唯一相关的帖子回答大概意思是curl虽然支持简单的SMTP连接,但是不适合进行这种持续发送应答的tcp连接,最好使用sockets去完成,于是我使用了思路二的方式。
在这里插入图片描述

思路2

没办法使用curl(目前的能力不足)完成就只能使用sockets去连接了。没有办法偷懒,只能先去看一下socks5的协议和smtp的协议。这里难点其实是如何让socks5服务器连接上smtp服务器,连上以后又要如何让socks5服务器发消息给smtp服务器。而使用sockets去完成smtp发邮件的一整套流程,有比较多可以参考的资料。

smtp协议

对smtp协议没什么概念的话,建议可以参考一下一些使用cmd的telnet发送邮件的例子(随便贴一个例子),然后尝试使用telnet去发一封邮件。以qq的smtp服务器为例:(为回复消息)

  • telnet smtp.qq.com 587(220 smtp.qq.com Esmtp QQ Mail Server)
  • EHLO smtp.qq.com250-smtp.qq.com 250-PIPELINING 250-SIZE 73400320 250-STARTTLS 250-AUTH LOGIN PLAIN 250-AUTH=LOGIN 250-MAILCOMPRESS 250 8BITMIME)
  • STARTTLS auth login(220 Ready to start TLS)
  • AUTH LOGIN(334 VXNlcm5hbWU6)
  • {base64加密后的qq邮箱账号}(334 VXNlcm5hbWU6)
  • {base64加密后的qq邮箱密码}(235 Authentication successful)
  • mail from: <发件人邮箱地址>(250 OK)
  • rcpt to:<接收人邮箱地址>(250 OK)
  • data(354 END DATA WITH <CR><LF>.<CR><LF>)(意思是空行加一个"." 代表结束)
  • 输入一些邮件的补充信息标题、日期、回复地址、版本 等等(其中标题如果是中文需要拼接一下成Subject:=?UTF-8?B?{base64加密标题}?= )
  • 正文
  • /*空一行*/
  • .(250 OK queued as)
    到这里就已经完成发送邮件了,可以看到自己的邮箱已经收到一封没有附件的邮件。我的代码中就是按照这种形式去完成的发送邮件。

socks5协议

接下来就是socks5协议,这里我找到一篇比较详细的帖子,对socks5服务器的一些应答有一定的解释说明socks5代理服务器协议说明。按照我需要的,我只需要完成几步:

  • 连上socks5服务器
  • 完成socks服务器认证
  • 让socks服务器连上smtp服务器

而我需要做的是:

  • 向代理服务器对应端口发送0x05 0x01 0x02 且服务器回复0x05 0x02 (5 1 2 说明是认证密码模式 还有不需要认证的模式 这里我就没有管这个 在上面的帖子有对不同的模式进行说明)
  • 向代理服务器发送0x01 代理服务器账号长度 代理服务器账号 代理服务器密码长度 代理服务器密码 且服务器回复0x01 0x00(发送0x01 固定,然后指定之后的多少个字节为账号 然后是账号 然后指定之后多少个字节为密码 然后是密码 服务器回复1 0说明认证成功)
  • 向代理服务器发送0x05 0x01 0x00 0x03 smtp服务器域名长度 smtp服务器域名 smtp服务器端口 且服务器回复0x05 0x00 0x00 0x01 再加上6位数字(发送5 1 0 3 说明让代理服务器 访问后面指定的域名和端口 如果是 ip 则发 5 1 0 1 回复的 前4位固定 后面6位表示代理服务器使用了哪个端口去进行连接)
测试时因为这个不能像smtp一样使用telnet去测试,所以这里我直接使用代码来测试
pfsockopen($this->proxyHost,$this->proxyPort,$errno,$errbuf, 60);//创建一个socket句柄
fwrite($this->sock, pack("C3", 0x05, 0x01, 0x02));//发送5 1 2 
$res=fread($this->sock,512);//代理服务器回复的内容 这里直接打印出来是乱码,通过打印unpack('C'.strlen($res),$res) 可以查看返回值

到这里其实就已经完成了代理服务器的部分(就是这么简单),后面就是按smtp的协议直接发送,接收。

testSMTP.php例子代码

<?php
use Mail\ProxySMTP;

require('ProxySMTP.php');
$SMTP=new ProxySMTP;
$SMTP->proxyHost="代理服务器ip";
$SMTP->proxyPort="代理服务器端口";
$SMTP->proxyUsername="代理服务器用户名";
$SMTP->proxyPassword= "代理服务器密码";
$SMTP->smtpHost='smtp.qq.com';//smtp服务器域名
$SMTP->smtpPort='587';//smtp服务器端口
$SMTP->smtpUsername='2592515244@qq.com';//填邮箱
$SMTP->smtpPassword='smtp服务器的账号对应的密码';//填设置里面的授权码 不是qq密码
$SMTP->title='测试标题';
$SMTP->content='测试内容';
$SMTP->from='2592515244@qq.com';//发信人 和账号一样
$SMTP->to='2592515244@qq.com';//接收人
$SMTP->attachment='TIM图片20190
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值