メール
一言でいうと
メール連携は「受信メールをテーブルレコードとして取り込み、一覧・検索・スレッド表示できるようにする」機能です。IMAP をポーリングして受信し、SMTP で送信します。既読/フラグ/移動/削除といったユーザー操作は、まずローカルのレコードを更新し、対応する IMAP 操作は永続キューに積んで非同期に反映する local-first 設計です。
主要ドメイン概念
| 概念 | 役割 |
|---|---|
UserMailbox | ユーザーごとの IMAP/SMTP 接続設定 |
InboundMailEvent / InboundMailMessage | 受信イベントと解析済みメッセージ |
MailThreadResolver | メッセージをスレッドにまとめる |
MailOutboundOp | 既読/フラグ/移動/削除などローカル変更に対応する、IMAP側へ反映すべき操作の永続キューエントリ |
MailPlacement | 受信メールをどのワークスペース/テーブルへ配置するかの解決結果 |
Backend 構造
api/controller/:MailMailboxController(接続設定・接続テスト・プロバイダ自動検出)、MailInboxController、MailFolderController、MailReadController/MailFlagController/MailMoveController/MailTrashController(既読・フラグ・移動・削除・復元・完全削除)、MailDraftController/MailSendController(下書き・送信)、MailImportController/MlMailboxImportController(.eml/.mboxインポート)、TenantMailEventsControllerdomain/service/InboundMailIngestionService.kt: 受信メールをRecordService経由でテーブルレコード化し、添付ファイルはStorageAwareDocumentServiceでドキュメントツリーへ保存。添付が抽出対象ならOrganizeJobCreatorで AI 取込パイプラインに回すdomain/service/MailOutboundProjector.kt: ローカル変更 → 永続キュー enqueue を同一トランザクションで行う、outbound の唯一の入口(下記callout参照)domain/service/MailOutboundOpQueueService.kt: キューの再試行ポリシー(bounded exponential backoff → 最終的に FAILED。ローカル変更自体はそのまま残り、次の reconcile が収束させる)infrastructure/scheduler/MailImapPollingScheduler.kt/MailOutboundDrainScheduler.kt: 受信ポーリングと、outbound キューのドレイン(owner ごとにrunAs(tenant, owner)で分離実行、1件の失敗が他をブロックしない)infrastructure/listener/MailDeadlineExtractionListener.kt: 受信メールから AI で締切を抽出し、Google カレンダーへ反映する@TransactionalEventListener(AFTER_COMMIT)+@Async
Frontend 構造
composables/:useMailMailbox(接続設定)、useMailConnectForm、useMailReadStatus/useMailFlag/useMailMove/useMailTrash/useMailDelete(メッセージ操作)、useMailDrafts、useMailAttachmentPreviewcomponents/:MailConnectForm.vue/MailConnectFields.vue/MailConnectPrompt.vue(接続設定UI)、MailConversationListItem.vue/MailMessagePanel.vue(スレッド表示)、MailComposeDialog.vue、MailboxSettingsPanel.vue、MailConversationPane.vue/MailOutputTableField.vue(テーブル上でのメールレコード表示)
他モジュールとの辺
table: 受信メールはRecordService経由でレコードとして保存される。MailRecordAccessPortが owner の RLS context でアクセス制御するorganize: メール添付ファイルは AI 取込パイプライン(OCR → AI → 構造化レコード)に回せるeditor: 添付ファイルの実体はStorageAwareDocumentServiceを通してドキュメントツリーに保存されるcalendar:MailDeadlineExtractionListenerが受信メールから締切を抽出し、Google カレンダー連携(GoogleOAuthService)へ書き込むdisplay:ViewType.MAILとして受信箱をテーブル表示ビューの一種に描画できる
既読/フラグ/移動/削除といったメール状態変更は、必ず MailOutboundProjector を経由すること。MailImapPort を直接呼んではいけません。MailOutboundProjector は①ownerのRLS contextでの所有権チェック、②ローカルレコード更新、③IMAP操作の永続キューへの enqueue、の②③を同一トランザクションで行う契約になっており(「ローカル変更には必ず対応するキュー済み操作がある」を保証)、これを迂回すると local-first の整合性が壊れます。