SPAM/Virus Filter on Sarge

Posted by ncb on Fri 3 Mar 2006 at 10:01

This documents my adventure of setting up a spam/virus fighting mail server on Sarge. It is not the most fancy way of doing it, but should be suitable for an environment with not too many users, nor a bunch of road warriors. It's also probably a decent starting point for building more advanced configurations. The end product is a server that dicards virus-infected mail, identifies spam, and sorts it into a local user's junk folder. Courier's Maildrop is used instead of procmail, Maildir directories are used instead of mbox, and the SSL enabled version of Courier IMAP is used for mail retrieval by users.

I should note that there are many other, and far better, howtos out in the world for doing this, but many are more involved and I was shooting for relative simplicity. For example this howto does not cover the setup of SMTP Auth, TLS, or SASL, and so does not allow users that are external to the network to relay mail through the server. For this, a similar but more indepth howto is this article at Fat of the LAN. If however, you want the full-on (and kick-ass) ISP style server, with virtual domains and MySQL to keep track of everything, you'll like this article at workaround.org.

UPDATE: After I initially posted this article, some commenters politely pointed out concerns with the configuration, which I think can be summarized into three main points:

  1. The configuration in this article uses after-queue content filtering, instead of before-queue content filtering. I've not tried before-queue filtering, but some commenters have said it is the newer/better way. You can read more about it on the Postfix Before-Queue Content Filter page. Following is the the Pros and Cons section from that page (the cons sound a bit scary to me, but obviously some are having good results).
    • Pro: Postfix can reject mail before the incoming SMTP mail transfer completes, so that Postfix does not have to send rejected mail back to the sender (which is usually forged anyway). Mail that is not accepted remains the responsibility of the remote SMTP client.
    • Con: The remote SMTP client expects an SMTP reply within a deadline. As the system load increases, fewer and fewer CPU cycles remain available to answer within the deadline, and eventually you either have to stop accepting mail or you have to stop filtering mail. It is for this reason that the before-queue content filter can be used only on low-traffic sites.
    • Con: Content filtering software can use lots of memory resources. In order to not run out of memory you have to reduce the number of before-filter SMTP server processes so that a burst of mail will not drive your system into the ground with too many content filter processes. This, in turn, means that SMTP clients have to wait for a long time before they receive service.

    Note also that if you go the before-queue route, doing it with amavisd-new is not recommended (thanks to jooray for pointing it out).

  2. This configuration tags and sorts all spam to a junk folder, rejecting none of it. The rationale for this choice is to minimize the likelihood of losing wanted mail (especially since no bounce messages are being sent), and also to negate the need for any quarantine. Someone pointed out that anything Spamassassin scores higher than 10 or so is something you'll likely never miss, so accepting it is unnecessary. If this is what you want it is easily remedied. Assuming 10 is your magic number, set amavisd.conf's $sa_kill_level_deflt = 10 and make sure to set $spam_quarantine_to = undef. Anything scored 10 or higher will just go away.
  3. There was also at least one mention of the need to never ever send bounce messages to virus or spam senders. I totally agree. Strictly speaking this configuration didn't do that, but I had stuck with the default of sending a bounce message for banned file attachments. I've never been burned by this, but it's probably a risk one shouldn't take, and so I've changed the article to set amavisd.conf's $final_banned_destiny from the default of D_BOUNCE to D_DISCARD.

Also, I initially left out the step of configuring Postfix's mynetwoks directive, so I added it.

Before you start

What gets installed

These are the main players and versions being installed at the time of writing (March 2006).

Installing Postfix and Company

This installs postfix, amavisd-new, clamav, and some recommended packages (zoo, unarj, and unzip let amavisd-new access archives). You know the drill . . .

:# apt-get update
:# apt-get upgrade
:# apt-get install postfix amavisd-new spamassassin clamav clamav-daemon clamav-docs zoo unzip unarj 

Some guidance on the ensuing configuration questions ...

Installing Courier-IMAP and Company

Now lets install all the Courier tools, plus some of their recommended packages. This will pull in everything you need for IMAP, including the courier-imap and openssl packages. You can just accept all the defaults on the upcoming config questions.

