feat: Mail Exchange#345
Merged
Merged
Conversation
e23eec3 to
931b994
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces a new Mail Exchange doctype that enables JMAP-based email import/export functionality, supporting multiple formats (eml, jmap, mbox, maildir, maildir-nested). It also refactors the existing Mail Data Exchange to use new directory utilities and improves error handling.
Key Changes
- New client-side
Mail Exchangedoctype with JMAP-based import/export - Refactored directory management with separate paths for data vs mail exchange
- Updated validation logic for Maildir and JMAP structures
- Streamlined notification and error handling in both exchange doctypes
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
mail/utils/validation.py |
Updated validate_jmap_structure signature and improved Maildir validation logic |
mail/utils/__init__.py |
Added separate directory functions for mail and data exchange operations |
mail/server/doctype/mail_data_exchange/mail_data_exchange.py |
Refactored to use new directory utilities and simplified notification handling |
mail/server/doctype/mail_data_exchange/mail_data_exchange.json |
Updated field layout and precision settings |
mail/client/doctype/mail_exchange/mail_exchange.py |
New 914-line implementation with format loaders, exporters, and JMAP integration |
mail/client/doctype/mail_exchange/mail_exchange.json |
New doctype configuration with import/export fields |
mail/client/doctype/mail_exchange/mail_exchange.js |
Client-side form logic with retry functionality |
mail/client/doctype/mail_exchange/mail_exchange_list.js |
List view configuration with status indicators |
mail/client/doctype/mail_exchange/test_mail_exchange.py |
Test file placeholder following codebase conventions |
mail/hooks.py |
Registered new permission handlers and scheduled tasks |
Comments suppressed due to low confidence (1)
mail/utils/validation.py:205
- The parameter
required_filesis of typelist[str], but on line 199 it's being compared withorto a set. When a non-empty list is passed, it will always be truthy, but the logic should check if the list is None or empty and use the default set. This should be changed to use proper type checking or default parameter value. Additionally, the type annotation should be updated tolist[str] | Noneto match the intended behavior.
def validate_jmap_structure(
base_dir: str, required_files: list[str], raise_exception: bool = False
) -> list[str]:
"""Validates a JMAP import directory. Returns a list of missing files or folders."""
required_files = required_files or {
"emails.json",
"identities.json",
"mailboxes.json",
"sieve.json",
"vacation.json",
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is the JMAP-based implementation of #224. It enables importing and exporting emails using the JMAP protocol.
Import
Export
Configurations
The following configuration values can be set in
site_config.json:mail_exchange_max_import: Maximum number of emails that can be imported in a single operation. Default: 1000mail_exchange_max_export: Maximum number of emails that can be exported in a single operation. Default: 1000mail_exchange_import_timeout: Timeout (in seconds) for the import job. Default: 3600mail_exchange_export_timeout: Timeout (in seconds) for the export job. Default: 3600mail_exchange_export_batch_size: Number of blobs downloaded concurrently during export. Default: 500Manual Test
Notes
Mailbox Creation Order
Mailboxes must be created before creating the exchange. They are not automatically created based on the mbox filename or the Maildir nested directory structure, as there is an important edge case. If the directory structure indicates that mailbox
Xis the parent ofY, but on the server,Yis configured as the parent ofX, this inconsistency will break any attempt to auto-create mailboxes based on the directory hierarchy.Received-AtTimestamp AccuracyIn Stalwart versions prior to
0.15.x, theReceived-Attimestamp may be incorrect and may match the import time instead. ThereceivedAtproperty inMetadatais read-only and is not set during email import, as some JMAP servers reject customreceivedAtvalues. Instead, this timestamp should be derived by parsing the most recent Received header from the message by the server.