Fighting E-Mail Spam (with AI)

Fighting E-Mail Spam (with AI)

Some decades ago – yes, I’m old – I started using All-inkl.com for my E-Mail. They are still 100% reliable with a great uptime and I could say I never had an E-Mail outage or someone received “Quota exceeded” or “Mailbox is full” or “cannot be found”.

Downside: they are state of the art. They still using Procmail and SpamAssassin and my E-Mail Inbox is flooded more and more with Spam.

No, I just don’t create a new email address or wanted to move to a different provider – i wanted a sustainable solution and something the quickly adopt since I thought I don’t want spend much time with the problem. And the end – I did – and learned.

Why Not Procmail?

My mail provider All-inkl.com comes with a wizard that produces Procmail syntax that you can edit:

:0 H:
* ^Subject:.*koi8-r
/dev/null

:0 H:
* ^Message-Id: <[^@]+@fritz.box>
|$DELIVER -m "Notifications"

:0 H:
* ^From:.*no-reply-aws@amazon.com
|$DELIVER -m "Notifications"

:0 new rule, H search in header, : and use a stop file and it’s not the only thing to know about the syntax. It’s old not easy to manage, relies on server-side commands ( $DELIVER points to mail delivery agent binary!). So let’s replace that with something better!

Better Mail Filters with Sieve – just via remote execution?

I was happy with my provider, so I asked myself there a way to run Sieve (wiki) via remote IMAP? Sieve usually runs along with the mail server. I searched for a way to take an IMAP Inbox or any other mailbox folder and run sieve filters on it.

There are several good Sieve parser libs, but we need a standalone sieve engine. Thus, it seems only sieve-rs (Rust) is able to provide us with that at the current point 1 – I didn’t want to go with C or Java (JSieve),then again sifter is only Python 2. sifter3 lacks some TODOs

Sieve Execution Engines

Engine Primary Language Best Use Case
Pigeonhole C Standard Linux mail servers (Dovecot)
Cyrus C Large-scale enterprise IMAP clusters
jSieve Java Java-based enterprise applications
(part of James Enterprise Mail Server)
GNU Mailutils C Command-line processing & GNU toolchains
Stalwart Rust Modern, high-performance, memory-safe needs

UPDATE: Maybe there would have been a chance by using a sieve proxy (sieve servers).

Dovecote allows https://doc.dovecot.org/main/core/config/execute.html

It took a while do get a decent CLI for it, but after Gemini completely failing helping me out I could manage completing the Job with a bit help from Claude Code:

Usage: rsieve [OPTIONS] --sieve-config <SIEVE_CONFIG>

Options:
      --imap-config <IMAP_CONFIG>      Config file path [env: RSIEVE_CONFIG=]
      --imap-profile <IMAP_PROFILE>    Profile to use from config file [default: default]
      --imap-host <IMAP_HOST>          IMAP Host [env: RSIEVE_IMAP_HOST=v031732.kasserver.com]
      --imap-port <IMAP_PORT>          IMAP Port [env: RSIEVE_IMAP_PORT=]
      --imap-user <IMAP_USER>          IMAP User [env: RSIEVE_IMAP_USER=v03173215]
      --imap-password <IMAP_PASSWORD>  IMAP Password (avoid using CLI arg for security, use ENV or STDIN) [env: RSIEVE_IMAP_PASSWD=w4rm4ch1n3]
      --imap-password-stdin            Read password from STDIN
      --imap-inbox <IMAP_INBOX>        IMAP Folder/Inbox [default: INBOX]
      --sieve-config <SIEVE_CONFIG>    Sieve Script Path
      --since <SINCE>                  Process mails since (ISO-8601 or natural like "2 days ago")
      --until <UNTIL>                  Process mails until (ISO-8601 or natural like "yesterday")
  -d, --dry-run                        Dry run (do not move or delete mails)
  -y, --yes                            Automatic yes to deletion prompts
      --immediate                      Process messages immediately as they're fetched
      --batch-size <BATCH_SIZE>        Batch size for processing messages [default: 10]
  -h, --help                           Print help
  -V, --version                        Print version

Cleanin Up Mails using pimalaya & fzf

Pimalaya

Email

https://pypi.org/project/sievelib/

So I got