:# apt-get install courier-maildrop courier-imap-ssl courier-doc ca-certificates fam

Creating Maildir directories

Now we need to create the Maildir directories for incoming mail to land in. We do this with the tool maildirmake, and we do it within the user's home directories. Do the following for existing users.

:# su user
:# cd ~
:# maildirmake Maildir (creates ~/Maildir plus cur, new, and tmp subdirs)
:# maildirmake -f Drafts Maildir (creates ~/Maildir/.Drafts)
:# maildirmake -f Junk Maildir (creates ~/Maildir/.Junk)
:# maildirmake -f Sent Maildir (creates ~/Maildir/.Sent)
:# maildirmake -f Templates Maildir (creates ~/Maildir/.Templates)
:# exit (back to being root)

Now repeat the above process as root in /etc/skel so new users will get Maildir directories automatically.

Configuring Maildrop

Maildrop is a replacement for procmail that includes it's own perl-like filtering language. We can use this filtering language to sort spam to the Junk folder we created. We do this by creating the file /etc/courier/maildroprc and adding some system-wide configuration there. Create the file, and then add the following.

# /etc/courier/maildroprc

# Our shell
SHELL="/bin/bash"

# The default path
DEFAULT = "$HOME/Maildir"

# Our log file
logfile "/var/log/maildrop"

# Our verbosity in the log file
VERBOSE="5"

# This get's added above each entry in the log file.
# It's just a visual aid.
log "------------------------"

# If the Spam-Flag is YES, sort to Junk folder
# ---------------------------------------------
if ( /^X-Spam-Flag: YES/)
{
       to $DEFAULT/.Junk/
}

The above tells maildrop where it's log file is, and also to sort anything with "X-Spam-Flag: YES" in the headers to the Junk folder. Note that users can create their own ~/.mailfilter file to further sort mail. What I have above is a very basic use of maildrop filtering. For more info try man maildropfilter or look here.

We also need to create the log file we mentioned in the maildroprc file above.

:# touch /var/log/maildrop
:# chown root.adm /var/log/maildrop
:# chmod 642 /var/log/maildrop

This log should be rotated. Create /etc/logrotate.d/maildrop and add the following to it.

/var/log/maildrop {
   weekly
   missingok
}

Sanity Checking Postfix

Let's take a look at our default postfix config. Open up /etc/postfix/main.cf in an editor. Look it over and give it a sanity check. Look for your own domain whenever you see example.com. It should look something like the following.

# See /usr/share/postfix/main.cf.dist for a commented, more complete version

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

myhostname = smtp.example.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = smtp.example.com, localhost.example.com, example.com, localhost
relayhost =
mynetworks = 127.0.0.0/8
mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all

Setting mynetworks

This is a good point to add any networks you want to relay mail for to the mynetworks list. For example, if your local LAN is on network 192.168.10.0/24 do this ...

mynetworks = 127.0.0.0/8, 192.168.10.0/24

Configuring Postfix to use Maildrop

Now let's edit this file so that Postifx will use maildrop (instead of the default procmail), and deliver to our user's Maildirs. First, comment out the existing mailbox_command line.

# mailbox_command = procmail -a "$EXTENSION"

Then add these lines at the bottom of the file.

# Use maildrop instead of procmail
mailbox_command = /usr/bin/maildrop

# Deliver to user's Maildir (trailing slash is required)
home_mailbox = Maildir/

Save the file, and reload Postfix.

/etc/init.d/postfix reload

Testing Postfix and Maildrop

Now, assuming DNS is working, you should be able to send a test mail from another machine. Remember there is no MX record for this box yet, so use the FQDN in the e-mail address (i.e. user@smtp.example.com not user@example.com). To watch the message go through you can tail the mail log while sending it.

:# tail -f /var/log/mail.log

