<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Settings: what is not stock, when a save takes effect, and the three levels]]></title><description><![CDATA[<p dir="auto">This topic is about the settings themselves, whichever interface you use: where a setting is stored, which of yours are not what 6.3.4 ships with, when a saved value is in effect, and how the twenty-seven settings a domain or an account may hold its own value of combine with the server's. The one thing to know first: since 6.3.4 the database is the settings store. A <code>[Settings]</code> line edited by hand in <code>hMailServer.ini</code> changes nothing; at the next start the server uses the stored value, names the key in the error log as <code>HM5804</code>, and, where the service may write the file, puts the line back. Everything below describes 6.3.4 unless it says otherwise; a server on 6.3.3 still reads the file and applies a change at the next start.</p>
<h3><a class="anchor-offset" name="two-stores-and-how-a-setting-is-changed"></a>Two stores, and how a setting is changed</h3>
<p dir="auto"><strong>The table <code>hm_settings</code>.</strong> Everything the COM <code>Settings</code> object has always carried, such as the anti-spam thresholds and the delivery options. Since 6.3.4 every new setting goes here, and no key is added to <code>[Settings]</code>. 6.3.4 added 193 rows for its features.</p>
<p dir="auto"><strong>The <code>[Settings]</code> keys.</strong> 241 keys read by the settings loader, plus <code>UseLanguage</code>, read per call. On 6.3.3 they live in the file, mirrored into <code>hm_inisettings</code>. Since 6.3.4 (schema 6042) <code>hm_inisettings</code> is the store and the file's section is a copy, which the server keeps current where the service may write the file.</p>
<p dir="auto"><strong>Where the service cannot write the file, the copy goes stale.</strong> That is a new Windows installation, whose service runs as <code>NT SERVICE\hMailServer</code>, and a Linux package installation, where <code>/etc/hmailserver/hMailServer.ini</code> is <code>0640 root:hmailserver</code>. There the copy is not refreshed and an edited line is not put back; the database's values are still the ones used. The server reports this once a start in the application log, not as an error, and <code>ServiceAccount.md</code> says the same of the Linux packages; the wiki's Installing on Linux page names <code>HM5806</code> at a save and <code>HM5803</code> at every start for them instead. On such a server read a setting from the store, not from the file.</p>
<p dir="auto"><strong>The migration is the first start.</strong> A key the table has never seen is adopted with the file's value, and there is nothing to run by hand. A line edited after the old server last started, including one edited to prepare the upgrade, is taken for an edit and put back, so make such a change after upgrading. A 6.3.3 server refuses a database at schema 6042 or later with <code>HM5011</code>; see <a href="/topic/28193">Upgrading to 6.3.4</a>.</p>
<p dir="auto"><strong>What stays in the file.</strong> <code>[Database]</code>, <code>[Directories]</code>, <code>[Security]</code> and <code>[GUILanguages]</code> are the bootstrap, read before the database is open and never in the store. <code>[LDAP]</code>, <code>[SendingLimits]</code> and <code>[SendingLimitsOverrides]</code> stay in the file. <code>PasswordPepper</code> is kept in the file only, never in the database and never in a backup. <code>[SettingsOverride]</code> is the one way to make the file win, for a database that is unreachable or holds a value the server will not start on: a key written there is applied over whatever is stored and named in the error log as <code>HM5807</code> at every start, because no page shows it and no backup carries it. Storing a value for a key an override shadows is accepted and reported as <code>HM5808</code>.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Surface</th>
<th>Set a <code>[Settings]</code> key</th>
<th>Return it to the default</th>
</tr>
</thead>
<tbody>
<tr>
<td>Control Panel (Windows only)</td>
<td>the key's editor, written over COM even on the server itself</td>
<td>No. Clearing a box stores an empty value, which a number reads as <code>0</code></td>
</tr>
<tr>
<td>REST</td>
<td><code>PUT /api/v1/settings/ini/{name}</code> with <code>{"value": "..."}</code></td>
<td><code>DELETE /api/v1/settings/ini/{name}</code></td>
</tr>
<tr>
<td><code>hmctl</code>, over REST</td>
<td><code>hmctl ini set &lt;name&gt; &lt;value&gt;</code></td>
<td><code>hmctl ini delete &lt;name&gt;</code></td>
</tr>
<tr>
<td>PowerShell module</td>
<td><code>Set-HmIniSetting</code></td>
<td>none</td>
</tr>
<tr>
<td>COM (Windows only)</td>
<td><code>Settings.SetIniSetting(name, value)</code></td>
<td><code>Settings.DeleteIniSetting(name)</code></td>
</tr>
<tr>
<td>Linux command line, as root</td>
<td><code>hmailserver --set-setting NAME=VALUE</code>, with no listener running. A secret's value is refused on the command line: give the name alone and type the value at the prompt</td>
<td>none</td>
</tr>
<tr>
<td>Control Deck</td>
<td>only <code>SmtpTarpitCount</code>, <code>SmtpTarpitDelaySeconds</code>, <code>UseLanguage</code> and <code>RewriteEnvelopeFromWhenForwarding</code></td>
<td>none</td>
</tr>
</tbody>
</table>
<p dir="auto">The REST ini routes take the administrator password only; an API key of any scope is refused. Since 6.3.4 a setting the environment names, as <code>HM_SETTING_&lt;key&gt;</code> or <code>HM_PROPERTY_&lt;name&gt;</code> (<a href="/topic/28231">configuration from the environment</a>), refuses an administrator's change, 409 over REST, until a start without the variable.</p>
<h3><a class="anchor-offset" name="what-this-server-has-changed-from-stock"></a>What this server has changed from stock</h3>
<p dir="auto"><strong>Since 6.3.4.</strong> One list of every setting whose value is not the one this version ships with, with the shipped value beside it. The example in <code>ChangedFromStock.md</code>:</p>
<pre><code class="language-text">STORE     NAME                       VALUE           DEFAULT
ini       LogLevel                   5               9
ini       MaxLogLineLen              2000            500
ini       SMTPDMaxTimeout            600             1800
ini       OAuth2HmacSecret           (set)
ini       DnsServer                  10.0.0.1 (forced from [SettingsOverride])
database  smtpnoofretries            6               4
database  maxsmtpconnections         200             0

7 of 391 settings are not what this version ships with.
</code></pre>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Where</th>
<th>What to ask</th>
</tr>
</thead>
<tbody>
<tr>
<td>Control Deck</td>
<td><strong>Changed from stock</strong>, in the navigation beside Settings</td>
</tr>
<tr>
<td>REST</td>
<td><code>GET /api/v1/settings/changed</code></td>
</tr>
<tr>
<td>Command line</td>
<td><code>hmctl config changed</code></td>
</tr>
<tr>
<td>PowerShell</td>
<td><code>Get-HmChangedSetting</code></td>
</tr>
<tr>
<td>COM</td>
<td><code>Settings.GetChangedFromDefault</code></td>
</tr>
</tbody>
</table>
<p dir="auto">The REST route and the COM call answer the same document. <code>store</code> is <code>ini</code> (<code>hm_inisettings</code>) or <code>database</code> (<code>hm_settings</code>).</p>
<p dir="auto"><strong>What "default" means.</strong> The value the server behaves as though the setting has when nothing has been stored for it, not what a fresh installation's files contain. <code>hMailServer.ini</code> ships with lines the packaging wrote, such as <code>RestApiBindAddress=127.0.0.1</code>, and a line holding the shipped value is not a change; one holding another value is listed.</p>
<p dir="auto"><strong>An upgraded installation lists more than a new one.</strong> <code>database</code> defaults are what a database created by this version holds. An installation upgraded from an old schema got its values from the upgrade scripts of the time, and where those differ (<code>maxmessagesize</code>, <code>usecache</code>, <code>protocolimap</code>, <code>smtpallowincorrectlineendings</code> and half a dozen more) the older installation is genuinely different and is listed. A row nothing reads any more (<code>useordb</code>, <code>usespamhaus</code>, <code>tarpitcount</code>, <code>filters</code>, <code>imapport</code>, <code>relaymode</code>) is not reported at all.</p>
<p dir="auto"><strong>The marks on an entry.</strong></p>
<ul>
<li><code>secret</code>: a setting whose name says its value is a secret is listed by name, with <code>(set)</code> or empty, and never shown. A key file, such as <code>RestApiPrivateKeyFile</code>, is a path and is shown.</li>
<li><code>known</code> false: the server holds a value and ships no default for it, such as a key stored for a script of your own. <code>hmctl</code> prints <code>(none: this server does not read it)</code>.</li>
<li><code>overridden</code>: <code>[SettingsOverride]</code> is forcing the value. Such a key is listed even when neither store holds anything for it; <code>hmctl</code> prints <code>(forced from [SettingsOverride])</code>.</li>
<li><code>environment</code> is <code>variable</code> or <code>file</code>, and <code>hmctl</code> prints <code>(set by the environment)</code>. <code>profile</code> names the setting profile whose apply wrote the value, while the setting still holds it.</li>
</ul>
<p dir="auto"><strong>Which values these are.</strong> The value stored, not the value the server settled on where the two differ: a <code>PasswordHashIterations</code> outside the range the server accepts is reported as <code>HM5561</code> and the built-in work factor used; an unusable <code>PreferredHashAlgorithm</code> is reported as <code>HM5528</code> (or <code>HM5607</code>, for Argon2id on a build whose OpenSSL has none).</p>
<p dir="auto"><strong>Who may see it.</strong> The administrator password, and nothing else. An API key of any scope is refused with a 401, and an account holding an administrative role, an <code>auditor</code> included, with a 403, because the list includes commands the server runs: <code>AutoBanCommand</code> runs as the service account. The feature changes nothing. It does not compare two servers (two <code>hmctl config changed --json</code> answers and <code>diff</code> do), and it does not say when or by whom a setting was changed; <a href="/topic/28273">the audit trail</a> does (<code>GET /api/v1/audit?object_type=setting</code>).</p>
<h3><a class="anchor-offset" name="when-a-saved-setting-takes-effect"></a>When a saved setting takes effect</h3>
<p dir="auto"><strong>Since 6.3.4.</strong> Until then every <code>[Settings]</code> key was latched when the service started. Now a save publishes: the store takes the value, the server rebuilds its settings from the rows, and every key whose readers can take a new value is in effect when the save returns, whichever door saved it. Every key carries one of three marks:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Mark</th>
<th>Keys</th>
<th>What it means</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>now</code></td>
<td>211</td>
<td>A save applies it</td>
</tr>
<tr>
<td><code>reinitialize</code></td>
<td>28</td>
<td>Bound into something the servers build when they start, so it waits for a reinitialise: <strong>Apply now</strong> in the Control Panel or the Deck, <code>POST /api/v1/server/reinitialize</code>, or <code>Application.Reinitialize</code> over COM</td>
</tr>
<tr>
<td><code>restart</code></td>
<td>31</td>
<td>Read once per process: 2 <code>[Settings]</code> keys and the 29 bootstrap keys (20 <code>[Database]</code>, 5 <code>[Directories]</code>, 3 <code>[Security]</code>, 1 <code>[GUILanguages]</code>)</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>The 28 that wait for a reinitialise.</strong></p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>What is rebuilt</th>
<th>Keys</th>
</tr>
</thead>
<tbody>
<tr>
<td>The REST listener</td>
<td><code>RestApiBindAddress</code>, <code>RestApiPort</code>, <code>RestApiCertificateFile</code>, <code>RestApiPrivateKeyFile</code></td>
</tr>
<tr>
<td>The metrics listener</td>
<td><code>MetricsServerBindAddress</code>, <code>MetricsServerPort</code>, <code>MetricsServerCertificateFile</code>, <code>MetricsServerPrivateKeyFile</code>, <code>MetricsServerAuthPassword</code>, <code>MetricsServerAuthToken</code>, <code>MetricsServerAuthUsername</code></td>
</tr>
<tr>
<td>The web-services listener</td>
<td><code>WebServicesBindAddress</code>, <code>WebServicesHttpPort</code>, <code>WebServicesHttpsPort</code>, <code>WebServicesCertificateFile</code>, <code>WebServicesPrivateKeyFile</code></td>
</tr>
<tr>
<td>The ManageSieve listener</td>
<td><code>ManageSieveServerBindAddress</code>, <code>ManageSieveServerPort</code></td>
</tr>
<tr>
<td>The SSL contexts of the SMTP, IMAP, POP3 and ManageSieve listeners and the outbound client</td>
<td><code>TlsCipherSuites13</code>, <code>TlsKeyExchangeGroups</code>, <code>TlsSessionCacheSize</code>, <code>TlsSessionTicketsEnabled</code>, <code>TlsSessionTimeoutSeconds</code>, <code>TlsTicketKeyRotationSeconds</code></td>
</tr>
<tr>
<td>ACME, the database pool, the fetch queue</td>
<td><code>AcmeEnabled</code>, <code>AcmeCertificateDirectory</code>, <code>DatabaseStatementTimeout</code>, <code>MaxNumberOfExternalFetchThreads</code></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>The 2 that wait for a restart</strong> are <code>ServiceAccountName</code> and <code>ServiceAccountPassword</code>, which are retired: since 6.3.4 <code>hMailServer.exe /Register</code> takes the account from its command line alone, and a stored value is shown as pending until the next start. The bootstrap keys are never in the store, so none is ever pending.</p>
<p dir="auto"><strong>Some keys are <code>now</code> because a subscriber re-latches them.</strong> <code>MaxSubmissionsPerIPPerMinute</code> and <code>MaxOutboundPerDestinationPerMinute</code> start each limit's one-minute window again, so a saved limit counts from when it was saved. A cache of data is not a setting: a changed <code>DNSServer</code> is used for the next lookup, and an answer already cached stays until its TTL runs out.</p>
<p dir="auto"><strong>Pending.</strong> A <code>reinitialize</code> or <code>restart</code> key whose stored value is not the value the server is running on is pending. The list is recomputed at every request and never remembered, so a value put back before anything applied it is not pending.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Where</th>
<th>What</th>
</tr>
</thead>
<tbody>
<tr>
<td>REST</td>
<td><code>GET /api/v1/server/settings/pending</code> answers <code>[{name, stored, running, applies, secret}]</code>, and <code>applies</code> and <code>pending</code> come on every <code>/api/v1/settings/ini/{name}</code> answer. The administrator password's route</td>
</tr>
<tr>
<td>COM</td>
<td><code>Settings.IniSettingApplies(name)</code>, <code>Settings.IniSettingAppliesAll</code>, <code>Settings.PendingIniSettings</code></td>
</tr>
<tr>
<td>Control Panel</td>
<td><strong>Applies on save</strong>, <strong>After reinitialize</strong> or <strong>After a restart</strong> under each field kept in the store, and a pending bar with <strong>Apply now</strong></td>
</tr>
<tr>
<td>Control Deck</td>
<td>The same words as a badge, and <strong>Apply now</strong> above its Settings view</td>
</tr>
</tbody>
</table>
<p dir="auto">A name the loader does not read (<code>UseLanguage</code>, a key a script of your own reads, a misspelling) has no mark: COM's <code>IniSettingApplies</code> refuses it and REST answers <code>applies: null</code>.</p>
<p dir="auto"><strong>Apply now is a reinitialise.</strong> Every service stops and starts again in place, which takes every <code>reinitialize</code> key and not a <code>restart</code> key. It asks first. A reinitialise ends maintenance mode, and <code>POST /api/v1/server/reinitialize</code> answers <code>{"reinitializing": true, "drained": true}</code> when it ended a drain. The Deck's session ends with the REST listener it was using; the Control Panel's COM session survives.</p>
<p dir="auto"><strong>What a save does not do.</strong> It does not re-read the bootstrap sections or <code>[SettingsOverride]</code>; a reinitialise or a start re-reads the override section and announces it as <code>HM5807</code>. It does not reconcile the file against the table; that is a start's and a reinitialise's only. And a value stored by another process (another node on the same database, or <code>hmailserver --set-setting</code> while the service runs) reaches this server at the next save here, a reinitialise or a restart, because nothing watches the table. <code>hmctl</code> has no pending verb.</p>
<p dir="auto"><strong>On Linux</strong> the regression fixture alone proves the marks, with the three COM members answered over REST; the internal tester that swaps settings under load does not run there.</p>
<h3><a class="anchor-offset" name="one-value-three-levels"></a>One value, three levels</h3>
<p dir="auto"><strong>Since 6.3.4</strong> (schema 6088). Twenty-seven settings may be set for the server, for a domain and for an account, and every place that shows one shows what is in effect and where it came from. For an account: its own value, else its domain's, else the server's. Every setting on the list is exactly one kind:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Kind</th>
<th>How many</th>
<th>The rule</th>
<th>Who sets a level below the server</th>
</tr>
</thead>
<tbody>
<tr>
<td>Limit</td>
<td>15</td>
<td>A level below may tighten the level above and never loosen it. A looser value is refused when it is written; a value the level above has since tightened past is capped when it is read</td>
<td>Anybody who administers that level: a domain administrator, a key restricted to the domain</td>
</tr>
<tr>
<td>Gate</td>
<td>4</td>
<td>The deepest level that holds a value wins, either way</td>
<td>The server administrator alone; a domain-restricted key is refused with 403</td>
</tr>
<tr>
<td>Preference</td>
<td>8</td>
<td>The deepest level that holds a value wins</td>
<td>The domain's administrators, and a domain-restricted key</td>
</tr>
</tbody>
</table>
<p dir="auto">The last column is the rule for the levels held in <code>hm_settingoverrides</code>. A field the domain already had keeps the authority it had, whatever its kind: the domain's maximum message size and the domain's retention are the server administrator's.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Kind</th>
<th>Settings</th>
</tr>
</thead>
<tbody>
<tr>
<td>Limits</td>
<td><code>max_message_size_kb</code>, <code>session_idle_seconds</code>, <code>session_lifetime_seconds</code>, <code>session_one_per_device</code>, <code>session_bind_to_address</code>, <code>quota_grace_percent</code>, <code>quota_send_stop_percent</code>, <code>recall_days</code>, <code>recover_deleted_days</code>, <code>sending_max_messages</code>, <code>sending_max_recipients</code>, <code>reader_fetch_accounts_max</code>, <code>reader_sender_addresses_max</code>, <code>reader_masked_addresses_max</code>, <code>reader_offline_days_max</code></td>
</tr>
<tr>
<td>Gates</td>
<td><code>plus_addressing_enabled</code>, <code>openpgp_portal_enabled</code>, <code>zero_access_allowed</code>, <code>directory_user_editable</code></td>
</tr>
<tr>
<td>Preferences</td>
<td><code>quarantine_digest</code>, <code>quarantine_digest_hour</code>, <code>external_tag_subject</code>, <code>external_tag_header</code>, <code>impersonation_action</code>, <code>quota_warning_percent</code>, <code>country_policy</code>, <code>message_retention_days</code></td>
</tr>
</tbody>
</table>
<p dir="auto">A server setting not on the list is the server's alone: its name is refused on the domain and account routes (400, <code>unknown field</code>) and by COM's <code>SettingOverride</code>. Of the <code>[Settings]</code> keys only <code>QuotaWarningPercent</code> has levels.</p>
<p dir="auto"><strong>Where each level is held.</strong> A field the domain or the account already had, such as the domain's <code>MaxMessageSize</code> or <code>MessageRetentionDays</code>, stays where it was, with the meaning it always had; its 0 or -1 is the level holding nothing. The rest are rows of <code>hm_settingoverrides</code>, where no row means "take the level above". An owner's rows are cached for sixty seconds; every write through the interfaces drops the cache at once, and so does <code>POST /api/v1/settings/cache/clear</code> or COM <code>Cache.Clear</code>. A row put in by hand that the interfaces would refuse is treated as holding nothing and reported as <code>HM7311</code>. Nothing changes for a domain or an account that holds no value of its own.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Where</th>
<th>What</th>
</tr>
</thead>
<tbody>
<tr>
<td>REST</td>
<td><code>GET /api/v1/settings/levels</code> lists the twenty-seven. <code>GET /api/v1/domains/{domain}</code> and <code>GET /api/v1/accounts/{address}</code> answer <code>&lt;name&gt;_effective</code> and <code>&lt;name&gt;_source</code>, and <code>&lt;name&gt;</code> where the level is held in the overlay. For a level held in the overlay a <code>PUT</code> takes a value of the setting's own JSON type, and <code>null</code> makes it inherit; for a level held in a field of its own <code>null</code> leaves it unchanged, and the field's own 0 or -1 is "take the level above"</td>
</tr>
<tr>
<td>COM (Windows only)</td>
<td><code>Domain.SettingOverride(name)</code> and <code>Account.SettingOverride(name)</code>, an empty string for "take the level above", written at once and not by <code>Save</code>; <code>EffectiveSetting(name)</code> and <code>EffectiveSettingSource(name)</code></td>
</tr>
<tr>
<td><code>hmctl</code></td>
<td><code>hmctl domain set &lt;domain&gt; &lt;name&gt; &lt;value\|inherit&gt;</code> and <code>hmctl account set &lt;address&gt; &lt;name&gt; &lt;value\|inherit&gt;</code></td>
</tr>
<tr>
<td>Control Panel (Windows only)</td>
<td>A <strong>Levels</strong> tab on the domain and account dialogs, with "In effect: ..., from the ..." beside each setting and <strong>Save levels now</strong></td>
</tr>
<tr>
<td>Control Deck</td>
<td>The same card in its domain and account editors</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>A saved level applies at once</strong>, at every level and from every door, because the resolver is asked when the value is used (at <code>MAIL FROM</code>, when a session is checked) and never latched.</p>
<p dir="auto"><strong>Deleting, backing up and moving.</strong> Deleting an account or a domain deletes its rows; a delete that cannot remove them is reported as <code>HM7310</code> for a domain and <code>HM6109</code> for an account. The XML backup carries the rows, and on restore a row the build refuses is left out and reported as <code>HM7312</code>. A mailbox moved to another domain keeps its own values.</p>
<p dir="auto"><strong>What is thinner than it sounds.</strong></p>
<ul>
<li>Attachment blocking, web push, passkeys and account recovery have no levels.</li>
<li>The domain's session seconds and switches and its quota grace and send-stop shares could always be set looser than the server's and still can; the ceiling binds the account below them.</li>
<li>The maximum message size is resolved at <code>MAIL FROM</code> and at IMAP <code>APPEND</code>; the EHLO <code>SIZE</code> advertisement, the webmail's own send and the send API stay the server's.</li>
<li>The session policies are the browser sessions' (the webmail, the portal, the Deck); IMAP, POP3 and SMTP sessions have none.</li>
<li><code>country_policy</code> cannot be set to empty over COM, where an empty string means "take the level above"; REST's <code>""</code> does it.</li>
<li>Twelve of the twenty-seven are proved by what the account and its domain answer rather than by driving the behaviour per account, and the levels' own regression fixture is Windows-only.</li>
</ul>
<h3><a class="anchor-offset" name="when-a-setting-appears-to-do-nothing"></a>When a setting appears to do nothing</h3>
<ol>
<li>Is it pending? A <code>reinitialize</code> key waits for <strong>Apply now</strong> and a <code>restart</code> key for a service restart.</li>
<li>Was it typed into <code>hMailServer.ini</code>? The stored value wins and <code>HM5804</code> names the key. Store it instead.</li>
<li>Is the key spelled exactly as the code reads it, and is a boolean literally <code>1</code>? An unknown key is the default, and only <code>1</code> is true: <code>2</code>, <code>yes</code> and <code>true</code> all read as false.</li>
<li>Does it need a companion? <code>SRSEnabled</code> needs <code>SRSSecret</code>, ACME needs <code>AcmeDomains</code>, autoconfig needs <code>WebServicesHttpPort</code> or <code>WebServicesHttpsPort</code>, and MTA-STS hosting needs the HTTPS one.</li>
<li>Does the error log show <code>HM5807</code> or <code>HM5808</code>? A <code>[SettingsOverride]</code> section is forcing a value.</li>
</ol>
<h3><a class="anchor-offset" name="where-to-read-more"></a>Where to read more</h3>
<ul>
<li>The tour: <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Settings-Overview" rel="nofollow ugc">https://gitlab.com/hmailserver/hmailserver/-/wikis/Settings-Overview</a>. Every key with its default, validation and mark: <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Settings-Reference" rel="nofollow ugc">https://gitlab.com/hmailserver/hmailserver/-/wikis/Settings-Reference</a>. Where the two disagree, the reference is generated from the code and is right.</li>
<li>The three documents behind this topic: <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/ChangedFromStock.md" rel="nofollow ugc">https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/ChangedFromStock.md</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/SettingsApply.md" rel="nofollow ugc">https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/SettingsApply.md</a> and <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/SettingLevels.md" rel="nofollow ugc">https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/SettingLevels.md</a></li>
<li>The public documentation's settings chapter: <a href="https://www.progressiverobot.com/hmailserver-documentation/#21-settings-reference-hmailserverini" rel="nofollow ugc">https://www.progressiverobot.com/hmailserver-documentation/#21-settings-reference-hmailserverini</a></li>
<li>On this forum: <a href="/topic/28223">the Control Panel on Windows</a>, <a href="/topic/28265"><code>hmctl</code> and the PowerShell module</a>, <a href="/topic/28245">the <code>hmailserver</code> command line</a>, <a href="/topic/28192">the Control Deck</a>, <a href="/topic/28193">Upgrading to 6.3.4</a> and <a href="/topic/28189">hMailServer on Linux</a>.</li>
</ul>
]]></description><link>https://www.hmailserver.co.uk/topic/28222/settings-what-is-not-stock-when-a-save-takes-effect-and-the-three-levels</link><generator>RSS for Node</generator><lastBuildDate>Fri, 06 Nov 2026 09:05:52 GMT</lastBuildDate><atom:link href="https://www.hmailserver.co.uk/topic/28222.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 27 Sep 2026 19:04:13 GMT</pubDate><ttl>60</ttl></channel></rss>