"""
邮件发送服务模块
=============================================================
封装 Flask-Mail 提供邮件发送能力,供业务模块和定时任务调用。
使用方式:
from application.services import mail_svc
# 简单发送
mail_svc.send_mail(to='user@example.com', subject='标题', body='内容')
# HTML 邮件
mail_svc.send_mail(to='user@example.com', subject='标题', html='
Hello
')
# 多收件人 / 抄送
mail_svc.send_mail(
to=['a@example.com', 'b@example.com'],
subject='标题',
body='内容',
cc=['cc@example.com'],
)
"""
import logging
from typing import List, Optional, Union
from extensions.mail import mail
from flask import current_app
from flask_mail import Message
logger = logging.getLogger(__name__)
def send_mail(
to: Union[str, List[str]],
subject: str,
body: Optional[str] = None,
html: Optional[str] = None,
cc: Optional[Union[str, List[str]]] = None,
bcc: Optional[Union[str, List[str]]] = None,
reply_to: Optional[str] = None,
) -> bool:
"""
发送邮件
Args:
to: 收件人地址,字符串或列表
subject: 邮件主题
body: 纯文本正文(与 html 二选一,都提供时邮件客户端自行选择显示)
html: HTML 正文
cc: 抄送地址
bcc: 密送地址
reply_to: 回复地址
Returns:
bool: 发送成功返回 True,失败返回 False
"""
if not to:
logger.warning("发送邮件失败:收件人不能为空")
return False
if not subject:
logger.warning("发送邮件失败:主题不能为空")
return False
if not body and not html:
logger.warning("发送邮件失败:正文不能为空")
return False
# 统一转为列表
if isinstance(to, str):
to = [to]
if cc and isinstance(cc, str):
cc = [cc]
if bcc and isinstance(bcc, str):
bcc = [bcc]
try:
msg = Message(
subject=subject,
recipients=to,
cc=cc,
bcc=bcc,
reply_to=reply_to,
body=body,
html=html,
)
mail.send(msg)
logger.info(f"邮件发送成功: to={to}, subject={subject}")
return True
except Exception as e:
logger.error(f"邮件发送失败: to={to}, subject={subject}, error={str(e)}")
return False