Feb 28 14:44:18 smtp postfix/smtpd[5843]: connect from someserver.somedomain.com[123.456.78.9]
Feb 28 14:44:18 smtp postfix/smtpd[5843]: 43F4C11E65C: client=someserver.somedomain.com[123.456.78.9]
Feb 28 14:44:18 smtp postfix/cleanup[5846]: 43F4C11E65C: message-id=<4404D1BA.2060504@somedomain.com>
Feb 28 14:44:18 smtp postfix/qmgr[5838]: 43F4C11E65C: from=<user@somedomain.com>, size=1414, nrcpt=1 (queue active)
Feb 28 14:44:18 smtp postfix/smtpd[5843]: disconnect from someserver.somedomain.com[123.456.78.9]
Feb 28 14:44:18 smtp postfix/local[5847]: 43F4C11E65C: to=<user@smtp.example.com>, relay=local, delay=0, status=sent (delivered to command: /usr/bin/maildrop)
Feb 28 14:44:18 smtp postfix/qmgr[5838]: 43F4C11E65C: removed

You should also be able to see something like this in /var/log/maildrop

------------------------
Date: Wed Feb  28 14:44:20 2006
From: Some Name <user@example.com>
Subj: testing 
File: /home/user/./Maildir                                            (1531)

Further, you should be able to find the message in the user's new mail folder under a really long file name.

:# ls ~username/Maildir/new
1141137858.M361578P5848V0000000000000301I000578F3_0.smtp,S=1508

If this test fails check the mail.log for errors, check for typos, make sure you reloaded postfix, and look for firewall or DNS issues. This needs to work before you proceed.

Configuring Amavisd-new

Now that we know Postfix and maildrop are working, we want to add spam and virus filtering to the mix. This is where amavisd-new comes in to play. amavisd-new acts as the glue between postifx and content checkers such as spamassassin and clamav. We need to configure it, and after that we'll configure postifx to forward mail through it.

The config file for amavisd-new is /etc/amavis/amavisd.conf. This is a huge (and a bit daunting) config file, with lots of options and comments. There are a number of changes to make, so I'll just go right down the file and make some brief explanations along the way.

Before we start, here is an overview of what we want amavisd-new to do for us:

OK, open up amavisd.conf in an editor and let's get started. First, set the domain and host names. Find these lines and change them.

$mydomain = 'example.com';      # (no useful default) -->
$myhostname = 'smtp.example.com';  # fqdn of this host, default by uname(3)

