-
Notifications
You must be signed in to change notification settings - Fork 3
Backup and Restore
This page began as a chapter of the 6.2.10 manual and has been corrected and extended for 6.2.28. The Control Panel's pages are grouped differently now, so the paths below use today's groups; the TLS ports 465, 993 and 995 exist only after you create them on the TCP/IP ports page (a fresh install seeds 25, 587, 110 and 143); and everything added since 6.2.10 is in Changes-Since-6210. Where a value here disagrees with the Settings Reference, which is generated from the code, the reference is right.
- The built-in backup writes one 7-Zip archive per run, named
HMBackup YYYY-MM-DD HHMMSS.7z, into the destination folder you configure. - It contains an XML index (domains, accounts, settings) and, when you ask for it, the whole message store.
- It does not include your messages unless you tick the box. Many people learn this at the worst possible moment.
- It does not include
hMailServer.INI's[Database]and[Directories]sections — those are per-machine and are yours to keep. - A restore is destructive and has no transaction: it deletes every domain and every public folder before it puts the backup's back. That is why it checks everything it can before it deletes anything, and why you should rehearse it.
- Since 6.2.25 a backup can run on a schedule, with retention, and each run is verified by extracting it again and reconciling it against the index.
| What | Where | In the built-in backup? |
|---|---|---|
Messages (.eml files) |
The data directory (default C:\Program Files\hMailServer\Data) |
Yes, with Back up messages ticked |
| Sieve scripts, vacation and duplicate state | <data directory>\Sieve\<domain>\<local part>\ |
Yes — they live inside the data directory, so they travel with the messages |
| ACME certificates and keys |
<data directory>\ACME by default (AcmeCertificateDirectory overrides it) |
Yes when they are under the data directory; no if you moved them elsewhere |
| Database | Your database server, or Database\hMailServer.sdf for the built-in one |
Its contents are exported to XML — see §15.3 for what is and is not exported |
hMailServer.INI |
Bin\hMailServer.INI |
[Settings] yes (mirrored into the database since schema 6011). [Database] and [Directories] no, deliberately |
| Manually placed TLS certificates and private keys | Wherever you put them | No. The database stores the paths, not the files. Copy the files yourself |
| Manually placed DKIM private keys | Wherever you put them |
No. Same reason: hm_domains stores the path |
The last two rows are the ones that quietly ruin a restore. The certificate and DKIM rows in the database are file paths; restoring the database onto a machine where those paths hold nothing gives you a server that starts, serves no TLS and signs nothing. Keep certificates and DKIM keys inside the data directory, or back them up alongside it.
Maintenance → Backup & restore configures the destination, chooses what goes in, starts a run by hand, and sets the schedule and retention.

