I dug into the export code and I think this is expected behavior rather than a bug, but let me explain what “skipped” means so we can confirm.
vandelay export is stateless and convergent: on every run it re-queries the target account and matches each object in your archive against what is already there. “skipped” specifically means “this object already exists on the target, so nothing was created”. It matches mailboxes by role then name, calendars and address books by name, contacts and events by UID, and emails by Message-ID. An object can only be counted as skipped if the target server actually returned a matching object for it.
That is the key point: if the target account were truly empty, the queries would return nothing, nothing would match, and every object would be reported as created, not skipped. There is no code path that turns an empty target into an all-skipped run. So a result of 0 created and everything skipped, with the counts mirroring your archive almost exactly (26 mailboxes, 5902 emails, 4107 events, and so on), means the account that the export resolved to already contains all of that data. A freshly created Stalwart account only has a handful of role mailboxes and one default calendar and address book, so it could never match 26 custom mailboxes by name.
The most likely explanations, roughly in order:
- The export already ran once and populated the target, so this is a second run that correctly matches everything and skips it.
- The
--url is pointing at the wrong instance. If you have the old source and the new target both on localhost, it is easy to swap the ports and end up querying the source, where everything matches.
- You are looking at a different account than the one
--account-name resolved to.
You can confirm in a few seconds by querying the same account directly with the same credentials and URL you passed to vandelay:
curl -s -u 'user@domain:pass' http://127.0.0.1:8082/jmap \
-H 'Content-Type: application/json' \
-d '{"using":["urn:ietf:params:jmap:core","urn:ietf:params:jmap:mail"],
"methodCalls":[["Email/query",{"accountId":"<account-id>","calculateTotal":true},"q"]]}'
If total comes back non-zero, the target is not empty and vandelay is doing the right thing by skipping. If it genuinely returns 0 while vandelay still reports everything as skipped, that would be a real bug and I would love to see the request and response plus the resolved account id so I can chase it down.