import asyncio import logging import email import platform from email.policy import default from aiosmtpd.controller import Controller from aiosmtpd.smtp import SMTP as SMTPProtocol from aiosmtpd.handlers import Message import os import sys import threading from ..models.domain import Domain from ..models.mailbox import Mailbox logger = logging.getLogger(__name__) # 检测是否Windows环境 IS_WINDOWS = platform.system().lower() == 'windows' class EmailHandler(Message): """处理接收的电子邮件""" def __init__(self, mail_store): super().__init__() self.mail_store = mail_store def handle_message(self, message): """处理邮件消息,这是Message类的抽象方法,必须实现""" # 这个方法在异步DATA处理完成后被调用,但我们的邮件处理逻辑已经在handle_DATA中实现 # 所以这里只是一个空实现 return async def handle_DATA(self, server, session, envelope): """处理接收到的邮件数据""" try: # 获取收件人和发件人 peer = session.peer mail_from = envelope.mail_from rcpt_tos = envelope.rcpt_tos # 获取原始邮件内容 data = envelope.content mail = email.message_from_bytes(data, policy=default) # 保存邮件到存储服务 for rcpt in rcpt_tos: result = await self.mail_store.save_email(mail_from, rcpt, mail, data) # 记录日志 if result: logger.info(f"邮件已保存: {mail_from} -> {rcpt}, 主题: {mail.get('Subject')}") else: logger.warning(f"邮件未保存: {mail_from} -> {rcpt}, 可能是无效地址") return '250 Message accepted for delivery' except Exception as e: logger.error(f"处理邮件时出错: {str(e)}") return '451 Requested action aborted: error in processing' # 为Windows环境自定义SMTP控制器 if IS_WINDOWS: class WindowsSafeController(Controller): """Windows环境安全的Controller,跳过连接测试""" def _trigger_server(self): """Windows环境下跳过SMTP服务器自检连接测试""" # 在Windows环境下,我们跳过自检连接测试 logger.info("Windows环境: 跳过SMTP服务器连接自检") return class SMTPServer: """SMTP服务器实现""" def __init__(self, host='0.0.0.0', port=25, mail_store=None): self.host = host self.port = port self.mail_store = mail_store self.controller = None self.server_thread = None def start(self): """启动SMTP服务器""" if self.controller: logger.warning("SMTP服务器已经在运行") return try: handler = EmailHandler(self.mail_store) # 根据环境选择适当的Controller if IS_WINDOWS: # Windows环境使用自定义Controller logger.info(f"Windows环境: 使用自定义Controller启动SMTP服务器 {self.host}:{self.port}") self.controller = WindowsSafeController( handler, hostname=self.host, port=self.port ) else: # 非Windows环境使用标准Controller self.controller = Controller( handler, hostname=self.host, port=self.port ) # 在单独的线程中启动服务器 self.server_thread = threading.Thread( target=self.controller.start, daemon=True ) self.server_thread.start() logger.info(f"SMTP服务器已启动在 {self.host}:{self.port}") return True except Exception as e: logger.error(f"启动SMTP服务器失败: {str(e)}") return False def stop(self): """停止SMTP服务器""" if not self.controller: logger.warning("SMTP服务器没有运行") return try: self.controller.stop() self.controller = None self.server_thread = None logger.info("SMTP服务器已停止") return True except Exception as e: logger.error(f"停止SMTP服务器失败: {str(e)}") return False