### fdm configuration
### vim:ft=config
###
### All in one replacement for {get,fetch}mail and procmail.
### <http://fdm.sf.net>
###
### Frank Terbeck <ft@bewatermyfriend.org>
### <http://ft.bewatermyfriend.org/comp/data/fdm/fdm.conf.html>
### Last-Modified: Thu Mar  8 17:03:05 2007
###

###########################################################################

### The following strings are replaced in pipe commands and
### maildir/mbox paths:
###   %a: account name
###   %h: user's home directory
###   %n: user's uid
###   %t: action name if performing action
###   %u: name of user
###   %H: current hour (00-23)
###   %M: current minute (00-59)
###   %S: current second (00-59)
###   %d: current day of the month (00-31)
###   %m: current month (01-12)
###   %y: current year
###   %W: current day of the week (0-6, Sunday is 0)
###   %Y: current day of the year (000-365)
###   %Q: current quarter (1-4)

###########################################################################
### Some macros used below.

### where I keep my mail
    $path       = "%h/Mail"

### where I keep my config files
    $cfgdir     = "%h/etc/fdm"

### location of killfile
    $killfile   = "%h/etc/mailnews/killfile"

### spam filter commands
    $com_spam_filter = "spamprobe receive"
    $com_train_good  = "spamprobe good"
    $com_train_spam  = "spamprobe spam"

### some filters use these unix commands:
    $com_sed        = "sed"
    $com_awk        = "awk"
    $com_perl       = "perl"

### spam header expressions
    $header_spam    = "X-SpamProbe"
    $filtered_spam  = "SPAM"
    $filtered_good  = "GOOD"
    $filter_trained = " TRAINED"

### if do_catchall is "yes", all incoming mail will be saved
### to ${catchall_mbox}; useful for testing (so nothing gets lost).
    $do_catchall    = "nope"
    $catchall_mbox  = "%h/catchall.mbox"

### this is used by my archive action.
### Mails older than this (in days) are moved to the archive.
    %max_age    = 30

### zblog <http://zblog.bewatermyfriend.org>
    $com_zblog  = "%h/bin/zblog"

### print from headers (Sender, From, From:, Reply-To:)
### used for killfiling.
    $com_pfh = "${com_awk} '/^(From|From:|Reply-To:|Sender)/{sub(/[^ \\t]*[ \\t]*/,\"\",$0);print};/^\$/{exit 0}'"

### list of headers I don't want.
    $ill_headers = "("
    $ill_headers = "${ill_headers}X-Qmail-Scanner.*|X-SA-Exim.*|X-CR-.*|"
    $ill_headers = "${ill_headers}X-MIME-.*|X-Authentication-.*|"
    $ill_headers = "${ill_headers}X-Mailman-.*|X-Spam-.*|X-MimeOLE|"
    $ill_headers = "${ill_headers}X-Msmail-.*|X-Priority|X-MS-.*|"
    $ill_headers = "${ill_headers}Thread-Topic|Thread-Index|"
    $ill_headers = "${ill_headers}X-OriginalArrivalTime|"
    $ill_headers = "${ill_headers}X-Face|DKIM-Signature|"
    $ill_headers = "${ill_headers}X-IronPort-.*|DomainKey-Signature|"
    $ill_headers = "${ill_headers}X-Rc-.*"
    $ill_headers = "${ill_headers})"

### perl script that filters out unwanted headers
    $com_filter_headers = "${com_perl} -e '\$k=\$e=0;while(<>){if(\$e||m/^$/){\$e=1;print;next;}"
    $com_filter_headers = "${com_filter_headers}if(m/^[ \\t]+/&&\$k){next;}if(m/^${ill_headers}:/i)"
    $com_filter_headers = "${com_filter_headers}{\$k=1;next;}if(\$k){\$k=0;}print;}'"

###########################################################################

### This is used to set the maximum size of a mail. Mails larger than
### this limit are dropped and, if applicable, not deleted from the
### server.
    set maximum-size 128M

