refactor: 移除邮件功能

发信能力整体下线,唯一的调用方(忘记密码)前端也从来没接过。

- utils/shortcuts.py 删 send_email,连带四个 django.core.mail 相关 import
- account/tasks.py 整个删除,里面只有 send_email_async 一个 actor
- 删 ApplyResetPasswordAPI / ResetPasswordAPI 及其路由、serializer,
  User.reset_password_token 和 reset_password_token_expire_time 两个
  字段(account/0010)
- 删 SMTPAPI / SMTPTestAPI 及其路由、三个 SMTP serializer、
  SysOptions.smtp_config
- account/templates/reset_password_email.html

options/0003 数据迁移删掉库里的 smtp_config 行:_init_option 会为每个
OptionKey 建行,key 从代码里去掉后它会变成孤儿,而且配过 SMTP 的话
value 里存着明文密码。

保留 ResetUserPasswordAPI(管理端直接重置密码,不发信,前端在用)和
User.email(注册要填)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-05 23:17:48 -06:00
parent 8d35d5c2de
commit 927f235537
13 changed files with 46 additions and 245 deletions

View File

@@ -3,22 +3,6 @@ from utils.api import serializers
from .models import JudgeServer
class EditSMTPConfigSerializer(serializers.Serializer):
server = serializers.CharField(max_length=128)
port = serializers.IntegerField(default=25)
email = serializers.CharField(max_length=256)
password = serializers.CharField(max_length=128, required=False, allow_null=True, allow_blank=True)
tls = serializers.BooleanField()
class CreateSMTPConfigSerializer(EditSMTPConfigSerializer):
password = serializers.CharField(max_length=128)
class TestSMTPConfigSerializer(serializers.Serializer):
email = serializers.EmailField()
class CreateEditWebsiteConfigSerializer(serializers.Serializer):
website_base_url = serializers.CharField(max_length=128)
website_name = serializers.CharField(max_length=64)

View File

@@ -1,18 +1,14 @@
from django.urls import path
from ..views import (
SMTPAPI,
DashboardInfoAPI,
JudgeServerAPI,
RandomUsernameAPI,
SMTPTestAPI,
TestCasePruneAPI,
WebsiteConfigAPI,
)
urlpatterns = [
path("smtp", SMTPAPI.as_view()), # DEPRECATED: 前端未调用
path("smtp_test", SMTPTestAPI.as_view()), # DEPRECATED: 前端未调用
path("website", WebsiteConfigAPI.as_view()),
path("random_user", RandomUsernameAPI.as_view()),
path("judge_server", JudgeServerAPI.as_view()),

View File

@@ -4,7 +4,6 @@ import os
import random
import re
import shutil
import smtplib
from datetime import timedelta
from asgiref.sync import sync_to_async
@@ -20,83 +19,19 @@ from problem.models import Problem
from submission.models import Submission
from utils.api import APIView, AsyncAPIView, CSRFExemptAPIView, validate_serializer
from utils.cache import JsonDataLoader
from utils.shortcuts import get_env, send_email
from utils.shortcuts import get_env
from utils.websocket import push_config_update
from utils.xss_filter import XSSHtml
from .models import JudgeServer
from .serializers import (
CreateEditWebsiteConfigSerializer,
CreateSMTPConfigSerializer,
EditJudgeServerSerializer,
EditSMTPConfigSerializer,
JudgeServerHeartbeatSerializer,
JudgeServerSerializer,
TestSMTPConfigSerializer,
)
# DEPRECATED: 前端未调用 (2026-05-26)
class SMTPAPI(APIView):
@super_admin_required
def get(self, request):
smtp = SysOptions.smtp_config
if not smtp:
return self.success(None)
smtp.pop("password")
return self.success(smtp)
@super_admin_required
@validate_serializer(CreateSMTPConfigSerializer)
def post(self, request):
SysOptions.smtp_config = request.data
return self.success()
@super_admin_required
@validate_serializer(EditSMTPConfigSerializer)
def put(self, request):
smtp = SysOptions.smtp_config
data = request.data
for item in ["server", "port", "email", "tls"]:
smtp[item] = data[item]
if "password" in data:
smtp["password"] = data["password"]
SysOptions.smtp_config = smtp
return self.success()
# DEPRECATED: 前端未调用 (2026-05-26)
class SMTPTestAPI(APIView):
@super_admin_required
@validate_serializer(TestSMTPConfigSerializer)
def post(self, request):
if not SysOptions.smtp_config:
return self.error("Please setup SMTP config at first")
try:
send_email(
smtp_config=SysOptions.smtp_config,
from_name=SysOptions.website_name_shortcut,
to_name=request.user.username,
to_email=request.data["email"],
subject="You have successfully configured SMTP",
content="You have successfully configured SMTP",
)
except smtplib.SMTPResponseException as e:
# guess error message encoding
msg = b"Failed to send email"
try:
msg = e.smtp_error
# qq mail
msg = msg.decode("gbk")
except Exception:
msg = msg.decode("utf-8", "ignore")
return self.error(msg)
except Exception as e:
msg = str(e)
return self.error(msg)
return self.success()
class WebsiteConfigAPI(AsyncAPIView):
async def get(self, request):
ret = await SysOptions.aget_many(