Files
yakpanel-core/class/mailUnsubscribe.py

201 lines
7.1 KiB
Python
Raw Normal View History

2026-04-07 02:04:22 +05:30
#coding: utf-8
# +-------------------------------------------------------------------
# | YakPanel
# +-------------------------------------------------------------------
# | Copyright (c) 2015-2099 YakPanel(www.yakpanel.com) All rights reserved.
# +-------------------------------------------------------------------
# | Author: lotk
# | 邮局调用退订接口(免登录)
# +-------------------------------------------------------------------
import public,os,sys,db,time,json,re
try:
import jwt
except:
public.ExecShell('btpip install pyjwt')
import jwt
class mailUnsubscribe:
# 获取 SECRET_KEY
def get_SECRET_KEY(self):
path = '/www/server/panel/data/mail/jwt-secret.txt'
if not os.path.exists(path):
secretKey = public.GetRandomString(64)
public.writeFile(path, secretKey)
secretKey = public.readFile(path)
return secretKey
def M(self, table_name):
import db
sql = db.Sql()
sql._Sql__DB_FILE = '/www/vmail/postfixadmin.db'
sql._Sql__encrypt_keys = []
return sql.table(table_name)
def M3(self, table_name):
import db
sql = db.Sql()
sql._Sql__DB_FILE = '/www/vmail/mail_unsubscribe.db'
sql._Sql__encrypt_keys = []
return sql.table(table_name)
def Unsubscribe(self, get):
token = get.get('jwt', '')
if not token:
# return 'There is no token'
return public.returnJson(False, public.lang("There is no token"))
SECRET_KEY = self.get_SECRET_KEY()
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
email = payload['email']
# etypename = payload['etypename'] # 邮件类型名
# 优先取用户设置的退订
untype = get.get('id', '')
if not untype:
# 兼容旧退订 邮件类型id
etypes = payload.get('etypes', '')
if not etypes:
etypes = payload.get('etype', '')
else:
etypes = untype
# 任务主题 发件时间 todo
subject = payload.get('subject', '')
send_time = payload.get('send_time', 0)
task_id = payload.get('task_id', 0) # 群发任务
args = public.dict_obj()
args.email = email
args.etypes = etypes
args.task_id = task_id
args.subject = subject
args.send_time = send_time
self.submit_recipient_blacklist(args)
# return public.lang("The unsubscribe of email {} is successful", email)
return {"status": True, "msg": public.lang("The unsubscribe of email {} is successful", email)}
except jwt.ExpiredSignatureError:
# return public.lang('Operation failed,The token expires')
return {"status": False, "msg": public.lang('Operation failed,The token expires')}
except jwt.InvalidTokenError:
# return public.lang('Operation failed,Invalid tokens')
# return abort(404)
return {"status": False, "msg": public.lang('Operation failed,Invalid tokens')}
except Exception as e:
return {"status": False, "msg": f"error: {e}"}
# 订阅调用 获取类型和邮箱 判断邮箱可用?(邮箱校验 校验后插入) 可用插入数据库 (邮箱校验和邮箱发送营销邮件)
def Subscribe(self, get):
etype = get.get('etype', '')
public.print_log('etype {}'.format(etype))
email = get.get('email', '')
public.print_log('email {}'.format(email))
# todo 验证邮箱 生成验证链接
# 查询类型存在
etype = int(etype)
with self.M('mail_type') as obj:
etype_exit = obj.where('id =?', etype).count()
if not etype_exit:
# 无对应类型跳过
return
# 插入邮箱
with public.S("mail_unsubscribe", '/www/vmail/mail_unsubscribe.db') as obj:
# 有退订 改为订阅
exit_un = obj.where('recipient', email).where('etype', etype).where('active', 0).count()
if exit_un:
obj.where('recipient', email).where('etype', etype).update({'active': 1})
return
# 不存在 新增
exit = obj.where('recipient', email).where('etype', etype).where('active', 1).count()
if not exit:
created = int(time.time())
insert = {
'created': created,
'recipient': email,
'etype': etype,
'active': 1,
}
obj.insert(insert)
return
# 退订接口调用的提交黑名单
def submit_recipient_blacklist(self, args):
email = args.email
etypes = args.etypes
task_id = args.task_id
subject = args.subject
send_time = args.send_time
created = int(time.time())
etype_list = etypes.split(",")
with self.M('mail_type') as obj:
data_list = obj.select()
types = {str(item["id"]): item["mail_type"] for item in data_list}
try:
with public.S("mail_unsubscribe", '/www/vmail/mail_unsubscribe.db') as obj:
for etype in etype_list:
etype = int(etype)
if not types.get(str(etype), None):
continue
# 有退订 跳过
exit_un = obj.where('recipient', email).where('etype', etype).where('active', 0).count()
if exit_un:
continue
# 有订阅 改为退订记录任务
exit = obj.where('recipient', email).where('etype', etype).where('active', 1).count()
if exit:
# 更新退订时间
bb = obj.where('recipient', email).where('etype', etype).update({'active': 0, 'task_id': task_id, 'created':created})
continue
return True
except Exception as e:
# public.print_log(public.get_error_info())
return False
# 获取退订类型
def get_mail_type_list(self, get):
email = get.get('email', '')
if not email:
# return 'There is no email'
return {"status": False, "msg": public.lang("There is no email")}
with self.M('mail_type') as obj:
typelist = obj.order('created desc').select()
typelist = {str(item["id"]): item["mail_type"] for item in typelist}
with public.S("mail_unsubscribe", '/www/vmail/mail_unsubscribe.db') as obj:
mail_type = []
etypes = obj.where('active', 1).where('recipient like ?', '{}%'.format(email)).field('etype').select()
for j in etypes:
if typelist.get(str(j['etype']), None):
mail_type.append({'id': j['etype'], 'mail_type':typelist[str(str(j['etype']))]})
# return mail_type
return {"status":True, "msg": mail_type}