import os import json from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Boolean, JSON from sqlalchemy.orm import relationship from datetime import datetime import re import sys from . import Base import config active_config = config.active_config class Email(Base): """电子邮件模型""" __tablename__ = 'emails' id = Column(Integer, primary_key=True) mailbox_id = Column(Integer, ForeignKey('mailboxes.id'), nullable=False, index=True) sender = Column(String(255), nullable=False) recipients = Column(String(1000), nullable=False) subject = Column(String(500), nullable=True) body_text = Column(Text, nullable=True) body_html = Column(Text, nullable=True) received_at = Column(DateTime, default=datetime.utcnow) read = Column(Boolean, default=False) headers = Column(JSON, nullable=True) # 提取的验证码和链接 verification_code = Column(String(100), nullable=True) verification_link = Column(String(1000), nullable=True) # 关联关系 mailbox = relationship("Mailbox", back_populates="emails") attachments = relationship("Attachment", back_populates="email", cascade="all, delete-orphan") def save_raw_email(self, raw_content): """保存原始邮件内容到文件""" storage_path = active_config.MAIL_STORAGE_PATH mailbox_dir = os.path.join(storage_path, str(self.mailbox_id)) os.makedirs(mailbox_dir, exist_ok=True) # 保存原始邮件内容 file_path = os.path.join(mailbox_dir, f"{self.id}.eml") with open(file_path, 'wb') as f: f.write(raw_content) def extract_verification_data(self): """ 尝试从邮件内容中提取验证码和验证链接 这个方法会在邮件保存时自动调用 """ # 合并文本和HTML内容用于搜索 content = f"{self.subject} {self.body_text or ''}" # 提取可能的验证码(4-8位数字或字母组合) code_patterns = [ r'\b[A-Z0-9]{4,8}\b', # 大写字母和数字 r'验证码[::]\s*([A-Z0-9]{4,8})', # 中文格式 r'验证码是[::]\s*([A-Z0-9]{4,8})', # 中文格式2 r'code[::]\s*([A-Z0-9]{4,8})', # 英文格式 ] for pattern in code_patterns: matches = re.findall(pattern, content, re.IGNORECASE) if matches: self.verification_code = matches[0] break # 提取验证链接 link_patterns = [ r'https?://\S+(?:verify|confirm|activate)\S+', r'https?://\S+(?:token|auth|account)\S+', ] for pattern in link_patterns: matches = re.findall(pattern, content, re.IGNORECASE) if matches: self.verification_link = matches[0] break def __repr__(self): return f"" def to_dict(self): """转换为字典,用于API响应""" return { "id": self.id, "mailbox_id": self.mailbox_id, "sender": self.sender, "recipients": self.recipients, "subject": self.subject, "received_at": self.received_at.isoformat() if self.received_at else None, "read": self.read, "verification_code": self.verification_code, "verification_link": self.verification_link, "has_attachments": len(self.attachments) > 0 if self.attachments else False }