refactor(email): 重构邮件配置从settings.py迁移到数据库

将邮件配置从Django的settings.py迁移到数据库的SystemConfig模型
更新测试文件以使用新的配置方式
添加邮件后端连接配置以提高灵活性
This commit is contained in:
2026-01-18 17:10:12 +08:00
parent 0049f23909
commit 9215de5a3d
5 changed files with 261 additions and 91 deletions

View File

@@ -620,11 +620,13 @@ timeout 300
当需要更新代码时,可以使用以下命令:
退出虚拟环境
deactivate
```bash
# 退出虚拟环境
deactivate
# 切换到项目目录
cd /var/www/diary-family
# 1. 拉取远程最新代码(只获取,不合并)

View File

@@ -1,2 +1,50 @@
2026-01-13 21:34:19.816 | INFO | __main__:main:167 - 开始PDF生成功能测试
2026-01-13 21:36:11.549 | INFO | __main__:main:216 - 开始Windows环境PDF生成测试
2026-01-18 16:23:51.077 | INFO | __main__:test_email_config:39 - 邮件配置信息:
2026-01-18 16:23:51.092 | WARNING | __main__:test_email_config:42 - smtp_server: 未配置
2026-01-18 16:23:51.093 | INFO | __main__:test_email_config:44 - smtp_port: 587
2026-01-18 16:23:51.093 | WARNING | __main__:test_email_config:42 - smtp_username: 未配置
2026-01-18 16:23:51.093 | WARNING | __main__:test_email_config:42 - smtp_password: 未配置
2026-01-18 16:23:51.093 | WARNING | __main__:test_email_config:42 - recipient_email: 未配置
2026-01-18 16:23:51.094 | INFO | __main__:test_email_config:44 - send_time: 08:00
2026-01-18 16:23:51.094 | ERROR | __main__:test_email_config:54 - 缺少必要的邮件配置: smtp_server, smtp_username, smtp_password
2026-01-18 16:23:51.094 | INFO | __main__:test_email_config:55 - 请在系统配置页面配置以下参数:
2026-01-18 16:23:51.094 | INFO | __main__:test_email_config:56 - - SMTP服务器: SMTP服务器地址
2026-01-18 16:23:51.095 | INFO | __main__:test_email_config:57 - - SMTP端口: SMTP端口通常是587或465
2026-01-18 16:23:51.095 | INFO | __main__:test_email_config:58 - - SMTP用户名: 发件邮箱
2026-01-18 16:23:51.095 | INFO | __main__:test_email_config:59 - - SMTP密码: 发件邮箱密码
2026-01-18 16:23:51.095 | INFO | __main__:main:510 -
[测试2] SMTP连接测试
2026-01-18 16:23:51.095 | INFO | __main__:test_smtp_connection:72 - 开始测试SMTP连接...
2026-01-18 16:23:51.118 | INFO | __main__:test_smtp_connection:92 - 连接SMTP服务器: localhost:587
2026-01-18 16:23:51.119 | INFO | __main__:test_smtp_connection:93 - 使用TLS: True, 使用SSL: False
2026-01-18 16:23:51.119 | INFO | __main__:test_smtp_connection:108 - 正在建立SMTP连接...
2026-01-18 16:23:56.491 | ERROR | __main__:test_smtp_connection:131 - SMTP连接测试失败: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
2026-01-18 16:23:56.492 | ERROR | __main__:test_smtp_connection:171 - 请检查:
2026-01-18 16:23:56.493 | ERROR | __main__:test_smtp_connection:172 - 1. SMTP服务器配置是否正确
2026-01-18 16:23:56.494 | ERROR | __main__:test_smtp_connection:173 - 2. 邮箱账号和密码是否正确
2026-01-18 16:23:56.494 | ERROR | __main__:test_smtp_connection:174 - 3. 网络连接是否正常
2026-01-18 16:23:56.495 | ERROR | __main__:test_smtp_connection:175 - 4. 防火墙是否允许出站连接
2026-01-18 16:23:56.496 | INFO | __main__:main:515 -
[测试3] 发送简单文本邮件
2026-01-18 16:23:56.496 | INFO | __main__:test_send_simple_email:182 - 开始测试发送简单邮件...
2026-01-18 16:23:56.502 | ERROR | __main__:test_send_simple_email:198 - 未配置发件邮箱 (smtp_username)
2026-01-18 16:23:56.503 | INFO | __main__:main:520 -
[测试4] 发送HTML邮件带附件
2026-01-18 16:23:56.503 | INFO | __main__:test_send_html_email_with_attachment:288 - 开始测试发送HTML邮件带附件...
2026-01-18 16:23:56.506 | ERROR | __main__:test_send_html_email_with_attachment:304 - 未配置发件邮箱
2026-01-18 16:23:56.507 | INFO | __main__:main:525 -
[测试5] 邮件发送性能测试
2026-01-18 16:23:56.508 | INFO | __main__:test_email_performance:398 - 开始测试邮件发送性能...
2026-01-18 16:23:56.510 | ERROR | __main__:test_email_performance:415 - 未配置发件邮箱
2026-01-18 16:23:56.511 | INFO | __main__:main:530 -
============================================================
2026-01-18 16:23:56.511 | INFO | __main__:main:531 - 测试总结:
2026-01-18 16:23:56.511 | INFO | __main__:main:532 - 通过测试: 0/5
2026-01-18 16:23:56.512 | INFO | __main__:main:533 - ============================================================
2026-01-18 16:23:56.512 | ERROR | __main__:main:556 - 多数测试失败,邮件系统无法正常工作。
2026-01-18 16:23:56.512 | INFO | __main__:main:557 -
紧急处理:
2026-01-18 16:23:56.512 | INFO | __main__:main:558 - 1. ❌ 检查SMTP服务器配置
2026-01-18 16:23:56.512 | INFO | __main__:main:559 - 2. ❌ 验证邮箱账号和密码
2026-01-18 16:23:56.513 | INFO | __main__:main:560 - 3. ❌ 检查网络连接
2026-01-18 16:23:56.513 | INFO | __main__:main:561 - 4. 参考README中的邮件配置章节
2026-01-18 16:23:56.513 | INFO | __main__:main:562 - 5. 查看详细错误日志

View File

@@ -24,6 +24,7 @@ def test_celery_email_config():
from django.conf import settings
from diary_family.celery import app
from core.models import SystemConfig
# 检查Celery配置
celery_config = {
@@ -45,21 +46,19 @@ def test_celery_email_config():
else:
logger.info(f" {key}: {value}")
# 检查邮件配置
# 从数据库获取邮件配置
config = SystemConfig.get_config()
email_config = {
'EMAIL_BACKEND': getattr(settings, 'EMAIL_BACKEND', None),
'EMAIL_HOST': getattr(settings, 'EMAIL_HOST', None),
'EMAIL_PORT': getattr(settings, 'EMAIL_PORT', None),
'EMAIL_HOST_USER': getattr(settings, 'EMAIL_HOST_USER', None),
'smtp_server': config.smtp_server,
'smtp_port': config.smtp_port,
'smtp_username': config.smtp_username,
'recipient_email': config.recipient_email,
}
logger.info("邮件配置信息:")
for key, value in email_config.items():
if value is None:
logger.warning(f" {key}: 未配置")
else:
if 'password' in key.lower():
logger.info(f" {key}: ***")
else:
logger.info(f" {key}: {value}")
@@ -67,10 +66,12 @@ def test_celery_email_config():
missing_configs = []
if not getattr(settings, 'CELERY_BROKER_URL', None):
missing_configs.append('CELERY_BROKER_URL')
if not getattr(settings, 'EMAIL_HOST', None):
missing_configs.append('EMAIL_HOST')
if not getattr(settings, 'EMAIL_HOST_USER', None):
missing_configs.append('EMAIL_HOST_USER')
if not config.smtp_server:
missing_configs.append('smtp_server')
if not config.smtp_username:
missing_configs.append('smtp_username')
if not config.smtp_password:
missing_configs.append('smtp_password')
if missing_configs:
logger.error(f"缺少必要的配置: {', '.join(missing_configs)}")
@@ -179,17 +180,34 @@ def celery_send_test_email(self, test_mode=True):
logger.info(f"[任务 {task_id}] 开始执行异步邮件发送任务")
try:
# 获取邮件配置
from_email = getattr(settings, 'EMAIL_HOST_USER', None)
# 从数据库获取邮件配置
from core.models import SystemConfig
from django.core.mail.backends.smtp import EmailBackend
config = SystemConfig.get_config()
from_email = config.smtp_username
if not from_email:
raise ValueError("未配置发件邮箱 (EMAIL_HOST_USER)")
raise ValueError("未配置发件邮箱 (smtp_username)")
to_email = getattr(settings, 'EMAIL_HOST_USER', from_email)
if isinstance(to_email, list):
recipient_list = to_email
else:
to_email = config.recipient_email or from_email
recipient_list = [to_email]
# 获取SMTP配置
host = config.smtp_server or 'localhost'
port = config.smtp_port or 587
username = config.smtp_username or ''
password = config.smtp_password or ''
use_tls = True # 默认使用TLS
# 创建邮件后端
backend = EmailBackend(
host=host,
port=port,
username=username,
password=password,
use_tls=use_tls,
fail_silently=False
)
# 创建邮件内容
subject = f"[Celery测试] 异步邮件发送成功 - {timezone.now().strftime('%Y-%m-%d %H:%M:%S')}"
@@ -206,8 +224,8 @@ def celery_send_test_email(self, test_mode=True):
- 执行重试次数: {self.request.retries}
邮件配置:
- 发件服务器: {getattr(settings, 'EMAIL_HOST', '未知')}:{getattr(settings, 'EMAIL_PORT', '未知')}
- 使用TLS: {getattr(settings, 'EMAIL_USE_TLS', '未知')}
- 发件服务器: {host}:{port}
- 使用TLS: {use_tls}
---
家庭日报系统
@@ -222,7 +240,7 @@ def celery_send_test_email(self, test_mode=True):
任务ID: {task_id}
这是一封测试邮件用于验证Celery异步邮件发送功能。
"
""
# 创建邮件
email = EmailMessage(
@@ -230,6 +248,7 @@ def celery_send_test_email(self, test_mode=True):
body=body,
from_email=from_email,
to=recipient_list,
connection=backend
)
email.content_subtype = 'plain'
email.encoding = 'utf-8'
@@ -294,17 +313,27 @@ def celery_send_html_report_email(self, include_attachment=False):
logger.info(f"[任务 {task_id}] 开始执行HTML报告邮件发送任务")
try:
# 获取邮件配置
from_email = getattr(settings, 'EMAIL_HOST_USER', None)
# 从数据库获取邮件配置
from core.models import SystemConfig
from django.core.mail.backends.smtp import EmailBackend
config = SystemConfig.get_config()
from_email = config.smtp_username
if not from_email:
raise ValueError("未配置发件邮箱")
to_email = getattr(settings, 'EMAIL_HOST_USER', from_email)
to_email = config.recipient_email or from_email
if isinstance(to_email, list):
recipient_list = to_email
else:
recipient_list = [to_email]
# 获取SMTP配置
host = config.smtp_server or 'localhost'
port = config.smtp_port or 587
username = config.smtp_username or ''
password = config.smtp_password or ''
use_tls = True # 默认使用TLS
# 准备报告数据
today = timezone.now().date()
yesterday = today - timedelta(days=1)
@@ -374,6 +403,16 @@ def celery_send_html_report_email(self, include_attachment=False):
</html>
"""
# 创建邮件后端
backend = EmailBackend(
host=host,
port=port,
username=username,
password=password,
use_tls=use_tls,
fail_silently=False
)
# 创建邮件
subject = f"[Celery] 家庭日报 {report_data['today']} - 测试报告"
@@ -382,6 +421,7 @@ def celery_send_html_report_email(self, include_attachment=False):
body=html_content,
from_email=from_email,
to=recipient_list,
connection=backend
)
email.attach_alternative(html_content, "text/html")
email.encoding = 'utf-8'
@@ -525,9 +565,34 @@ def main():
from django.conf import settings
from django.core.mail import EmailMessage
from django.utils import timezone
from core.models import SystemConfig
from django.core.mail.backends.smtp import EmailBackend
from_email = getattr(settings, 'EMAIL_HOST_USER', None)
to_email = getattr(settings, 'EMAIL_HOST_USER', from_email)
# 从数据库获取邮件配置
config = SystemConfig.get_config()
from_email = config.smtp_username
if not from_email:
raise ValueError("未配置发件邮箱")
to_email = config.recipient_email or from_email
recipient_list = [to_email] if isinstance(to_email, str) else to_email
# 获取SMTP配置
host = config.smtp_server or 'localhost'
port = config.smtp_port or 587
username = config.smtp_username or ''
password = config.smtp_password or ''
use_tls = True # 默认使用TLS
# 创建邮件后端
backend = EmailBackend(
host=host,
port=port,
username=username,
password=password,
use_tls=use_tls,
fail_silently=False
)
subject = f"[直接测试] Celery邮件测试 - {timezone.now().strftime('%H:%M:%S')}"
body = f"""
@@ -547,7 +612,8 @@ def main():
subject=subject,
body=body,
from_email=from_email,
to=[to_email] if isinstance(to_email, str) else to_email,
to=recipient_list,
connection=backend
)
sent = email.send(fail_silently=False)

View File

@@ -21,19 +21,19 @@ def test_email_config():
django.setup()
from django.conf import settings
from django.core.mail import get_connection
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from core.models import SystemConfig
# 从数据库获取系统配置
config = SystemConfig.get_config()
# 检查邮件配置
email_config = {
'EMAIL_BACKEND': getattr(settings, 'EMAIL_BACKEND', None),
'EMAIL_HOST': getattr(settings, 'EMAIL_HOST', None),
'EMAIL_PORT': getattr(settings, 'EMAIL_PORT', None),
'EMAIL_USE_TLS': getattr(settings, 'EMAIL_USE_TLS', None),
'EMAIL_USE_SSL': getattr(settings, 'EMAIL_USE_SSL', None),
'EMAIL_HOST_USER': getattr(settings, 'EMAIL_HOST_USER', None),
'EMAIL_HOST_PASSWORD': '***' if getattr(settings, 'EMAIL_HOST_PASSWORD', None) else None,
'smtp_server': config.smtp_server,
'smtp_port': config.smtp_port,
'smtp_username': config.smtp_username,
'smtp_password': '***' if config.smtp_password else None,
'recipient_email': config.recipient_email,
'send_time': config.send_time,
}
logger.info("邮件配置信息:")
@@ -44,16 +44,19 @@ def test_email_config():
logger.info(f" {key}: {value}")
# 验证必要配置
required_configs = ['EMAIL_HOST', 'EMAIL_PORT', 'EMAIL_HOST_USER']
missing_configs = [cfg for cfg in required_configs if not getattr(settings, cfg, None)]
required_configs = ['smtp_server', 'smtp_port', 'smtp_username', 'smtp_password']
missing_configs = []
for cfg in required_configs:
if not getattr(config, cfg, None):
missing_configs.append(cfg)
if missing_configs:
logger.error(f"缺少必要的邮件配置: {', '.join(missing_configs)}")
logger.info("请在系统配置页面或settings.py中配置以下参数:")
logger.info(" - EMAIL_HOST: SMTP服务器地址")
logger.info(" - EMAIL_PORT: SMTP端口通常是587或465")
logger.info(" - EMAIL_HOST_USER: 发件邮箱")
logger.info(" - EMAIL_HOST_PASSWORD: 发件邮箱密码")
logger.info("请在系统配置页面配置以下参数:")
logger.info(" - SMTP服务器: SMTP服务器地址")
logger.info(" - SMTP端口: SMTP端口通常是587或465")
logger.info(" - SMTP用户名: 发件邮箱")
logger.info(" - SMTP密码: 发件邮箱密码")
return False
logger.success("邮件配置测试通过!")
@@ -73,17 +76,17 @@ def test_smtp_connection():
import django
django.setup()
from django.conf import settings
from django.core.mail import get_connection
from django.core.mail.backends.smtp import EmailBackend
from core.models import SystemConfig
# 获取SMTP配置
host = getattr(settings, 'EMAIL_HOST', 'localhost')
port = getattr(settings, 'EMAIL_PORT', 587)
username = getattr(settings, 'EMAIL_HOST_USER', '')
password = getattr(settings, 'EMAIL_HOST_PASSWORD', '')
use_tls = getattr(settings, 'EMAIL_USE_TLS', True)
use_ssl = getattr(settings, 'EMAIL_USE_SSL', False)
# 从数据库获取SMTP配置
config = SystemConfig.get_config()
host = config.smtp_server or 'localhost'
port = config.smtp_port or 587
username = config.smtp_username or ''
password = config.smtp_password or ''
use_tls = True # 默认使用TLS
use_ssl = False # 默认不使用SSL
timeout = 10 # 连接超时时间
logger.info(f"连接SMTP服务器: {host}:{port}")
@@ -183,29 +186,28 @@ def test_send_simple_email():
import django
django.setup()
from django.conf import settings
from django.core.mail import EmailMessage
from django.utils import timezone
from core.models import SystemConfig
from django.core.mail.backends.smtp import EmailBackend
# 获取配置
from_email = getattr(settings, 'EMAIL_HOST_USER', None)
# 从数据库获取配置
config = SystemConfig.get_config()
from_email = config.smtp_username or None
if not from_email:
logger.error("未配置发件邮箱 (EMAIL_HOST_USER)")
logger.error("未配置发件邮箱 (smtp_username)")
return False
# 获取收件人(如果没有配置,使用发件人自己)
to_email = getattr(settings, 'EMAIL_HOST_USER', from_email)
if isinstance(to_email, list):
recipient_list = to_email
else:
to_email = config.recipient_email or from_email
recipient_list = [to_email]
# 获取SMTP配置
host = getattr(settings, 'EMAIL_HOST', 'localhost')
port = getattr(settings, 'EMAIL_PORT', 587)
username = getattr(settings, 'EMAIL_HOST_USER', '')
password = getattr(settings, 'EMAIL_HOST_PASSWORD', '')
use_tls = getattr(settings, 'EMAIL_USE_TLS', True)
host = config.smtp_server or 'localhost'
port = config.smtp_port or 587
username = config.smtp_username or ''
password = config.smtp_password or ''
use_tls = True # 默认使用TLS
# 创建测试邮件
subject = f"家庭日报系统测试邮件 - {timezone.now().strftime('%Y-%m-%d %H:%M:%S')}"
@@ -228,12 +230,23 @@ def test_send_simple_email():
logger.info(f" 收件人: {recipient_list}")
logger.info(f" 主题: {subject}")
# 创建邮件后端
backend = EmailBackend(
host=host,
port=port,
username=username,
password=password,
use_tls=use_tls,
fail_silently=False
)
# 创建邮件
email = EmailMessage(
subject=subject,
body=body,
from_email=from_email,
to=recipient_list,
connection=backend
)
email.content_subtype = 'plain'
email.encoding = 'utf-8'
@@ -279,19 +292,28 @@ def test_send_html_email_with_attachment():
import django
django.setup()
from django.conf import settings
from django.core.mail import EmailMessage
from django.template.loader import render_to_string
from django.utils import timezone
from core.models import SystemConfig
from django.core.mail.backends.smtp import EmailBackend
# 获取配置
from_email = getattr(settings, 'EMAIL_HOST_USER', None)
to_email = getattr(settings, 'EMAIL_HOST_USER', from_email)
if isinstance(to_email, list):
recipient_list = to_email
else:
# 从数据库获取配置
config = SystemConfig.get_config()
from_email = config.smtp_username or None
if not from_email:
logger.error("未配置发件邮箱")
return False
to_email = config.recipient_email or from_email
recipient_list = [to_email]
# 获取SMTP配置
host = config.smtp_server or 'localhost'
port = config.smtp_port or 587
username = config.smtp_username or ''
password = config.smtp_password or ''
use_tls = True # 默认使用TLS
# 创建HTML内容
html_content = f"""
<!DOCTYPE html>
@@ -328,12 +350,23 @@ def test_send_html_email_with_attachment():
subject = f"家庭日报系统 HTML测试邮件 - {timezone.now().strftime('%Y-%m-%d')}"
# 创建邮件后端
backend = EmailBackend(
host=host,
port=port,
username=username,
password=password,
use_tls=use_tls,
fail_silently=False
)
# 创建邮件
email = EmailMessage(
subject=subject,
body=html_content,
from_email=from_email,
to=recipient_list,
connection=backend
)
email.content_subtype = 'html'
email.encoding = 'utf-8'
@@ -369,19 +402,39 @@ def test_email_performance():
import django
django.setup()
from django.conf import settings
from django.core.mail import EmailMessage
from django.utils import timezone
from core.models import SystemConfig
from django.core.mail.backends.smtp import EmailBackend
import time
# 获取配置
from_email = getattr(settings, 'EMAIL_HOST_USER', None)
to_email = getattr(settings, 'EMAIL_HOST_USER', from_email)
if isinstance(to_email, list):
recipient_list = to_email
else:
# 从数据库获取配置
config = SystemConfig.get_config()
from_email = config.smtp_username or None
if not from_email:
logger.error("未配置发件邮箱")
return False
to_email = config.recipient_email or from_email
recipient_list = [to_email]
# 获取SMTP配置
host = config.smtp_server or 'localhost'
port = config.smtp_port or 587
username = config.smtp_username or ''
password = config.smtp_password or ''
use_tls = True # 默认使用TLS
# 创建邮件后端
backend = EmailBackend(
host=host,
port=port,
username=username,
password=password,
use_tls=use_tls,
fail_silently=False
)
# 性能测试
test_count = 3
times = []
@@ -395,6 +448,7 @@ def test_email_performance():
body=body,
from_email=from_email,
to=recipient_list,
connection=backend
)
start_time = time.time()