Repository navigation
Control Panel Reference
How hMailCP connects, its navigation map, and every page and dialog with the setting behind each field, checked against the Control Panel's source. File and line references point into the repository at the commit this page was written from (6.2.24, master of 4 September 2026). Sections headed Unconfirmed or Contradictions record what could not be verified or where documents disagreed, and are left in on purpose.
All paths below are relative to hmailserver/source/Tools/ControlPanel/ unless stated. "IDL" = hmailserver/source/Server/hMailServer/hMailServer.idl. "IniFileSettings.cpp" = hmailserver/source/Server/Common/Application/IniFileSettings.cpp. Line numbers were read on 2026-09-04 at commit 4d5da3f (branch server-fixes-wave) and are exact where given as :N, approximate where given as ~N. Corrections made on 2026-09-08 cite the tree at commit 40ae9491d (master HEAD); anything present there but not in the latest published release, v6.2.27 (2026-09-07), is marked "in the tree after 6.2.27, not yet released".
- Assembly name
hMailCP(hMailCP.exe), targetnet10.0-windows, WPF, x64 only, version 6.2.27 (the csproj is stamped with each release), product "hMailServer Control Panel", company Progressive Robot Ltd (source: ControlPanel.csproj:5-8, 15, 19, 39-40) - Not self-contained; the installer bundles the .NET 10 Desktop Runtime (source: ControlPanel.csproj:38-39 comment; README.md:130)
- UI framework WPF-UI 4.3.0 (Fluent), charts LiveChartsCore.SkiaSharpView.WPF 2.0.5, QR codes QRCoder 1.8.0, plus System.Management and System.ServiceProcess.ServiceController (both 10.0.11); DPAPI comes from the .NET runtime's
ProtectedDataclass, not a package (source: ControlPanel.csproj:52-56; Services/Totp.cs:223) - Solution
Tools/ControlPanel.slnholds three projects: ControlPanel (WPF), ControlPanel.Core (WPF-free logic: navigation map, palette search, setting claims, pipelines), ControlPanel.Tests (source:ls Tools/; NavigationMap.cs class summary "the tests reference ControlPanel.Core, which has no WPF") - Test files exist for: AccessibleNames, ApiKeyStore, ChartDataTable, ChartPalette, ColourVision, DirectorySyncReport, HostReachability, ListenerProbe, Loc, MessageStoreConsistencyReport, MnemonicText, NavigationMap, NumericField, PageSplit, PaletteSearch, PaletteUsage, PasswordGenerator, PasswordStrength, SearchTerms, SettingClaims, SettingsSearchIndex, SpamPipeline, StatusSemantics, TlsPosture, VirusPipeline, WelcomeIntents, WindowsServiceInfo (source:
ls Tools/ControlPanel.Tests/Services) - Installer: Start Menu shortcut "hMailServer Control Panel" ->
{app}\ControlPanel\hMailCP.exe, componentcontrolpanel(source: hmailserver/installation/section_icons.iss:3); post-install checkbox "Run hMailServer Control Panel" (source: section_run.iss:9) - The Control Panel does NOT need the
admintools(COM type library) component - it binds late through IDispatch (source: README.md:146; ServerSession.cs:11-14 "late binding (IDispatch), so no interop assembly is required") - Main window title "hMailServer Control Panel", default 1280x800, minimum 760x520, Mica backdrop, content extends into title bar (source: MainWindow.xaml:9-15)
- Command line:
hMailCP.exe /connect <host> <user> <password>connects automatically on load (source: MainWindow.xaml.cs constructor ~88-101, comment "Optional auto-connect") - Per-user state lives in
HKCU\Software\hMailServer\ControlPanel: values WindowWidth, WindowHeight, WindowLeft, WindowTop, WindowMaximized ("1"/"0"), Theme ("Light"/"Dark"), PaletteUsage and - in the tree after 6.2.27, not yet released - Language (a BCP 47 tag such assvorpt-BR; empty = the Windows display language) (source: MainWindow.xaml.cs:29, 807-855; Services/LanguageChoice.cs:26-27, 47-48, 100-101) - Theme follows the OS until the toggle button (bottom of the sidebar, sun/moon icon) is pressed; the choice is then stored (source: MainWindow.xaml.cs ApplySavedTheme, Theme_Click, UpdateThemeToggle_)
- Localisation (in the tree after 6.2.27, not yet released): every caption is written once in English and marked where it is used -
L("...")translates,F("...", args)translates and formats,N("...")only marks (the navigation map keeps its English titles and translates them where shown) in C#,{loc:L '...'}in XAML - and the English text is the key intoResources/Strings.<culture>.resx; a missing entry falls back to English. Seventeen languages ship, each named in itself in the picker: English, Čeština (cs), Dansk (da), Deutsch (de), Español (es), Suomi (fi), Français (fr), Italiano (it), 日本語 (ja), Norsk bokmål (nb), Nederlands (nl), Polski (pl), Português (Brasil) (pt-BR), Русский (ru), Svenska (sv), Türkçe (tr), Українська (uk), 简体中文 (zh-Hans), plus "Windows display language" (the default:CultureInfo.InstalledUICulture; an English or unknown culture means untranslated English). The choice is per Windows user (HKCU\Software\hMailServer\ControlPanel\Language), offered on the sign-in card's "Language" combo and by the globe button ("Change the language") next to the theme toggle in the sidebar footer, and changing it restarts the Control Panel after a Yes/No prompt.Resources/Strings.resx(English) is generated from the source bybuild/check-localisation.py, which fails CI when it is behind, when any of the seventeen catalogues (all listed as COMPLETE) lacks a key, or when a translation loses a{n}placeholder or an Alt-key underscore;build/check-catalogues.pychecks that server-side literals, page titles and numbers survive translation;build/check-mnemonics.pychecks every catalogue's translated captions for a unique key per scope. The palette matches a query against the translated outcome phrases as well as the English ones (source: Services/Loc.cs:54-75, 128-165; Services/LanguageChoice.cs; Views/ConnectView.xaml:59-72; MainWindow.xaml:212-217; MainWindow.xaml.cs:966-989; build/check-localisation.py; build/check-catalogues.py; build/check-mnemonics.py) - The Control Panel's own error log:
%LOCALAPPDATA%\hMailServer\ControlPanel\control-panel-errors.log; an unhandled UI exception shows a dialog "An unexpected error occurred..." offering to restart the app (source: App.xaml.cs:28-81) - About page reports "Version {assembly version, 3 parts} - .NET {runtime}", "Connected server: hMailServer {Application.Version} @ {host}", and states the panel "is built with WPF-UI (Fluent design) and LiveCharts2 on .NET 10" (source: Views/AboutView.cs:43-44, 85, 183-185)
- The connect card is titled "Connect to server" with subtitle "Sign in with the hMailServer administrator credential."; fields: Server (pre-filled
localhost), User name (pre-filledAdministrator), Password; button "Connect"; link "Set up two-factor authentication…"; below it (in the tree after 6.2.27, not yet released) a "Language" combo listing the seventeen catalogues plus "Windows display language" - choosing one restarts the Control Panel in that language (source: Views/ConnectView.xaml:19-72) - Enter in any field submits; a second Connect while one is in progress is ignored (source: Views/ConnectView.xaml.cs:23-35)
- An empty host is normalised to
localhost(source: Services/ServerSession.cs Connect():normalizedHost) - Before touching COM,
HostReachability.CheckAsyncprobes TCP port 135 (RPC endpoint mapper) on the target with a 4-second default timeout, off the UI thread, so an unreachable host fails in seconds instead of the DCOM RPC timeout (source: Services/HostReachability.cs:55, 62; Views/ConnectView.xaml.cs:44-57) - COM activation:
Type.GetTypeFromProgID("hMailServer.Application")for a local host,Type.GetTypeFromProgID("hMailServer.Application", host)(DCOM) for a remote one; thenAuthenticate(user, password)must return a non-null account (source: Services/ServerSession.cs Open() ~401-441) - "Local" is decided by
LocalHostNames.IsLocal(host)(source: ServerSession.cs IsLocalHost; Services/LocalHostNames.cs) - Error strings: "hMailServer COM API is not registered on the target machine." / "Authentication failed. Check the user name and password." / "Unable to reach the server (RPC unavailable)." (HRESULT -2147023174) (source: ServerSession.cs Open())
- The password is kept in memory DPAPI-protected (
ProtectedSecret) so the session can re-authenticate after a service restart without prompting (source: ServerSession.cs Connect(); Services/ProtectedSecret.cs) - Self-healing link: every read of
ServerSession.Applicationre-verifies the link at most once per 2 s by readingServerState(the value is ignored - a paused engine still counts as alive); on a transport failure it reconnects with up to 5 attempts 300 ms apart, never more often than every 3 s, and only if the localhMailServerWindows service is Running or StartPending - because activating the COM class would START a stopped service (source: ServerSession.cs:31-38, VerifiedApplication(), ServiceLooksRunning(), IsAlive()) - On a reconnect after a restart the link is adopted only once
ServerState == 3(running) unless it is the last attempt (source: ServerSession.cs Reconnect(), IsServerReady(); StateRunning = 3 at :29) - Transport-failure HRESULTs treated as "link gone": 0x800706BA, 0x800706BE, 0x800706BF, 0x800706B5, 0x80010108, 0x80010105, 0x800401FD, 0x80080005, plus InvalidComObjectException (source: ServerSession.cs IsTransportFailure())
- After a self-heal the shell shows a toast "Reconnected to {host} after the service restarted." (title "Connection restored") and re-enters the current page (source: MainWindow.xaml.cs OnSessionReconnected)
-
DescribeComErrormaps: transport failure -> "the connection to the hMailServer service was lost - it was most likely restarted. The Control Panel will reconnect by itself; press Reload to try again."; message containing "connection to the database" -> "the server cannot reach its database..."; "do not have access" -> "you must connect with the hMailServer server-administrator account to view or change these settings." (source: ServerSession.cs DescribeComError()) - Status snapshot read for dashboard/status/queue:
Application.StatusProcessedMessages, RemovedSpamMessages, RemovedViruses, SessionCount[1/3/5] (SMTP/POP3/IMAP per IDL eSessionType), StartTime, UndeliveredMessages (tab-separated rows) (source: ServerSession.cs:24-27, ReadStatus()) - Once connected: sidebar footer shows a green dot and "{user} @ {host}" (accessible name "Connected to {host} as {user}") and "hMailServer {Application.Version}"; navigation and search are enabled; the app navigates to the Dashboard (source: MainWindow.xaml:194-201; MainWindow.xaml.cs OnConnected() -> NavigateTo("dashboard"))
- Connecting also wires
IniFeatureStore.ComReadSetting/ComWriteSettingtoSettings.GetIniSetting/Settings.SetIniSetting, so [Settings] INI values can be edited on a remote server (source: ServerSession.cs SetCurrent() :66-104; IDL:735-739 GetIniSetting/SetIniSetting/DeleteIniSetting)
- Secret stored under
HKLM\SOFTWARE\hMailServer, valueAdminTotpSecret, as base64 of a machine-scope DPAPI blob (no entropy) - the same value the retired hMailServer Administrator used, so an existing 2FA setup carries over (source: Services/Totp.cs:3-7, 166-167, 212-241) - RFC 6238 TOTP: HMAC-SHA1, 30-second period, 6 digits, accepted window +/-1 step (source: Totp.cs:17-21, 49-57)
- Prompt appears after a successful COM authentication whenever a secret is configured; 3 attempts, then back to the Connect screen; Cancel also returns to Connect (source: MainWindow.xaml.cs VerifyTwoFactor(), OnConnected())
- Prompt dialog title "Two-factor authentication", text "Enter the 6-digit code from your authenticator app:" (source: Views/TotpPromptDialog.cs:30, 40)
- Setup dialog title "Two-factor authentication setup"; shows a QR code (QRCoder) for
otpauth://totp/hMailServer%20Control%20Panel?secret=<base32>&issuer=hMailServer&digits=6&period=30and the base32 key in 4-char groups; enabling or disabling requires a valid current code; button reads "Enable two-factor authentication" / "Disable two-factor authentication" (source: Views/TotpSetupDialog.cs:65, 159-176, 208-236; Totp.cs:60-65) - Writing the secret needs local administrator rights (HKLM); the dialog reports "Changing two-factor authentication settings requires administrator rights. Restart the Control Panel as an administrator and try again." on UnauthorizedAccessException (source: TotpSetupDialog.cs:239-242)
- Reachable from the Connect screen link and from Access & abuse protection > Administrative access > "Two-factor" tab (button "Set up or turn off two-factor authentication…") (source: ConnectView.xaml:54; Views/ServerSettingsView.xaml.cs BuildAdminAccess ~2700-2735)
- Applies only to Control Panel sign-in, not to the REST API or COM scripts (source: ServerSettingsView.xaml.cs BuildAdminAccess card blurb "Two-factor authentication")
- Server-enforced administrator second factor (added 5 Sep 2026), the recommended one: enrol/remove from Access & abuse protection > Administrative access > "Two-factor" tab, card "Second factor on the administrator credential (recommended)" (button "Set up or turn off the server-enforced second factor"), dialog
AdministratorTwoFactorDialog. The secret is the server's (hMailServer.ini [Security] AdministratorTotpSecret, DPAPI-protected), enrolled via COMSettings.EnrolAdministratorTOTP; the dialog confirms with a code and rolls the enrolment back if you close without confirming. Once enrolled, EVERY client of the administrator credential needs the code: the connect screen prompts for it (ServerSession.Connect(host,user,password,code)after a password-only attempt setsSecondFactorRequired), COM callers useAuthenticateWithCode, the REST API uses anX-hMailServer-OTPheader. The old HKLMAdminTotpSecretcard is retained as "Two-factor for this Control Panel only" and relabelled the weaker option (source: ServerSettingsView.xaml.cs BuildAdminAccess; Views/AdministratorTwoFactorDialog.cs; Services/ServerSession.cs; Views/ConnectView.xaml.cs) - Per-ACCOUNT (mailbox) two-factor is a separate feature on the Account dialog "Two-factor" tab, with app passwords on the "App passwords" tab (see section 7.2)
-
The sidebar tree is built from
Services/NavigationMap.cs(data, WPF-free, tested); MainWindow contains no page names (source: MainWindow.xaml.cs BuildNavTree() comment; MainWindow.xaml:96-98) -
Groups are expanded by default and carry a Fluent icon; every node's tool tip is "{Title} - {Purpose}"; automation ids
nav-<key>for pages andnavgroup-<slug>for groups (source: MainWindow.xaml.cs BuildNavItem()) -
Search: a "Search Ctrl+K" button above the tree and the Ctrl+K shortcut open the command palette; both only work while connected (source: MainWindow.xaml:75-94; MainWindow.xaml.cs PreviewKeyDown, ShowPalette())
-
Palette placeholder:
Search, or say what you want to do - "stop spam", "block an IP"; footer "↑↓ move Enter open Esc close"; no-match hint suggests an outcome phrase, a page name, or an hMailServer.INI key (source: Views/NavigationPalette.cs:105, 150, 189-190) -
Palette result sections: "Recently visited", "Most used", "Tasks", "Pages", "Settings" (source: Services/PaletteSearch.cs:97-101)
-
The palette searches page titles + aliases + legacy paths, outcome phrases from
Services/IntentIndex.cs(e.g. "stop spam" -> antispam, "block an ip" -> ipranges, "someone is trying to guess passwords" -> autoban, "use microsoft 365 or google sign-in" -> authentication), and the generated settings index of 388 entries (label, INI key or COM path, owning page) produced bybuild/generate-settings-index.ps1- 347 at 6.2.24 (source: PaletteSearch.cs class summary; IntentIndex.cs:67-227; Services/SettingsSearchIndex.g.cs header andgrep -c 'new SettingEntry('= 388) -
Every palette result names the page it lives on ("in {group} > {page}" / "Opens {page}") (source: NavigationPalette.cs:25-31, Describe())
-
Breadcrumb bar above the content: group segments are buttons that reveal the group in the tree; up to three "Related:" links from the page's SeeAlso list; a "Found by search" marker after a palette jump (source: MainWindow.xaml:228-253; MainWindow.xaml.cs UpdateBreadcrumb(), GroupSegment(), RelatedLink(), SearchMarker())
-
Pages are created once per session and cached; each implements
IPageLifecycle.OnEnter/OnLeave; an OnEnter exception is shown as a toast "Could not load this page: ..." (title "Server unavailable") rather than crashing (source: MainWindow.xaml.cs NavTree_SelectedItemChanged(), EnterPage(), interface at end of file) -
"Most used" counts only pages the user chose, not the automatic Dashboard navigation at connect (source: MainWindow.xaml.cs NavTree_SelectedItemChanged()
automaticNavigation_) -
Welcome page tiles call
MainWindow.NavigateTo(key); External setup, Dashboard and the overview pages navigate the same way (source: Views/WelcomeView.cs:105; Views/ExternalSetupView.cs:348) -
Alt-key access mnemonics (5 September 2026): every static caption carries one - 372 captions today (369 at 6.2.24) across the 14 XAML views and 36 code-built views and dialogs, 340 with a key and 32 exempt (Cancel/OK/Close answer to Escape and Enter, the "…" browse buttons, and captions repeated per row, card, record or generated setting, which are reached with the arrow keys). Buttons and check boxes read the underscore through the Wpf.Ui templates (
RecognizesAccessKey); the TextBlock above an editor goes throughViews/Mnemonic.cs, which underlines the letter, registers the key withAccessKeyManagerfor the editor, answers the manager's AccessKeyPressed question for it (a bare text box does not and is skipped) and setsAutomationProperties.AccessKey- which the .NET 10 WPF runtime does not yet surface through its text box peer, so screen readers hear the key on buttons and check boxes today. Verified through the UI Automation tree: keys unique per page, Alt+H focuses the LDAP host box, Alt+E invokes the dashboard's External setup button. Keys are unique per page, per dialog tab (with the dialog's Save global to every tab) and are enforced bybuild/check-mnemonics.pyin the style workflow.MnemonicText(Services, tested) is the one parser and escape: data-driven captions are escaped with a doubled underscore.build/check-mnemonics.pyalso checks each translated catalogue (Resources/Strings..resx): every translated caption carries its own key, chosen for that language, and no two in a scope share one. Page titles are level-1 headings (AutomationProperties.HeadingLevelvia thePageTitlestyle); the XAML views' status, empty-state and sign-in-error text blocks are live regions (source: Views/Mnemonic.cs; Services/MnemonicText.cs; build/check-mnemonics.py; App.xaml PageTitle style; Roadmap.md row "No screen-reader or keyboard audit has ever been done")
Registered page factories: 55 keys (source: MainWindow.xaml.cs RegisterPages() :114-171). The tree (source: NavigationMap.cs BuildRoots() :344-757):
Top level:
-
welcome"Welcome" - Start here: jump straight to a common task, or press Ctrl+K (class WelcomeView) -
dashboard"Dashboard" - Live counters and charts for processed mail, spam, viruses and sessions (DashboardView)
Group "Monitoring & troubleshooting" (icon Pulse24):
-
status"Server status" (StatusView) -
queue"Delivery queue" (QueueView) -
stalledmail"Diagnosing stalled mail" (Views/StalledMailView.cs; added 5 Sep 2026, v6.2.25) - which half stalled (accepting vs delivering), "Turn on debug logging now" / "Turn it off again" (Settings.Logging.Enabled + LogDebug over COM), the what-the-log-shows table, the saturation report, the nine bounding settings with buttons to their pages, "Open the full guide"; aliases "Stalled mail", "Mail is stalled", "Accepted but never delivered", "Diagnosing slow mail"; related: queue, logs, diagnostics -
messagetrace"Message trace" (MessageTraceView) -
logs"Live logs" (LogsView) -
diagnostics"Diagnostics" (DiagnosticsView in UtilityViews.cs) -
mxquery"MX query" (MxQueryView in UtilityViews.cs) -
externalsetup"External setup" (ExternalSetupView) -
dnsrecords"DNS records" (DnsRecordsView) -
logging"Logging" (ServerSettingsView Section.Logging) -
api"API & monitoring" (FeatureSettingsView Section.Integration) -
apikeys"REST API keys" (ApiKeysView)
Group "Accounts & domains" (Globe24):
-
domains"Domains" (DomainsView; on-screen title "Domains & accounts" - DomainsView.xaml:16) -
publicfolders"Public folders" (PublicFoldersView) -
groups"Groups" (CollectionSpecs.Groups -> GroupsPageView)
Group "Mail flow & delivery" (MailArrowForward20):
-
delivery"Delivery of e-mail" (ServerSettingsView Section.Delivery) -
routes"Routes" (RoutesView) -
relays"Incoming relays" (IncomingRelaysView in UtilityViews.cs) -
rules"Rules" (RulesView; on-screen title "Global rules" - RulesView.xaml:18) -
servermessages"Server messages" (CollectionSpecs.ServerMessages) -
sendout"Server sendout" (SendoutView in UtilityViews.cs)
Group "Spam & virus filtering" (ShieldCheckmark24):
-
spamoverview"Spam filtering overview" (SpamOverviewView, read-only) -
quarantine"Quarantine" (QuarantineView) -
antispam"Anti-spam settings" (ServerSettingsView Section.AntiSpam; on-screen title "Anti-spam") -
surbl"SURBL servers" (CollectionSpecs.SurblServers) -
dnsbl"DNS blacklists" (CollectionSpecs.DnsBlackLists; on-screen "DNS blacklists (DNSBL)") -
spamwhitelist"White list" (CollectionSpecs.SpamWhiteList; on-screen "Anti-spam white list") -
blockedsenders"Blocked senders" (CollectionSpecs.BlockedSenders) -
greylistwhitelist"Greylisting white list" (CollectionSpecs.GreyListWhiteList) -
virusoverview"Virus scanning overview" (VirusOverviewView, read-only) -
antivirus"Anti-virus settings" (ServerSettingsView Section.AntiVirus; on-screen "Anti-virus") -
blockedattachments"Blocked attachments" (CollectionSpecs.BlockedAttachments)
Group "Connections & protocols" (PlugConnected24):
-
protocols"Protocols" (ServerSettingsView Section.Protocols) -
ports"TCP/IP ports" (TcpIpPortsView) -
webservices"Web services & autoconfiguration" (FeatureSettingsView Section.WebServices; on-screen "Web services & client autoconfiguration") -
dns"DNS resolver" (FeatureSettingsView Section.Dns)
Group "TLS & certificates" (LockClosed24):
-
certs"SSL certificates" (SslCertificatesView) -
acme"Certificates (ACME)" (FeatureSettingsView Section.Automation; on-screen "Automatic certificates (ACME)") -
tlsoverview"Transport encryption overview" (TlsOverviewView, read-only) -
tls"SSL/TLS" (ServerSettingsView Section.Tls) -
security"Transport security" (FeatureSettingsView Section.Security)
Group "Access & abuse protection" (ShieldKeyhole24):
-
authentication"Authentication" (FeatureSettingsView Section.Authentication) -
ldap"Directory authentication (LDAP)" (LdapSettingsView) -
directorysync"Directory synchronisation" (DirectorySyncView) -
adminaccess"Administrative access" (ServerSettingsView Section.AdminAccess) -
autoban"Auto-ban" (ServerSettingsView Section.AutoBan) -
ipranges"IP ranges" (IPRangesView)
Group "Maintenance" (Wrench24):
-
backup"Backup & restore" (BackupView) -
performance"Performance" (ServerSettingsView Section.Performance) -
advanced"Advanced" (ServerSettingsView Section.Advanced; on-screen "Advanced"; was "Advanced & scripting" until 5 September 2026 - the old title stays as a search alias, and the Scripting card is now titled "Scripting engine" with the Event scripts page named as where the script is edited) -
scripts"Event scripts" (ScriptsView) -
hardening"Server limits & expert settings" (FeatureSettingsView Section.Hardening; formerly "Advanced INI settings"/"Advanced hardening", key unchanged)
Top level:
-
about"About" (AboutView)
Design rules pinned by tests: every registered key appears in the map exactly once (NavigationMapTests); page titles do not change - better names are aliases; "Auto-ban & SSL/TLS" is the one page that was split, and both halves carry the old title as an alias and signpost each other (PageSplitTests) (source: NavigationMap.cs class summary and comments on tls/autoban)
Legacy paths the palette resolves (old Administrator and 6.2.18 Control Panel paths) include "Status > Server status", "Settings > Protocols", "Settings > Anti-spam", "Settings > Advanced > Routes", "Settings > Security > Auto-ban & SSL/TLS" -> autoban, "Settings > Security > SSL/TLS" -> tls, "Settings > Maintenance > Advanced INI settings" -> hardening, "Utilities > Backup & restore" -> backup, and others (source: NavigationMap.cs LegacyPaths dictionary)
- Two data-driven settings views:
ServerSettingsViewedits the COMapp.Settingstree via dotted paths ("AntiSpam.SpamMarkThreshold") resolved by reflection over IDispatch;FeatureSettingsVieweditshMailServer.INI[Settings]keys throughIniFeatureStore(source: Views/ServerSettingsView.xaml.cs:16-21, ResolveOwner/GetProperty/SetProperty; Views/FeatureSettingsView.xaml.cs:27-33) - ServerSettingsView pages also carry INI-backed rows (IniBool/IniNumber/IniText/SectionIniNumber) so that a setting sits with its feature regardless of where it is stored (source: ServerSettingsView.xaml.cs BuildProtocols comments; Save_Click
IIniSetting) - ServerSettingsView "Save" writes every row on every tab of the page; toast "Saved N settings — applied immediately." or "... — INI settings need a service restart."; rows marked inert (INotPersisted) and action buttons are not counted; the Advanced page additionally calls
Settings.Scripting.Reload()(source: ServerSettingsView.xaml.cs:3325-3396) - FeatureSettingsView "Save" writes every card, then asks "Settings saved. The hMailServer service must be restarted for the changes to take effect. Restart it now?" and, on Yes, restarts the Windows service
hMailServervia ServiceController (60 s waits) (source: FeatureSettingsView.xaml.cs:2948-3040) -
IniFeatureStorelocates the INI fromHKLM\SOFTWARE\hMailServer\InstallLocation(Bin\hMailServer.INI, thenhMailServer.INI) in the 64- then 32-bit registry view, else from thehMailServerservice's PathName via WMI (hMailServer.inibeside the exe);IsAvailable= file found locally (source: Services/IniFeatureStore.cs:61-120) - Read/Write of
[Settings]uses the local file when available, otherwise COMGetIniSetting/SetIniSetting; a COM write also updates the database mirror; writes always SetIniSetting even for an empty value (source: IniFeatureStore.cs:130-187; ServerSession.cs SetCurrent comment) -
[Database]and[Directories](and any non-[Settings] section) are readable/writable only from the server machine - deliberately not exposed over COM (source: IniFeatureStore.cs:39-44, 199-212) - Secrets (OAuth2 HMAC, SRS, BATV, password pepper, metrics token/password, service account password) use a write-only
SecretSettingeditor that never shows the stored value and writes only when a new value is typed; several offer "generate" (source: settings.md:54-55; FeatureSettingsView.xaml.cs SecretSetting usages with OfferGenerate) - Every settings row has a stable AutomationId (its COM path or INI key) and an accessible name; blurbs are printed under the editor and attached as help text (source: ServerSettingsView.xaml.cs ComSetting.Describe/Annotate; FeatureSettingsView.xaml.cs Setting.Describe/Annotate)
-
SettingClaimspins wording for settings the server only partly honours:WorkerThreadPriorityis INERT (shown read-only, "the server stores this value and never reads it");UserInterfaceLanguageonly reaches third-party COM tools;Cache.*MaxSizeKbapply immediately but reset to 10240 KB at every restart;JsonLoggingis overridden whileLogging.LogFormatis NCSA;Logging.LogFormatNCSA = NCSA Common Log Format (not combined, not AWStats);Logging.DeviceSQL falls back to files if the database is unreachable;OtelEndpoint= traces only,OtelMetricsEndpoint,OtelLogsEndpointseparate (source: Services/SettingClaims.cs:96-236)
- Welcome: title "Welcome", line "Connected to hMailServer {version} on {host}.", subtitle "Start with what you want to do, browse by area below, or press Ctrl+K to search every page and setting."; heading "What do you want to do?" with twelve intent rows (Services/WelcomeIntents.cs; added 5 September 2026, v6.2.25: "Mail is stuck or slow" -> stalledmail, "See what is waiting to go out" -> queue, "Watch the server work" -> logs, "Add a domain or a mailbox" -> domains, "Stop the spam" -> spamoverview, "Someone is guessing passwords" -> autoban, "Let a device or printer send mail" -> ipranges, "Renew or install a certificate" -> certs, "Send everything through my provider" -> delivery, "Check the server is healthy" -> diagnostics, "Back up the configuration and the mail" -> backup, "Protect the administrator credential" -> adminaccess; WelcomeIntentsTests holds every entry to a page that exists); then "Or browse by area" with six tiles: "Domains & accounts" -> domains, "Server settings" -> protocols, "Dashboard" -> dashboard, "Live logs" -> logs, "Transport security" -> security, "Backup & restore" -> backup (source: Views/WelcomeView.cs:21-74, 115, 178; Services/WelcomeIntents.cs:45-80)
- Dashboard: title "Dashboard", subtitle "Live server statistics, refreshed every 2 seconds." (timer 2 s); KPI cards Uptime, Messages processed, In queue (with a "Backlog" badge above
StatusSemantics.QueueBacklogThreshold), Spam blocked, Viruses removed; two AccessibleChartCard charts (throughput in messages/minute derived from ProcessedMessages deltas, and SMTP/IMAP/POP3 sessions) with a range selector - Live (the two-second buffer, 90 samples), 24 hours, 7 days, 30 days (the last three loadUtilities.GetMetricHistoryfor processed_messages_total, shown as messages per minute from the difference between buckets, and the three session gauges; a note says when the server keeps no history because MetricsHistoryDays is 0; added 5 September 2026, v6.2.25) - each with a table view and High Contrast palette; a "needs attention" card that runs the sameExternalSetupChecksas the External setup page and links each action item to its owning page, with an "External setup…" button (source: Views/DashboardView.xaml:11-133; Views/DashboardView.xaml.cs:15-66, 103, 160, Refresh(), ShowQueue_(), BeginSetupCheck_(), RenderAttention_())
- Server status (
status): cards Server (Version incl.VersionArchitecture, State, Started, Uptime, and - in the tree after 6.2.27, not yet released - Update: what the last scheduled or on-demand check found, fromStatus.UpdateState/AvailableVersion/AvailableVersionPublished/UpdateLastChecked/UpdateLastError, prefixed by the last apply's outcome fromStatus.UpdateApplyOutcome), Database (Type viaDatabase.DatabaseType1 MySQL/MariaDB, 2 MS SQL, 3 PostgreSQL, 4 built-in SQL CE; Host; Name; Schema =Database.CurrentVersion), Statistics (processed, spam removed, viruses removed, SMTP/IMAP/POP3 sessions), Warnings; buttons - in the tree after 6.2.27, not yet released - "Check for updates" (Status.CheckForUpdate(): reads the release feed now, downloads nothing), "Download update" (Status.DownloadUpdate(): fetches the installer and its Sigstore bundle and keeps it only when verified; enabled once a newer release is known or a failed download can be retried), "Install update" (Status.InstallUpdate()after a confirmation: hands the verified installer to the update helper, the service stops and starts, a service that does not come back is rolled back; enabled only while UpdateState is 3), then "Pause"/"Resume" (Application.Stop()/Start()- the engine stops, the Windows service keeps running) and "Refresh" (source: Views/StatusView.xaml:17-138; Views/StatusView.xaml.cs:42-80, 186-206, 285-297; IDL:540-550) - Server status warnings computed client-side: no
HostName(High);DenyMailFromNullon (High); any IP range with AllowDeliveryFromRemoteToRemote and not RequireSMTPAuthExternalToExternal (Critical, open relay); 127.0.0.1 range that Expires (High, localhost banned); count of expiring (auto-ban) ranges (Medium) (source: StatusView.xaml.cs LoadWarnings() :224-289) - Delivery queue (
queue): grid of Id, Created, From, Recipients, NextTry, Tries, File fromStatus.UndeliveredMessages(tab-separated: id, created, from, recipients, next try, file, locked, tries); buttons "View source" (MessageViewerDialog reads the .eml from disk), "Deliver now" (GlobalObjects.DeliveryQueue.ResetDeliveryTime(id)+StartDelivery()), "Remove" (DeliveryQueue.Remove(id)), "Refresh"; search box (source: Views/QueueView.xaml:17-36; Views/QueueView.xaml.cs:40-137) - Message trace (
messagetrace): title "Message trace"; Address box + "Search" (GlobalObjects.MessageTrace.Search(address), matches sender or recipient, newest first), "Follow this message" (SearchByQueueID), "Remove expired" (DeleteExpired(), window =MessageTraceRetentionDays); columns Time, Event, Sender, Recipient, Status; queue id 0 = refused before queueing. Initial status text says the trace records nothing unlessMessageTraceEnabledis set - off by default (source: Views/MessageTraceView.cs:76-78, 152-234; IDL:2362 GlobalObjects.MessageTrace) - Live logs (
logs): tails the newesthmailserver_*.login[Directories] LogFolderread from the LOCAL hMailServer.INI, starting at the last 64 KB, polling every 750 ms, keeping 2000 lines, colour-classified (ERROR/Severity 1-2, SMTPD, IMAPD, POP3D, APPLICATION); "Pause"/"Resume" and "Clear"; needs a local server ("Log folder not found on this machine (live logs need a local server).") (source: Views/LogsView.xaml.cs:18, 54-151) - Diagnostics (
diagnostics): "Run diagnostics" callsApplication.Diagnosticswith LocalDomainName (pre-filled with the first hosted domain) and TestDomainName (defaultgmail.com) thenPerformTests()and prints [ OK ]/[FAIL] per test; a "Message-store consistency" card reads the local recovery report (MessageStoreConsistencyReport.FileNamein the log folder) written by the server'sMessageStoreConsistencyChecktask (start-up + hourly), with "Refresh"/"Open report"; on a remote session it says the number is also published as metrichmailserver_messagestore_missing_files(source: Views/UtilityViews.cs DiagnosticsView ~436-851; IDL:1676 Diagnostics) - MX query (
mxquery): callsApplication.Utilities.ResolveMXRecords(domain)- the server's own resolver, honouringDNSServerin hMailServer.INI (issue #29 replaced annslookupshell-out); "Query"/"Copy" (source: UtilityViews.cs MxQueryView RunQuery(); IDL:1196) - External setup (
externalsetup): read-only checklist with four states Done / Not needed / Action needed / Cannot tell, each item linking to its owning page via "Settings…"; DNS TXT checks run in the background via the Windows resolver; items: Windows service account (-> hardening), DKIM public key in DNS (-> domains), ARC inbound filtering trusted sealers (-> antispam), ARC sealing needs a domain DKIM key (-> security), MTA-STS policy hosting (-> webservices), TLS-RPT sender address (-> security), DANE TLSA for MX hosts (-> security), TLS private key passphrase (-> certs), ACME reachability (-> acme), inbound client certificates CA bundle (-> ports), OAuth2/XOAUTH2 key material (-> authentication), client autoconfiguration listener + DNS names (-> webservices) (source: Views/ExternalSetupView.cs:20-68, 153-190; Services/ExternalSetupChecks.cs:504-1493) - DNS records (
dnsrecords): per hosted domain (combo), generates SPF (fromSettings.HostName), DKIM (public key derived from the domain's configured private key file), DMARC (_dmarc.<domain>, starting policy p=none), MTA-STS (what the server will serve, from INIMtaStsHostingEnableddefault 1,WebServicesHttpsPort,MtaStsPolicyModedefault enforce,MtaStsPolicyMaxAgedefault 604800,MtaStsPolicyMx) and TLS-RPT (usesTlsRptFromAddress), plus PTR guidance; each record has copy buttons and a "Check" against the Windows resolver with a four-way verdict (not published / different / correct / lookup failed); the MTA-STS policy fetch uses HttpClient with redirects disabled and a 10 s timeout (source: Views/DnsRecordsView.cs:30-85, 971-992, 1258-1261) - Logging (
logging, ServerSettingsView): one tab with cards "Log categories" (COMLogging.Enabled,LogApplication,LogSMTP,LogIMAP,LogPOP3,LogTCPIP,LogDebug,AWStatsEnabled,KeepFilesOpen,Logging.Devicecombo "Files on disk"/"Database (SQL)",Logging.LogFormatcombo "hMailServer (tab separated)"/"NCSA Common Log Format", INIJsonLoggingdefault 0), "Log detail" (INILogLeveldefault 9,MaxLogLineLendefault 500,SepSvcLogsdefault 0), "Log retention" (INILogDeleteDaysdefault 0), "Message trace" (INIMessageTraceEnableddefault off,MessageTraceRetentionDaysdefault 30), "Log files" (shows[Directories] LogFolderand "Open log folder" - local only) (source: ServerSettingsView.xaml.cs BuildLogging :2029-2192) - API & monitoring (
api, FeatureSettingsView Integration): title "API & monitoring"; cards: "REST administration API + Web Control Deck" (link to apikeys;RestApiPortdefault 0 = disabled, placeholder 8045;RestApiBindAddressdefault 127.0.0.1;RestApiCertificateFile,RestApiPrivateKeyFileoptional, falls back to the ACME certificate; "TLS is required unless the listener is bound to 127.0.0.1"), "Monitoring" (MetricsServerPortdefault 0,MetricsHistoryDaysdefault 7 - days of per-minute metric history kept in the database for the dashboard's 24 h/7 d/30 d ranges, 0 = do not record; added 5 September 2026, v6.2.25 -MetricsServerBindAddressdefault 127.0.0.1,MetricsServerAuthToken,MetricsServerAuthUsername,MetricsServerAuthPassword,MetricsServerCertificateFile,MetricsServerPrivateKeyFile,OtelEndpoint,OtelMetricsEndpoint,OtelLogsEndpoint,OtelMetricsIntervaldefault 60,OtelServiceNamedefault hmailserver,SlowQueryLogMillisecondsdefault 0) with five live warnings (invalid IPv4 bind, non-loopback bind without credential -> /metrics answers 503, half a Basic pair, half a TLS pair, credential without TLS), "Updates" (in the tree after 6.2.27, not yet released:UpdateCheckEnableddefault 0 - a daily read of the release feed, off until turned on, sends nothing but the request;UpdateCheckHours24 (1-168);UpdateChannelstable/prerelease;UpdateFeedUrlempty = this project's GitHub releases, set for a mirror;UpdateAutoDownload0;UpdateWindowempty = never apply on its own, e.g.03:00,Sun 03:00,Sat,Sun 02:00-05:00- inside it the scheduled task applies a verified installer, stops and starts the service and rolls back one that does not come back;UpdateBackupBeforeApply1 - no destination or a failed backup means no apply;UpdateRequireAuthenticode0 - leave off, this project's releases are not Authenticode-signed so 1 refuses every release, the Sigstore check is not optional;UpdateServiceWaitSeconds180; and five private-Sigstore settingsUpdateSourceRepository,UpdateSigningIdentity,UpdateSigningIssuer,UpdateTrustRootsFile,UpdateLogPublicKeyFile- all empty by default, meaning the server trusts exactly one thing: an installer signed by this project's release workflow and recorded in the public transparency log; every setting on the card applies after a service restart), "Windows Event Log" (WindowsEventLogEnableddefault 1,WindowsEventLogLeveldefault 2 with options 1-4), "ManageSieve (RFC 5804)" (ManageSieveServerPortdefault 0, placeholder 4190;ManageSieveServerBindAddressdefault 127.0.0.1; live STARTTLS-availability state), "Operability" (ShutdownDrainSecondsdefault 0) (source: FeatureSettingsView.xaml.cs:1695-1795, 1928-1985, 2037; IniFileSettings.cpp:426, 453, 489-509, 591, 628, 735) - REST API keys (
apikeys): title "REST API keys"; file-based - reads/creates/revokeshMailServerApiKeys.inibeside hMailServer.INI (one[Key.<id>]section with Label, Expires "yyyy-MM-dd HH:mm:ss", AllowedFrom, Scope, Domains, Hash written LAST); token formathmapi_+ 64 lower-case hex (32 random bytes), only its SHA-256 hex is stored; a created key is shown once ("Copy this key now" card) and cleared on leaving the page; scope fails closed - only the literal "full" is read/write, everything else read-only; default lifetime 90 days, label max 64 chars; the server re-reads the file on every request so no restart; works while the REST listener is off; LOCAL machine only (needs the INI path) (source: Views/ApiKeysView.cs:20-40, 63-70; Services/ApiKeyStore.cs:75-137, 329-340)
- Domains (
domains): on-screen "Domains & accounts"; left list of domains (search, "Properties", "Add domain" with boxnewdomain.com), accounts of the selected domain (search, "Edit", "Delete", create with address + password + "Generate" + "Create account"), Aliases panel (alias@domain->target@anywhere, "Add"/delete), Distribution lists panel ("Properties", "Members", "Add"); all viaApplication.Domains(source: Views/DomainsView.xaml:16-272; Views/DomainsView.xaml.cs) - Domain dialog: title "Domain - {name}"; tabs General, Names, Limits, Signature, Relay, Out of office, DKIM; writes
Active,Name,Postmaster,ADDomainName(Active Directory link),MaxSize,MaxMessageSize,MaxAccountSize,MessageRetentionDays(Limits tab, "Delete messages in this domain's mailboxes older than (days; 0 = no policy, an account's own value overrides it)", added 5 September 2026 on schema 6027),MaxNumberOfAccounts(+Enabled),MaxNumberOfAliases(+Enabled),MaxNumberOfDistributionLists(+Enabled),PlusAddressingEnabled/Character,SignatureEnabled/Method/PlainText/HTML,RelayHost/Port/RequiresAuthentication/Username/Password/ConnectionSecurity,VacationMessageIsOn/VacationSubject/VacationMessage/VacationInternalSubject/VacationInternalMessage/VacationExternalOverride,DKIMSignEnabled/Selector/PrivateKeyFile/SecondarySelector/SecondaryPrivateKeyFile/SigningAlgorithm/HeaderCanonicalizationMethod/BodyCanonicalizationMethod/SignAliasesEnabled; the DKIM tab generates keys ("Save the DKIM private key" / "Save the new DKIM private key" file dialogs) and shows the DNS record; the Names tab embeds the Domain aliases collection editor (source: Views/DomainDialog.cs:7-10, 130-161, 216, 617; property grep; Views/CollectionSpecs.cs:184-201) - Account dialog: title "Account - {address}"; tabs General, Forwarding, Auto-reply, Spam, Signature, Sieve, External, App passwords, Two-factor, Rules, Folders, Directory; General has Address, Administration level (Normal user 0 / Domain administrator 1 / Server administrator 2), Quota (MB), "Delete messages older than (days; 0 = the domain's policy, -1 = keep forever)" (
MessageRetentionDays, added 5 September 2026 on schema 6027), first/last name, New password with "Generate strong password" and a strength meter, Last logon; writesActive,Address,AdminLevel,MaxSize,MessageRetentionDays,PersonFirstName/LastName,Password,ForwardEnabled/Address/KeepOriginal/AbortSpamFlagged,VacationMessageIsOn/VacationMessage/VacationMessageExpires/ExpiresDate/BeginDate/AbortSpamFlagged,SpamMarkThreshold/SpamDeleteThreshold(per-account),SignatureEnabled/PlainText/HTML,SieveScript,ADDomain/ADUsername(source: Views/AccountDialog.cs:114-150, 183-200; property grep) - Account "External" tab = FetchAccounts collection editor: Enabled, Name, POP3 server, Port (default 110), user/password, Minutes between downloads (15), Days to keep (0), Connection security combo 0 None(110)/1 SSL-TLS(995)/2 STARTTLS optional/3 STARTTLS required (replaces the old UseSSL checkbox that could not express STARTTLS), UseAntiSpam, UseAntiVirus (source: CollectionSpecs.cs:203-252)
- Account "App passwords" tab:
account.AppPasswordscollection; columns Name, State, Issued, Last used; buttons Create, Revoke / restore, Delete, Refresh; a generated password is shown once (server stores only a hash) (source: Views/AppPasswordsPanel.cs:7-22, 156, 194-255) - Account "Two-factor" tab: per-mailbox TOTP enrolment with a QR code shown once; enrolling means the account password stops authenticating mail clients, so app passwords are required (source: Views/AccountTwoFactorPanel.cs:7-20)
- Account "Rules" tab: per-account rules (add/rename/enable/delete; criteria and actions via the embedded RulesView) (source: CollectionSpecs.cs:254-272; RulesView.xaml.cs ConfigureForRules)
- Distribution list dialog: title "Distribution list - {address}"; writes
Active,Address,Mode,RequireSMTPAuth,RequireSenderAddress,ModeratorAddress,BounceAddress; members edited in "Recipients - {list}" dialog (source: Views/DistributionListDialog.cs:35; Views/RecipientsDialog.cs:31; property grep) - "Browse Active Directory" dialog: lists forest domains, searches users (Account/Name/E-mail), single or multi select; used to fill an account's AD fields and to bulk-import members (source: Views/ActiveDirectoryPickerDialog.cs:54, 188-190)
- Public folders (
publicfolders): listsSettings.PublicFolders; "Add folder" (prompt), "Permissions" (double-click too), "Delete" (confirms "and all messages in it"), "Refresh" (source: Views/PublicFoldersView.cs:42-165) - Folder permissions dialog "Permissions - {folder}": ACL entries per account or group with eACLPermission bits Lookup 1, Read 2, ..., Insert/append 16, Post 32 - labelled "Post - and send as this mailbox's address over SMTP (Send-As, when SmtpAuthenticatedSenderCheck is on)" since 5 September 2026 (v6.2.25) - ..., Expunge 512, Administer 1024 (source: Views/FolderPermissionsDialog.cs:66-79, 95, 263-267)
- Groups (
groups):Settings.Groupslist plus a "Members…" button opening "Members - {group}" (resolves member AccountIDs to addresses; "Add account to group") - the member editor did not exist before, so groups granted folder rights to nobody (source: CollectionSpecs.cs:128-147, 285-386; Views/GroupMembersDialog.cs:49, 300; IDL:655)
- Delivery of e-mail (
delivery): tabs Delivery (COMSMTPNoOfTries,SMTPMinutesBetweenTry,MaxNumberOfMXHosts, INIMXTriesFactordefault 0, COMSMTPDeliveryBindToIP,SMTPConnectionSecuritycombo,AddDeliveredToHeader, INIQuickRetries0,QuickRetriesMinutes6,QueueRandomnessMinutes0,MaxOutboundPerDestinationPerMinute0, and - in the tree after 6.2.27, not yet released - INIOutboundPipeliningdefault on (send a transaction's commands without waiting for each answer, only to a server that advertises PIPELINING),OutboundChunkingdefault on (BDAT instead of dot-stuffed DATA; also what relays a BINARYMIME message onward unchanged),DeliveryHardLinksdefault off (one file linked per local recipient instead of copied; needs the data directory on NTFS, otherwise the server copies and says so in the SMTP log); all three apply after a service restart), Relayer ("SMTP relayer (smart host)":SMTPRelayerwithhost1|host2failover,SMTPRelayerPort,SMTPRelayerConnectionSecurity,SMTPRelayerRequiresAuthentication,SMTPRelayerUsername, password viaSetSMTPRelayerPassword; card "OAuth2 for the relay (Microsoft 365)": INIOutboundOAuth2Hostsdefaultsmtp.office365.com,OutboundOAuth2TokenUrl,OutboundOAuth2ClientId,OutboundOAuth2ClientSecret,OutboundOAuth2Scope,OutboundOAuth2FixedToken,FetchOAuth2Hostsdefaultoutlook.office365.com), Rules (RuleLoopLimit) (source: ServerSettingsView.xaml.cs BuildDelivery :1218-1356, the three INI rows at :1228-1252; IniFileSettings.cpp:312, 732-733) - Routes (
routes): grid Domain/Target host/Port/Retries/Auth fromSettings.Routes; inline add (domain, host, port default 25; NumberOfTries 3, MinutesBetweenTry 10), "Edit" opens "Route - {domain}" with tabs General, Delivery, Addresses, Security, Authentication writingTargetSMTPHost/Port,Description,NumberOfTries,MinutesBetweenTry,AllAddresses,TreatSenderAsLocalDomain,TreatRecipientAsLocalDomain,ConnectionSecurity,RelayerRequiresAuth,RelayerAuthUsername, route addresses (source: Views/RoutesView.xaml.cs; Views/RouteDialog.cs:49-70; property grep) - Incoming relays (
relays): title "Incoming relays", subtitle "Upstream gateways (spam filters, load balancers) whose IP addresses should not count as the connecting client in anti-spam host checks.";Settings.IncomingRelaysName/LowerIP/UpperIP add/delete (source: UtilityViews.cs:15-33, 100-185) - Rules (
rules): on-screen "Global rules", subtitle "Server-wide message rules, evaluated top to bottom.";Application.Rules; grid #/Name/Enabled; buttons Move up, Move down, Enable / disable, Delete rule, Add rule; IF criteria (Add…/Edit…/Remove) and THEN actions (Add…/Edit…/Remove/Up/Down) (source: Views/RulesView.xaml:18-108; Views/RulesView.xaml.cs:31, 249-420) - Rule action types offered: Delete e-mail 1, Forward e-mail 2, Reply 3, Move to IMAP folder 4, Run script function 5, Stop rule processing 6, Set header value 7, Send using route 8 (server-level only), Create copy 9, Bind to address 10 (server-level only) (source: Views/RuleActionDialog.cs:73-84)
- Server messages (
servermessages):Settings.ServerMessagesName/Text, fixed set (no add/delete) (source: CollectionSpecs.cs:149-162) - Server sendout (
sendout): wildcard (default*), from address/name, subject, body ->Utilities.EmailAllAccounts(...); reports "The server did not queue the sendout" when the call returns false (source: UtilityViews.cs SendoutView; IDL:1177)
- Spam filtering overview (
spamoverview): read-only; readsSettings.AntiSpamthresholds, headers, HELO/PTR/MX checks and scores, SPF/DKIM/DMARC and scores, SpamAssassin, greylisting and bypasses, blocked-sender count; judgement inServices/SpamPipeline.cs; every row links to the owning page; "Refresh" (source: Views/SpamOverviewView.cs:21-40, 126-156) - Quarantine (
quarantine):Settings.AntiSpam.Quarantine(Refresh(),Count, indexer pages the table); columns Held, Sender, Recipients, Score, Subject, row tooltip "Held because: {reason}"; buttons "Release" (ReleaseByDBID), "Delete" (DeleteByDBID, confirmation defaults to No - the only copy), "Remove expired" (DeleteExpired(), windowQuarantineRetentionDays), "Refresh"; empty state text says quarantining is off unlessQuarantineEnabledis set (source: Views/QuarantineView.cs:14-33, 87-166, 241-360; IDL:2595 "Empty and inert unless QuarantineEnabled is set in hMailServer.ini") - Anti-spam settings (
antispam): on-screen "Anti-spam"; tabs General ("Thresholds & actions":AntiSpam.SpamMarkThreshold,SpamDeleteThreshold,AddHeaderSpam,AddHeaderReason,PrependSubject,PrependSubjectText,MaximumMessageSize; "Quarantine instead of refusing": INIQuarantineEnabledoff by default,QuarantineRetentionDaysdefault 30; "Recipient tarpit": COMAntiSpam.TarpitCount- recipients a message may name before the delay starts, 0 = off - andAntiSpam.TarpitDelay- seconds each further RCPT TO in an unauthenticated session waits, at most 30; stored as INISmtpTarpitCount/SmtpTarpitDelaySeconds, takes effect at once, authenticated sessions and IP ranges with spam protection off are exempt; added 5 September 2026, v6.2.25), Sender auth (UseSPF+UseSPFScore, INISpfVoidLookupLimit,DKIMVerificationEnabled+DKIMVerificationFailureScore, INIDkimAcceptSha1off,DMARCEnabled+DMARCFailureScore, INIDmarcTreeWalkEnabled, INIDmarcRptSchemaVersiondefault 1, COMArcFilteringEnabled+ArcTrustedSealers- "does nothing at all" with an empty sealer list), Host checks (CheckHostInHelo(+Score),CheckPTR(+Score),UseMXChecks(+Score)), Greylisting (GreyListingEnabled,GreyListingInitialDelay,GreyListingInitialDeleteandFinalDeleteshown in days (stored hours, Divisor 24),BypassGreylistingOnMailFromMX,BypassGreylistingOnSPFSuccess, INIGreylistingEnabledDuringRecordExpirationdefault 1,GreylistingRecordExpirationIntervaldefault 240, button "Clear greylisting triplets"), SpamAssassin (SpamAssassinEnabled/Host/Port/MergeScore/Score, "Test SpamAssassin connection", INISAMinTimeout30,SAMaxTimeout90,SAMoveVsCopyoff,SpamAssassinUserempty andSpamAssassinUserFromRecipientoff - the spamdUser:header, applied on Reinitialize (added 5 September 2026); in the tree after 6.2.27, not yet released: INISpamAssassinLearnOnMovedefault off - moving a message into the folder designated Junk reports it to sa-learn as spam and moving it back out as ham, one sa-learn run per move, applies after a service restart; card "External filtering engine (rspamd and anything else that speaks HTTP)": INIFilterHookUrl(empty = none),FilterHookTimeoutSeconds10,FilterHookFailClosedoff,FilterHookRejectScore100,FilterHookMaxMessageSizeKB10240) (source: ServerSettingsView.xaml.cs BuildAntiSpam :1357-1610, tarpit card :1374-1378, learn-on-move :1558-1566; IDL:2583-2586; IniFileSettings.cpp:354, 676-679) - SURBL servers (
surbl):AntiSpam.SURBLServersActive/DNSHost/RejectMessage/Score (default 5) (source: CollectionSpecs.cs:38-51) - DNS blacklists (
dnsbl):AntiSpam.DNSBlackListsActive/DNSHost/ExpectedResult/RejectMessage/Score (default 5) (source: CollectionSpecs.cs:53-67) - White list (
spamwhitelist): on-screen "Anti-spam white list";AntiSpam.WhiteListAddressesLowerIPAddress/UpperIPAddress/EmailAddress/Description (source: CollectionSpecs.cs:69-82) - Blocked senders (
blockedsenders):AntiSpam.BlockedSendersAddress (exact with @, else domain + subdomains)/Score default 100/Description; matches the CLAIMED sender - not anti-spoofing (source: CollectionSpecs.cs:84-100) - Greylisting white list (
greylistwhitelist):AntiSpam.GreyListingWhiteAddressesIPAddress/Description (source: CollectionSpecs.cs:102-113) - Virus scanning overview (
virusoverview): read-only; reads ClamAV/ClamWin/custom scanner settings; exists becauseVirusScanner::ScanFile_treats "every scanner errored" as NoVirusFound, so an enabled-but-broken scanner looks like a clean scan; judgement inServices/VirusPipeline.cs(source: Views/VirusOverviewView.cs:21-44, 131-139) - Anti-virus settings (
antivirus): on-screen "Anti-virus"; tabs General (AntiVirus.Actioncombo,NotifySender,NotifyReceiver,MaximumMessageSize,EnableAttachmentBlocking; card "When a scanner cannot run": INIAVFailAction0 deliver / 1 hold (default 0),AVFailRetryMinutes15,AVFailMaxHolds16), ClamAV (ClamAVEnabled/Host/Port, "Test ClamAV connection", INIClamMinTimeout15,ClamMaxTimeout90), ClamWin (ClamWinEnabled/Executable/DBFolder, "Auto-detect ClamWin", "Test ClamWin scanner"), Custom (CustomScannerEnabled/Executable/ReturnValue, preset picker, "Test custom scanner") (source: ServerSettingsView.xaml.cs BuildAntiVirus :1667-1777) - Anti-virus "Test ClamAV connection" (5 September 2026): the server asks clamd
nPING(expectsPONG) andnVERSIONbefore scanning, so the result names the daemon ("ClamAV 1.5.4/28085/..."), a port with something else on it is reported as not answering PING, and both samples (plain, EICAR) are streamed from memory - the EICAR file used to be written to the data directory, where Windows Defender removed it before clamd saw it and the button reported a missing file. The ClamWin and custom-scanner tests still write a file and say so when a host antivirus removes it first (source: VirusScannerTester.cpp; ClamAVVirusScanner::ScanData) - Blocked attachments (
blockedattachments):AntiVirus.BlockedAttachmentsWildcard (default*.exe)/Description; requiresAntiVirus.EnableAttachmentBlockingon the Anti-virus page (source: CollectionSpecs.cs:115-126)
- Protocols (
protocols): tabs Services (COMServiceSMTP,ServiceIMAP,ServicePOP3), SMTP (HostName,MaxSMTPConnections,MaxMessageSize,MaxSMTPRecipientsInBatch,WelcomeSMTP,AllowSMTPAuthPlain,DenyMailFromNull, INIRejectFullMailboxAtRcptdefault on, INIQuotaWarningPercentdefault 90, INIArchiveRetentionDaysdefault 0, INIMetricsPerDomainEnableddefault off,AllowIncorrectLineEndings,DisconnectInvalidClients,MaxNumberOfInvalidCommands, INISmtpAuthenticatedSenderCheckdefault off - "An authenticated session may only send as an address its account owns or has been granted": MAIL FROM must be the account's own address, an alias resolving to it, or a mailbox whose owner granted the post (p) right on its INBOX as the Send-As grant, otherwise 550 5.7.1; added 5 September 2026, v6.2.25), IMAP (MaxIMAPConnections,WelcomeIMAP,IMAPIdleEnabled,IMAPQuotaEnabled,IMAPSortEnabled,IMAPACLEnabled,IMAPSASLPlainEnabled,IMAPSASLInitialResponseEnabled,IMAPPublicFolderName,IMAPMasterUser,IMAPHierarchyDelimiter,CreateDefaultSpecialUseFoldersEnableddefault off - creates Drafts, Sent, Trash and Junk with their RFC 6154 designation when an account is created; they survive Account.DeleteMessages and go with the account; added 5 September 2026, schema 6026; in the tree after 6.2.27, not yet released: INIIMAPCompressionEnableddefault on - lets a client ask for the rest of the session to be compressed (COMPRESS=DEFLATE, RFC 4978); a client that does not ask is unaffected; applies after a service restart; card "IMAP search limits": INIIMAPSearchTimeout60,IMAPSearchMaxMegabytes2048; card "Change history for synchronising clients": INIIMAPExpungeRetentionRecords5000; card "Repair": button "Recalculate folder UID counters"), POP3 (MaxPOP3Connections,WelcomePOP3; card "How often a client may check for mail": INIPop3LoginDelaySeconds0), Timeouts (INISMTPDMinTimeout10,SMTPDMaxTimeout1800,SMTPCMinTimeout30,SMTPCMaxTimeout600,POP3DMinTimeout10,POP3DMaxTimeout600,POP3CMinTimeout30,POP3CMaxTimeout900) (source: ServerSettingsView.xaml.cs BuildProtocols :1038-1217, SmtpAuthenticatedSenderCheck :1067, IMAPCompressionEnabled :1109-1116; IniFileSettings.cpp:497, 641, 643, 656) - TCP/IP ports (
ports): grid ofSettings.TCPIPPortsProtocol (1 SMTP/3 POP3/5 IMAP), Address, Port, Security (None / SSL/TLS / STARTTLS (optional) / STARTTLS (required)), Certificate name, and a live "Listening"/"Not listening"/"Server off"/"Unknown" badge from the local TCP table (ListenerProbe, local sessions only) with a summary line naming unbound ports; inline add (protocol, address, port, security), "Edit" opens "TCP/IP port" dialog (writesProtocol,Address,PortNumber,ConnectionSecurity,SSLCertificateID,ClientCertificatePolicy,ClientCertificateCAFile- mutual TLS), "Restore defaults" =TCPIPPorts.SetDefault()(SMTP 25 + 587, POP3 110, IMAP 143, no security), Delete (source: Views/TcpIpPortsView.xaml.cs:15-34, 55-175, 291-323; Views/TcpIpPortDialog.cs:13-36; property grep) - Web services & autoconfiguration (
webservices): on-screen "Web services & client autoconfiguration"; cards "Listener" (WebServicesHttpPortdefault 0,WebServicesHttpsPortdefault 0 - "Nothing below is served until a port is set here",WebServicesBindAddressdefault 0.0.0.0,WebServicesCertificateFile/WebServicesPrivateKeyFileoptional, fall back to ACME), "Client autoconfiguration (autoconfig & autodiscover)" (AutoconfigEnableddefault 1,AutoconfigClientHost), "MTA-STS policy hosting" (MtaStsHostingEnableddefault 1,MtaStsPolicyModedefault enforce,MtaStsPolicyMaxAgedefault 604800,MtaStsPolicyMx), "Calendar and contacts discovery (CalDAV / CardDAV)" (CalDavRedirectUrl,CardDavRedirectUrl- redirects only; "hMailServer does NOT implement CalDAV or CardDAV") (source: FeatureSettingsView.xaml.cs:2668-2760; IniFileSettings.cpp:602-611) - DNS resolver (
dns): cards "Name servers" (DNSServer- single IPv4, port 53; empty = Windows resolvers), "DNS cache" (UseDNSCachedefault 1 - toggles DNS_QUERY_BYPASS_CACHE, i.e. Windows' cache, ignored when DNSServer is set), "DNS blacklist checks" (DNSBLChecksAfterMailFromdefault 1) (source: FeatureSettingsView.xaml.cs:2624-2666; IniFileSettings.cpp:249, 400)
- SSL certificates (
certs): grid ofSettings.SSLCertificatesName, Certificate file, Private key file, Certificate state (parses, expiry, days remaining), Private key state (exists, encrypted, matches the certificate) viaCertificateInspectoroff the UI thread - honest "cannot be checked from here" on a remote session; "Private key passphrase" card (COMPrivateKeyPassword, DPAPI-protected, write-only; needed for an encrypted key or the TLS ports do not start - server error 6170) with "Save passphrase"/"Remove stored passphrase"; "Add certificate" (name, PEM cert file, PEM key file, optional passphrase), "Delete selected"; ACME-issued certificates appear here automatically (source: Views/SslCertificatesView.xaml:18-120; Views/SslCertificatesView.xaml.cs:14-40, 103-155, 384-667) - Certificates (ACME) (
acme): on-screen "Automatic certificates (ACME)"; card "ACME (Let's Encrypt)":AcmeEnableddefault 0,AcmeContactEmail,AcmeDomains,AcmeDirectoryUrldefaulthttps://acme-v02.api.letsencrypt.org/directory,AcmeHttpPortdefault 80,AcmeCertificateDirectory(empty = Data\ACME),AcmeReuseKeydefault 1; a live warning reads the issued certificate's expiry from disk (source: FeatureSettingsView.xaml.cs:1759-1792; IniFileSettings.cpp:595) - Transport encryption overview (
tlsoverview): read-only; readsTlsVersion10..13Enabled,SslCipherList,VerifyRemoteSslCertificate, the ports and certificates; judgement inServices/TlsPosture.cs; flags e.g. a TLS port with no certificate (fails to start, no plaintext fallback), AEAD-ONLY with TLS 1.0/1.1 enabled (no usable suite), expired certificates, plaintext-password exposure (the IP-range "require TLS for auth" control) (source: Views/TlsOverviewView.cs:21-40, 132-142; NavigationMap.cs comment ontlsoverview) - SSL/TLS (
tls): tabs Protocol versions (COMTlsVersion10Enabled,TlsVersion11Enabled,TlsVersion12Enabled,TlsVersion13Enabled), Ciphers (SslCipherList- "TLS 1.2 and below (OpenSSL format)", the single valueAEAD-ONLYis a named preset; INITlsCipherSuites13for TLS 1.3 RFC 8446 names;TlsOptionPreferServerCiphersEnabled;TlsOptionPrioritizeChaChaEnabled- only effective with server order + TLS 1.2/1.3, wired live;VerifyRemoteSslCertificate; in the tree after 6.2.27, not yet released: INITlsKeyExchangeGroups- the elliptic-curve and finite-field groups the server will agree a key with, in OpenSSL group-list syntax such asx25519:secp256r1; the editor says empty = OpenSSL's default list, and the server's built-in value when the key is absent isX25519MLKEM768:SecP256r1MLKEM768:X25519:secp384r1:secp256r1; a list naming nothing the client supports ends the handshake; applies after a service restart), Session resumption (INITlsSessionTicketsEnableddefault 1,TlsSessionCacheSizedefault 0 (-1 = no cache),TlsSessionTimeoutSecondsdefault 0,TlsTicketKeyRotationSecondsdefault 0) (source: ServerSettingsView.xaml.cs BuildTls :1719-1843, TlsKeyExchangeGroups :1736-1743; IniFileSettings.cpp:584, 687) - Transport security (
security): cards "DANE & DNSSEC" (DaneEnforcementEnableddefault 1,DnssecValidationEnableddefault 1,DnssecTrustAnchors), "MTA-STS" (MtaStsEnableddefault 1 - honouring OTHER domains' policies), "ARC sealing" (ArcSealingEnableddefault 0; needs a hosted domain with DKIM or it "reads enabled and seals nothing"), "ARC inbound filtering" (information only - points to the Anti-spam page), "DKIM signature timestamps" (DKIMSignatureValiditySeconds0,DKIMEnforceSignatureExpiry1,DKIMExpiryClockSkewSeconds300), "DKIM oversigning" (DkimOversignHeadersempty = off), "Authentication results on inbound mail" (AuthenticationResultsEnabled0,ReceivedSpfHeaderEnabled0,AuthenticationResultsIdentity), "TLS reporting (TLS-RPT)" (TlsRptFromAddressempty = disabled,TlsRptOrganizationNamedefault hMailServer), "DMARC aggregate reporting (rua)" (DmarcRptFromAddressempty = disabled,DmarcRptOrganizationName), "Forwarded mail & bounce protection (SRS / BATV)" (RewriteEnvelopeFromWhenForwarding0,SRSEnabled0 +SRSSecret,BATVEnabled0 +BATVSecret; live warnings when enabled with no secret - SRS-on-no-secret also suppresses the plain rewrite) (source: FeatureSettingsView.xaml.cs:1470-1757; IniFileSettings.cpp:402-404, 455, 480, 614-616)
- Authentication (
authentication): cards "OAuth2 / external identity provider" (OAuth2Enableddefault 0,OAuth2RequireTLS1,OAuth2Issuer,OAuth2Audience,OAuth2AllowedAlgorithmsdefault RS256,OAuth2UsernameClaimdefault email,OAuth2PublicKeyFile,OAuth2HmacSecret, and since 5 September 2026OAuth2JwksUrl,OAuth2JwksCacheSeconds3600,OAuth2IntrospectionUrl,OAuth2IntrospectionClientId,OAuth2IntrospectionClientSecret,OAuth2IntrospectionCacheSeconds300,OAuth2IntrospectionFailOpenoff; live coherence warning - the mailbox must still exist locally), "Password storage" (PreferredHashAlgorithmdefault 4 with options 5 Argon2id / 4 PBKDF2 / 3 SHA-256 / 2 MD5 / 1 Blowfish;MinimumAcceptedHashAlgorithmdefault 0 with 0/3/4/5;PasswordPepper- changing it invalidates ALL existing passwords; INIPasswordHashIterations0,PasswordHashMemoryKB0,PasswordHashTimeCost0 - work factors for new hashes, 0 = the built-in default, bounded; a stored hash cheaper than the configured value is re-derived on the next logon, never a costlier one; added 5 September 2026), "SMTP authentication" (DisableAUTHList- ports where AUTH is not offered) (source: FeatureSettingsView.xaml.cs:2539-2622; IniFileSettings.cpp:171, 208) - Directory authentication (LDAP) (
ldap): edits the[LDAP]section of the LOCAL hMailServer.INI directly (ProfileApi, not IniFeatureStore); keysEnabled(default 0),Server,Port(0 = protocol default),Security(combo: 2 "LDAPS - TLS from the first byte (default, port 636)", 1 "StartTLS - connect on 389, upgrade to TLS before anything is sent", 0 "Unprotected LDAP - cleartext (lab networks only)"; server default 2, an unrecognised value is read as LDAPS),VerifyCertificate(1),AllowUnprotectedPassword(0),BindMethod(combo: 0 "Simple bind - the password is sent to the directory (use with TLS)", 1 "Negotiate (Kerberos/NTLM) - the password never crosses the network"; default 0),SearchBase,UserSearchFilter(default(&(objectCategory=person)(objectClass=user)(sAMAccountName=%u))),UserDnTemplate,ServiceUsername,ServicePassword(write-only, clear via checkbox),TimeoutSeconds(10, page allows 1-90),FallbackToWindowsLogon(0); cards "Is this configuration complete?", "Directory server", "How the password is proved", "Finding the user's directory entry", "Service account (search mode only)", "If the directory cannot answer", "What has to exist outside this server", "Test the connection" (user name + AD domain + password); the server re-reads[LDAP]within two seconds of a save - no restart (source: Views/LdapSettingsView.cs:23-60, 345-624, 715-866; hmailserver/source/Server/Common/LDAP/LdapSettings.cpp:17, 229-276) - Directory synchronisation (
directorysync): provisions mailboxes from LDAP for domains whoseADDomainNameis set; INI[LDAP]keysSyncFilter,SyncMailAttribute(default mail),SyncUsernameAttribute(sAMAccountName),SyncDisplayNameAttribute(displayName),SyncMaxUsers(5000),SyncScheduleMinutes(0 = no unattended run); "Preview" ->Settings.PreviewDirectorySync(domain, disableMissing, out text)and "Apply" ->Settings.ApplyDirectorySync(...)run inside the server; Apply is disabled until a Preview has run with identical options; "mark absent accounts inactive" is part of the preview; never deletes accounts or messages (source: Views/DirectorySyncView.cs:19-50, 96-125, 215-386, 498-507, 799-809; LdapSettings.cpp:54-62, 278-322) - Administrative access (
adminaccess): tabs Password ("Administrator password" viaSetAdministratorPassword- used by the Control Panel, the REST API and COM scripts, stored hashed in hMailServer.ini; "Policy for mailbox passwords": INIPasswordPolicyMinimumLength0,PasswordPolicyRequireMixedCase,PasswordPolicyRequireDigit,PasswordPolicyRequireNonAlphanumeric,PasswordPolicyRejectCommon- all off, applied when a password is CHOSEN, never at logon; "Reuse and expiry":PasswordPolicyHistoryCount0,PasswordPolicyMaximumAgeDays0 - no self-service reset exists, AD accounts exempt), Two-factor (button opening TotpSetupDialog) (source: ServerSettingsView.xaml.cs BuildAdminAccess :2568-2737) - Auto-ban (
autoban): card "Auto-ban" (COMAutoBanOnLogonFailure,MaxInvalidLogonAttempts- 0 disables even when ticked,MaxInvalidLogonAttemptsWithin- record lifetime, not a sliding window,AutoBanMinutes- 0 drops the connection but creates no range; button "Clear logon-failure list" =Settings.ClearLogonFailureList()which does NOT lift existing bans - delete the "Auto-ban: {user}" range (priority 100) on the IP ranges page), card "Per-name lockout" (INIAccountLockoutThreshold0 = off,AccountLockoutWindowMinutes30,AccountLockoutMinutes30; counted per user name across SMTP AUTH, POP3, IMAP, ManageSieve, REST), card "Logon tarpit" (INILogonTarpitSeconds0 = off; the first wrong password on a connection waits this many seconds, the second twice as long and so on up to 30 s, on SMTP, POP3 and IMAP alike; a correct password is never delayed; the wait is a timer on the connection, not a thread asleep; 2 is a reasonable start; applies after a service restart; added 5 September 2026, v6.2.25) (source: ServerSettingsView.xaml.cs BuildAutoBan :1844-1949 and the doc comment above it; IDL:666; IniFileSettings.cpp:675) - IP ranges (
ipranges): grid ofSettings.SecurityRanges(Name, Lower/Upper IP, Priority, SMTP/IMAP/POP3 allowed); inline permissions panel (Allow SMTP/IMAP/POP3,RequireSSLTLSForAuth, the four AllowDeliveryFrom{Local,Remote}To{Local,Remote} flags) with "Save"; inline add (name, lower, upper, priority default 15; all three protocols allowed); "Edit" opens "IP range" dialog with tabs General, Connections, Relaying, Require auth (RequireSMTPAuthLocalToLocal/LocalToExternal/ExternalToLocal/ExternalToExternal), Protection (EnableSpamProtection,EnableAntiVirus,Expires,ExpiresTime); "Restore defaults" =SecurityRanges.SetDefault()("My computer" 127.0.0.1 priority 30 and "Internet" 0.0.0.0-255.255.255.255 priority 10 - removes auto-ban entries too) (source: Views/IPRangesView.xaml.cs:38-287; Views/IPRangeDialog.cs:13-78; property grep; IDL:1496)
- Backup & restore (
backup): COMSettings.BackupDestination, BackupDomains, BackupMessages, BackupSettings, CompressDestinationFiles (setters persist immediately - no Save method); INIBackupMessagesDBOnly(local only); checkbox "Verify each backup by extracting its message store and reconciling it against the rows" = INIBackupVerifyRestore(default on), read and written with BackupMessagesDBOnly, disabled with an explanation when hMailServer.ini is not on the machine (added 5 September 2026, v6.2.25); "Start backup now" =Application.BackupManager.StartBackup(); Restore: pickHMBackup*.xmlon the server, RestoreDomains/Messages/Settings,BackupManager.LoadBackup(file).StartRestore(); "Scheduled backups" card (local INI only):ScheduledBackupTime(strict 24-hour HH:MM, empty = off),ScheduledBackupIntervalMinutes(0),ScheduledBackupKeepCount(0 = keep all),ScheduledBackupMaxAgeDays(0) - daily time wins over interval; status lines say whether a schedule exists and the age of the newestHMBackup YYYY-MM-DD HHMMSS.7zarchive in the destination, Critical when older than twice the expected interval (source: Views/BackupView.xaml:11-124; Views/BackupView.xaml.cs:15-96, 141-244, 313-420; IDL:1672) - Performance (
performance): tabs Threads (COMMaxDeliveryThreads,MaxAsynchronousThreads,TCPIPThreads, INIMaxNumberOfExternalFetchThreads15,WorkerThreadPriorityshown INERT), Cache (Cache.Enabled, four*CacheTTL, four*CacheMaxSizeKb(session-only, reset to 10240 KB at restart), live "How the caches are performing" hit-rate/memory readout fromCache.*HitRate), Indexing (MessageIndexing.Enabled, INIIndexerFullMinutes720,IndexerFullLimit25000,IndexerQuickLimit1000,IndexerFullText0 - needs indexing on,IndexerFullTextBatchSize250,IndexerFullTextMinTokenLength3,IndexerFullTextMaxTokensPerMessage2048; buttons "Index now, and show how far behind it is", "Discard the index and rebuild it"), Database (LOCAL INI[Database]NumberOfConnections5 - forced to 1 on MSSQLCE and labelled so,ConnectionAttempts6,ConnectionAttemptsDelay5;[Settings]DatabaseStatementTimeout30) (source: ServerSettingsView.xaml.cs BuildPerformance :2213-2466; IDL:2243-2257; IniFileSettings.cpp:365) - Advanced (
advanced; "Advanced & scripting" until 5 September 2026): on-screen "Advanced"; tabs General (DefaultDomain,IPv6PreferredEnabled,UserInterfaceLanguage- third-party COM tools only), Copies of mail ("Mirroring"MirrorEMailAddress; "Message archiving" INIArchiveDir(empty = off),ArchiveHardLinks0,ArchiveDomains"Only archive mail for these domains (comma-separated; empty = every message)" (added 5 September 2026, v6.2.25); "Disk space" INIDiskSpaceWarningThresholdMB1024,MinimumFreeDiskSpaceMB100), Scripting (Scripting.Enabled,Scripting.LanguageVBScript/JScript; engine reloads on Save; in the tree after 6.2.27, not yet released: INIScriptAllowedObjects- the COM program identifiers an event script may instantiate besides hMailServer's own objects, comma separated (e.g. a scripting file system object or an HTTP client); the editor documents empty as "only hMailServer's own", while the server reads an absent key as*(IniFileSettings.cpp:389) - the exact server semantics of*versus an empty value are not verified here; applies after a service restart) (source: ServerSettingsView.xaml.cs BuildAdvanced :2344-2440, ArchiveDomains :2390, ScriptAllowedObjects :2433-2440) - Event scripts (
scripts): loads the file atSettings.Scripting.CurrentScriptFile(orDirectory\EventHandlers.vbs) from the LOCAL disk; "Save & reload" writes a.bak, thenScripting.Reload()+CheckSyntax(); "Check syntax"; "Reload from disk"; "Insert template…" with three VBScript OnAcceptMessage starters (external AV/DLP, webhook, HTTP API verdict) (source: Views/ScriptsView.cs:13-18, 52-96, 120-295) - Server limits & expert settings (
hardening): cards "Timeouts and queue bounds" (FinalizationTimeout240,DNSQueryTimeout10,ClientSessionCeiling1800,DBConnectionAcquireTimeout60,ScriptTimeout60,ExternalProcessTimeout300,AsyncQueueStallThreshold120,AsyncQueueReservedThreads2), "Front-end proxies (PROXY protocol and XCLIENT)" (SMTPProxyProtocolEnabled0,SMTPProxyProtocolTrustedIPs,SMTPXClientEnabled0,SMTPXClientTrustedIPs- empty lists trust nobody), "Received headers" (AuthUserReplacementIP,AddXAuthUserHeader0,AddXAuthUserIP1,AddXOriginalRcptTo0), "Refused connections" (BlockedIPHoldSeconds0), "Message store durability" (MessageStoreFsync0,MessageStoreConsistencyCheck0), "Per-account sending limits" (INI sections[SendingLimits]MaxMessagesPerAccountPerPeriod0,MaxRecipientsPerAccountPerPeriod0,PeriodHours24,StateSaveIntervalSeconds10 and[SendingLimitsOverrides]linesaddress=messages:recipients[:hours]- re-read within seconds, NO restart), "Submission rate limits" (MaxSubmissionsPerIPPerMinute0), "Server-generated mail" (DaemonAddressDomain), "Low-level tuning" (SMTPDMaxSizeDrop0,LoadHeaderReadSize4000,LoadBodyReadSize4000), "Stored secret protection" (ProtectStoredSecretsWithDPAPI1 - covers exactly five secrets: DB password, relayer password, route passwords, fetch-account passwords, certificate passphrases; NOT the SRS/BATV/OAuth2/pepper/metrics/service-account secrets), "Windows service account" (ServiceAccountName- read only at service REGISTRATION, empty = leave unchanged;ServiceAccountPasswordstored as typed; live SCM readout and the grants the account needs), "Settings that used to be on this page" (links) (source: FeatureSettingsView.xaml.cs:2135-2537; IniFileSettings.cpp:236, 410, 620-622)
- "About": Control Panel version and .NET runtime, connected server version/host, GitHub link
github.com/Progressiverobot/hmailserver, licence AGPLv3, maintainer card (Christopher Holloway / Progressive Robot Ltd, www.progressiverobot.com) (source: Views/AboutView.cs:23-176)
| Page / card | Gate | Default | Source |
|---|---|---|---|
| Message trace page; Logging > "Message trace" card | INI MessageTraceEnabled
|
0 | IniFileSettings.cpp:626; MessageTraceView.cs:76-78 |
| Quarantine page; Anti-spam > "Quarantine instead of refusing" | INI QuarantineEnabled
|
0 | IniFileSettings.cpp:624; IDL:2595 |
| API & monitoring > REST API; REST API keys page (works while the listener is off) | INI RestApiPort
|
0 | IniFileSettings.cpp:591; ApiKeysView.cs:31-35 |
| API & monitoring > Monitoring | INI MetricsServerPort; Otel*Endpoint
|
0; empty | IniFileSettings.cpp:426; FeatureSettingsView.xaml.cs Monitoring card |
| API & monitoring > ManageSieve | INI ManageSieveServerPort
|
0 | IniFileSettings.cpp:453 |
| Certificates (ACME) | INI AcmeEnabled
|
0 | IniFileSettings.cpp:595 |
| Web services & autoconfiguration (all cards) | INI WebServicesHttpPort / WebServicesHttpsPort
|
0 / 0 | IniFileSettings.cpp:602-603; card "Nothing below is served until a port is set here" |
| Authentication > OAuth2 | INI OAuth2Enabled
|
0 | IniFileSettings.cpp:208 |
| Directory authentication (LDAP) | INI [LDAP] Enabled
|
0 | LdapSettings.cpp:229 |
| Directory synchronisation > Unattended synchronisation | INI [LDAP] SyncScheduleMinutes
|
0 | LdapSettings.cpp:322 |
| Transport security > ARC sealing, SRS, BATV, Authentication-Results, TLS-RPT, DMARC rua |
ArcSealingEnabled, SRSEnabled, BATVEnabled, AuthenticationResultsEnabled 0; TlsRptFromAddress, DmarcRptFromAddress empty |
off | IniFileSettings.cpp:455, 480, 614, 616; FeatureSettingsView.xaml.cs Security cards |
| Anti-spam > ARC inbound filtering | COM ArcFilteringEnabled + non-empty ArcTrustedSealers
|
does nothing with an empty list | IDL:2583-2586 |
| Anti-spam > External filtering engine (rspamd) | INI FilterHookUrl
|
empty | ServerSettingsView.xaml.cs BuildAntiSpam |
| Auto-ban > Per-name lockout | INI AccountLockoutThreshold
|
0 (page default) | ServerSettingsView.xaml.cs BuildAutoBan |
| Auto-ban > Logon tarpit | INI LogonTarpitSeconds
|
0 | IniFileSettings.cpp:675 |
| Anti-spam > Recipient tarpit | COM AntiSpam.TarpitCount (INI SmtpTarpitCount) |
0 | IniFileSettings.cpp:676 |
| Anti-spam > SpamAssassin learns from Junk (in the tree after 6.2.27, not yet released) | INI SpamAssassinLearnOnMove
|
0 | IniFileSettings.cpp:354 |
| Delivery of e-mail > hard-linked local copies (in the tree after 6.2.27, not yet released) | INI DeliveryHardLinks
|
0 | IniFileSettings.cpp:312 |
| API & monitoring > Updates (in the tree after 6.2.27, not yet released) | INI UpdateCheckEnabled
|
0 | IniFileSettings.cpp:489; FeatureSettingsView.xaml.cs:1932 |
| Server limits > PROXY protocol / XCLIENT |
SMTPProxyProtocolEnabled, SMTPXClientEnabled
|
0 | IniFileSettings.cpp:620-622 |
| Server limits > fsync / consistency check; Diagnostics consistency card |
MessageStoreFsync, MessageStoreConsistencyCheck
|
0 / 0 (page default) | IniFileSettings.cpp:410; UtilityViews.cs ReadConsistencyReport |
| Performance > Full-text term index | INI IndexerFullText
|
0 | IniFileSettings.cpp:365 |
| Logging > JSON lines | INI JsonLogging
|
0 | IniFileSettings.cpp:406 |
| Backup > Scheduled backups |
ScheduledBackupTime / ScheduledBackupIntervalMinutes
|
empty / 0 | BackupView.xaml.cs:33-39 |
| Advanced > Message archiving | INI ArchiveDir
|
empty | ServerSettingsView.xaml.cs BuildAdvanced |
| Web services > CalDAV/CardDAV discovery |
CalDavRedirectUrl/CardDavRedirectUrl
|
empty (404) | FeatureSettingsView.xaml.cs WebServices |
On by default (for contrast): DaneEnforcementEnabled, DnssecValidationEnabled, MtaStsEnabled, MtaStsHostingEnabled, AutoconfigEnabled, WindowsEventLogEnabled, ProtectStoredSecretsWithDPAPI, TlsSessionTicketsEnabled, UseDNSCache, DNSBLChecksAfterMailFrom, RejectFullMailboxAtRcpt, GreylistingEnabledDuringRecordExpiration all default 1, and - in the tree after 6.2.27, not yet released - IMAPCompressionEnabled, OutboundPipelining, OutboundChunking and UpdateBackupBeforeApply (meaningful only once the update check is on) (source: IniFileSettings.cpp:161, 236, 249, 400-404, 497, 509, 584, 607, 611, 628, 641, 732-733)
-
hmailserver documentation/hmailserver-documentation.md§5 (line 328) and §19 (line 1210) andsettings.mdline 3 say the Control Panel is a .NET 8 app / needs the .NET 8 Desktop Runtime. Code:net10.0-windows(ControlPanel.csproj:5); About page says .NET 10 (AboutView.cs:85); README.md:111 and :130 say .NET 10. - Documentation §5.3 (lines 353-367) and §20 (lines 1322-1362) describe the OLD tree: groups Status / Domains / Rules / Settings (with Anti-spam ▸ Anti-virus ▸ Logging ▸ Security ▸ Network ▸ Maintenance) / Utilities, and pages "Settings → Auto-ban & SSL/TLS" and "Settings → Advanced hardening". Code: eight task-based groups (section 5 above); "Auto-ban & SSL/TLS" is split into "Auto-ban" and "SSL/TLS"; "Advanced hardening" is now titled "Server limits & expert settings" (NavigationMap.cs BuildRoots and comments). The doc's statement (line 1207) that the tree "deliberately mirrors the old Administrator's layout" is what NavigationMap.cs explicitly replaced.
- Documentation §20 lists 38 pages; code registers 55. Absent from the doc: Diagnosing stalled mail, Message trace, External setup, DNS records, REST API keys, Spam filtering overview, Quarantine, Blocked senders, Virus scanning overview, Transport encryption overview, Authentication, Directory authentication (LDAP), Directory synchronisation, Administrative access, DNS resolver, Web services & autoconfiguration (the doc folds web services into "API & monitoring") (source: MainWindow.xaml.cs RegisterPages :114-171 vs documentation lines 1324-1362).
- Documentation §17.4 (line 1094) locates admin two-factor at "Settings → ... → Two-factor authentication". Code: Access & abuse protection > Administrative access > "Two-factor" tab, plus the link on the Connect screen (ServerSettingsView.xaml.cs BuildAdminAccess; ConnectView.xaml:54).
- Documentation §21 (line 1401) and README.md:300 say the Control Panel "offers to restart the service when a change requires it". Code: only the INI-backed FeatureSettingsView pages (Transport security, ACME, API & monitoring, Server limits, Authentication, DNS resolver, Web services) prompt "Restart it now?" (FeatureSettingsView.xaml.cs:2966); ServerSettingsView pages that contain INI rows only show a toast "INI settings need a service restart" without offering one (ServerSettingsView.xaml.cs:3376); the LDAP pages and API keys need no restart; Backup's schedule card says "apply after a service restart" with no prompt.
- README.md:300 refers to "the Control Panel under Settings" - there is no "Settings" group any more.
-
settings.md(dated 2026-06-15, server 6.2.5) says FeatureSettingsView spans "four nav pages" and that "All 104 INI keys" are covered; code has seven FeatureSettingsView sections (enum at FeatureSettingsView.xaml.cs:35-44) and the generated settings index holds 347 entries across both views. Its Section A table lists "Auto-ban & SSL/TLS" as one page and files "admin password" under "Advanced & scripting"; both have moved (AdminAccess section, ServerSettingsView.xaml.cs:2568). -
settings.mdSection A says ServerSettingsView pages "mirror the classic Administrator" - superseded by the task-based map. - Documentation §5.2 and
Views/WelcomeView.cs:11("Landing page shown after connecting") imply Welcome is the landing page; code navigates to the Dashboard after connecting (MainWindow.xaml.cs OnConnected: NavigateTo("dashboard")). - Documentation §20 "Dashboard: Live graphs — throughput, sessions, service state": the dashboard has no service-state readout (that is on Server status); it has five KPIs, two charts and the external-setup summary (DashboardView.xaml).
- Documentation §20 "Incoming relays: Trusted forwarders whose Received headers are believed" vs code subtitle "whose IP addresses should not count as the connecting client in anti-spam host checks" (UtilityViews.cs:33).
- Documentation §20 "Blocked attachments: Refuse attachments by file extension" - code strips matching wildcards and only when
AntiVirus.EnableAttachmentBlockingis on (CollectionSpecs.cs:118). - NavigationMap.cs class summary (:91) says "Of 42 pages, 30 sat under a single Settings group" - historical; 55 pages are registered today (internal comment, not user-facing).
- The "Web Control Deck at the listener root" named on the API & monitoring card is real (confirmed 2026-09-08): the REST listener serves
GET /and/index.htmlfrom{app}\WebAdmin\index.htmlwithout authentication (hmailserver/source/Server/Common/Util/RestApiServer.cpp:1275-1277, HandleWebAdminPage_ :2977-2980; installed by hmailserver/installation/section_files_64.iss:13), a single-page browser UI titled "hMailServer — Control Deck" with four views - Dashboard, Domains (with accounts), Delivery queue and DANE/TLSA (Roadmap.md:933) - that reads and writes through /api/v1 and cannot edit settings, logs, certificates or rules. In the tree after 6.2.27, not yet released: the same listener also serves the self-service portal at/portal(RestApiServer.cpp:1281), which is for mailbox owners, not administrators. - Totp.cs header comment (line 5-7) says the secret is stored "exactly like hMailServer Administrator" - consistent with documentation line 1209 ("TOTP secret carries over"); no contradiction, recorded as confirmed.
- Server-side defaults for
AccountLockoutThreshold/WindowMinutes/Minutes,MessageStoreConsistencyCheck,ScheduledBackup*,AVFail*,FilterHook*,IMAPSearch*,Pop3LoginDelaySeconds,TlsSession*,PasswordPolicy*,Outbound/FetchOAuth2*were taken from the Control Panel'sDefault =values, not re-grepped in IniFileSettings.cpp. - The exact contents of the Account dialog "Sieve", "Folders" and "Directory" tabs beyond the COM properties they write (
SieveScript,ADDomain,ADUsername) were not read line by line. - Whether the External setup "Cannot tell" logic and the DNS-records checks behave correctly on a remote session was not exercised; the code states the intent (ExternalSetupView.cs:42-49; DnsRecordsView.cs:326-327).
- README.md:146 says the Control Panel does not need the
admintoolscomponent; consistent with late binding in ServerSession.cs but not tested on a machine without the type library.
hMailServer 6.3.8, the latest release (2 November 2026, schema 6108) · AGPL-3.0-or-later · Repository · Mirror on GitHub · Report a documentation error (a GitLab issue naming the page)
Home — full index
Start here
1. Install and run
- Before You Install
- Installing hMailServer
- Installing on Linux
- Running in a Container
- Profiles and Environment
- The Control Panel
- The Control Deck
- Your First Domain and Mailbox
- Connecting a Mail Client
- The Webmail
- DNS for Your Domain
- Migration
2. Secure it
- Encryption and Certificates
- Database TLS
- Encryption for People
- Stopping Spam
- Stopping Viruses
- Security Hardening
- Secure Defaults
- The Service Account
- Secrets at Rest
- Sign-in and Identity
- Security Policy
3. Operate it
- Monitoring and Health
- The SNMP Agent
- Backup and Restore
- Message Storage
- Compliance and eDiscovery
- Troubleshooting
- Diagnosing Stalled Mail
- Relocating an Installation
- Upgrading hMailServer
- Upgrading Guide
- The Update Feed
- Migrating the Database Backend
- High Availability Runbook
- Warm Standby
- Runbooks Digest
4. Extend it
- Rules and Sieve
- Aliases Lists and Public Folders
- Rooms and Equipment
- Mailing Lists
- Routes and Relays
- Mail In to a Webhook
- Outbound Shaping
- The COM API and Scripting
- Event Scripts
- The REST API
- Command Line
- 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
- Settings Reference
- Settings Overview
- Capabilities and Configuration
- Control Panel Reference
- Control Panel Pages
- Ports Reference
- Changes-Since-6210
- Version-History-to-6210
- Glossary
About this wiki
- hMailServer 6.3.8 is the latest release (2 November 2026, schema 6108)
- Pages say since 6.3.4 where a feature is new in it
- AGPL-3.0-or-later
- Repository, the one place the project is worked on
- Its mirror on GitHub, since 18 October 2026, with no Issues
- Questions: a GitLab issue with the Question template, GitHub Discussions Q&A, or the forum
- Report a documentation error: a GitLab issue naming the page