### If this option is specified, fdm(1) attempts to delete messages
### which exceed maximum-size, and continue.If it is not specified,
### oversize messages are a fatal error and cause fdm(1) to abort.
   #set delete-oversized

### If this option is specified, fdm(1) does not attempt to create a
### lock file and allows multiple instances to run simultaneously.
   #set allow-multiple

### This sets an alternative lock file. The default is ~/.fdm.lock
### for non-root users and /var/db/fdm.lock for root.
    set lock-file "${cfgdir}/fdm.lock"

### This specifies the locks to be used for mbox locking.  Possible
### types are fcntl, flock, and dotlock. The flock and fcntl types
### are mutually exclusive. The default is flock.
   #set lock-types flock

### This sets the default user to change to before delivering mail,
### if fdmis running as root and no alternative user is specified as
### part of the action or rule.
   #set default-user "hawk"


### This specifies the domains to be used when looking for users with
### the from-headers keyword. The default is the computer's hostname.
   #set domain "bewatermyfriend.org"

### This allows the headers to be examined when looking for users to
### be set. The default is to look only at the "From" and "Cc"
### headers. The headers are case-insensitive.
   #set header

### This instructs fdm to proxy all connections through url. HTTP
### and SOCKS5 proxies are supported at present (URLs of the form
### http://host[:port] or socks://[user:pass@]host[:port]).
### No authentication is supported for HTTP.
   #set proxy

### This option controls what fdm does with mail that reaches the
### end of the ruleset (mail that matches no rules or matches only
### rules with the continue keyword). drop will cause such mail to
### be discarded, and keep will attempt to leave the mail on the
### server.  The default is to keep the mail and log a warning that
### it reached the end of the ruleset.
    set unmatched-mail keep

### This option makes fdm attempt to purge deleted mail from the
### server (if supported) after count mails have been retrieved.
    set purge-after none

### If set, fdm will not insert a 'Received' header into each mail.
   #set no-received

### This specifies the umask(2) to use when creating files. 'user'
### means to use the umask set when fdm is started, or umask may be
### specified as a three-digit octal number.
    set file-umask 077

### This option allows the default group ownership of files and
### directories created by fdm(1) to be specified. 'group' may be a
### group name string or a numeric gid. 'user' does nothing.
    set file-group user

### This controls the maximum time to wait for a server to send data
### before closing a connection. The default is 900 seconds.
    set timeout 900

###########################################################################

### include account information from seperate file.
### it contains lines that look like this:
### account "name" server pop3 "pop3.serv.tld" user "uname" pass "pwd"
    include "${cfgdir}/accounts.conf"

###########################################################################

### simple actions
    action "drop" drop
    action "keep" keep

### zblog
    action "zblog" pipe "${com_zblog} email"
    action "zcomm" pipe "${com_zblog} commentmode"

### killfiling
    action "killfile" maildir "${path}/Trash"

### a mailbox to rule them all
    action "catchall" mbox "${catchall_mbox}"

### spam actions
    action "spam"                 maildir       "${path}/Spam"
    action "train-spam"           pipe          "${com_train_spam}"
    action "train-good"           pipe          "${com_train_good}"
    action "sp-add-header"        add-header    "${header_spam}" "%[command1]"
    action "sp-remove-header"     remove-header "${header_spam}"
    action "sp-add-trained-good"  add-header    "${header_spam}" "${filtered_good}${filter_trained}"
    action "sp-add-trained-spam"  add-header    "${header_spam}" "${filtered_spam}${filter_trained}"

### action for adding Lines: headers
### Current CVS versions can do this themselves.
    action "add-lines-header" add-header "Lines" "%[body_lines]"

### action to remove unneeded headers
    action "remove-ill-headers" rewrite "${com_filter_headers}"

