Setting up Dovecot with Fetchmail and SpamAssassin
Dovecot is a really cool imap server. If you, like me, have a lot of mail accounts around the internet, a bit of gmail there, some hotmail over here, and want to collect everything on your nice local home server, this is the howto to follow.
Fetchmail
First of all we need to configure Fetchmail to fetch our mail. Fetchmail can't handle multiple IMAP accounts with IDLE with a single Fetchmail running, so we need to run multiple Fetchmail instances, one for each IMAP account we want to monitor.
To do this we use this script:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87#!/bin/bash
# searches for subdirectories of $HOME/.fetchmail, and considers each as a
# directory to run fetcmail from. The config should be stored as "fetchmailrc"
# within this directory; without the leading ".". Networks can be started and
# stopped independently, or all together. See the --help option for detail on
# invoking the script.
FETCHMAILROOT=~/.fetchmail
cd "$FETCHMAILROOT"
ACTION="start"
while [ "$1" ]; do
ARG="$1"
case "$ARG" in
-k|--kill) ACTION="kill" ;;
-l|--list) ACTION="list" ;;
-h|--help) ACTION="help" ;;
--) shift; break ;;
-*) echo "Unknown argument $ARG"; exit 1 ;;
*) break ;;
esac
shift
done
WHICH="$1"
function find_fetchmail_homes() {
# Find directories immediately off FETCHMAILROOT
for ENT in *; do
if [ -d "$ENT" ]; then
echo "$ENT"
fi
done
}
case "$ACTION" in
help)
echo "$0: [options..] [network]"
echo "Options are:"
echo " -h, --help: This text"
echo " -k, --kill: Stop network"
echo " -l, --list: List networks, running or not"
echo "If a network is named, the action applies only to that network"
exit 0
;;
start)
for ENT in `find_fetchmail_homes`; do
if [ "$WHICH" -a "$ENT" != "$WHICH" ]; then continue; fi
export FETCHMAILHOME=`pwd`/$ENT
fetchmail $EXTRAOPTS #$ENT
done
;;
list)
for ENT in `find_fetchmail_homes`; do
if [ "$WHICH" -a "$ENT" != "$WHICH" ]; then continue; fi
export FETCHMAILHOME=`pwd`/$ENT
FETCHMAILPID=$FETCHMAILHOME/fetchmail.pid
echo "Config $ENT in $FETCHMAILHOME"
if [ -r $FETCHMAILPID ]; then
echo " running as PID `cat $FETCHMAILPID`"
else
echo " not running"
fi
done
;;
kill)
for ENT in `find_fetchmail_homes`; do
if [ "$WHICH" -a "$ENT" != "$WHICH" ]; then continue; fi
export FETCHMAILHOME=`pwd`/$ENT
FETCHMAILPID=$FETCHMAILHOME/fetchmail.pid
echo "Config $ENT in $FETCHMAILHOME"
if [ -r $FETCHMAILPID ]; then
fetchmail -q #$ENT
fi
done
;;
*)
echo "Ahh; unknown action $ACTION"
exit 1
;;
esac
We call it fetchmultimail.sh
and save it somewhere, maybe in our ~/bin/fetchmultimail.sh
.
The script is configured with fetchmailrc
files, one for every account:1
2
3
4
5
6
7
8
9
10$ tree .fetchmail
.fetchmail
├── email1@gmail.com.INBOX@gmail.com
│ └── fetchmailrc
├── email2@outlook.com@imap-mail.outlook.com
│ └── fetchmailrc
└── email3@outlook.com@imap-mail.outlook.com
└── fetchmailrc
3 directories, 3 files
The fetchmailrc
configuration file in those directories is a standard fetchmailrc file, and looks something like this:1
2
3
4
5
6
7
8
9
10
11
12set postmaster "postmaster"
set bouncemail
set no spambounce
set properties ""
set daemon 300
set invisible
set syslog
poll imap-mail.outlook.com protocol IMAP port 993
user 'email2@outlook.com' there with ssl with password 'verysecureandsecretpassword' folder 'INBOX' idle ssl
mda "{ echo X-Mailbox: email2@outlook.com; cat; } | spamc -s 5000000 | /usr/lib/dovecot/deliver -d s2"
So fetchmail
fetches our mail from the IMAP server, and then delivers it to the mda
. In this case, we
- add a header to the mail, so we can sort it to the correct folder later, with
{ echo X-Mailbox: email2@outlook.com; cat; }
- check for spam with SpamAssassin with
spamc -s 5000000
- and then send it to Dovecot with
/usr/lib/dovecot/deliver -d s2
, wheres2
is the user we are delivering the mail to.
To run this script on startup the easy way, we can use crontab
:1
2
3$ crontab -l
@reboot /home/s2/bin/fetchmultimail.sh >/dev/null
$
This runs fetchmultimal.sh
after every server startup.
Dovecot
On the Dovecot side we now receive the mail, but we want to sort it to the correct folder using some custom rules. To do this, we can use Sieve.
So first of all, we install and configure Sieve for Dovecot. To do this follow the official guide, or one specific for your Linux distribution.
Once installed and configured Sieve, we can create a Sieve config file with the rules we want to have. A quick example:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34require "fileinto";
#webcam alerts
if address :is ["From"] "webcamalerts@home.in.tern.al" {
fileinto "webcamalerts";
stop;
}
#spam
if header "X-Spam-Flag" "YES" {
fileinto "Junk";
stop;
}
#email1@gmail.com
if header "X-Mailbox" "email1@gmail.com" {
fileinto "email1@gmail_com";
stop;
}
#email2@outlook.com
if header "X-Mailbox" "email2@outlook.com" {
fileinto "email2@outlook.com";
stop;
}
#email3@outlook.com
if header "X-Mailbox" "email3@outlook.com" {
fileinto "email3@outlook.com";
stop;
}
fileinto "INBOX";
As you can see, we use the X-Mailbox
header we set with Fetchmail to sort our mail. We could use the To
header too, but if someone sends you an email where you are in the Bcc
or the Cc
filed, the To
header field would be empty, so we use the custom X-Mailbox
header we set by ourselves, so we are sure the mail arrived to that account, and gets put in the correct folder.
The end
So that was all. I skipped uninteresting stuff like how to install SpamAssassin and stuff like that, because it's Linux distribution dependent, and is very easy.
Hope the notes above helped someone!