Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

第一部分:系统技术架构概述

1.1 总体技术架构

SmartMail AI助手采用经典的三层架构设计,从下至上依次为基础设施层、数据持久化层、业务逻辑层和接口层。整个系统基于Java 17构建,以Spring Boot 3.x为核心框架,通过模块化的设计思想实现各功能组件的解耦。

系统采用单体应用架构部署,所有模块集成在一个进程中运行,简化部署和运维复杂度。模块之间的通信通过Spring IoC容器管理的Bean依赖注入实现,部分非核心流程通过Spring事件机制进行异步解耦。

1.2 技术栈全景

技术组件 版本 作用
Java 17+ 基础运行环境
Spring Boot 3.2.x 应用主框架,IoC容器
Spring Mail 集成 邮件收发协议实现
Spring Scheduler 集成 定时任务调度
Spring Data JPA 3.2.x 数据持久化抽象
Jsoup 1.15.4 HTML内容解析清洗
FreeTTS 1.2.2 语音合成引擎
H2 Database 2.2.x 嵌入式数据库
Lombok 1.18.30 代码简化工具
SLF4J + Logback 集成 日志记录
RestTemplate/OkHttp 集成 HTTP客户端,调用阿里云API

第二部分:分层架构详解

2.1 基础设施层

基础设施层是系统运行的底座,包括Java运行时环境、操作系统文件系统和网络通信设施。

Java运行时环境 :要求JDK 17及以上版本,利用JDK 17的新特性如文本块、增强的Switch表达式、Record类等简化代码编写。同时依赖JVM的内存管理和垃圾回收机制保证系统长期运行的稳定性。

文件系统 :用于存储配置文件、日志文件、嵌入式数据库文件和生成的语音文件。系统遵循XDG Base Directory规范,在用户主目录下创建 .smartmail文件夹存放所有运行时数据,避免污染系统目录。

网络通信 :系统需要访问两个外部网络服务:邮箱服务器(通过IMAPS协议,端口993)和阿里云百炼API(通过HTTPS协议,端口443)。网络模块配置了连接超时(10秒)和读取超时(30秒)参数,避免网络问题导致线程阻塞。

2.2 数据持久化层

数据持久化层负责系统数据的存储和访问,采用Repository模式封装数据访问逻辑。

数据库选型 :采用H2 Database作为嵌入式数据库,支持两种运行模式:文件模式(持久化到磁盘)和内存模式(仅运行时存在)。生产环境使用文件模式,数据存储路径为 ~/smartmail/data/smartmail.mv.db。H2的优势在于零配置、支持标准SQL、体积小,适合个人桌面应用场景。

数据源配置 :通过Spring Boot自动配置H2数据源,连接池使用HikariCP,配置最小空闲连接2个,最大连接数10个,连接超时30秒。

ORM框架 :采用Spring Data JPA作为对象关系映射框架,配合Hibernate作为JPA实现。实体类使用JPA注解标记,利用Lombok的@Data注解简化实体类的编写。Repository接口继承 JpaRepository,自动获得基础的CRUD方法。

数据库版本管理 :集成Flyway进行数据库版本管理,每次启动自动检查并执行未执行的迁移脚本。迁移脚本存放在 resources/db/migration目录下,命名规范为 V1__init.sqlV2__add_index.sql等。

数据模型设计 :核心数据模型包含三个实体类:Email(邮件实体)、UserConfig(用户配置)、ProcessLog(处理日志)。Email实体与 UserConfig实体多对一关系,一封邮件属于一个用户配置。ProcessLog记录每次调度任务的执行情况。

2.3 业务逻辑层

业务逻辑层是系统的核心,包含六个核心服务组件,每个组件封装独立的业务功能。

2.3.1 邮件抓取服务

邮件抓取服务基于JavaMail API实现,封装为 MailFetcher组件。该服务通过IMAPS协议连接邮箱服务器,实现邮件的增量抓取。

