邮件处理
邮件处理
相关源文件
本章引用的主要源码文件:
.mypy-baseline.txt.pyrefly-baseline.jsondocker/compose/test-nginx.confsrc-ui/src/app/components/admin/trash/trash.component.scsssrc-ui/src/app/components/admin/trash/trash.component.spec.tssrc-ui/src/app/components/admin/trash/trash.component.tssrc-ui/src/app/components/admin/users-groups/users-groups.component.htmlsrc-ui/src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.htmlsrc-ui/src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.tssrc-ui/src/app/components/manage/mail/mail.component.htmlsrc-ui/src/app/components/manage/mail/mail.component.scsssrc-ui/src/app/components/manage/mail/mail.component.spec.tssrc-ui/src/app/components/manage/mail/mail.component.tssrc-ui/src/app/components/manage/workflows/workflows.component.htmlsrc-ui/src/app/components/manage/workflows/workflows.component.scsssrc-ui/src/app/components/manage/workflows/workflows.component.spec.tssrc-ui/src/app/components/manage/workflows/workflows.component.tssrc-ui/src/app/data/mail-rule.tssrc-ui/src/app/services/rest/mail-rule.service.spec.tssrc/documents/loggers.pysrc/documents/tests/test_api_trash.pysrc/paperless_mail/admin.pysrc/paperless_mail/mail.pysrc/paperless_mail/models.pysrc/paperless_mail/oauth.pysrc/paperless_mail/serialisers.pysrc/paperless_mail/tasks.pysrc/paperless_mail/tests/conftest.pysrc/paperless_mail/tests/factories.pysrc/paperless_mail/tests/test_api.pysrc/paperless_mail/tests/test_live_mail.pysrc/paperless_mail/tests/test_mail.pysrc/paperless_mail/tests/test_mail_oauth.pysrc/paperless_mail/tests/test_preprocessor.pysrc/paperless_mail/views.py
目的与范围
Paperless-ngx 中的邮件处理系统支持从电子邮件账户自动获取文档。它提供了一个灵活的框架,用于定义规则,以确定应处理哪些邮件和附件、如何对文档进行分类,以及在提取文档后对邮件执行哪些操作(例如,标记为已读、删除或移动到文件夹)。
本页面记录了邮件处理的架构、组件和行为。有关处理提取文档的文档消费管线的信息,请参阅文档处理管线。
系统架构
邮件处理系统由多个相互连接的组件组成,这些组件协同工作,以获取、过滤和处理邮件,从而提取文档。
标题:邮件处理系统流程
来源:src/paperless_mail/mail.py:515-523、src/paperless_mail/mail.py:79-210、src/paperless_mail/tasks.py:13-33
该系统主要由 process_mail_accounts Celery 任务驱动 src/paperless_mail/tasks.py:14-14,该任务调用 MailAccountHandler src/paperless_mail/mail.py:515-515 来处理一个或多个邮件账户。对于每个账户,处理器会处理所有已启用的规则,根据规则条件过滤邮件,并根据规则规范提取文档。文档提取后,会对邮件执行指定的邮件操作(删除、标记为已读等)。
邮件账户
邮件账户表示与邮件服务器的连接,文档将从这些服务器获取。每个账户存储访问邮件服务器所需的连接详细信息。
标题:MailAccount 数据结构
来源:src/paperless_mail/models.py:8-85
账户类型
Paperless-ngx 支持以下邮件账户类型 src/paperless_mail/models.py:18-21:
- IMAP - 使用用户名/密码认证的标准 IMAP 服务器。
- Gmail OAuth - 使用 OAuth2 认证的 Gmail 账户。
- Outlook OAuth - 使用 OAuth2 认证的 Microsoft Outlook/Office365 账户。
安全选项
对于 IMAP 账户,可以使用以下安全选项 src/paperless_mail/models.py:13-16:
- 无加密 - 未加密的连接(不推荐)。
- SSL - 使用 SSL 加密的安全连接。
- STARTTLS - 连接以未加密方式开始,然后升级为 TLS。
邮件规则
邮件规则定义了要处理哪些邮件以及如何处理它们。每条规则属于一个特定的邮件账户,并包含匹配邮件的条件、文档提取的规范以及处理完成后要执行的操作。
标题:MailRule 数据结构
来源:src/paperless_mail/models.py:87-305、src-ui/src/app/data/mail-rule.ts:1-87
邮件过滤
邮件规则支持多种过滤邮件的条件:
- 文件夹 - 要检查邮件的 IMAP 文件夹
src/paperless_mail/models.py:156-164。 - 发件人过滤 - 匹配发件人电子邮件地址
src/paperless_mail/models.py:166-171。 - 收件人过滤 - 匹配收件人电子邮件地址
src/paperless_mail/models.py:173-178。 - 主题过滤 - 匹配邮件主题中的文本
src/paperless_mail/models.py:180-185。 - 正文过滤 - 匹配邮件正文中的文本
src/paperless_mail/models.py:187-192。 - 最大天数 - 仅处理指定天数内的新邮件
src/paperless_mail/models.py:218-222。
附件过滤
规则还可以过滤要处理的附件:
- 附件文件名包含过滤 - 仅处理与指定模式匹配的文件(例如,
*.pdf、*invoice*)src/paperless_mail/models.py:194-204。 - 附件文件名排除过滤 - 排除与指定模式匹配的文件
src/paperless_mail/models.py:206-216。 - 附件类型 - 仅处理常规附件,或同时处理内联附件
src/paperless_mail/models.py:114-116。
消费选项
邮件规则通过 ConsumptionScope 支持从邮件中提取文档的不同方式 src/paperless_mail/models.py:103-112:
- 仅附件 - 仅将附件作为文档处理。
- 仅 EML - 将整个邮件作为文档处理(.eml 文件)。
- 全部 - 将邮件作为文档处理,同时将附件作为单独的文档处理。
文档元数据分配
规则可以自动为处理的文档分配元数据 src/paperless_mail/models.py:252-300:
- 标题 - 来自邮件主题、附件文件名或不设置。
- 标签 - 为文档分配特定标签。
- 文档类型 - 分配特定的文档类型。
- 通信方 - 来自电子邮件地址、发件人名称或自定义通信方。
- 所有者 - 可选地通过
assign_owner_from_rule将规则所有者设置为文档所有者。
邮件操作
处理完邮件后,Paperless-ngx 可以执行以下操作之一 src/paperless_mail/models.py:125-131:
- 删除 - 从服务器删除邮件。
- 移动 - 将邮件移动到指定的文件夹。
- 标记为已读 - 将邮件标记为已读。
- 标记 - 标记/星标邮件。
- 标签 - 使用指定的标签标记邮件(适用于 Gmail 标签和 Apple Mail 标签)。
处理管线
邮件处理管线遵循以下步骤来获取和处理邮件:
标题:邮件处理管线逻辑
来源:src/paperless_mail/mail.py:525-893、src/paperless_mail/tasks.py:13-33
管线中的关键组件
1. 邮件账户处理
MailAccountHandler.handle_mail_account src/paperless_mail/mail.py:525-525 方法是处理邮件账户的入口点。它连接到邮件服务器,在需要时刷新 OAuth 令牌 src/paperless_mail/mail.py:539-548,并处理该账户的每条已启用规则。
2. 邮件规则处理
对于每条规则,_handle_mail_rule src/paperless_mail/mail.py:593-593 方法会:
- 选择合适的文件夹
src/paperless_mail/mail.py:611-618。 - 根据规则过滤条件和邮件操作构建搜索条件
src/paperless_mail/mail.py:623-637。 - 使用
imap_tools获取匹配的邮件src/paperless_mail/mail.py:643-643。 - 处理每封之前未处理过的邮件
src/paperless_mail/mail.py:651-659。
3. 消息处理
_handle_message src/paperless_mail/mail.py:674-674 方法根据规则的消费范围从邮件中提取文档:
- 对于附件,它会根据文件模式和内容类型进行过滤
src/paperless_mail/mail.py:760-785。 - 对于仅邮件处理,它会使用
MailMessagePreprocessor创建一个.eml文件src/paperless_mail/mail.py:821-826。
4. 文档消费和 Celery Chord
queue_consumption_tasks src/paperless_mail/mail.py:864-864 函数使用 Celery chord 模式 src/paperless_mail/mail.py:15-15。它为提取的每个文档排队多个 consume_file 任务。一旦单封邮件的所有消费任务完成,就会执行回调任务 apply_mail_action src/paperless_mail/mail.py:304-304,以在服务器上执行邮件操作。
5. 邮件操作
apply_mail_action src/paperless_mail/mail.py:304-304 任务仅在文档成功排队等待消费后,才对邮件执行指定的操作(删除、标记为已读等)。
邮件操作的实现
邮件操作被实现为 BaseMailAction src/paperless_mail/mail.py:79-79 的子类,每个子类负责一个特定的操作:
标题:邮件操作类层次结构
来源:src/paperless_mail/mail.py:79-210
每个邮件操作类实现了两个关键方法:
get_criteria()- 返回过滤条件,以避免处理已执行过该操作的邮件(例如,MarkReadMailAction的{'seen': False})src/paperless_mail/mail.py:122-123。post_consume()- 在文档消费后对邮件执行实际的操作(例如,M.flag(...))src/paperless_mail/mail.py:125-126。
TagMailAction 对 Gmail 标签有特殊处理,通过 +X-GM-LABELS src/paperless_mail/mail.py:184-185 实现,对 Apple Mail 标签则使用 $MailFlagBit 关键字 src/paperless_mail/mail.py:64-72。
OAuth 集成
Paperless-ngx 通过 PaperlessMailOAuth2Manager src/paperless_mail/oauth.py:16-16 支持 Gmail 和 Outlook 账户的 OAuth2 认证。
标题:OAuth 令牌管理
来源:src/paperless_mail/oauth.py:16-118、src/paperless_mail/views.py:127-148、src/paperless_mail/mail.py:539-550
令牌刷新机制
OAuth 访问令牌会定期过期。Paperless 在 MailAccountHandler src/paperless_mail/mail.py:539-550 中处理此问题:
- 检查账户的
is_token是否为 true,以及expiration是否已过src/paperless_mail/mail.py:540-542。 - 使用
PaperlessMailOAuth2Manager().refresh_account_oauth_token(account)获取新的访问令牌src/paperless_mail/mail.py:544-544。 - 使用新的
password(访问令牌)和expiration更新MailAccount记录src/paperless_mail/oauth.py:110-116。
管理 API 和 UI
该系统通过 MailAccountViewSet src/paperless_mail/views.py:71-71 和 MailRuleViewSet src/paperless_mail/views.py:215-215 进行管理。
API 操作
- 测试连接:
MailAccountViewSet上的test操作src/paperless_mail/views.py:86-86允许在不保存账户的情况下验证凭据。 - 手动处理:
process操作src/paperless_mail/views.py:157-157会立即为特定账户触发process_mail_accountsCelery 任务。
网页界面
MailRuleEditDialogComponent src-ui/src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.ts:156-156 提供了配置规则的前端界面。它使用 MailRuleSerializer src/paperless_mail/serialisers.py:77-77 与后端通信。
跟踪已处理的邮件
Paperless-ngx 在 ProcessedMail 模型 src/paperless_mail/models.py:308-308 中跟踪已处理的邮件,以确保去重。
标题:ProcessedMail 实体
来源:src/paperless_mail/models.py:308-367、src/paperless_mail/mail.py:651-659
在处理消息之前,处理器会检查是否存在给定 rule、folder 和 uid 的 ProcessedMail 记录 src/paperless_mail/mail.py:651-653。如果记录存在且状态不是 FAILED,则跳过该邮件。记录的状态包括 SUCCESS src/paperless_mail/models.py:313-313、FAILED src/paperless_mail/models.py:314-314 或 PROCESSED_WO_CONSUMPTION src/paperless_mail/models.py:315-315。
定时处理
process_mail_accounts src/paperless_mail/tasks.py:14-14 任务被设计为定期运行。它会遍历所有账户 src/paperless_mail/tasks.py:21-21,检查它们是否有已启用的规则 src/paperless_mail/tasks.py:22-24,并使用 MailAccountHandler().handle_mail_account(account) src/paperless_mail/tasks.py:26-26 进行处理。
来源:src/paperless_mail/tasks.py:13-33