Uncomment the following two lines, these tell amavisd-new on what port to look for Postfix (port 10025, we'll configure postifx for this a bit later).

$forward_method = 'smtp:127.0.0.1:10025';  # where to forward checked mail
$notify_method = $forward_method;          # where to submit notifications

Comment out this line. Debian's amavisd-new does not use spamassassin by defualt, but we want it.

# @bypass_spam_checks_acl  = qw( . );    # No default dependency on spamassassin

The following 4 parameters tell amavisd-new what to do with mail that is virus infected or spam. They are somewhat self explanatory, but reading the notes just above these in amavisd.conf will give you a good idea of how they work. Set them like so:

$final_virus_destiny      = D_DISCARD; # (defaults to D_BOUNCE)
$final_banned_destiny     = D_DISCARD;  # (defaults to D_BOUNCE)
$final_spam_destiny       = D_PASS;  # (defaults to D_REJECT)
$final_bad_header_destiny = D_PASS;  # (defaults to D_PASS), D_BOUNCE suggested

Note: D_BOUNCE is the default for $final_banned_destiny, which I've found useful and never had ill effects from. Setting it to D_DISCARD however will ensure you are sending no automatic bounce messages, and is probably the safest way to go.

The $virus_admin variable sets the email address that will receive notifications of virus mails. No change is needed on this line unless you want this to be someone other than postmaster.

$virus_admin = "postmaster\@$mydomain";         # due to D_DISCARD default

We don't want to keep infected mail, and are going to pass tagged spam on to the user. So, there's nothing to quarnatine. Make the following few changes.

Find the line defining the $QUARANTINEDIR. Comment out the first line here, and then add the second one.

# $QUARANTINEDIR = '/var/lib/amavis/virusmails';
$QUARANTINEDIR = undef;

Then, comment out this line.

# $virus_quarantine_to  = 'virus-quarantine';    # traditional local quarantine

And then uncomment this line.

$virus_quarantine_to = undef;

If you want to adhere to the principle that postmaster should be able to receive all mail (except viruses), find and uncomment the following line.

$spam_lovers{lc("postmaster\@$mydomain")} = 1;

The $sa_local_tests_only variable controls whether Spamassassin can do checks that require it to access the internet. To allow it, change the value from 1 to 0.

$sa_local_tests_only = 0;   # (default: false)

The next three settings determine at what Spamassassin score a message's headers will be altered. Set them like so.

$sa_tag_level_deflt  = -999; # add spam info headers if at, or above that level
$sa_tag2_level_deflt = 6.3; # add 'spam detected' headers at that level
$sa_kill_level_deflt = 999; # triggers spam evasive actions

Here's a brief explanation of these settings.

$sa_tag_level_deflt = -999;
Setting this to a big negative number causes every message to be tagged as either spam or not (X-Spam-Status:Yes/No in the mail headers).
$sa_tag2_level_deflt = 6.3
This is the spamassassin score at which a message is considered to be spam, the string "***SPAM***" will be prepended to the subject line of a message, and "X-Spam-Flag:YES" is added to the headers. You can fine tune this number over time. I eventualy wound up at 5.0.
$sa_kill_level_deflt
This is the spamassassin score at which actions such as DISCARD or QUARANTINE will occur for spam. When taking such actions, this is set to the same value as $sa_tag2_level_deflt, but since we are just tagging spam we can set it very high.

Note: Over time you may decide that every message scoring above a certain level is definitely spam and should be discarded. This can greatly reduce the amount of spam in your user's junkf folder, and may decrease your exposeure to any virus clamav might have missed. If so you can tune the $sa_kill_level_deflt to a lower number, like somewhere between 10 or 20 for example.

Now go down to the section beginning with @av_scanners = (. Here you will find stanza after stanza defining the various virus scanners amavisd-new will look for at start up (several can be used at the same time). Following that is another large section defining the backup scanners that will be used if none of the primary scanners can be found. Personally, I don't like the idea of churning through all this at every startup, so I just delete every stanza I don't need leaving only those related to clamd and clamscan. But that's just me, and leaving this section alone entirely or just commenting out the sections you don't need is fine too. Anyway, below is what it looks like when I'm through with it.

@av_scanners = (

### http://www.clamav.net/
['Clam Antivirus-clamd',
  \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd.ctl"],
  qr/\bOK$/, qr/\bFOUND$/,
  qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
# NOTE: run clamd under the same user as amavisd;  match the socket
# name (LocalSocket) in clamav.conf to the socket name in this entry
# When running chrooted one may prefer: ["CONTSCAN {}\n","$MYHOME/clamd"],
);

# If no virus scanners from the @av_scanners list produce 'clean' nor
# 'infected' status (e.g. they all fail to run or the list is empty),
# then _all_ scanners from the @av_scanners_backup list are tried.
# When there are both daemonized and command-line scanners available,
# it is customary to place slower command-line scanners in the
# @av_scanners_backup list. The default choice is somewhat arbitrary,
# move entries from one list to another as desired.

@av_scanners_backup = (

  ### http://www.clamav.net/
  ['Clam Antivirus - clamscan', 'clamscan',
    "--stdout --no-summary -r --tempdir=$TEMPBASE {}", [0], [1],
    qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
);

That's it for amavisd.conf. Save and close the file, but don't reload amavisd-new quite yet.

One Last Thing

The notes in the above clamd stanza are important. amavisd-new and clamd both need to agree on the location of clamd's socket file (/var/run/clamav/clamd.ctl), and both need permission to see it. The file /usr/share/doc/amavisd-new/NEWS.Debian tells us how to handle this, and indeed nearly everything is already taken care of. If you look at /etc/clamav/clamd.conf you will see that clamd's LocalSocket setting already matches what is in amavisd.conf, that clamd runs as user clamav, and the setting AllowSupplementaryGroups is active. So, all that's left to do is to add the clamav user to the amavis group.

:# adduser clamav amavis
Adding user `clamav' to group `amavis'...
Done.

Testing Amavisd-new

I can't remember what was required here, just a reload, a restart, or what. So let's just do full restarts on both amavisd-new and clamd.

:#/etc/init.d/clamav-daemon restart
Stopping ClamAV daemon: clamd
Starting ClamAV daemon: clamd
:# /etc/init.d/amavis restart
Stopping amavisd: amavisd-new.
Starting amavisd: amavisd-new.

That oughta do it. Check /var/log/syslog and /var/log/clamav/clamav.log for errors. If all is well we should be able to telnet to amavisd-new on port 10024.

:# telnet 127.0.0.1 10024
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
220 [127.0.0.1] ESMTP amavisd-new service ready
quit
221 2.0.0 [127.0.0.1] (amavisd) closing transmission channel
Connection closed by foreign host.

Configuring Postfix to use Amavisd-new

OK, now we just need amavisd-new and postfix to start working together. We need to edit two postfix config files (More info on the following steps is in /usr/share/doc/amavisd-new/README.postfix).

Open up /etc/postfix/master.cf, paste the following at the end of the file, then save and close.

# Added per /usr/share/doc/amavisd-new/README.postfix
smtp-amavis unix -      -       n     -       2  smtp
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes

127.0.0.1:10025 inet n  -       n     -       -  smtpd
    -o content_filter=
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o smtpd_restriction_classes=
    -o smtpd_client_restrictions=
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o mynetworks=127.0.0.0/8
    -o strict_rfc821_envelopes=yes
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000

Then, open /etc/postfix/main.cf, add the following at the end of the file, then save and close.

# Added per /usr/share/doc/amavisd-new/README.postfix
content_filter=smtp-amavis:[127.0.0.1]:10024

Now reload postfix, (tail -f /var/log/mail.log to watch for errors).

:# /etc/init.d/postfix reload

Testing it All Together

Alrighty then, let's see if this really works. We'll use telnet, the EICAR virus test string, and the GTUBE spam test string. These strings are handily provided in /usr/share/doc/amavisd-new/README.postfix and /usr/share/doc/spamassassin/examples/sample-spam.txt.

Let's telnet to port 10024, and have an SMTP conversation like the following. Note, however, that the empty line which precedes both the EICAR and GTUBE strings is needed, as is the following period on the last line. Hitting enter after the final period sends the message. Also, it's important to use a real user, and your own domain in place of example.com.

Note: You should get similar results using port 25, but postfix will not give you as much info.

:# telnet 127.0.0.1 10024
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
220 [127.0.0.1] ESMTP amavisd-new service ready
MAIL FROM:<test@somedomain.com>
250 2.1.0 Sender test@somedomain.com OK
RCPT TO:<realuser@example.com>
250 2.1.5 Recipient realuser OK
DATA
354 End data with <CR><LF>.<CR><LF>
Subject: test virus

X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
.
250 2.7.1 Ok, discarded, id=01336-01 - VIRUS: Eicar-Test-Signature
quit
221 2.0.0 [127.0.0.1] (amavisd) closing transmission channel
Connection closed by foreign host.

The virus was discarded. That's good. Now let's try a spam messasge.

:# telnet 127.0.0.1 10024
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
220 [127.0.0.1] ESMTP amavisd-new service ready
MAIL FROM:<test@somedomain.com>
250 2.1.0 Sender test@somedomain.com OK
RCPT TO:<realuser@example.com>
250 2.1.5 Recipient realuser OK
DATA
354 End data with <CR><LF>.<CR><LF>
Subject: test spam

XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
.
250 2.6.0 Ok, id=01337-01, from MTA: 250 Ok: queued as 69F6811E65D
quit
221 2.0.0 [127.0.0.1] (amavisd) closing transmission channel
Connection closed by foreign host.

The spam was queued, which is also good, since we are passing it along.

After the above two SMTP sessions, the postmaster should have a virus notification message in ~/Maildir/new/ with something like the following in it:

A virus (Eicar-Test-Signature) was found.

Scanner detecting a virus: Clam Antivirus-clamd

The mail originated from: <test@somedomain.com>

There should also be a message in the user's ~/Maildir/.Junk/new/ folder with ***SPAM*** prepended to the subject, and X-Spam-Flag:YES appended to the headers. The bottom part should look like this.

Subject: ***SPAM*** test spam
Message-Id: <20060302231720.F267411E65D@smtp.example.com>
Date: Thu,  2 Mar 2006 15:17:20 -0800 (PST)
From: test@somedomain.com
To: undisclosed-recipients: ;
X-Virus-Scanned: by amavisd-new-20030616-p10 (Debian) at example.com
X-Spam-Status: Yes, hits=998.7 tagged_above=-999.0 required=6.3
        tests=ALL_TRUSTED, GTUBE, NO_REAL_NAME, UNDISC_RECIPS
X-Spam-Level: ****************************************************************
X-Spam-Flag: YES

XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X

Now, isn't that cool?

If all that worked, and your DNS and firewall cooperate, you should now be able to send mail to any real user at your machine's FQDN (user@smtp.example.com) from a machine outside your network, like a yahoo or gmail account for example.

Configuring Courier-IMAP-SSL

Now let's get IMAP working so we can check our mail. We're using SSL so the first thing we need is a cert. First move the existing imapd.pem out of the way, and make a backup copy of imapd.cnf.

#: cd /etc/courier
#: mv imapd.pem imapd.pem.original
#: cp imapd.cnf imapd.cnf.original

Now edit imapd.cnf to look something like the following, putting in the correct information for city, state, etc, and making sure to set the CN to the FQDN of your server. Then save and close.

RANDFILE = /usr/lib/courier/imapd.rand

[ req ]
default_bits = 1024
encrypt_key = yes
distinguished_name = req_dn
x509_extensions = cert_type
prompt = no

[ req_dn ]
C=US
ST=WA
L=Tacoma
O=Example.com
OU=Example.com SMTP Server
CN=smtp.example.com
emailAddress=postmaster@example.com


[ cert_type ]
nsCertType = server

Now just run the command mkimapdcert with no arguments. Your new cert will be created as /etc/courier/imapd.pem, and will be good for a year.

:# mkimapdcert
Generating a 1024 bit RSA private key
........++++++
.......++++++
writing new private key to '/usr/lib/courier/imapd.pem'
-----
1024 semi-random bytes loaded
Generating DH parameters, 512 bit long safe prime, generator 2
This is going to take a long time
....+......................................+........+.......+..................+..............+...+.............................+..............................+...................+......+........+.............+.....+..................+.....................+......+...........................................+......................+......................................................+...............................+.+............................+....................................+...+..............+.+...............................................................+..+.+.......................+...+...........................+..............+..+.........................+................+.................................................+.+....................................+..+..............+........................................................................................................+.........................................................+.........................++*++*++*++*++*++*
subject= /C=US/ST=WA/L=Tacoma/O=Example.com/OU=Example.com Mail Server/CN=smtp.example.com/emailAddress=postmaster@example.com
notBefore=Mar  3 01:42:28 2006 GMT
notAfter=Mar  3 01:42:28 2007 GMT

Now restart courier-imap.

:# /etc/init.d/courier-imap restart
Stopping Courier IMAP server: imapd.
Starting Courier IMAP server: imapd.
:# /etc/init.d/courier-imap-ssl restart
Restarting Courier IMAP-SSL server: done.

Checking Your Mail

Now all you should have to do is create an account in a mail client, point it at smtp.example.com, and tell it to use IMAP. Don't forget that little check box about using SSL (port 993). The first time you connect, your mail client will whine about the self-signed cert, but you can tell it to remember it permanently (or get a real cert). Also, you may need to tell your mail client to subscribe to all the Maildir folders we created. If you're using Thunderbird, just right-click on the account, select Subscribe..., and check all the little boxes.

That is all. Hope it helps someone.


This article can be found online at the Debian Administration website at the following bookmarkable URL:

This article is copyright 2006 ncb - please ask for permission to republish or translate.