Trusted senders
A message from someone the recipient knows is rarely spam, even when its content resembles spam. Short replies, messages from infrequent correspondents and automated notices from services the recipient uses all look suspicious to a content filter, and all are mail the recipient wants.
Stalwart uses two signals of an existing relationship to keep such messages out of the Junk folder. The first is that the sender is in the recipient’s address book. The second is that the message continues a conversation in which the recipient has written. Both are configured on the SpamSettings singleton, found in the WebUI under Settings › Spam Filter › General.
Inbox override
Section titled “Inbox override”The override is applied when a message is delivered to a local mailbox, separately for each recipient. It applies only to messages that the spam filter has classified as spam. When one of the conditions below holds for the recipient, the message is delivered to the inbox instead of the Junk folder, and its X-Spam-Status header reads No with the reason that applied:
| Field | Default | Condition | X-Spam-Status |
|---|---|---|---|
trustContacts | enabled | The first address of the From header is in one of the recipient’s address books, is not the recipient’s own address, and the sender is authenticated. | No, reason=card-exists |
trustReplies | enabled | The message belongs to a conversation thread that contains a message in the recipient’s Sent folder. | No, reason=trusted-reply |
The override changes only where the message is filed. The score is unchanged, and so are the X-Spam-Result and X-Spam-Score headers. It also cannot rescue a message that never reaches delivery: a message refused by the reject threshold, or dropped by the discard threshold at SMTP time, is not delivered at all, so no override can apply to it.
Authentication of contacts
Section titled “Authentication of contacts”An address book entry alone would be easy to abuse, because anyone can put a contact’s address in the From header. The address-book check therefore also requires the sender to be authenticated. The sender counts as authenticated when the message passed DMARC for the From domain, or was submitted by an authenticated user of the server. A message that merely claims a contact’s address in its From header, without passing DMARC, is not trusted.
Conversation threads
Section titled “Conversation threads”The thread check has no authentication condition. It relies instead on the message being part of a conversation that the recipient took part in. Stalwart determines that from the message’s In-Reply-To and References headers and its subject.
Learning from overrides
Section titled “Learning from overrides”A message that the filter classified as spam but that a trusted-sender rule delivered to the inbox was probably misclassified. That mistake is worth feeding back. When the statistical classifier is enabled, such a message can be stored as a ham sample, so that the classifier learns from it.
Each rule has its own switch on the SpamClassifier singleton: learnHamFromCard for the address-book rule, and learnHamFromReply for the thread rule. Automatic learning describes the other sources of samples.
Exempting a sender, domain or server
Section titled “Exempting a sender, domain or server”The trusted-sender rules act per recipient, and only after the message has been scored. Mail that should be exempt for every recipient needs a different mechanism, and the right one depends on what identifies the mail.
A domain whose mail is authenticated belongs in the trusted domains list. Messages whose From domain is in the list and that pass DMARC receive TRUSTED_DOMAIN, which scores -7.0.
A sender address, domain or IP address can be favoured with a rule that adds a local tag, together with a negative score for that tag. For example, a rule of the Any variant with the condition if_then(remote_ip == '192.0.2.10', 'LOCAL_TRUSTED_RELAY', false), and a SpamTag scoring LOCAL_TRUSTED_RELAY at -20, let a known relay’s mail through unless other evidence is overwhelming. Because the tag only lowers the score, the rest of the filter still runs on such mail.
A server whose mail should not be filtered at all is excluded through the enableSpamFilter expression of the DATA stage. By default, the expression filters every unauthenticated session. Change it so that it returns false for the server, for example is_empty(authenticated_as) && remote_ip != '192.0.2.10'. Messages from that server then carry no X-Spam-Result or X-Spam-Score header, and are never filed in the Junk folder.
Mail submitted by local users needs no exemption, because authenticated users are not filtered by default.