### mark as read in maildirs. this requires /bin/sh to be somewhat POSIXly
### correct. ash, ksh, bash etc. will do; older bourne shells (like /bin/sh
### on OpenSolaris) will not. You'll need to use {base,dir}name with these.
    action "maildir-mark-as-read" exec "mf=\"%[mail_file]\" ; mv \"\${mf}\" \"\${mf%%/*}\"/../cur/\"\${mf##*/}:2,S\""

### archiving action
    action "archive" mbox "${path}/archive/%[maildir]-%yq%Q" compress

### handle mailinglists

### path actions
#{{{
    action "inbox"                      maildir "${path}/Inbox"
    action "debian-announce"            maildir "${path}/debian-announce"
    action "debian-boot"                maildir "${path}/debian-boot"
    action "debian-curiosa"             maildir "${path}/debian-curiosa"
    action "debian-devel"               maildir "${path}/debian-devel"
    action "debian-devel-announce"      maildir "${path}/debian-devel-announce"
    action "debian-mentors"             maildir "${path}/debian-mentors"
    action "debian-news-german"         maildir "${path}/debian-news-german"
    action "debian-outbox"              maildir "${path}/debian-outbox"
    action "debian-policy"              maildir "${path}/debian-policy"
    action "debian-project"             maildir "${path}/debian-project"
    action "debian-pts"                 maildir "${path}/debian-pts"
    action "debian-publicity"           maildir "${path}/debian-publicity"
    action "debian-release"             maildir "${path}/debian-release"
    action "debian-security"            maildir "${path}/debian-security"
    action "debian-vote"                maildir "${path}/debian-vote"
    action "debian-women"               maildir "${path}/debian-women"
    action "openbsd-announce"           maildir "${path}/openbsd-announce"
    action "openbsd-ipv6"               maildir "${path}/openbsd-ipv6"
    action "openbsd-misc"               maildir "${path}/openbsd-misc"
    action "openbsd-ports"              maildir "${path}/openbsd-ports"
    action "openbsd-ports-bugs"         maildir "${path}/openbsd-ports-bugs"
    action "openbsd-ports-security"     maildir "${path}/openbsd-ports-security"
    action "openbsd-security-announce"  maildir "${path}/openbsd-security-announce"
    action "openbsd-tech"               maildir "${path}/openbsd-tech"
    action "openbsd-www"                maildir "${path}/openbsd-www"
    action "openbsd-x11"                maildir "${path}/openbsd-x11"
    action "mutt-dev"                   maildir "${path}/mutt-dev"
    action "mutt-users"                 maildir "${path}/mutt-users"
    action "fvwm"                       maildir "${path}/fvwm"
    action "fvwm-workers"               maildir "${path}/fvwm-workers"
    action "grml"                       maildir "${path}/grml"
    action "grml-devel"                 maildir "${path}/grml-devel"
    action "zsh-users"                  maildir "${path}/zsh-users"
    action "zsh-workers"                maildir "${path}/zsh-workers"
    action "cmus-devel"                 maildir "${path}/cmus-devel"
    action "leafnode"                   maildir "${path}/leafnode"
    action "remind-fans"                maildir "${path}/remind-fans"
    action "screen-users"               maildir "${path}/screen-users"
    action "slrn-users"                 maildir "${path}/slrn-users"
    action "tuhs"                       maildir "${path}/tuhs"
    action "vim-users"                  maildir "${path}/vim-users"
    action "linux-kernel"               maildir "${path}/linux-kernel"
    action "kernelnewbies"              maildir "${path}/linux-kernel-newbies"
    action "linux-elitists"             maildir "${path}/linux-elitists"
    action "bugtraq"                    maildir "${path}/bugtraq"
    action "full-disclosure"            maildir "${path}/full-disclosure"
    action "pen-test"                   maildir "${path}/pen-test"
    action "schopppe"                   maildir "${path}/schopppe"
#}}}

