Commit Graph
37 Commits
Author SHA1 Message Date
jcoffey-dev 2f33cd76a1 import: keep what an interrupted IMAP or Maildir import wrote
ci / test (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m51s
ci / announce (pull_request) Skipped
IMAP import wrote a whole folder in one transaction and stopped the folder
at the first message it could not import. A crash near the end of a large
INBOX kept nothing, and one bad INTERNALDATE lost the rest of the folder.
Worse, when a folder stopped early, fetches still in flight for it could be
filed into the next folder's mailbox.

- The transaction is committed after every fetch chunk. Each message is
  written in its own savepoint, so what is committed is always whole, and a
  rerun fetches only the UIDs still missing.
- A message that cannot be imported is rolled back on its own, logged with
  its folder and UID, and counted as failed; the folder carries on, and the
  message stays out of the UID map so the next run tries it again. Archive
  and I/O errors still stop the run.
- Fetch jobs and events carry a folder generation. Moving to a new folder
  cancels queued work for older ones, and any event from an older
  generation is dropped, never filed. Shutdown drains in-flight events
  before joining the workers, so it cannot hang on a blocked worker.
- INTERNALDATE month names are matched in any case.
- Maildir import gets the same per-message savepoint, and commits every 500
  new messages instead of once per folder.
2026-09-30 12:24:37 -07:00
jcoffey-dev 687027c7cb export: bring matched items up to date on every run
ci / test (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m50s
ci / announce (pull_request) Skipped
Export matched each item against the target and then skipped it, so a second
run -- the usual final pass of a cutover -- never carried anything that had
changed at the source since the first: read and flagged state, moves between
folders, edited contacts, events and Sieve scripts. It reported them as
skipped and exited 0, while the usage guide said matched items were updated.

Matched items are now updated, with one batched /set per type:

- Email: keywords are set to the archive's, added and removed, compared
  case-insensitively. Memberships of folders this run migrated are added and
  removed to match; folders that exist only on the target are left alone,
  and a message is never left in no folder. Properties the server did not
  report are not touched.
- Contacts and events: when both copies carry `updated`, the archive's is
  written only if it is newer, compared as instants so an offset or a
  fraction of a second is not taken for a change; otherwise each property the
  archive writes is compared, and those that differ are sent whole.
- Sieve scripts: the target's copy is downloaded and compared byte for byte
  with what export would write -- after renaming Stalwart's vendor names for
  an inbuxa target -- and replaced when it differs, so a renamed script is
  not re-uploaded on every run.

Updated items are counted as `updated`; unchanged ones stay `skipped`. The
usage guide now describes this.
2026-09-30 11:37:39 -07:00
jcoffey-dev 14a797cd65 Merge pull request 'Time out every connection, and scope --allow-invalid-certs' (#6) from fix/connection-safety into main
ci / test (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 3m31s
ci / announce (push) Skipped
2026-09-30 18:34:50 +00:00
jcoffey-dev 01ac1a5b3e Merge pull request 'export: write a message once, in every folder it was in' (#4) from fix/one-message-many-folders into main
ci / test (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Canceled after 1m36s
ci / announce (push) Canceled after 0s
2026-09-30 18:33:09 +00:00
jcoffey-dev 234b3203d7 Scope --allow-invalid-certs to the server the user named
ci / test (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m33s
ci / announce (pull_request) Skipped
The flag switched certificate checks off for every connection in the run.
That included the Microsoft sign-in endpoints, so a user passing it for a
self-signed source also sent refresh tokens, device codes and EWS client
secrets over unverified TLS. It also covered the export target, and any host
a server redirected to or named for its API, uploads or downloads.

It now applies only where the user pointed it: the host of --url, for the
source of an import or the target of an export. For an Exchange import with
no --url, it covers the mailbox's own domain, where on-premises Autodiscover
looks, and then only the EWS endpoint Autodiscover finds. The Microsoft and
Google sign-in and cloud hosts are always verified, with or without the flag.

Each HTTP client keeps a verifying agent and, only when the flag applies, a
second one that accepts invalid certificates, and picks per request by host.
The sign-in modules no longer take the flag at all. Autodiscover v2, which is
Microsoft's own service, is always verified.
2026-09-30 11:31:44 -07:00
jcoffey-dev 5ae0625ee1 export: write a message once, in every folder it was in
ci / test (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m11s
ci / announce (pull_request) Skipped
A source that files one message in several folders -- IMAP and Maildir
copies, Gmail labels -- leaves one archive row per folder, all pointing at the
same blob. Export imported each row on its own, so the message arrived on the
target once per folder. Worse, an interrupted export matched the rest by
Message-ID alone on the next run and skipped them, so their folders were never
added.

Export now folds rows with the same blob into one email, with the union of
their folders and keywords. On a match it adds, with one batched Email/set,
any migrated folder the target copy is missing; folders that exist only on the
target are left alone. Matching is still by Message-ID (or the fallback
digest), with size deciding between several messages that share one, so two
different messages are never folded onto one target email.

The archive is unchanged: the fold happens at export, so imports, resumes and
deletions work exactly as before.
2026-09-30 11:25:04 -07:00
jcoffey-dev 470fda6ac8 Rename Stalwart's Sieve names for inbuxa, and fail when activation does
ci / test (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m11s
ci / announce (pull_request) Skipped
inbuxa accepts vnd.inbuxa.while and vnd.inbuxa.expressions, and names its
environment items vnd.inbuxa.*, with no alias for Stalwart's vnd.stalwart.*
names. A script carried over unchanged failed to compile on the target, and
the account was left with no filtering behind a single warning.

When the target lists vnd.inbuxa extensions in its sieveExtensions, export
now renames Stalwart's names in the three places they are names: the strings
of a require list, the item name of an environment test, and
${env.vnd.stalwart.*} references inside strings. A small tokenizer skips
comments and reads quoted strings and text: blocks whole, so other text that
happens to contain the name is copied unchanged. Each rename is printed.
Against a target without the inbuxa names nothing changes.

The activation call is now checked. A method error, or an active script
that could not be created, is logged as an error naming the script and
counted as a failure, so export exits non-zero instead of leaving
filtering off with one warning line.
2026-09-30 11:24:16 -07:00
jcoffey-dev 5931b06392 Rename to inbuxa-migrate
The crate, binary, library path and every name the tool writes or reads
become inbuxa-migrate: the CLI name and about text, the HTTP user agent,
the credential variables (INBUXA_MIGRATE_PASSWORD, _TOKEN,
_EWS_CLIENT_SECRET and _GRAPH_TOKEN, with no fallback to the old names),
thread names, synthesized UIDs and calendar addresses
(urn:x-inbuxa-migrate:attendee:), and the Maildir file suffix used by the
export script. This is a new tool, so archives written by Vandelay are not
read back.

The version moves to the date scheme the release tags use (2026.9.30), and
the package metadata points at the inbuxa-migrate repository. The cargo-dist
and MSI metadata goes with the release tooling it served.

Modified files carry an added copyright line; the original notices stay.
2026-09-30 10:09:10 -07:00
Maurus Decimus 70fa688d25 Fix IMAP: import failed after authenticating to Dovecot when a capability contained :, such as IMAPSIEVE=sieve://... (fixes #43) 2026-09-28 11:38:10 +02:00
Maurus Decimus 5dc92c7329 Migrate to encodify 2026-09-28 10:45:15 +02:00
Maurus Decimus e00909640a MS Exchange Graph fixes 2026-08-27 19:51:18 +02:00
Maurus Decimus e8d98abccb MS Exchange Graph: Import the default Contacts folder, recover series exceptions (fixes #39) 2026-08-27 19:15:03 +02:00
Maurus Decimus 423b761617 v1.0.9 2026-08-22 18:46:54 +02:00
Maurus Decimus 1cc633f39c v1.0.8 (fixes #29 fixes #30 fixes #31) 2026-08-16 12:29:05 +02:00
Maurus Decimus c4e06bd87d Testcontainer fixes 2026-07-28 09:12:10 +02:00
Maurus Decimus 846fc88f7e Improve verbosity (closes #4 closes #19) 2026-07-18 11:41:08 +02:00
Maurus Decimus 9fc9178b67 Crypto provider test fixes 2026-07-17 18:53:09 +02:00
Maurus Decimus c13435b8f7 Report user friendly error message when urn:ietf:params:jmap:principals is not supported and no accountId is provided (closes #21) 2026-07-17 15:51:05 +02:00
Maurus Decimus 0f28e9b17e WebDAV import materialised the account root collection as a directory named after the account displayname (fixes #18) 2026-07-12 18:54:43 +02:00
Maurus Decimus 7f9e77ae58 Add vCard X-label tests 2026-07-08 11:34:59 +02:00
Maurus Decimus 24dadff463 Mapping existing special mailbox fails after alreadyExists response (fixes #17) 2026-07-07 11:36:47 +02:00
Maurus Decimus ceb8e1815c Self heal on blobNotFound errors when exporting data (closes #13) 2026-06-28 11:11:23 +02:00
Maurus Decimus 6ca561fff5 Fix: Strict RFC822.SIZE == BODY[] length check discards good mail 2026-06-27 12:00:12 +02:00
Maurus Decimus 0aaad2fd57 v1.0.4 2026-06-21 19:02:19 +02:00
Maurus Decimus cbcf0a1a84 Fix: Failures are double-counted 2026-06-21 08:42:58 +02:00
Maurus Decimus 4102b5f4ae Include correct JMAP capabilities in using 2026-06-19 11:05:04 +02:00
Maurus Decimus c1f3f742fe Mailbox roles must be unique per archive (fixes #8) 2026-06-15 21:28:27 +02:00
Maurus Decimus f263f57c09 EWS fixes - part 3 2026-06-10 22:19:28 +02:00
Maurus Decimus adbd0276a6 EWS fixes 2026-06-10 20:26:41 +02:00
Maurus Decimus f7371cc2ae Fix MS Exchange EWS: add support for version negotiation and other enhancements (closes #6) 2026-06-10 15:27:39 +02:00
Maurus Decimus 295038d8c0 Fix MS Exchange EWS: add support for version negotiation and other enhancements (closes #6) 2026-06-10 14:19:23 +02:00
Maurus Decimus bf0ef2083b Fix MS Exchange EWS: add support for version negotiation and other enhancements (closes #6) 2026-06-10 11:43:09 +02:00
Maurus Decimus 49f344660a Fix IMAP: Import fails with BAD on servers that advertise LIST-EXTENDED without SPECIAL-USE (closes #5) 2026-06-09 10:15:33 +02:00
Maurus Decimus 5197ed6a11 Fix MS Exchange duplicate ids issue 2026-06-04 13:13:02 +02:00
Maurus Decimus b173805212 v1.0.0 2026-05-30 08:09:57 +02:00
Maurus Decimus 0dfbaf8096 Fix sync issues 2026-05-29 19:49:37 +02:00
Maurus Decimus 576073f8c9 Initial commit 2026-05-29 18:02:15 +02:00