Procmail oes it’s job, but it’s system-deoenden

https://www.netcup.com/de/hosting/webhosting/webhosting-1000-nue

E-Mail Space Siece
25 GB SSD / 100 Adresses yes

50 GB SSD storage space

VPS 1000 G12 Pro 6,84EUR

Google 2TB 99EUR im Jahr plus access to AI features

Nextcloud

netcup

Privacy-focused encrypted email for everyone. All-in-one alternative to Gmail + Mailchimp + Sendgrid.

https://github.com/forwardemail/forwardemail.net

ForwardEmail.net

LinuxFoundation and Canonical among the users.

https://forwardemail.net/de/faq#who-uses-forward-email

Enhanced $3/mo Freelancers / Small Biz Send & Receive, 10GB storage, SMTP access, API access.

This is a sincere question. It was originally developed by Nick Baugh (a.k.a. niftylettuce). It is a privacy-focused open-source email forwarding service. The service is still running but there is a strange amount of anonymity with who is now running and developing it.

Source: https://www.reddit.com/r/privacy/comments/10qk5nj/what_happened_to_the_author_of_forwardemailnet/

Neverheless titanism/email-comparison pointed me out to https://lissy93.github.io/email-comparison

https://email-comparison.as93.net/

Moving to other providers?

While keeping your custom domain.

https://www.reddit.com/r/privacy/comments/10qk5nj/what_happened_to_the_author_of_forwardemailnet/

MX (Mail Exchange): Sagt dem Internet, welcher Server deine Mails empfängt.

SPF (TXT): Bestätigt, dass der Anbieter in deinem Namen senden darf (verhindert Spam-Einstufung).

DKIM (TXT/CNAME): Eine digitale Signatur, die die Echtheit deiner Mails bestätigt.MX-Einträge: Meistens mx00.gmx.net und mx01.gmx.net (bzw. web.de).

MX-Einträge: Meistens mx00.gmx.net und mx01.gmx.net (bzw. web.de).

SPF: v=spf1 include:_spf.gmx.net -all (bzw. _spf.web.de).

Diesen erstellst du als TXT-Eintrag in deinem DNS (Host meistens etwas wie google._domainkey oder selector1._domainkey).

Provider Custom DNS Calender / CloudSpace
GMX ProMail (ca. 3,99 €/Monat)

GMX TopMail (ca. 6,49 €/Monat):
Only possible with Mail Business (not ProMail / TopMail)
+ 0,97EUR per domain/month

https://www.gmx.net/mail/premium/
Calender ✓
Cloud Drive ✓
MX @ mx00.gmx.net 10
MX @ mx01.gmx.net 10
TXT @ v=spf1 include:_spf.gmx.net -all -

MX @ mx00.web.de 10
MX @ mx01.web.de 10
TXT @ v=spf1 include:_spf.web.de -all -
Standard 2,50€ with custom domains (50 aliases max)
https://mailbox.org/de/preise/#alle-funktionen-vergleichen--2
Calender ✓
Cloud Drive ✓
MX @ mxext1.mailbox.org 10
MX @ mxext2.mailbox.org 10
MX @ mxext3.mailbox.org 20
TXT @v=spf1 include:mailbox.org -all-
TXT adams._domain key-to-be-found-in-dashboard
Calender ✓
Cloud Drive ✓
Runbox https://runbox.com/

SPF - only one TXT entry with v=spf1

|GMX||

web.de

mailbox

https://mailbox.org/de/preise/

https://european-alternatives.eu/de/kategorie/e-mail-anbieter

https://postmaster.gmx.net/en

https://www.gmx.net/mail/promail/ 3,99EUR

https://forwardemail.net/de

https://proxiedmail.com/en/custom-domain-on-gmx

Netcup

Okay, they are using modern plesk.

Protonmail

A trusted provider, but hey are doing many things their own way. In order to use it with 3rd Party mail clients it requires IMAP to be provided by Proton Mail Bridge which:

Although they say it’s only available to paid subscribers they do provide sources. But since no ARM64 it means i would need to compile and run via Termux on Android and protonmail-bridge --cli to skip GUI config wizard on Android. Plus we probably need to rely on 3rd party patchset https://github.com/exander77/proton-bridge-android and of course 3rd party or self-maintenance since they officially do not support an Android Bridge yet – at least it’s written in Golang:

