51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

简易Python 3 IMAP 邮件接收 Flask WSGI 网站 API 搭建

最近遇到一个需求,就是一个朋友买了一个教育邮箱的账号,这个账号可以无限别名,这个朋友想卖教育账号赚钱,用laravel写了个PHP的接码网站,但是却迟迟困在电子邮件的收件了。因为很多服务都对教育账号有着免费或者优惠,所以干这行还是挺挣钱的。他知道我比较擅长Python,所以就咨询我有没有办法用Python写一个收电子邮件的接口。

朋友的请求我当然不会拒绝,况且这是一个很简单的项目!

我使用的是Miniconda,这个虚拟环境可以装很多不同版本的python。但是我喜欢在一般情况下使用Pipenv环境,所以我使用pipenv环境初始化这个项目。

Terminal

$ mkdir email-receiver
$ cd email-receiver
$ git init
$ pipenv install flask
$ touch main.py

然后使用喜欢的编辑器写代码:

main.py

import imaplib
import email
import flask
import random
import string

创建Flask对象

app = flask.Flask(name)

设置session加密,每次启动随机生成32位字母

app.secret_key = random.choices(string.ascii_letters,k=32)

IMAP服务器信息

IMAP_SERVER = "imap.exmail.qq.com"
IMAP_PORT = 993

IMAP类

class Mail:

类初始化函数

def init(self,username,password,inbox='INBOX'):
self.username = username
self.password = password
self.mailbox = inbox
self.connect()
self.login()
self.setbox()
self.mails = []
self.lastmail = 0
self.pull()

连接IMAP服务器

def connect(self):
self.conn = imaplib.IMAP4_SSL(IMAP_SERVER,IMAP_PORT)

登录

def login(self):
self.conn.login(self.username,self.password)
self.status = 1

设置收件箱

def setbox(self):
self.conn.select(self.mailbox)

拉取邮件

def pull(self):
result,data = self.conn.search(None,"ALL")
if result!='OK':
print("或许什么地方出错了")
for i in data[0].split():
if int(i)<=self.lastmail:
continue
self.lastmail = int(i)
result,data = self.conn.fetch(i,"(RFC822)")
if result!='OK':
("或许什么地方出错了")
data = email.message_from_bytes(data[0][1])
self.mails.append(
{
"id": int(i),
"sender": data["From"],
"receiver": data["To"],
"subject": data["Subject"],
"time": data["Date"],
"content": data.get_payload(decode=True)
}
)

断开与SMTP服务器的连接

def disconnect(self):
self.conn.close()
self.conn.logout()
self.status = 0

IMAP_CONNECTIONS = {}

路由/login路径,接收POST请求

@app.route("/login",methods=['POST'])
def login():

临时变量,存储用户请求带有的信息,如果不存在返回None

username = flask.request.form.get("username")
password = flask.request.form.get("password")

如果username或password中有任意为空(None),跳出并返回错误。

if not username or not password:
flask.session["errMsg"] = "未设置凭据"
return flask.redirect("/login")

否则登入服务器

flask.session["imapkey"] = ".join(random.choices(string.ascii_letters,k=16))
IMAP_CONNECTIONS[flask.session["imapkey"]] = Mail(username,password)
return flask.redirect("/mailbox")

路由/login,接受GET请求,返回HTML页面。

@app.route("/login",methods=['GET'])
def loginUI():
return flask.render_template("loginPage.html",err=flask.session.get("errorMsg"))

路由/mailbox,接收GET请求,返回HTML页面。

@app.route("/mailbox",methods=['GET'])
def mailbox():
srv = flask.session.get("imapkey")
if not srv: return flask.redirect("/login")
imap = IMAP_CONNECTIONS.get(srv)
if not imap: return flask.redirect("/login")
return flask.render_template("mailList.html",mails=imap.mails)

路由/mail/{id},接收GET请求,返回HTML页面

@app.route("/mail/<id>",methods=['GET'])
def mail(id):
srv = flask.session.get("imapkey")
if not srv: return flask.redirect("/login")
imap = IMAP_CONNECTIONS.get(srv)
if not imap: return flask.redirect("/login")
mail = {"subject":"","content":""}
for i in imap:
if i["id"]==int(id):
mail=i
break
return "<h1>%s</h1><div>%s</div>"%(mail["subject"],mail["content"])

刷新邮件列表

@app.route("/pullemails",methods=['GET'])
def pullEmails():
srv = flask.session.get("imapkey")
if not srv: return flask.redirect("/login")
imap = IMAP_CONNECTIONS.get(srv)
if not imap: return flask.redirect("/login")
imap.pull()
return flask.redirect("/mailbox")

登出

@app.route("/logout",methods=['GET'])
def logout():
srv = flask.session.get("imapkey")
if srv:
imap = IMAP_CONNECTIONS.get(srv)
if imap:
imap.disconnect()
IMAP_CONNECTIONS.remove(imap)
return flask.redirect("/login")

if name == "main":
app.debug = True
app.run("127.0.0.1",7788)

HTML代码:

templates/loginPage.html
<!DOCTYPE html>
<html>
<head>
<title>Email Login</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
text-align: center;
padding-top: 100px;
}

.container {
width: 300px;
margin: 0 auto;
background-color: #fff;
padding: 20px;
border-radius: 5px;
box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.2);
}

.container h2 {
margin-bottom: 20px;
}

.container input[type="text"],
.container input[type="password"] {
width: 100%;
padding: 10px;
margin-bottom: 15px;
border: 1px solid #ccc;
border-radius: 3px;
box-sizing: border-box;
}

.container input[type="submit"] {
width: 100%;
background-color: #4CAF50;
color: #fff;
padding: 10px;
border: none;
border-radius: 3px;
cursor: pointer;
}

.container input[type="submit"]:hover {
background-color: #45a049;
}

.err {
color: red;
}
</style>
</head>
<body>
<div class="container">
<h2>Email Login</h2>
<form method="POST">
<input type="text" name="username" placeholder="Email" required><br>
<input type="password" name="password" placeholder="Password" required><br>
<input type="submit" value="Login">
</form>
</div>
<p class="err">{{err}}</p>
</body>
</html>

templates/mailList.html
<!DOCTYPE html>
<html>
<head>
<title>Email Viewer</title>
</head>
<body>
<p><a href="/pullemails">刷新邮件列表</a></p>
<div class="email-list">
<ul>
{% for i in range(len(mails)-1,-1,-1) %}
<li onclick="loadEmail('/mail/{{mails[i]["id"]}}')">{{i["subject"]}}</li>
{% endfor %}
</ul>
</div>
<div class="email-content">
<iframe id="emailFrame" src="" frameborder="0"></iframe>
</div>
</div>

<script>
function loadEmail(url) {
var iframe = document.getElementById('emailFrame');
iframe.src = url;
}
</script>
</body>
</html>

(注:2023/8/13修改:删除了一些GPT生成的问题内容,目前页面较简陋,敬请理解!)

然后就可以流畅使用uwsgi或者直接执行程序来获得一个收件箱了!

886~

赞(0)
未经允许不得转载:工具盒子 » 简易Python 3 IMAP 邮件接收 Flask WSGI 网站 API 搭建