### rewrite actions (some mailinglist add tags to their subjects...)
### '1,/^$/...' only rewrites lines in the mail _headers_.
#{{{
    action "strip-full-disclosure"  rewrite "${com_sed} '1,/^$/s/^\\(Subject:.*\\)\\[Full-disclosure\\] /\\1/'"
    action "strip-remind-fans"      rewrite "${com_sed} '1,/^$/s/^\\(Subject:.*\\)\\[Remind-Fans\\] /\\1/'"
    action "strip-fvwm"             rewrite "${com_sed} '1,/^$/s/^\\(Subject:\\) FVWM:/\\1/'"
    action "strip-grml"             rewrite "${com_sed} '1,/^$/s/^\\(Subject:.*\\)\\[Grml\\] /\\1/'"
    action "strip-leafnode"         rewrite "${com_sed} '1,/^$/s/^\\(Subject:.*\\)\\[leafnode-list\\] /\\1/'"
    action "strip-linux-elitists"   rewrite "${com_sed} '1,/^$/s/^\\(Subject:.*\\)\\[linux-elitists\\] /\\1/'"
    action "strip-tuhs"             rewrite "${com_sed} '1,/^$/s/^\\(Subject:.*\\)\\[TUHS\\] /\\1/'"
#}}}

###########################################################################

### accounts for spam-training
###   -asp-train-spam
###     trains the message from stdin as spam;
###     moves the mail to the appropriate folder
###   -asp-train-good
###     trains the message from stdin as ham;
###     continues with normal rules to sort the message
###     to the folder it belongs to.
    account "sp-train-spam" disabled stdin
    account "sp-train-good" disabled stdin

### sometimes you want to test new things by providing mails on stdin
    account "stdin" disabled stdin

###########################################################################

### Automatic archiving.
### This is a nice idea, I shamelessly stole from NicM's config.
###   Mail is kept in Maildirs for 30 days. After that it is
###   automatically moved to compressed mboxes, which in turn
###   may by periodically removed (by cron for examples, or
###   by hand). This (again) uses an account that is disabled,
###   so it can be explicitly called by '-aarchive'.
    account "archive" disabled maildirs {
#{{{
      "${path}/Inbox"
      "${path}/bugtraq"
      "${path}/cmus-devel"
      "${path}/debian-*"
      "${path}/full-disclosure"
      "${path}/fvwm*"
      "${path}/grml*"
      "${path}/leafnode"
      "${path}/linux-*"
      "${path}/mutt-*"
      "${path}/openbsd-*"
      "${path}/pen-test"
      "${path}/remind-fans"
      "${path}/schopppe"
      "${path}/screen-users"
      "${path}/slrn-users"
      "${path}/tuhs"
      "${path}/vim-users"
      "${path}/zsh-*"
#}}}
    }
    match account "archive" and age > %{max_age} days action "archive"
    match account "archive" action "keep"

###########################################################################

### handle mail

### do catchall as early as possible.
    match string "${do_catchall}" to "^yes$" action "catchall" continue

      ########## zblog messages ##########
### mails to blog -at- bewatermyfriend -dot- org are meant for zblog.
    match account "blog"      action "zblog"
    match account "comments"  action "zcomm"

      ########## killfiling ##########
### killfiling on From, From:, Reply-To: and Sender headers
### If your killfile is rather large, this will slow down fdm
### considerably. So do this only on people that really disturb you.
    match pipe "${com_pfh} | grep -Eqif ${killfile}" returns ( 0, )
      actions { "killfile" "maildir-mark-as-read" }

      ########## spam handling ##########
### force message from stdin to spamfolder and train it as spam
    match account "sp-train-spam" {
      match all action "train-spam" continue
      match "^${header_spam}" in headers action "sp-remove-header" continue
      match all action "sp-add-trained-spam" continue
      match all action "spam"
    }

### train message from stdin as ham
    match account "sp-train-good"
        action "train-good"           continue
    match account "sp-train-good" and
	"^${header_spam}" in headers
      	action "sp-remove-header"     continue
    match account "sp-train-good"
        action "sp-add-trained-good"  continue