Note Back up messages unticked while the other three are on: that is precisely the
combination this section exists to warn about, and it is already a step further on than a
fresh install, where backupoptions is seeded 0 and nothing at all is ticked. Two of the
six options in the table below arrived after this shot — Message metadata only and Verify each
backup — as did the schedule and retention boxes, which are new in 6.2.25 and sit under
the Backup card.
| Option | INI equivalent | What it changes |
|---|---|---|
| Back up domains (accounts, aliases, lists) | — | The domain tree goes into the XML index. Required for messages to mean anything: without it the message store is copied but no rows describe it |
| Back up messages | — | Copies the whole data directory into the archive. Only when Back up domains is ticked as well — the copy sits inside the domains branch of the run, so messages-without-domains stages nothing and then fails when it tries to compress a folder that was never created |
| Message metadata only — do not copy the message files | BackupMessagesDBOnly=1 |
Records which messages exist but not their contents. A restore then expects the files still to be in the data directory. Applies to backup and restore, after a service restart |
| Back up settings | — | Server settings, [Settings], security ranges, rules, TCP/IP ports, SSL certificate rows, blocked attachments, routes, incoming relays, public folders, groups, DNSBL/SURBL/white lists |
| Compress destination files (zip) | — | Compresses the message files into the archive too. Off, and every run overwrites the same DataBackup folder — see the warning below |
| Verify each backup by extracting its message store and reconciling it against the rows |
BackupVerifyRestore=1 (default on) |
§15.5 |
What the destination folder looks like after two runs, with compression on:
D:\Backups\hMailServer\
├── HMBackup 2026-09-07 020003.7z one complete backup
└── HMBackup 2026-09-08 020004.7z the next one
and with compression off:
D:\Backups\hMailServer\
├── HMBackup 2026-09-07 020003.7z index only
├── HMBackup 2026-09-08 020004.7z index only
└── DataBackup\ ONE copy of the message store,
├── example.com\ overwritten by every run
└── ...
Tick domains and messages together, always. Every combination that leaves one of them out is either useless or fails: messages without domains stages no files; domains without messages gives you a configuration backup and no mail.
With compression off you have exactly one generation of mail, whatever retention says. The archives keep generations of the index; the
DataBackupfolder beside them is overwritten every run. The server says so in the application log when it notices the combination. If you want more than one generation of mail, switch compression on.
The XML index is written to hMailServerBackup.xml in the destination, added to the
archive, and then deleted from disk — so what you restore from is the .7z, not
an XML file. (The Control Panel's file picker defaults its filter to *.xml; choose
All files and pick the archive.)
Everything below was read from the code that writes the index. "In" means a restore puts it back; "not in" means it does not, whatever the run reported.
In the archive
| Area | Detail |
|---|---|
| Domains | Name, postmaster, AD domain, active flag, size and message-size limits, plus-addressing, per-domain anti-spam options, signatures, account/alias/list limits, DKIM selectors and key paths, domain vacation messages |
| Accounts | Address, name, active flag, password hash and its algorithm, mailbox size limit, AD binding, vacation settings, admin level, forwarding, per-account spam thresholds, signature, last logon, TOTP secret, password-changed timestamp |
| Per account | External fetch accounts (with their passwords), app passwords (hashes), account rules |
| Folders | Folder name, subscription state, create time, UIDNEXT, RFC 6154 SPECIAL-USE flags; sub-folders recursively; ACL permissions for public folders
|
| Messages | One row per message in a folder: file name, sender, state, size, retry count, IMAP flags, id and UID — plus the file itself when messages are included |
| Aliases, domain aliases, distribution lists and their recipients | All of them |
| Server settings | The hm_settings property set, and the [Settings] mirror (hm_inisettings) |
| Collections | Security ranges (IP ranges), global rules, TCP/IP ports, SSL certificate rows, blocked attachments, routes and route addresses, incoming relays, public folders, groups and members, SURBL servers, DNS black lists, the anti-spam white list, blocked senders, greylisting white addresses |
| Secrets that must be presented | Route, external-fetch and SSL private-key passwords travel in the index in a portable encoding, so a restore onto different hardware keeps them (§15.8) |
Not in the archive
| Not carried | Consequence of a restore |
|---|---|
| The delivery queue | Queued outbound messages are not under any account's folders, so no rows describe them. Their .eml files are copied with the data directory, but nothing re-queues them |
| Per-domain relay settings (host, port, username, password, "requires authentication") | Silently lost. Re-enter them on the Domains dialog after a restore |
Per-domain message retention days |
Silently reset to 0 (keep for ever) |
Greylisting triplets (hm_greylisting_triplets) |
Every sender is greylisted afresh; first delivery from each is delayed once |
Auto-ban and login-failure state (hm_logon_failures, expiring hm_securityranges rows) |
Bans lapse. Permanent IP ranges are carried |
Quarantine (hm_quarantine) |
Quarantined messages are not restorable through this path |
Message trace (hm_messagetrace) and metric history (hm_metricsamples) |
History starts again |
IMAP METADATA (hm_imap_metadata) and QRESYNC expunge records (hm_imapexpunged) |
Clients resynchronise from scratch; nothing is lost from mailboxes |
Archive index (hm_archiveindex) and the full-text index (hm_messageindex*) |
Rebuilt by their own tasks |
Password history (hm_passwordhistory) |
The reuse check starts again from the current password |
[Database] and [Directories] in hMailServer.INI
|
Per-machine on purpose. Never copy the primary's INI over another machine's |
| Manually placed certificate, private-key and DKIM key files | The rows point at paths; the files are yours to copy |
Every refusal below happens before anything in the destination is written, or deletes only the archive this run created. The previous backups are never touched until the new one is complete and has been read back.
flowchart TD
A["Backup starts"] --> B{"Messages included, and every message file inside the data directory?"}
B -->|"no"| F1["Fail: All messages are not located in the data folder"]
B -->|"yes"| C{"Destination folder exists and is reachable?"}
C -->|"no"| F2["Fail: The specified backup directory is not accessible"]
C -->|"yes"| D{"Domains or settings wanted, and the database pool is up?"}
D -->|"no"| F3["Fail: no archive written, previous backups untouched"]
D -->|"yes"| E["Read domains, accounts, aliases and lists into the index"]
E --> G{"Did every database read actually run?"}
G -->|"no"| F3
G -->|"yes"| H["Copy the data directory to DataBackup - only reached when domains are included"]
H --> I["Read the settings into the index"]
I --> J{"Did every database read actually run?"}
J -->|"no"| F3
J -->|"yes"| K["Write hMailServerBackup.xml and add it to the archive"]
K --> L{"Compression on, and messages included?"}
L -->|"yes"| M["Add DataBackup to the archive, then delete the staged folder"]
L -->|"no"| N["Leave DataBackup beside the archive"]
M --> O["Verify: read the archive index back"]
N --> O
O -->|"unreadable, or does not describe this run"| F4["Fail and DELETE the incomplete archive"]
O -->|"good"| P{"BackupVerifyRestore on, and there is a store to check?"}
P -->|"yes"| Q["Extract the message store and reconcile it against the rows"]
P -->|"no"| R["Apply retention"]
Q -->|"store does not match what was written"| F4
Q -->|"could not be checked"| F5["Fail, but keep the archive and say it is unverified"]
Q -->|"matches"| R
R --> S["Backup completed successfully"]
Three properties of that shape are worth naming, because each replaces a way the backup used to lose data:
- A database outage cannot produce a hollow archive. The collections that back a domain return empty when their query fails, and an empty collection stores no XML — so a backup taken during an outage used to be written, reported as successful, and contain no domains at all. Restoring it deleted every domain and put nothing back. The run now watches every read and refuses before writing.
- Copying the data directory never terminates the service. A message file deleted between being listed and being copied is counted as vanished and skipped (that is just mail flow); a file something else holds open is retried for up to 30 seconds and then fails the run by name; an existing destination file is overwritten. Before this, any of the three threw, and an exception escaping the work-queue task took the whole service down with no explanation in the backup log.
- Retention runs at exactly one point — past every failure path, with the new archive complete on disk — and it is never allowed to delete the archive this run produced.
Two checks, with different consequences.
| Check | What it does | On failure |
|---|---|---|
| Archive index (always) | Opens the finished archive through the same code a restore uses and confirms the index says what this run put in it | The backup fails and the incomplete archive is deleted, so it cannot masquerade as the newest good backup |
Verified restore (BackupVerifyRestore=1, the default) |
Extracts the message store to the temp directory through the restore path, and holds it to exactly the file count and byte count this run staged. Then checks every message row in the index for its file | A mismatch in files or bytes means a truncated archive: the backup fails and the archive is deleted. A store that could not be checked fails the backup but keeps the archive, saying so in the log |
Rows whose file is missing are reported, never fatal: the rows were read before the copy started and mail flow does not stop for a backup, so a small number is what a live server looks like. The backup log names the first ten and says so:
Verified restore: the message store was extracted to <temp>\... and reads back as
41822 file(s) totalling 3915773440 byte(s), exactly what this run wrote.
40977 message row(s) in the index were checked against the extracted store; 3 of them
have no file in this backup.
The cost is that the store exists twice while the check runs. The server compares
the staged size against free space in the temp directory first and skips the check —
with an explanation in the backup log — rather than failing a good backup on a small
temp volume. BackupVerifyRestore=0 skips it altogether, and the log says that too,
so a missing verification is never something you have to infer from an absent line.
None of this is configured on a fresh install: the scheduled-backup task is not even created unless a schedule is set, so a default installation behaves exactly as every release before 6.2.25 did.
| Setting | Default | Meaning |
|---|---|---|
ScheduledBackupTime |
empty (off) |
HH:MM, 24-hour, local time. At most one backup per calendar day, taken at the first check at or after that time |
ScheduledBackupIntervalMinutes |
0 (off) |
Used only when no daily time is set. Measured against the newest archive in the destination, so it survives restarts; with no archive at all, the first backup is taken about a minute after the service starts |
ScheduledBackupKeepCount |
0 (keep all) |
How many of this server's own archives to keep |
ScheduledBackupMaxAgeDays |
0 (keep all) |
Delete archives older than this many days |
BackupVerifyRestore |
1 |
§15.5 |
BackupMessagesDBOnly |
0 |
§15.2 |
UpdateBackupBeforeApply |
1 |
The live updater takes a backup and waits for it to succeed before it applies an update |
ScheduledBackupTime wins when both schedule modes are set. The service reads all of
these at start, so restart it after changing them.
Retention has four rules, and each one is a way this could otherwise destroy data:
- Nothing is deleted until the replacement backup has completed successfully. Pruning first and writing afterwards is not retention, it is data loss: a destination with room for one more archive but not two would have had yesterday's deleted and today's fail to write, leaving nothing.
- The newest archive is never deleted, whatever the policy says.
-
The age rule always leaves the two newest archives alone. "Older than N days"
is a statement about the wall clock, and the wall clock is the one input that can
be wrong by years — a VM restored from a snapshot, a dead CMOS battery, a bad NTP
step. A count is immune to a wrong clock, so
ScheduledBackupKeepCountmay take the directory down to a single archive;ScheduledBackupMaxAgeDaysmay not. - Only files whose names the server generated are ever considered. The timestamp is read out of the file name, not from the file system, because copying, snapshot-restoring or re-syncing an archive resets its creation time to now — which would hand the retention pass exactly the wrong file to delete. Your own copies in the same folder are never touched.
The pre-flight refuses a scheduled run that is certain to fail, rather than claiming the single backup slot and reporting a critical error once a minute for as long as the condition lasts:
| Refusal | What it means |
|---|---|
no backup destination has been configured |
Set one on the Backup & restore page |
the backup settings do not include settings, domains or messages |
The run would contain nothing |
the database is not available, and a backup taken now would not contain the domains or accounts |
Wait for the database |
the backup destination is not accessible: <path> |
An unreachable share, or a path that no longer exists |
the previous backup is still running, so this run is covered by the one already in progress |
Not an error. The slot is treated as satisfied — an interval shorter than the time a backup takes must not become a back-to-back backup loop |
a restore is running, so the backup will be taken once it has finished |
Retried in 5 minutes. A restore is exactly when the next backup matters most |
A refused run backs off 5, 10, 20, 40 and then 60 minutes, which bounds how often the
scheduler's thread waits out a dead network share while still picking the backup up
within minutes of it coming back. Refusals are logged once, then once an hour, to
both the application log and hmailserver_backup.log — the latter because that is
where somebody investigating "why is there no backup from last night" will look, and
it does not roll over daily.
Two warnings fire before anything breaks, at most once a day:
-
... has N MB free and the previous backup archive is M MB, so the next backup is likely to run out of space.The run is attempted anyway — a write failure is authoritative and leaves the existing archives alone, whereas refusing on an estimate means no backup at all. -
... the backup destination is on the same volume as the message store. A backup that fills the volume will also stop mail being accepted.Pointing the destination at a folder under the install directory is the normal way to end up here.
A restore deletes every domain, every account, every public folder and the whole message store on purpose, and nothing can undo it. So it runs in two phases, and the first one touches nothing:
flowchart TD
subgraph P1["Phase one - decide. Nothing is changed."]
A["Open the archive"] --> B{"Is it one of ours, and readable?"}
B -->|"no"| X1["Refused. The server is untouched"]
B -->|"yes"| C{"Was it written by an older or equal version?"}
C -->|"newer"| X1
C -->|"yes"| D{"Does the archive contain what you asked to restore?"}
D -->|"no"| X1
D -->|"yes"| E["Extract the message store to a scratch directory"]
E -->|"fails"| X1
end
subgraph P2["Phase two - act. A failure here leaves a half-restored server."]
E --> F["Delete every domain"]
F --> G["Delete every public folder"]
G --> H["Empty the data directory and copy the staged store in"]
H --> I["Load domains, accounts, aliases and lists"]
I --> J["Load settings"]
J --> K["Reinitialise the server"]
end
Phase one exists because each of its four checks used to be reachable from the Control Panel's three restore tick-boxes, and each ended in a server with nothing on it:
- Restoring messages from an archive that has none (any backup taken with Back
up messages off) used to fault forty lines after the domains had been deleted.
The exception was trapped and logged, so the visible result was an empty server, no
BACKUP ERRORline and noOnBackupFailedevent. - Restoring domains from an archive that contains none deleted every domain and reported success — an absent XML node is indistinguishable from an empty collection.
- Restoring settings from an archive that contains none did the same to SSL certificates, TCP/IP ports, security ranges, global rules, blocked attachments, DNS black lists and white lists.
- An archive written by a newer hMailServer was restored into an older one without a word. The index has carried a version attribute since 2010 and nothing read it.
The order in phase two is also deliberate: domains are dropped before the data directory is restored, because dropping a domain also removes its folder from disk — do it the other way round and you restore the mail and then delete it.
The procedure:
- Install the same version of hMailServer, at the same drive letter and directory layout. (A newer server can read an older archive; an older one refuses a newer archive.)
- Restore or recreate the
[Database]connection inhMailServer.INIand confirm the Control Panel connects. Do not copy another machine's INI wholesale. -
Maintenance → Backup & restore → Restore: choose the
HMBackup … .7z, tick the categories, press Start restore. Watchhmailserver_backup.log. - Copy back anything the archive could not hold: certificate and private-key files, DKIM keys placed outside the data directory.
- Re-enter the per-domain relay settings for any domain that had them (§15.3).
- Start the service and check Monitoring & troubleshooting → Server status, then Diagnostics.
- Send a message in from outside and read it back over IMAP; send one out.
hMailServer holds two different kinds of secret, and they behave differently.
Passwords the server verifies — mailbox passwords, app passwords, the administration password — are stored as hashes. They are in the backup, they restore anywhere, and nobody has to retype anything.
Passwords the server has to present to somebody else — route smart-host
credentials, external POP3/IMAP fetch accounts, the per-domain relay password, SSL
private-key passphrases — cannot be hashed. In the database they are protected
with machine-scoped Windows DPAPI (ProtectStoredSecretsWithDPAPI=1, the default), so
a blob written by one machine cannot be decrypted by another. The protection is
the machine.
What that means in practice depends entirely on how you move the data:
| How you move it | Do route / fetch / key passwords survive? |
|---|---|
| Through the built-in backup and restore | Yes. The server decrypts them into memory to write the index, stores them in the archive in a portable encoding, and the restore re-protects them with the new machine's DPAPI |
By copying or replicating the database itself (a .sdf file, a SQL Server restore, a warm standby sharing one database — see Warm Standby) |
No. The DPAPI blobs travel and cannot be opened. Re-enter each password on the new machine |
| Per-domain relay credentials, either way | No — those fields are not in the index at all (§15.3) |
ProtectStoredSecretsWithDPAPI=0 keeps the older, portable encoding instead: weaker
at rest, movable between machines. That is a real trade-off rather than a wrong
answer, but make it deliberately.
The [Database] password in each machine's own INI is DPAPI-protected too, per
machine, and is never replicated. It causes no restore work; it is mentioned so
nobody "fixes" it by copying the primary's INI over another machine's, which breaks
that machine's database connection outright.
Take a backup now, and wait for it:
$app = New-Object -ComObject hMailServer.Application
$app.Authenticate("Administrator", "<password>") | Out-Null
# These properties write straight through - there is no Save() on this object.
$b = $app.Settings.Backup
$b.Destination = "D:\Backups\hMailServer"
$b.BackupDomains = $true
$b.BackupMessages = $true
$b.BackupSettings = $true
$b.CompressDestinationFiles = $true
$app.BackupManager.StartBackup()
# The run happens on a work queue; watch the log rather than the return value.
Get-Content "C:\Program Files\hMailServer\Logs\hmailserver_backup.log" -Tail 40 -WaitA successful run ends with Backup completed successfully.; a failed one with a
BACKUP ERROR line naming the reason.
Check what an archive contains before restoring it:
$backup = $app.BackupManager.LoadBackup("D:\Backups\hMailServer\HMBackup 2026-09-08 020004.7z")
"{0} settings={1} domains={2} messages={3}" -f "contains:", `
$backup.ContainsSettings, $backup.ContainsDomains, $backup.ContainsMessagesIf the archive is truncated, half-copied, not one of ours, or was written by a newer
hMailServer, LoadBackup returns nothing and raises an error rather than handing back
an object that would restore nothing — and the reason is written to
hmailserver_backup.log and the application log.
Restore it, choosing the categories:
$backup.RestoreDomains = $true
$backup.RestoreMessages = $true
$backup.RestoreSettings = $true
$backup.StartRestore()Confirm the destination is writable. Test backup directory on Monitoring & troubleshooting → Diagnostics writes a temporary file there and deletes it again; it is the check that catches a schedule that has been failing silently. Running the whole self-test from PowerShell is in Monitoring and Health §16.8.
List what retention would consider, which is only files matching the generated name:
Get-ChildItem "D:\Backups\hMailServer" -Filter "HMBackup *.7z" |
Sort-Object Name |
Format-Table Name, @{n="MB";e={[int]($_.Length/1MB)}}, LastWriteTimeA backup nobody has restored is a hope, not a backup. The whole drill on a scratch machine or VM:
- Install the same hMailServer version. Point
[Database]at a new, empty database (never at production). - Copy the newest archive across.
- Restore domains, messages and settings.
- Check: does the domain list match? Does an account you know log in over IMAP? Does its INBOX have the right message count? Does a message open?
- Check Monitoring & troubleshooting → Diagnostics — in particular Test message file locations, which proves the store and the rows agree.
- Write down what you had to fix by hand — certificate files, DKIM keys, per-domain relay settings — and keep that list with the backup. That list is the difference between a two-hour recovery and a two-day one.
Checked 8 September 2026 against hMailServer 6.2.28. The archive name, the run order,
the abort points and the deletion of an incomplete archive are
BackupExecuter::StartBackup and DiscardIncompleteArchive_; the tolerant tree copy
(overwrite, vanished-file count, 30-second retry budget) is CopyOneFile_ and
CopyTree_ in the same file, with the comment at the top of the file explaining what
FileUtilities::CopyDirectory used to do to the service. The two verification steps
are VerifyArchive_ and VerifyRestore_. The four backup options are
Backup::BackupOptions. What the index holds is Domain::XMLStore,
Account::XMLStore, IMAPFolder::XMLStore, Message::XMLStore,
Configuration::XMLStore, SMTPConfiguration::XMLStore,
IMAPConfiguration::XMLStore and AntiSpamConfiguration::XMLStore; the per-domain
relay fields and message retention days are members of Domain that appear in
PersistentDomain and in neither Domain::XMLStore nor Domain::XMLLoad, which is
the basis for the "not carried" rows. The two-phase restore, and the four failures it
was written to stop, are BackupRestorer (see its header) and
BackupExecuter::StartRestore. Retention's four rules are BackupRetention and
ParseArchiveName. The schedule, the pre-flight refusals, the back-off and the two
capacity warnings are BackupScheduleTask; the single-flight slot is
BackupManager::ClaimRunSlot_. LoadBackup returning nothing rather than an empty
object is BackupManager::LoadBackup. Secret handling is Crypt::ProtectSecret /
UnprotectSecret with DataProtector (CRYPTPROTECT_LOCAL_MACHINE), against
Route::XMLStore, FetchAccount::XMLStore and SSLCertificate::XMLStore, which use
the portable encoding. Sieve paths are SieveStorage::GetAccountDirectory_; the ACME
directory is AcmeClient::GetCertificateDirectory. The backup taken before an update
is UpdateCheckTask's BackupBeforeApply_. Every default in the tables is
IniFileSettings::LoadSettings. Regression coverage: BackupRestore.cs,
BackupRestoreSafety.cs, BackupVerifiedRestore.cs and ScheduledBackup.cs under
test/RegressionTests/Infrastructure.
hMailServer 6.3.2 · AGPL-3.0-or-later · Repository · Report a documentation error
Hmail Server — full index
Start here
1. Install and run
- Before You Install
- Installing hMailServer
- Installing on Linux
- Running in a Container
- The Control Panel
- Your First Domain and Mailbox
- Connecting a Mail Client
- DNS for Your Domain
2. Secure it
3. Operate it
- Monitoring and Health
- Backup and Restore
- Troubleshooting
- Diagnosing Stalled Mail
- Relocating an Installation
- Upgrading hMailServer
- Upgrading Guide
- Migrating the Database Backend
- High Availability Runbook
- Warm Standby
- Runbooks Digest
4. Extend it
- Rules and Sieve
- Aliases Lists and Public Folders
- Routes and Relays
- The COM API and Scripting
- The REST API
- APIs Reference
5. Contribute to it
- Project Handbook
- Architecture
- Contributing
- Release Process
- Governance
- Assurance Case
- Regression Test Environment
- Fuzzing
- Regulatory Scope
- Third-Party Binaries
Look it up — from any journey