Files
fastapi_best_architecture/backend/plugin/email/utils/send.py
Wu Clan 5762834744 Update the ruff rules and format the code (#846)
* Update the ruff rules and format the code

* Update the per-file-ignores

* Update the ci

* Update rules

* Fix codes

* Fix pagination

* Update rules
2025-10-10 19:02:49 +08:00

114 lines
3.8 KiB
Python

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from aiosmtplib import SMTP
from anyio import open_file
from jinja2 import Template
from sqlalchemy import inspect
from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession
from backend.common.enums import StatusType
from backend.common.exception import errors
from backend.common.log import log
from backend.core.conf import settings
from backend.core.path_conf import PLUGIN_DIR
from backend.database.db import async_engine
from backend.plugin.config.crud.crud_config import config_dao
from backend.utils.serializers import select_list_serialize
from backend.utils.timezone import timezone
async def render_message(subject: str, from_header: str, content: str | dict, template: str | None) -> bytes:
"""
渲染邮件内容
:param subject: 邮件内容主题
:param from_header: 邮件来源
:param content: 邮件内容
:param template: 邮件内容模板
:return:
"""
message = MIMEMultipart()
message['Subject'] = subject
message['From'] = from_header
message['date'] = timezone.now().strftime('%a, %d %b %Y %H:%M:%S %z')
if template:
async with await open_file(PLUGIN_DIR / 'email' / 'templates' / template, encoding='utf-8') as f:
html = Template(await f.read(), enable_async=True)
mail_body = MIMEText(await html.render_async(**content), 'html', 'utf-8')
else:
mail_body = MIMEText(content, 'plain', 'utf-8')
message.attach(mail_body)
return message.as_bytes()
async def send_email(
db: AsyncSession,
recipients: str | list[str],
subject: str,
content: str | dict,
template: str | None = None,
) -> None:
"""
发送电子邮件
:param db: 数据库会话
:param recipients: 邮件接收者
:param subject: 邮件内容主题
:param content: 邮件内容
:param template: 邮件内容模板
:return:
"""
# 本地配置
email_host = settings.EMAIL_HOST
email_port = settings.EMAIL_PORT
email_ssl = settings.EMAIL_SSL
email_username = settings.EMAIL_USERNAME
email_password = settings.EMAIL_PASSWORD
# 动态配置
dynamic_config = None
def get_config_table(conn: AsyncConnection) -> bool:
inspector = inspect(conn)
return inspector.has_table('sys_config', schema=None)
async with async_engine.begin() as coon:
exists = await coon.run_sync(get_config_table)
if exists:
dynamic_config = await config_dao.get_all(db, 'EMAIL')
if dynamic_config:
status_key = 'EMAIL_STATUS'
host_key = 'EMAIL_HOST'
port_key = 'EMAIL_PORT'
ssl_key = 'EMAIL_SSL'
username_key = 'EMAIL_USERNAME'
password_key = 'EMAIL_PASSWORD'
configs = {d['key']: d['value'] for d in select_list_serialize(dynamic_config)}
if configs.get(status_key):
if len(dynamic_config) < 6:
raise errors.NotFoundError(msg='缺少邮件动态配置,请检查系统参数配置-邮件配置')
email_host = configs.get(host_key)
email_port = int(configs.get(port_key, 0))
email_ssl = configs.get(ssl_key, '') == str(StatusType.enable.value)
email_username = configs.get(username_key)
email_password = configs.get(password_key)
try:
message = await render_message(subject, email_username, content, template)
smtp_client = SMTP(
hostname=email_host,
port=email_port,
use_tls=email_ssl,
)
async with smtp_client:
await smtp_client.login(email_username, email_password)
await smtp_client.sendmail(email_username, recipients, message)
except Exception as e:
log.error(f'电子邮件发送失败:{e}')