### scan for spam
    match not "^${header_spam}" in headers {
      match pipe "${com_spam_filter}" returns ( , "(.*)" ) {
        match "^${header_spam}" in headers action "sp-remove-header" continue
        match all action "sp-add-header" continue
      }
    }

### move messages marked as spam to spamfolder
    match "^${header_spam}:[ \t]*${filtered_spam}" in headers action "spam"

      ########## modifying headers ##########
### add Lines: header if it is missing.
    match not "^Lines:" in headers action "add-lines-header" continue

### remove headers I don't care about
    match "^${ill_headers}:" in headers action "remove-ill-headers" continue

      ########## sorting ##########
### debian- mailinglists and pts
    match "^List-Id:[ \t]*<debian-([a-z-]*)\\.lists\\.debian\\.org" in headers action "debian-%1"
    match "^X-PTS-Package:.*[a-z].*" in headers action "debian-pts"

### openbsd- mailinglists
    match "^Sender:[ \t]*owner-([a-z-]*)@openbsd\\.org" in headers action "openbsd-%1"

### grml mailinglists
    match "^List-Post:[ \t]*<mailto:grml(.*)@mur\\.at" in headers {
      match string "%1" to "^$" action "strip-grml" continue
      match all action "grml%1"
    }

### zsh- mailinglists
    match "^Mailing-List:.*zsh-([a-z]*)-help@" in headers {
      match string "%1" to "announce" action "inbox"
      match all action "zsh-%1"
    }

### mutt- mailinglists
    match "^List-Unsubscribe:.*mutt-([a-z]*)-request@mutt\\.org" in headers {
      match string "%1" to "announce" action "inbox"
      match all action "mutt-%1"
    }

### fvwm mailinglists
    match "^List-Id:.*fvwm(.*)\\.(fvwm\\.org|lists\\.math\\.uh\\.edu)" in headers {
      match string "%1" to "announce" action "inbox"
      match string "%1" to "^$" action "strip-fvwm" continue
      match all action "fvwm%1"
    }

### other mailinglists
    match "^List-Post:.*bugtraq@securityfocus\\.com" in headers action "bugtraq"
    match "^List-Id:.*cmus-devel\\.lists\\.sourceforge\\.net" in headers action "cmus-devel"
    match "^List-Id:.*full-disclosure\\.lists\\.grok\\.org\\.uk" in headers actions { "strip-full-disclosure" "full-disclosure" }
    match "^List-Id:.*leafnode-list\\.dt\\.e-technik\\.uni-dortmund\\.de" in headers actions { "strip-leafnode" "leafnode" }
    match "^X-BeenThere:.*linux-elitists@zgp\\.org" in headers actions { "strip-linux-elitists" "linux-elitists" }
    match "^X-Mailing-List:.*linux-kernel@vger\\.kernel\\.org" in headers action "linux-kernel"
    match "^List-Id:.*kernelnewbies\\.nl\\.linux\\.org" in headers action "kernelnewbies"
    match "^List-Post:.*pen-test@securityfocus\\.com" in headers action "pen-test"
    match "^List-Id:.*remind-fans\\.lists\\.whatexit\\.org" in headers actions { "strip-remind-fans" "remind-fans" }
    match "^List-Id:.*schopppe\\.de" in headers action "schopppe"
    match "^List-Id:.*screen-users\\.gnu\\.org" in headers action "screen-users"
    match "^List-Id:.*slrn-user\\.lists\\.sourceforge\\.net" in headers action "slrn-users"
    match "^List-Id:.*Unix Heritage.*tuhs\\.minnie\\.tuhs\\.org" in headers actions { "strip-tuhs" "tuhs" }
    match "^Mailing-List:.*vim-help@vim\.org" in headers action "vim-users"

### match the rest
    match all action "inbox"
