mirror of
https://github.com/Cccc-owo/CheckInApp.git
synced 2026-06-17 05:56:29 +00:00
fix: email notification
This commit is contained in:
@@ -80,6 +80,11 @@ class CheckInService:
|
|||||||
# 执行打卡
|
# 执行打卡
|
||||||
result = perform_check_in(task, user_token)
|
result = perform_check_in(task, user_token)
|
||||||
|
|
||||||
|
# 如果是 Token 过期导致的失败,标记用户的 token_expired_notified 标志
|
||||||
|
if result["status"] == "token_expired" and task.user:
|
||||||
|
task.user.token_expired_notified = True
|
||||||
|
logger.info(f"标记用户 {task.user.alias} 的 token_expired_notified 为 True")
|
||||||
|
|
||||||
# 更新记录
|
# 更新记录
|
||||||
db.query(CheckInRecord).filter(CheckInRecord.id == record_id).update({
|
db.query(CheckInRecord).filter(CheckInRecord.id == record_id).update({
|
||||||
"status": result["status"],
|
"status": result["status"],
|
||||||
@@ -264,6 +269,11 @@ class CheckInService:
|
|||||||
logger.info(f"🤖 调用 Selenium Worker 执行打卡...")
|
logger.info(f"🤖 调用 Selenium Worker 执行打卡...")
|
||||||
result = perform_check_in(task, user.authorization)
|
result = perform_check_in(task, user.authorization)
|
||||||
|
|
||||||
|
# 如果是 Token 过期导致的失败,标记用户的 token_expired_notified 标志
|
||||||
|
if result["status"] == "token_expired" and user:
|
||||||
|
user.token_expired_notified = True
|
||||||
|
logger.info(f"标记用户 {user.alias} 的 token_expired_notified 为 True")
|
||||||
|
|
||||||
# 保存打卡记录
|
# 保存打卡记录
|
||||||
record = CheckInRecord(
|
record = CheckInRecord(
|
||||||
task_id=task.id,
|
task_id=task.id,
|
||||||
|
|||||||
@@ -666,6 +666,33 @@ class EmailService:
|
|||||||
|
|
||||||
subject = f"【接龙自动打卡】打卡{status_text} - {user.alias}"
|
subject = f"【接龙自动打卡】打卡{status_text} - {user.alias}"
|
||||||
|
|
||||||
|
# 判断是否是 Token 失效导致的失败
|
||||||
|
is_token_error = not success and message and (
|
||||||
|
"Token" in message or "token" in message or
|
||||||
|
"失效" in message or "授权" in message or "登录" in message
|
||||||
|
)
|
||||||
|
|
||||||
|
# Token 失效时的额外提示内容
|
||||||
|
token_error_section = ""
|
||||||
|
if is_token_error:
|
||||||
|
token_error_section = f"""
|
||||||
|
<div class="error-box">
|
||||||
|
<strong>⚠️ 打卡凭证已过期</strong>
|
||||||
|
<p style="margin: 10px 0;">打卡凭证已过期,无法自动打卡。所有自动打卡任务已暂停,请尽快刷新 Token 以恢复服务。</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><strong>如何刷新 Token:</strong></p>
|
||||||
|
<ol style="margin: 10px 0; padding-left: 20px;">
|
||||||
|
<li>登录系统(扫码或密码登录)</li>
|
||||||
|
<li>进入"仪表盘"或点击右上角的"刷新 Token"按钮</li>
|
||||||
|
<li>使用手机 QQ 扫描二维码完成刷新</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p style="text-align: center; margin-top: 20px;">
|
||||||
|
<a href="{settings.FRONTEND_URL}/dashboard" class="btn">立即登录刷新</a>
|
||||||
|
</p>
|
||||||
|
"""
|
||||||
|
|
||||||
body_html = f"""
|
body_html = f"""
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
@@ -714,6 +741,21 @@ class EmailService:
|
|||||||
color: #999;
|
color: #999;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}}
|
}}
|
||||||
|
.error-box {{
|
||||||
|
background-color: #f8d7da;
|
||||||
|
border-left: 4px solid #dc3545;
|
||||||
|
padding: 15px;
|
||||||
|
margin: 15px 0;
|
||||||
|
}}
|
||||||
|
.btn {{
|
||||||
|
display: inline-block;
|
||||||
|
padding: 12px 24px;
|
||||||
|
background-color: #667eea;
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 10px 0;
|
||||||
|
}}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -738,10 +780,10 @@ class EmailService:
|
|||||||
<td>打卡状态</td>
|
<td>打卡状态</td>
|
||||||
<td><strong style="color: {status_color};">{status_text}</strong></td>
|
<td><strong style="color: {status_color};">{status_text}</strong></td>
|
||||||
</tr>
|
</tr>
|
||||||
{f'<tr><td>详细信息</td><td>{message}</td></tr>' if message else ''}
|
{f'<tr><td>失败原因</td><td>{message}</td></tr>' if message else ''}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<p>如有问题,请及时检查您的打卡配置。</p>
|
{token_error_section if is_token_error else '<p>如有问题,请及时检查您的打卡配置。</p>'}
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<p>此邮件由系统自动发送,请勿直接回复。</p>
|
<p>此邮件由系统自动发送,请勿直接回复。</p>
|
||||||
|
|||||||
@@ -199,8 +199,10 @@ def check_token_expiration():
|
|||||||
else:
|
else:
|
||||||
logger.warning(f"用户 {user.alias} 的打卡 Token 即将过期邮件发送失败")
|
logger.warning(f"用户 {user.alias} 的打卡 Token 即将过期邮件发送失败")
|
||||||
|
|
||||||
# 情况2:Token 已过期(过期后 30 分钟内)
|
# 情况2:Token 已过期
|
||||||
elif -1800 < time_until_expiry <= 0: # 过期后 30 分钟内
|
# 修改逻辑:只要过期就发送提醒(不限制在30分钟内)
|
||||||
|
# 但为了避免频繁发送,使用 token_expired_notified 标志
|
||||||
|
elif time_until_expiry <= 0: # Token 已过期
|
||||||
if user.email and not user.token_expired_notified:
|
if user.email and not user.token_expired_notified:
|
||||||
logger.info(f"用户 {user.alias} 的打卡 Token 已过期,发送邮件提醒到 {user.email}...")
|
logger.info(f"用户 {user.alias} 的打卡 Token 已过期,发送邮件提醒到 {user.email}...")
|
||||||
from backend.services.email_service import EmailService
|
from backend.services.email_service import EmailService
|
||||||
|
|||||||
@@ -252,9 +252,12 @@ def perform_check_in(task, user_token: str) -> Dict[str, Any]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
# 情况4: Token 失效的特征标识 → 失败
|
# 情况4: Token 失效的特征标识 → 失败
|
||||||
elif ("登录" in response_text):
|
# 扩展检测条件:检测多种 Token 失效的响应特征
|
||||||
logger.warning(f"⚠️ 检测到登录失败关键字,Token 可能已失效")
|
elif ("登录" in response_text or "授权" in response_text or
|
||||||
# 发送失败邮件通知
|
"未登录" in response_text or "token" in response_text.lower() or
|
||||||
|
"Unauthorized" in response_text or response.status_code == 401):
|
||||||
|
logger.warning(f"⚠️ 检测到Token失效特征,Token 可能已失效")
|
||||||
|
# 发送打卡失败邮件通知(邮件内容已包含Token失效提醒和刷新指引)
|
||||||
if task.user and task.user.email:
|
if task.user and task.user.email:
|
||||||
try:
|
try:
|
||||||
from backend.services.email_service import EmailService
|
from backend.services.email_service import EmailService
|
||||||
@@ -262,13 +265,14 @@ def perform_check_in(task, user_token: str) -> Dict[str, Any]:
|
|||||||
'thread_id': payload.get('ThreadId', '未知'),
|
'thread_id': payload.get('ThreadId', '未知'),
|
||||||
'name': getattr(task, 'name', '打卡任务')
|
'name': getattr(task, 'name', '打卡任务')
|
||||||
}
|
}
|
||||||
|
# 只发送打卡失败通知(内容已说明Token失效)
|
||||||
EmailService.notify_check_in_result(task.user, task_info, False, "Token 已失效,需要重新授权")
|
EmailService.notify_check_in_result(task.user, task_info, False, "Token 已失效,需要重新授权")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"发送打卡失败邮件失败: {e}")
|
logger.error(f"发送打卡失败邮件失败: {e}")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"success": False,
|
"success": False,
|
||||||
"status": "failure",
|
"status": "token_expired", # 特殊状态,用于标识 Token 过期
|
||||||
"response_text": response_text,
|
"response_text": response_text,
|
||||||
"error_message": "Token 已失效,需要重新授权"
|
"error_message": "Token 已失效,需要重新授权"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user