Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save thedaveCA/2a4f254ba1d2a7ee658d1864c5d4feb5 to your computer and use it in GitHub Desktop.
Save thedaveCA/2a4f254ba1d2a7ee658d1864c5d4feb5 to your computer and use it in GitHub Desktop.
### Label messages with ${domain}.${mailbox}
#
# This is overkill, but read the preamble and then look for the "configuration"
#
### PREAMBLE
#
# Fastmail uses . as a folder separator, and ^ as a literal dot. Ugh.
#
# X-Delivered-To header is used to determine the actual destination of the
# message after alias processing. If you wanted the raw RCPT TO, try:
# if envelope :regex "to" ...
#
# Since there is no loop construct, we repeat the replacement until we get
# bored, then truncate the string with ... (^^^), which is unlikely to occur
#
# Note that Fastmail roots your mailbox at "INBOX.", therefore the initial
# "INBOX." is effectively discarded (from the perspective of the web client).
# tl;dr: If you want a label "example.com" under your inbox, use "INBOX.INBOX."
#
# Fastmail creates mailbox.domain and *@mailbox.domain addresses automatically,
# subdomains are handled as follows:
# [email protected] -> example.com\dave
# [email protected] -> example.com\dave\test
#
# @fastmail.co.uk would be parsed asthough it were [email protected] therefore
# we check for the suffixes we use and adjust the regex accordingly.
# I have no intention of stress-testing Fastmail's sieve implementation by
# importing the entire public suffix list, so you'll have to add your own.
# co.uk and com.au are listed as examples.
#
### CONFIGURATION
# Set to INBOX. to file labels under the inbox, or "" to file at the root.
# Must end with a dot (.) or be completely blank.
set "labelprefix" "INBOX.";
# Set to true to create parent labels, e.g.
# [email protected] -> example.com, example.com\dave, example.com\dave\test
#
# Set to false to only create the most specific label, e.g.
# example.com\dave\test
set "parentlabels" "true";
# List your suffixes here, separated by pipes (|) and escaped dots (\\.)
set "subdomainsplitter" ".*(co\\.uk|com\\.au)$";
### END OF CONFIGURATION
# This is a bit of a hack for when the root domain contains 2 dots.
if header :regex "X-Delivered-to" "${subdomainsplitter}" {
set "subdomainsplitter" "^(.*)@([^.]*)\\.(.*\\..*\\..*)$";
} else {
set "subdomainsplitter" "^(.*)@([^.]*)\\.(.*\\..*)$";
}
# Handle MailFetch, based on no X-Delivered-To and a X-LinkName+X-LinkId
if allof (not exists ["X-Delivered-To"],
header :value "ge" :comparator "i;ascii-numeric" ["X-LinkId"] ["0"],
header :regex "X-LinkName" "(.*@.*)") {
addheader "X-Delivered-To" "${1}";
}
# Extract the mailbox, subdomain(?), and rootdomain from the header
if header :regex "X-Delivered-To" "${subdomainsplitter}" {
set :lower "mailbox" "${1}";
set :lower "subdomain" "${2}";
set :lower "rootdomain" "${3}";
set "subdomainexists" "true";
} elsif header :regex "X-Delivered-To" "^(.*)@(.*)$" {
set :lower "mailbox" "${1}";
set :lower "rootdomain" "${2}";
}
# Replace each dot (.) with a caret (^) in rootdomain
if string :regex "${rootdomain}" "^([^.]*)\\.(.*)$" { set "rootdomain" "${1}^${2}";
if string :regex "${rootdomain}" "^([^.]*)\\.(.*)$" { set "rootdomain" "${1}^${2}";
if string :regex "${rootdomain}" "^([^.]*)\\.(.*)$" { set "rootdomain" "${1}^${2}";
if string :regex "${rootdomain}" "^([^.]*)\\.(.*)$" { set "rootdomain" "${1}^${2}";
if string :regex "${rootdomain}" "^([^.]*)\\.(.*)$" { set "rootdomain" "${1}^${2}";
if string :regex "${rootdomain}" "^([^.]*)\\.(.*)$" { set "rootdomain" "${1}^^^";
}}}}}} # I'm so sorry
# Replace each dot (.) with a caret (^) in mailbox
if string :regex "${mailbox}" "^([^.]*)\\.(.*)$" { set "mailbox" "${1}^${2}";
if string :regex "${mailbox}" "^([^.]*)\\.(.*)$" { set "mailbox" "${1}^${2}";
if string :regex "${mailbox}" "^([^.]*)\\.(.*)$" { set "mailbox" "${1}^${2}";
if string :regex "${mailbox}" "^([^.]*)\\.(.*)$" { set "mailbox" "${1}^${2}";
if string :regex "${mailbox}" "^([^.]*)\\.(.*)$" { set "mailbox" "${1}^${2}";
if string :regex "${mailbox}" "^([^.]*)\\.(.*)$" { set "mailbox" "${1}^^^";
}}}}}} # It isn't my fault, there are no loops in Sieve
# Finally, file the message into the appropriate folder.
if string :is "${subdomainexists}" "true" {
if string :is "${parentlabels}" "true" {
fileinto :copy :create "INBOX.${labelprefix}${rootdomain}";
fileinto :copy :create "INBOX.${labelprefix}${rootdomain}.${subdomain}";
}
fileinto :copy :create "INBOX.${labelprefix}${rootdomain}.${subdomain}.${mailbox}";
} else {
if string :is "${parentlabels}" "true" {
fileinto :copy :create "INBOX.${labelprefix}${rootdomain}";
}
fileinto :copy :create "INBOX.${labelprefix}${rootdomain}.${mailbox}";
}
if header :matches "Subject" "SIEVE Test*"
{
addheader "X-SIEVE-TROUBLESHOOTING" "labelprefix: ${labelprefix} rootdomain: ${rootdomain} subdomain: ${subdomain} mailbox: ${mailbox}";
set "hasmailbox" "Y";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment