搞事情
這是一溝絕望的死水,清風吹不起半點漪淪。 在這隻許州官放火不許百姓電燈的年代,我們不如一起拿起幾行簡單的python程式碼,向這死水中多扔些破銅爛鐵。
我們的目標就是把這網際網路搞的更亂更臭,所以我們是不被規則束縛的。今天要拿來開刀的,是郵件系統。
垃圾郵件,很多人都深受其害,但我們今天並不是要搞它。以相反的方式進行思考,我們並不討厭它,而且歡迎它的到來。比如,我要批量註冊一萬個github賬號。github通過郵箱驗證就算註冊成功了,這個時候,我們需要一個郵件伺服器,具體流程如下:
這個時候就想啊,能不能把郵件接收這塊給自動化呢?自動化涉及兩個點: 1)要有無窮無盡的郵箱供你使用 2)要非常容易的獲得郵件內容進行解析
稍作思考,一個方案就在腦海中浮現,竟然是超簡單的存在。
其中: 1) 閹割的郵件系統不需要登入,只管收,不管發 2)郵件系統可以接受帶有某字尾的任意郵件 3)提供簡單的REST介面返回郵件JSON供解析
下面我們直接進入正題,說一下實現方式。
域名解析配置
開啟域名管理,以阿里云為例,加入兩條資訊
加入一條A記錄,指向我們將要部署的服務IP地址
A mx 6x.216.2xx.1xx
複製程式碼
加入一條MX記錄,指向上面配置的收郵件的域名地址。
MX * mx.sayhiai.com
複製程式碼
注意
*
號,意思是所有的域名包括二級域名等,都會被收到。比如xxxx@sayhiai.com 、 xjksfdsf@dfjsdlfjsd.sayhiai.com。 是不是無窮無盡?
編寫SMTPD伺服器
使用python可以很容易的實現一個SMTPD伺服器,具體的是使用aiosmtpd
庫。郵件預設收到後是BASE64編碼,還分很多部分和型別,解析起來還是比較麻煩的。需要猜解其編碼並遞迴拼接郵件等。程式碼片段如下:
def decode_str(s):
value, charset = decode_header(s)[0]
if charset:
value = value.decode(charset)
return value
def guess_charset(msg):
charset = msg.get_charset()
if charset is None:
content_type = msg.get('Content-Type', '').lower()
pos = content_type.find('charset=')
if pos >= 0:
charset = content_type[pos + 8:].strip()
return charset
def print_part(msg):
rs = ""
content_type = msg.get_content_type()
if content_type == 'text/plain' or content_type == 'text/html':
content = msg.get_payload(decode=True)
charset = guess_charset(msg)
if charset:
content = content.decode(charset)
rs = rs + str(content)
else:
rs = rs + str(content_type)
return rs
def print_info(msg):
rs = ""
if (msg.is_multipart()):
parts = msg.get_payload()
for n, part in enumerate(parts):
if part.is_multipart():
rs = rs + print_info(part)
else:
rs = rs + print_part(part)
else:
return print_part(msg)
return rs
複製程式碼
編寫REST服務
解析完郵件後,我們把內容存放在sqlite3中。接下來就是編寫資料介面了。
我們的目的是儘量方便郵件的獲取,REST+json
是首選的。python的flask
庫無疑是最簡單最適合的。
import json
from flask import Flask
from flask import send_file
from data import dataInstance
app = Flask(__name__)
dao = dataInstance
def web_start(host, port):
app.run(host=host, port=port)
@app.route('/')
def index():
return send_file('static/index.html')
@app.route('/all')
def msg_all():
rows = dao.read_all()
return json.dumps(rows)
@app.route('/from/<addr>')
def msg_from(addr):
rows = dao.read_from(addr)
return json.dumps(rows)
@app.route('/to/<addr>')
def msg_to(addr):
rows = dao.read_to(addr)
return json.dumps(rows)
複製程式碼
如你所見,提供了三個介面 1)/all 獲取所有郵件 2) /from/{addr} 根據傳送方查詢郵件 3) /to/{addr} 根據接收方查詢郵件
每次查詢做多返回100條記錄,反正多了你也用不著。
試驗一下
使用 skdfkdsjf@sayhiai.com 註冊一個賬號。使用curl或者瀏覽器獲取郵件資訊:
curl -XGET http://sayhiai.com:14000/to/skdfkdsjf@sayhiai.com
複製程式碼
或者使用 sayhiai.com:14000/ 線上查詢一下。
我的太慢,記得自己搭建一個啊,別忘了SMTPD的埠是25,繫結其他的是不行的
結尾
至此, 一個完美的閉環完成了。我記的前段時間某些同學還對微軟收購github心存不滿,是時候給你一個發洩的途徑了,注意多弄幾個ip。
你瞧瞧你瞧瞧,即使github這麼大的一個網站,僅僅郵箱驗證就通過了,可以預見網路上有多少的網站可以使用相同的思路去搞。
我已經把程式碼放到github上了 :) :) :). github.com/lycying/cra…
要是你幹了壞事的話,就先不要留名了~