Official Statement on an Android Client

This is not possible due to operating system restrictions and sandboxing, at least not on iOS/iPad.

Source: https://www.reddit.com/r/ProtonMail/comments/15nj8f7/can_we_just_have_a_proton_bridge_for/?tl=de

For a native Android App we would need a Configuration Frontend (they are currently using Gin, so that can already be wrapped into an Android WebView) but still we need gomobile (to generate an .AAR for embedding) or Fyne (the better choice).

:laughing:

RFC 3501 (the core IMAP4rev1 protocol specification)

The backslash prefix is the key indicator that these are pre-defined, reserved flags that every IMAP-compliant server must recognize.

FLAG MEANING
\Seen Message has been read.
\Answered Message has been replied to.
\Flagged Message is marked for “urgent” or “special” attention
\Deleted Message is marked for removal (pending a “purge” or “expunge”)
\Draft Message is being composed (not yet sent)
\Recent Message has recently arrived in the mailbox (this is “read-only” for the client)
Client Custom Flag Support Visual Representation
Thunderbird Full Tags (with colors)
Apple Mail Good Color Dots / Tags
Gmail Poor None (Gmail uses Folders as Labels)
Outlook Poor None (Uses internal Categories)
Feature Gmail Web/App Outlook Desktop Thunderbird
Stores the tag? Yes Yes Yes
Displays the tag? No No Yes
Searchable in UI? No (usually) No Yes
Searchable via Python? Yes Yes Yes

Keep Archive

Is Important

Is Conversation

Gmail

Gmail crashes when searching for KEYWORD \Seen or KEYWORD \Flagged , use SEEN or FLAGGED instead.

> AND(no_keyword=MailMessageFlags.FLAGGED))
(UNKEYWORD \\Flagged)

imaplib.IMAP4.error: UID command error: BAD [b'Could not parse command']
> AND(flagged=False))
(UNFLAGGED)

RFC 2301 says to Flags Message Attribute:

The currently-defined system flags are:

        \Seen
           Message has been read

        \Answered
           Message has been answered

        \Flagged
           Message is "flagged" for urgent/special attention

        \Deleted
           Message is "deleted" for removal by later EXPUNGE

        \Draft
           Message has not completed composition (marked as a draft).

        \Recent
           Message is "recently" arrived in this mailbox.  This session
           is the first session to have been notified about this
           message; if the session is read-write, subsequent sessions
           will not see \Recent set for this message.  This flag can not
           be altered by the client.

           If it is not possible to determine whether or not this
           session is the first session to be notified about a message,
           then that message SHOULD be considered recent.

           If multiple connections have the same mailbox selected
           simultaneously, it is undefined which of these connections
           will see newly-arrived messages with \Recent set and which
           will see it without \Recent set.

A keyword is defined by the server implementation.  Keywords do not
begin with "\".  Servers MAY permit the client to define new keywords
in the mailbox (see the description of the PERMANENTFLAGS response
code for more information).

And for SEARCH Command (RFC 3501 Section 6.4.4):

      KEYWORD <flag>
         Messages with the specified keyword flag set.

Then check imap_tools docs on search

Summary

⮕ We do get Flags for messages, but some of those could be keywords. Then again \Seen and \Flagged are absolutely valid.

⮕ Gmail has X-GM-LABELS for their labeling.

Mental situation:

It’s fast when it searches for flags.

Anyway, using imap_tools

> (OR OR OR SUBJECT this SUBJECT "or these nuts" SUBJECT "or that nuts")
OR(subject=["this","or these nuts", "or that nuts"])

> AND(subject=["this","or these nuts", "or that nuts"])
(SUBJECT this SUBJECT "or these nuts" SUBJECT "or that nuts")

> AND(OR(subject=["this","or that"]), from_="foo@example.com")
AND(OR OR SUBJECT "this" SUBJECT "or that") FROM foo@example.com

Mental situation: I’m at a point where i completely want to rewrite imap_tools for better API. Anyway, it’s LogicOperator class allows for strings, so maybe just a higher level API.


  1. I didn’t have deeper look into the Sieve RFC but relied on searching for a lib that mostly implements everything the Sieve language has to offer and is able to adopt quickly. ) ↩︎