前言

前些天测试订阅邮件发送,每次发送订阅邮件,都报错504,我就想,没理由呀,我也设置了超时时间,为啥会这样呢,结果等我排查到vercel的log的时候我明白了,原来是因为vercel的普通用户只是默认支持一个请求的超时时间为10秒,详细请看这里vercel说明文档
所以我只能将它改成多线程的模式来操作了,不阻塞主线程请求返回就行,只要保证邮箱的正确,接下来就交给接口了。下面就教小伙伴们如何在qexo中使用python的多线程threading模块。

增加Email设置

找到 core\settings.py 文件,在文件末尾添加如下代码:

1
2
3
4
5
6
7
8
9
# 固定写法设置Email引擎
EMAIL_BACKEND ='django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.qq.com' # 腾讯QQ邮箱 SMTP 服务器地址
# EMAIL_PORT = 25 # SMTP服务的端口号
EMAIL_PORT = 465 # SMTP服务的端口号
EMAIL_HOST_USER = 'xxx' #你的qq邮箱,邮件发送者的邮箱
EMAIL_HOST_PASSWORD = 'xxx' #你申请的授权码(略)
# EMAIL_USE_TLS = False #与SMTP服务器通信时,是否启用安全模式
EMAIL_USE_SSL = True

如果小伙伴不知道怎么设置邮箱授权码,可以看下这个邮箱授权码设置,这是qq邮箱的授权码设置教程。

创建私有api

找到文件 hexoweb\api.py 文件,在文件末尾添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
from .functions import *   #在文件开头的地方添加

# 发送订阅邮件
@login_required(login_url="/login/")
def send_email(request):
from_email = "你的邮箱"
email_passd = "你的邮箱授权码"
html_content = getSubscribeHtml()
for to_email in ["邮箱","邮箱","邮箱","邮箱","邮箱","邮箱","邮箱",]:
SendMail(to_email.mail, to_email.name, from_email, email_passd, html_content, 'html').start()
return JsonResponse(safe=False, data={"msg":"OK,邮件已经发送完成。", "status":"true"})

创建功能类与方法

找到 hexoweb\functions.py 文件,在文件中添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import django  #在文件开头引入模块
import threading #在文件开头引入模块

# 邮件模板
def getSubscribeHtml():
return '<!DOCTYPE html> <html lang = "en"> <head> <base target="_blank" /> <style id="scrollbar" type="text/css"> ::-webkit-scrollbar { width: 0 !important } pre { white-space: pre-wrap !important; word-wrap: break-word !important; *white-space: normal !important } #letter img { max-width: 300px } </style> <style id="from-wrapstyle" type="text/css"> #form-wrap { overflow: hidden; height: 447px; position: relative; top: 0px; transition: all 1s ease-in-out.3s; z-index: 0 } </style> <style id="from-wraphoverstyle" type="text/css"> #form-wrap:hover { height: 1300px; top: -200px } </style> </head> <body> <div style="width: 530px;margin: 20px auto 0;height: 1000px;"> <div id="form-wrap"><img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/before.png" alt="before" style="position: absolute;bottom: 126px;left: 0px;background-repeat: no-repeat;width: 530px;height: 317px;z-index:-100"> <div style="position: relative;overflow: visible;height: 1500px;width: 500px;margin: 0px auto;transition: all 1s ease-in-out .3s;padding-top:200px;"> <form> <div style="background: white;width: 95%;max-width: 800px;margin: auto auto;border-radius: 5px;border: 1px solid;overflow: hidden;-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);"> <img style="width:100%;overflow: hidden;" src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/violet.jpg" /> <div style="padding: 5px 20px;"><br> <div> <h3 style="text-decoration: none; color: rgb(246, 214, 175);">来自Shine的博客的订阅信息:</h3> </div><br><br> <div id="letter" style="overflow:auto;height:300px;width:100%;display:block;word-break: break-all;word-wrap: break-word;"> <div style="border-bottom: #ddd 1px solid;border-left: #ddd 1px solid;padding-bottom: 20px;background-color: #eee;margin: 15px 0px;padding-left: 20px;padding-right: 20px;border-top: #ddd 1px solid;border-right: #ddd 1px solid;padding-top: 20px;font-family: " Arial", "Microsoft YaHei" , "黑体" , "宋体" , sans-serif;">Shine的博客发布了新文章哦~!</div> </div> <div style="text-align: center;margin-top: 40px;"><img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/line.png" alt="hr" style="width:100%; margin:5px auto 5px auto; display: block;" /><a style="text-transform: uppercase;text-decoration: none;font-size: 14px;border: 2px solid #6c7575;color: #2f3333;padding: 10px;display: inline-block;margin: 10px auto 0;background-color: rgb(246, 214, 175);" href="blog.shinyu.cn" target="_blank" > Shine|请您过目~</a></div> <p style="font-size: 12px;text-align: center;color: #999;">自动书记人偶竭诚为您服务!<br>©2020<a style="text-decoration:none; color:rgb(246, 214, 175)" href="blog.shinyu.cn">Shine - 热爱生活点滴,分享精彩时刻</a></p> </div> </div> </form> </div><img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/after.png" alt="after" style=" position: absolute;bottom: -2px;left: 0;background-repeat: no-repeat;width: 530px;height: 259px;z-index:100"> </div> </div> </body> </html>'

# 发送邮件
def send_custom_email(rev_mail, rev_name, from_email, email_passd, content, content_subtype):
subject = '使用多线程发送邮件'
msg = django.core.mail.EmailMessage(
subject,
content,
from_email,
[rev_mail],
connection=get_connection(
username=from_email,
password=email_passd,
fail_silently=False
)
)
msg.content_subtype = content_subtype
msg.send()

class SendMail(threading.Thread):
def __init__(self,rev_mail, rev_name, from_email, email_passd, content, content_subtype):
self.rev_mail = rev_mail
self.rev_name = rev_name
self.from_email = from_email
self.email_passd = email_passd
self.content = content
self.content_subtype = content_subtype
threading.Thread.__init__(self)

def run(self):
send_custom_email(
self.rev_mail,
self.rev_name,
self.from_email,
self.email_passd,
self.content,
self.content_subtype
)

定义私有api的路由

找到 core\urls.py 文件,添加如下代码:

1
2
3
    path('api/del_talk/', del_talk, name='del_talk'),
path('api/run_online_script/', run_online_script, name='run_online_script'),
+ path('api/send_email/', send_email, name="send_email"),

Qexo四连

在cmd命令行中输入如下命令运行部署Qexo项目:

1
2
3
4
E:\Qexo> pip3 install -r requirements.txt
E:\Qexo> python3 manage.py makemigrations
E:\Qexo> python3 manage.py migrate
E:\Qexo> python3 manage.py runserver --noreload

访问接口 http://127.0.0.1:8000/api/send_email ,查看是否收到邮件。