Cursed IMAP forwarding service.
- harden against disconnects etc.
- ensure unsolicited EXISTS are picked up/check EXISTS races
- clean shutdown
- obviously optimizable part:
if x { flag y } else { flag z }
=> CTE.
Add the repository to your flake inputs:
inputs.recogedor.url = github:kivikakk/recogedor;
Add the NixOS module exposed by the flake:
nixosSystem {
# ...
modules = [
# ...
recogedor.nixosModules.${system}.default
];
}
Configure your system to use recogedor:
services.recogedor = {
enable = true;
settings = lib.importTOML ./recogedor.toml;
};
Configure a source and one or more destination mailboxes. imap
is currently the only supported
type
. TLS is always used. host
is used for SNI. The ip
can be specified manually.
The source defines the list of folders to monitor. Mail items are appended to the corresponding folder on the destination side.
The process script is a Lisp. I'm terribly sorry. One or more sexps define the action to be taken on each mail item. You must implement your own idempotency method. Recogedor will rescan the entire source INBOX on startup and every time it's woken from IDLE.
Builtin names are unadorned symbols. Flags, recipient patterns, and destinations are strings. Statement and condition forms are cons cells where the car identifies the builtin.
The following statement forms are defined:
(if C T E)
-- evaluate the condition C and execute statement T if true, E otherwise. E may be omitted.(do ...)
-- execute the statements following.(halt!)
-- stop processing this mail item.(append! D)
-- append this mail item to destination D.(flag! F)
-- set the flag F on the mail item.(delete!)
-- delete the mail item on the source.
The following condition forms are defined:
(or C*)
-- true if any C is true.(flagged F)
-- true if the mail item has the flag F.(received-by R)
-- true if any recipient in the mail item's envelope matches the recipient pattern R.
Recipient patterns consist of an optional user part, an optional plus part, and an optional host
part. At least one part must be specified. A recipient matches a recipient pattern if all parts
defined in the pattern are case-insensitive equal to the corresponding parts of the recipient. The
+
character is not considered part of the plus part.
The syntax is roughly defined as follows: (user)?(+plus)?@(host)?
. Note that a recipient pattern
always contains an @
symbol. Examples follow:
abc@def.com
-- matchesabc@def.com
andABC+X@DEF.COM
.+@def.com
-- matchesabc@def.com
andxyz@def.com
. Does not matcha+b@def.com
.+debug@
-- matcheshello+debug@world.com
andx+debug@i.net
.support@
-- matchessupport@nyonk
andsupport+123@shomk
.
Forward new mail received on one Fastmail account with multiple aliases to two different local accounts. Mail is flagged to avoid double handling. Mail is flagged after appending to fail "safe" -- an untimely power outage will result in double appending, not zero appending.
[src]
type = "imap"
host = "imap.fastmail.com"
port = 993
user = "fox@den.com"
pass = "abc123"
folders = ["INBOX", "Spam"]
[dest.fox]
type = "imap"
host = "my.mx.com"
ip = "127.0.0.1"
port = 993
user = "fox@den.com"
pass = "ghi789"
[dest.wolf]
type = "imap"
host = "my.mx.com"
ip = "127.0.0.1"
port = 993
user = "wolf@den.com"
pass = "jkl012"
[process]
script = """
(if (flagged "Recogido") (halt!))
(if
(or
(received-by "fox@den.com")
(received-by "s.fox@foxden.net"))
(do
(append! "fox")
(flag! "Recogido"))
(do
(append! "wolf")
(delete!)))
"""
- Unit tests? Just design and write it correctly the first time.
Copyright (c) 2023, Asherah "Charlotte" Connor.
Licensed under the Zero-Clause BSD License.