查看原文
其他

一沟绝望的死水:模拟邮件服务器,批量注册利器

小姐姐养的狗 小姐姐味道 2021-05-19

搞事情

 

这是一沟绝望的死水,清风吹不起半点漪沦。 在这只许州官放火不许百姓电灯的年代,我们不如一起拿起几行简单的 python 代码,向这死水中多扔些破铜烂铁。

我们的目标就是把这互联网搞的更乱更臭,所以我们是不被规则束缚的。今天要拿来开刀的,是邮件系统。

垃圾邮件,很多人都深受其害,但我们今天并不是要搞它。以相反的方式进行思考,我们并不讨厌它,而且欢迎它的到来。比如,我要批量注册一万个 github 账号。github 通过邮箱验证就算注册成功了,这个时候,我们需要一个邮件服务器,具体流程如下

这个时候就想啊,能不能把邮件接收这块给自动化呢?自动化涉及两个点:
1)要有无穷无尽的邮箱供你使用
2)要非常容易的获得邮件内容进行解析

稍作思考,一个方案就在脑海中浮现,竟然是超简单的存在

其中:
1) 阉割的邮件系统不需要登录,只管收,不管发
2)邮件系统可以接受带有某后缀的任意邮件
3)提供简单的 REST 接口返回邮件 JSON 供解析

下面我们直接进入正题,说一下实现方式。

域名解析配置

打开域名管理,以阿里云为例,加入两条信息

加入一条 A 记录,指向我们将要部署的服务 IP 地址

  1. A    mx   6x.216.2xx.1xx

加入一条 MX 记录,指向上面配置的收邮件的域名地址。

  1. MX    *   mx.sayhiai.com

 

注意 *号,意思是所有的域名包括二级域名等,都会被收到。比如 xxxx@sayhiai.com 、 xjksfdsf@dfjsdlfjsd.sayhiai.com。
是不是无穷无尽?

编写 SMTPD 服务器

使用 python 可以很容易的实现一个 SMTPD 服务器,具体的是使用 aiosmtpd库。邮件默认收到后是 BASE64 编码,还分很多部分和类型,解析起来还是比较麻烦的。需要猜解其编码并递归拼接邮件等。代码片段如下:

  1. def decode_str(s):

  2.    value, charset = decode_header(s)[0]

  3.    if charset:

  4.        value = value.decode(charset)

  5.    return value

  6. def guess_charset(msg):

  7.    charset = msg.get_charset()

  8.    if charset is None:

  9.        content_type = msg.get('Content-Type', '').lower()

  10.        pos = content_type.find('charset=')

  11.        if pos >= 0:

  12.            charset = content_type[pos + 8:].strip()

  13.    return charset

  14. def print_part(msg):

  15.    rs = ""

  16.    content_type = msg.get_content_type()

  17.    if content_type == 'text/plain' or content_type == 'text/html':

  18.        content = msg.get_payload(decode=True)

  19.        charset = guess_charset(msg)

  20.        if charset:

  21.            content = content.decode(charset)

  22.        rs = rs + str(content)

  23.    else:

  24.        rs = rs + str(content_type)

  25.    return rs

  26. def print_info(msg):

  27.    rs = ""

  28.    if (msg.is_multipart()):

  29.        parts = msg.get_payload()

  30.        for n, part in enumerate(parts):

  31.            if part.is_multipart():

  32.                rs = rs + print_info(part)

  33.            else:

  34.                rs = rs + print_part(part)

  35.    else:

  36.        return print_part(msg)

  37.    return rs

编写 REST 服务

解析完邮件后,我们把内容存放在 sqlite3 中。接下来就是编写数据接口了。

我们的目的是尽量方便邮件的获取, REST+json是首选的。python 的 flask库无疑是最简单最适合的。

  1. import json

  2. from flask import Flask

  3. from flask import send_file

  4. from data import dataInstance

  5. app = Flask(__name__)

  6. dao = dataInstance

  7. def web_start(host, port):

  8.    app.run(host=host, port=port)

  9. @app.route('/')

  10. def index():

  11.    return send_file('static/index.html')

  12. @app.route('/all')

  13. def msg_all():

  14.    rows = dao.read_all()

  15.    return json.dumps(rows)

  16. @app.route('/from/<addr>')

  17. def msg_from(addr):

  18.    rows = dao.read_from(addr)

  19.    return json.dumps(rows)

  20. @app.route('/to/<addr>')

  21. def msg_to(addr):

  22.    rows = dao.read_to(addr)

  23.    return json.dumps(rows)

如你所见,提供了三个接口
1)/all 获取所有邮件
2) /from/{addr} 根据发送方查找邮件
3) /to/{addr} 根据接收方查找邮件

每次查询做多返回 100 条记录,反正多了你也用不着。

试验一下

使用 skdfkdsjf@sayhiai.com 注册一个账号。使用 curl 或者浏览器获取邮件信息:

  1. curl -XGET http://sayhiai.com:14000/to/skdfkdsjf@sayhiai.com

或者使用 http://sayhiai.com:14000/ 在线查询一下。

 

我的太慢,记得自己搭建一个啊,别忘了 SMTPD 的端口是 25,绑定其他的是不行的

结尾

至此, 一个完美的闭环完成了。我记的前段时间某些同学还对微软收购 github 心存不满,是时候给你一个发泄的途径了,注意多弄几个 ip。

你瞧瞧你瞧瞧,即使 github 这么大的一个网站,仅仅邮箱验证就通过了,可以预见网络上有多少的网站可以使用相同的思路去搞。

我已经把代码放到 github 上了 :) :) :). https://github.com/lycying/crazy-email-recv-srv ,对你有帮助的话别忘了关注微信公众号 小姐姐味道,如果顺便打赏几毛钱,那是最妙不过了。要是你干了坏事的话,就先不要留名了~


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存