连接管理采用连接池模式,MailConnectionPool内部维护一组 Store对象,每次抓取任务从池中获取连接,使用完毕后归还。连接参数包括:超时时间设置(连接超时10秒,读取超时30秒)、SSL安全套接字工厂、调试模式开关等。

增量抓取策略:服务记录每次成功抓取的时间戳,存储在 lastFetchTime变量中并持久化到数据库。下次抓取时,通过IMAP的 RECENT标志或 SINCE条件仅获取该时间戳之后的新邮件。抓取完成后,可以选择性将邮件标记为已读(通过设置 Flags.Flag.SEEN)。

异常处理机制:采用重试模板 RetryTemplate封装网络操作,配置指数退避策略:第一次失败后等待2秒重试,第二次等待4秒,第三次等待8秒,最多重试3次。连续失败超过阈值则抛出异常,由上层调度模块处理。

2.3.2 内容清洗服务

内容清洗服务 ContentCleaner负责将原始邮件内容转换为适合AI分析的纯净文本。该服务接收 javax.mail.Message对象,提取MIME内容后进行处理。

MIME类型检测:首先检查邮件的Content-Type,如果是 text/plain则直接读取文本;如果是 text/html则交给Jsoup处理器;如果是 multipart/*则递归解析各个部分,优先选择文本部分,如果没有文本则解析HTML部分。

HTML解析流程:Jsoup解析器将HTML字符串解析为DOM树,然后执行清理操作:移除所有 scriptstyleiframenoscript等标签;移除所有内联事件处理器(如 onclick);移除所有样式属性;移除隐藏元素(style="display:none")。清理后的DOM树调用 text()方法提取纯文本。

编码处理:从邮件头部的 Content-Type中提取 charset参数,如果没有则使用ICU4J的 CharsetDetector进行编码检测,确保中文字符正确解码。解码后的文本统一转换为UTF-8编码。

正文提取算法:采用启发式算法识别并剔除邮件签名、免责声明、营销信息。算法基于文本块的特征进行判断:链接密度超过30%的区域判定为导航区;包含"退订"、"不再接收"等关键词的区域判定为营销尾部;连续的短行(少于10字符)判定为签名。这些区域被移除后,剩余文本作为邮件的核心内容。

长度控制策略:清洗后的文本如果超过2000字符,采用智能截断算法:首先检测是否存在"总结"、"要点"、"关键"等关键词,优先保留这些段落;如果没有,采用"开头+结尾"策略,保留前500字符和后300字符,中间用省略号连接。

2.3.3 AI分析服务

AI分析服务 AIAnalysisService封装对阿里云百炼平台的API调用,实现邮件分类和摘要生成。该服务基于HTTP客户端实现,支持同步调用和超时控制。

HTTP客户端配置:使用 RestTemplate作为HTTP客户端,配置连接工厂设置超时参数:连接超时5秒,读取超时30秒。请求拦截器添加认证头:Authorization: Bearer ${api-key}。响应拦截器记录响应状态和耗时,用于监控和调试。

请求封装:构建 AnalysisRequest对象,包含模型名称、消息列表、温度参数等字段。模型名称固定为 deepseek-r1,温度设置为0.1保证输出的确定性。消息列表包含两条消息:系统消息("你是一个专业的邮件助手,擅长分类和总结")和用户消息(包含邮件内容)。

批量处理实现:BatchAnalysisService继承 AIAnalysisService,实现批量逻辑。构建用户消息时,按顺序列出所有邮件的主题和内容,格式为:"邮件1主题:xxx\n邮件1内容:xxx\n邮件2主题:xxx\n邮件2内容:xxx..."。在提示词末尾指定返回格式:"请返回JSON数组,格式:[{id:1,category:"重要",summary:"摘要"},{id:2...}]"。

响应解析:API返回的JSON响应包含 choices[0].message.content字段,该字段是AI生成的文本内容。解析器提取该字段后,使用Jackson库将其解析为 List<AnalysisResult>对象。解析过程中进行严格的类型检查和字段验证,如果格式不正确则记录异常并抛出 AnalysisException

降级策略:在 AIAnalysisService接口中定义了默认方法 fallbackAnalyze(),当API调用失败或超时时调用。降级实现 LocalAnalysisService基于关键词规则进行分类,使用正则表达式匹配邮件内容中的关键信息。虽然准确率不如AI,但保证系统基本可用。

Token用量监控:每次API调用后解析响应头中的 x-ai-usage信息,记录消耗的token数量。累计用量达到阈值时发出告警,避免免费额度用尽后产生费用。

2.3.4 分类决策服务

分类决策服务 ClassificationService对AI分析结果进行后处理,结合用户偏好和历史数据进行优化。该服务实现 Classifier接口,支持多种分类器的组合使用。

分类体系实现:采用枚举类型 EmailCategory定义四种分类:IMPORTANTTODONOTIFICATIONOTHER。每个枚举包含优先级级别(1-4,1最高)和默认处理动作。

优先级排序算法:PriorityCalculator根据发件人域、发件人地址和历史行为计算邮件优先级。计算公式为:priority = basePriority - (favoriteBoost if in whitelist) + (spamPenalty if in blacklist)。基础优先级根据发件人角色确定:老板邮件基础优先级1,客户2,同事3,其他4。白名单中的发件人优先级提升1级,黑名单中的降低1级(最低为4)。

历史学习机制:LearningEngine组件收集用户对邮件的后续操作(如在邮箱客户端中标记重要、删除、回复等),通过简单的贝叶斯分类器更新分类权重。实现方式为统计每个发件人每类邮件的出现频率,当频率超过阈值时自动将该发件人加入对应分类的白名单。

去重聚合算法:ConversationAggregator检测邮件主题中是否包含"Re:"、"Fwd:"等前缀,将相同基础主题的邮件聚合为会话。对于会话线程,只播报最新一封邮件的摘要,但统计信息(如"您与张三有3封往来邮件")会播报。

2.3.5 语音合成服务

语音合成服务 VoiceSynthesisService基于FreeTTS引擎实现文本到语音的转换,生成可播放的音频流或文件。

引擎初始化:静态代码块中注册FreeTTS引擎中心:Central.registerEngineCentral("com.sun.speech.freetts.jsapi.FreeTTSEngineCentral")。创建合成器时指定语音风格,默认使用"kevin16"语音(美式英语,适合读中文)。

文本预处理:TextNormalizer对输入文本进行规范化处理。数字转换:将"123"转换为"一百二十三";日期转换:"2026-03-12"转换为"二零二六年三月十二日";英文单词按拼读规则处理,特殊符号替换为文字描述("&"→"和","%"→"百分之")。预处理后的文本更符合语音合成引擎的发音习惯。

分段播报实现:SegmentedSpeaker接收邮件列表,首先生成总述:"您有X封重要邮件",然后遍历列表逐条播报。每条邮件播报格式为:"第X封,来自[发件人],[摘要]"。分段之间插入300毫秒的静音间隔,便于用户区分。播报过程中支持暂停、继续、跳过等控制命令(通过键盘监听实现)。

音频输出控制:AudioOutput接口定义两种实现:RealtimePlayer通过Java Sound API实时播放音频;FileRecorder将音频编码为WAV格式保存到文件。文件命名格式为 smartmail_yyyyMMdd_HHmmss.wav,存储在 ~/smartmail/audio/目录下。用户可配置保留最近N天的音频文件,系统自动清理过期文件。

语音参数配置:支持语速(默认150字/分钟)、音调(默认1.0)、音量(默认0.8)的配置。这些参数通过 VoiceManager获取当前语音对象后设置,支持运行时动态调整。

2.3.6 定时调度服务

定时调度服务基于Spring Scheduler实现,是整个业务流程的驱动引擎。该服务封装为 ScheduledTasks组件,使用 @Scheduled注解标记调度方法。

调度策略配置:在 application.yml中定义两个cron表达式:mail.schedule.morning=0 30 8 * * MON-FRI(工作日上午8:30)和 mail.schedule.noon=0 0 12 * * MON-FRI(工作日上午12:00)。cron表达式支持在线修改,应用重启后生效。

任务编排实现:WorkflowEngine组件管理任务执行状态机。状态机定义六个状态:INITFETCHINGCLEANINGANALYZINGSYNTHESIZINGCOMPLETED。每个步骤执行前检查当前状态,执行成功后更新状态,执行失败时回滚到上一个状态。状态信息存储在数据库的 process_status表中,支持应用重启后恢复中断的任务。

并发控制机制:基于数据库悲观锁实现任务互斥。每次任务开始前尝试获取锁记录(select for update),如果锁已被其他进程持有则等待10秒后放弃。锁记录包含进程ID和开始时间,如果持有锁的进程超过30分钟未释放(可能是崩溃),则强制释放锁。

任务超时保护:每个任务步骤设置最大执行时间,通过 @Async配合 Future实现超时控制。邮件抓取步骤超时5分钟,AI分析步骤超时2分钟(每批),语音合成步骤超时1分钟。超时后强制中断任务并记录错误日志。


第三部分:模块间通信机制

3.1 依赖注入通信

基于Spring IoC容器,各服务组件通过构造器注入建立依赖关系。ScheduledTasks依赖 MailFetcherContentCleanerAIAnalysisService等核心服务;ClassificationService依赖 AIAnalysisServiceVoiceSynthesisService依赖 ClassificationService。这种显式依赖声明使得模块间的调用关系清晰可见,便于单元测试时模拟依赖。

3.2 事件驱动通信

对于非核心流程,采用Spring事件机制实现异步解耦。定义 EmailProcessedEvent事件,包含处理后的邮件列表和统计数据。StatisticsListener监听该事件,更新统计数据;NotificationListener监听该事件,发送处理完成通知。事件发布采用 ApplicationEventPublisher,监听器使用 @EventListener注解标记,默认异步执行(配合 @Async)。

3.3 缓存共享通信

对于需要多次访问的数据,采用内存缓存减少重复计算。使用Spring Cache抽象,底层实现选用Caffeine Cache。邮件清洗结果缓存配置过期时间10分钟,AI分析结果缓存配置过期时间30分钟。缓存键设计为邮件ID加时间戳的组合,确保不同时间处理的同一邮件不会冲突。


第四部分:外部接口设计

4.1 邮箱服务器接口

系统通过JavaMail API与邮箱服务器通信,实现IMAPS协议。接口调用封装在 MailFetcher中,对外暴露 fetchUnreadEmails()方法,返回 List<Email>对象。

协议细节 :IMAPS使用SSL/TLS加密,默认端口993。认证方式为用户名+密码(或授权码)。支持的邮件文件夹包括INBOX(收件箱)、SENT(已发送)、TRASH(垃圾箱),当前版本只处理收件箱。

邮件属性获取 :从 Message对象中提取以下属性:getFrom()获取发件人,getSubject()获取主题,getSentDate()获取发送时间,getContent()获取内容,getMessageNumber()获取消息编号,getFolder()获取所属文件夹。内容类型通过 isMimeType()方法判断。

标志位操作 :通过 message.getFlags()获取和设置邮件标志。主要使用 Flags.Flag.SEEN(已读)和 Flags.Flag.RECENT(最近到达)。处理完成后可选设置SEEN标志,避免重复处理。

4.2 阿里云百炼API接口

系统通过HTTPS协议调用阿里云百炼的API接口,实现大模型服务集成。

接口地址https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions

认证方式 :HTTP Header中添加 Authorization: Bearer ${api-key},API Key从阿里云控制台获取,存储在配置文件中。

请求格式 :JSON格式,包含以下字段:

  • model: 模型名称,固定为 deepseek-r1
  • messages: 消息列表,包含role和content
  • temperature: 温度参数,固定为0.1
  • max_tokens: 最大生成token数,默认2048
  • stream: 是否流式返回,固定为false

响应格式 :JSON格式,主要字段:

  • choices[0].message.content: AI生成的文本内容
  • usage.prompt_tokens: 提示词消耗token数
  • usage.completion_tokens: 生成内容消耗token数
  • usage.total_tokens: 总消耗token数

错误处理 :API返回非200状态码时,根据错误码进行差异化处理:401(认证失败)记录错误并禁用API调用;429(频率超限)等待后重试;500(服务器错误)降级到本地规则。

4.3 预留REST API接口

为未来Web管理界面预留REST API,通过Spring MVC实现。API遵循RESTful设计规范,使用JSON数据格式。

邮件管理API

  • GET /api/emails - 分页获取邮件列表,支持按分类、时间筛选
  • GET /api/emails/{id} - 获取邮件详情
  • PUT /api/emails/{id}/category - 修改邮件分类
  • DELETE /api/emails/{id} - 删除邮件记录

配置管理API

  • GET /api/config - 获取当前配置
  • PUT /api/config - 更新配置
  • POST /api/config/test - 测试邮箱连接

统计API

  • GET /api/stats/summary - 获取汇总统计
  • GET /api/stats/trend - 获取趋势数据
  • GET /api/stats/category - 获取分类占比

API统一返回 ResponseEntity包装的 ApiResponse对象,包含状态码、消息和数据字段。异常处理通过 @ControllerAdvice统一处理,返回友好的错误信息。


第五部分:安全机制设计

5.1 配置信息加密

敏感配置信息(邮箱密码、API密钥)在配置文件中加密存储。采用Jasypt库实现配置加密,启动时通过环境变量传入解密密钥。加密后的配置格式为 ENC(加密字符串)JasyptPropertySource在加载配置时自动解密。

5.2 邮件内容脱敏

发送到阿里云API的邮件内容经过脱敏处理。脱敏规则包括:发件人邮箱地址替换为 [发件人邮箱],收件人邮箱地址替换为 [收件人邮箱],姓名替换为 [姓名],手机号替换为 [手机号]。脱敏在内容清洗步骤之后、AI分析步骤之前执行,确保敏感信息不会离开本地。

5.3 本地数据加密

本地数据库文件默认不加密,但支持可选的AES加密配置。启用加密后,H2数据库连接URL添加 ;CIPHER=AES参数,启动时提示输入密码。音频文件默认不加密,如果存储在云同步文件夹(如iCloud、Dropbox),建议用户自行加密。

5.4 安全审计日志

记录所有安全相关事件,包括:登录尝试(成功/失败)、API调用、配置修改、敏感数据访问。日志格式包含时间戳、事件类型、结果、源IP(如果适用)。日志文件限制访问权限(600),仅文件所有者可读。


第六部分:性能与优化设计

6.1 连接池优化

邮件连接池配置:最大连接数5,最小空闲连接2,最大等待时间10秒,连接验证查询 NOOP(IMAP协议不需要验证查询)。连接空闲超时300秒,超时后自动关闭释放资源。

HTTP连接池配置:最大连接数20,每路由最大连接数10,连接存活时间5分钟,空闲连接检测周期1分钟。

6.2 批量处理优化

AI分析采用批量处理,每批处理5-10封邮件,减少API调用次数。批量大小动态调整:根据历史平均token消耗和剩余免费额度自动调整,剩余额度多时减小批量(获得更好效果),剩余额度少时增大批量(节省token)。

6.3 缓存优化

多级缓存设计:一级缓存Caffeine(内存),二级缓存H2(磁盘)。热点数据(最近处理的邮件、常用配置)驻留一级缓存,冷数据下沉到二级缓存。缓存命中率统计通过Micrometer暴露,用于调优缓存大小。

6.4 异步处理优化

非核心流程异步化:日志记录、统计更新、通知发送等操作通过 @Async异步执行,避免阻塞主流程。异步线程池配置:核心线程数2,最大线程数4,队列容量100,拒绝策略为调用者运行(避免任务丢失)。


第七部分:监控与可观测性

7.1 日志体系

采用SLF4J+Logback日志框架,配置三个日志级别:ERROR日志记录异常情况,WARN日志记录降级和重试,INFO日志记录任务执行情况。日志格式包含时间戳、线程名、日志级别、类名、消息内容。日志文件滚动策略:每天生成一个新文件,保留30天,单个文件最大100MB。

7.2 指标监控

集成Micrometer指标库,暴露JVM指标(内存、GC、线程)、业务指标(邮件处理数、API调用数、分类分布)和自定义指标(处理耗时、API响应时间)。指标可以通过JMX或HTTP(集成Prometheus)获取。

7.3 健康检查

Spring Boot Actuator提供健康检查端点 /actuator/health,包含以下健康指标:邮箱连接状态、API服务状态、磁盘空间、数据库连接。第三方监控系统可以定期轮询该端点,发现异常时告警。

7.4 分布式追踪

虽然单体应用不需要分布式追踪,但预留了Trace ID机制。每个任务生成唯一Trace ID,贯穿所有日志和数据库记录,便于问题排查时串联相关事件。


第八部分:部署与运维

8.1 部署结构

应用打包为可执行Jar文件,包含所有依赖(fat jar)。目录结构:

  • smartmail.jar - 可执行文件
  • config/application.yml - 外部配置文件
  • data/ - 数据库文件
  • logs/ - 日志文件
  • audio/ - 生成的音频文件

8.2 启动脚本

提供启动脚本 start.sh,包含以下功能:设置JVM参数(-Xmx256m,适合个人电脑)、加载环境变量(解密密钥)、启动应用、记录PID。停止脚本 stop.sh通过PID优雅关闭应用。

8.3 容器化支持

提供Dockerfile,基于 eclipse-temurin:17-jre-alpine基础镜像,减小镜像体积。容器启动时通过环境变量传入配置,数据卷挂载到宿主机,实现数据持久化。

8.4 升级策略

版本升级时,用户替换Jar文件重启即可。数据库版本管理通过Flyway自动执行迁移脚本,无需人工干预。配置文件新增项提供默认值,兼容旧版本配置。


第九部分:技术风险评估

9.1 API依赖风险

阿里云百炼API可能发生变更、限流或下线。应对策略:API调用封装在独立模块,便于切换供应商;实现本地降级规则,保证API不可用时系统基本可用;监控API调用成功率,异常时自动降级。

9.2 邮箱协议兼容性风险

不同邮箱服务商对IMAP协议的支持存在差异。应对策略:在 MailFetcher中实现多套策略,根据邮箱类型(通过域名识别)选择最佳策略;提供连接测试功能,用户配置后立即验证;常见邮箱(163、QQ、Outlook)单独测试和适配。

9.3 语音合成质量风险

FreeTTS音质一般,对中文支持有限。应对策略:允许用户选择其他TTS引擎,预留 TTSProvider接口;支持导出文本,用户可自行使用更高品质的TTS工具;未来可集成云端TTS服务(如阿里云语音合成)。

9.4 性能风险

邮件数量过多时可能影响系统性能。应对策略:单次处理上限50封;任务超时保护;逐步处理机制(分页获取);用户可配置处理频率和最大处理数量。

About

"SmartMail AI" is a Java-based intelligent email assistant that automatically fetches emails, classifies them using Alibaba Cloud's DeepSeek API, and delivers voice summaries of important messages during your commute.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages