# HOWTO: simple mail server (postfix/dspam/dovecot)



## vermaden (Aug 9, 2010)

Hi,

I do not have big experience in mail servers setup, so I wanted to share my current setup with You, If You have any comments, feel free to post them.

I needed a small and simple mail server and after a lot of googling I went with that setup:


```
postfix --> dspam --> dovecot
 [MTA]      [SPAM]     [LDA]
```

I do not have a problem (or at least I am not aware of it) with making these cooperate together, *postfix(1)* work well with SASL authentification, *dovecot(1)* serves well the imap/pop3 services, *dspam(1)* passes mails from *postfix(1)* into *dovecot(1)* properly.

Generally this setup supports virtual domains with virtual users, all with simple *passwd(5)* format file for authentification, mails are kept in Maildir format like that: /usr/mail/${DOMAIN}/${USER}@${DOMAIN}. Of course there is separate *passwd(1)* file per domain, with format as: /usr/mail/${DOMAIN}/dovecot_passwd, here is how it looks like:

/usr/mail/${DOMAIN}/dovecot_passwd

```
admin@domain.com:{PLAIN}password:2000:2000::/usr/mail/domain.com/admin@domain.com
virtual@domain.com:{DIGEST-MD5}22e693858f955b38b1a0cc4f13c3d8fc:2000:2000::/usr/mail/domain.com/virtual@domain.com
```

All mail is kept under /usr/mail dir, here is how it looks right now:

```
% ls -l /usr/mail
total 136
drwxr-x---  3    root  virtual      4 Aug  9 13:35 dspam/
-rw-r-----  1 virtual  virtual     80 Aug  9 13:41 dspam_transport
-rw-r-----  1 virtual  virtual  65536 Aug  6 11:36 dspam_transport.db
drwxr-x---  4 virtual  virtual      5 Aug  9 13:35 domain.com/
-rw-r-----  1 virtual  virtual    278 Aug  9 13:41 postfix_accounts
-rw-r-----  1 virtual  virtual  65536 Aug  9 13:42 postfix_accounts.db
drwxr-x---  2 virtual  virtual     11 Aug  9 13:35 scripts/

% ls -l /usr/mail/domain.com
-rw-r-----  1 virtual  virtual    277 Aug  5 11:04 dovecot_passwd
drwx------  7 virtual  virtual     13 Aug  9 13:46 admin@domain.com/
drwx------  5 virtual  virtual      9 Aug  6 11:22 virtual@domain.com/
```

Also, all accounts are listed (not per domain, but 'globally' in /usr/mail/postfix_accounts file, here:

/usr/mail/postfix_accounts

```
# mbox -----> admin@bot.pl bot.pl/admin
# maildir --> admin@bot.pl bot.pl/admin/
# FORMAT: user@domain domain/user@domain/

spam@domain.com  x
ham@domain.com   x

admin@domain.com     domain.com/admin@domain.com/
virtual@domain.com   domain.com/virtual@domain.com/
```

Here is the *dovecot(1)* configuration:

/usr/local/etc/dovecot.conf

```
ssl = no
disable_plaintext_auth = no

protocols = pop3 imap

protocol pop3 {
  listen = *:110
  login_processes_count = 1
  login_max_processes_count = 32
  pop3_client_workarounds = outlook-no-nuls
  }

protocol imap {
  listen = *:143
  login_processes_count = 1
  login_max_processes_count = 32
  imap_client_workarounds = outlook-idle
  }

auth default {
  mechanisms = plain login digest-md5
  userdb passwd-file {
    args = /usr/mail/%d/dovecot_passwd
    }
  passdb passwd-file {
    args = /usr/mail/%d/dovecot_passwd
    }
  socket listen {
    master {
      path  = /var/run/dovecot/auth-master
      mode  = 0660
      user  = virtual
      group = virtual
      }
    client {
      path  = /var/spool/postfix/private/auth
      mode  = 0660
      user  = postfix
      group = postfix
      }
    }
  }

mail_location      = maildir:/usr/mail/%d/%u

log_path             = /var/log/dovecot.log
info_log_path        = /var/log/dovecot_info.log
protocol lda {
  postmaster_address = admin@domain.com
  log_path = /var/log/dovecot_lda.log
  }
```

Here is the *dspam(1)* configuration:

/usr/local/etc/dspam.conf

```
Home /usr/mail/dspam
StorageDriver /usr/local/lib/dspam/libhash_drv.so
TrustedDeliveryAgent "/usr/local/libexec/dovecot/deliver -f ${sender} -d ${recipient}"

OnFail error

Trust root
Trust dspam
Trust virtual
Trust dovecot
Trust mail
Trust daemon

TrainingMode teft
TestConditionalTraining on
Feature whitelist
Algorithm graham burton
Tokenizer chain
PValue bcr
WebStats off

Preference "trainingMode=TEFT"
Preference "spamAction=quarantine"
Preference "spamSubject=[SPAM]"
Preference "statisticalSedation=5"
Preference "enableBNR=on"
Preference "enableWhitelist=on"
Preference "signatureLocation=message"
Preference "tagSpam=off"
Preference "tagNonspam=off"
Preference "showFactors=off"
Preference "optIn=off"
Preference "optOut=off"
Preference "whitelistThreshold=10"
Preference "makeCorpus=off"
Preference "storeFragments=off"
Preference "localStore="
Preference "processorBias=on"
Preference "fallbackDomain=off"
Preference "trainPristine=off"
Preference "optOutClamAV=off"
Preference "ignoreRBLLookups=off"
Preference "RBLInoculate=off"

AllowOverride enableBNR
AllowOverride enableWhitelist
AllowOverride fallbackDomain
AllowOverride ignoreGroups
AllowOverride ignoreRBLLookups
AllowOverride localStore
AllowOverride makeCorpus
AllowOverride optIn
AllowOverride optOut
AllowOverride optOutClamAV
AllowOverride processorBias
AllowOverride RBLInoculate
AllowOverride showFactors
AllowOverride signatureLocation
AllowOverride spamAction
AllowOverride spamSubject
AllowOverride statisticalSedation
AllowOverride storeFragments
AllowOverride tagNonspam
AllowOverride tagSpam
AllowOverride trainPristine
AllowOverride trainingMode
AllowOverride whitelistThreshold
AllowOverride dailyQuarantineSummary

HashRecMax              98317
HashAutoExtend          on  
HashMaxExtents          0
HashExtentSize          49157
HashPctIncrease         10
HashMaxSeek             10
HashConnectionCache     10

Notifications   off
PurgeSignatures 14
PurgeNeutral    90
PurgeUnused     90
PurgeHapaxes    30
PurgeHits1S     15
PurgeHits1I     15

LocalMX 127.0.0.1
SystemLog       on
UserLog         on
Opt out
ServerMode standard

ServerParameters        "--deliver=innocent -d %u"
ServerIdent             "mail.domain.com"
ServerDomainSocketPath  "/var/run/dspam.sock"

ProcessorURLContext on
ProcessorBias on
StripRcptDomain off
```

/usr/mail/dspam_transport

```
spam@domain.com  dspam-retrain:spam
ham@domain.com   dspam-retrain:innocent
```

The *postfix(1)* configuration:

/usr/local/etc/postfix/main.cf

```
queue_directory      = /var/spool/postfix
command_directory    = /usr/local/sbin
daemon_directory     = /usr/local/libexec/postfix
data_directory       = /var/db/postfix
mail_owner           = postfix
mynetworks_style     = host
sendmail_path        = /usr/local/sbin/sendmail
newaliases_path      = /usr/local/bin/newaliases
mailq_path           = /usr/local/bin/mailq
setgid_group         = maildrop
html_directory       = /usr/local/share/doc/postfix
manpage_directory    = /usr/local/man
sample_directory     = /usr/local/etc/postfix
readme_directory     = /usr/local/share/doc/postfix
mailbox_command      = /usr/local/libexec/dovecot/deliver
unknown_local_recipient_reject_code = 550

myhostname = mail.domain.com
mynetworks = 0.0.0.0/8,127.0.0.0/8

smtpd_use_tls = no
smtpd_sasl_auth_enable = yes
smtpd_sasl_path        = private/auth
smtpd_sasl_type        = dovecot
smtpd_recipient_restrictions =
  permit_mynetworks,
  permit_sasl_authenticated,
  reject_unauth_destination
broken_sasl_auth_clients = yes
strict_rfc821_envelopes = no

virtual_mailbox_domains = domain.com
virtual_mailbox_base    = /usr/mail
virtual_mailbox_maps    = hash:/usr/mail/postfix_accounts
virtual_minimum_uid     = 100
virtual_uid_maps        = static:2000
virtual_gid_maps        = static:2000
virtual_transport       = lmtp:unix:/var/run/dspam.sock
transport_maps          = hash:/usr/mail/dspam_transport
dspam_destination_recipient_limit = 1
```


----------



## vermaden (Aug 9, 2010)

/usr/local/etc/postfix/master.cf

```
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd
  -o content_filter=lmtp:unix:/var/run/dspam.sock
pickup    fifo  n       -       n       60      1       pickup
cleanup   unix  n       -       n       -       0       cleanup
qmgr      fifo  n       -       n       300     1       qmgr
tlsmgr    unix  -       -       n       1000?   1       tlsmgr
rewrite   unix  -       -       n       -       -       trivial-rewrite
bounce    unix  -       -       n       -       0       bounce
defer     unix  -       -       n       -       0       bounce
trace     unix  -       -       n       -       0       bounce
verify    unix  -       -       n       -       1       verify
flush     unix  n       -       n       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       n       -       -       smtp
relay     unix  -       -       n       -       -       smtp
        -o smtp_fallback_relay=
showq     unix  n       -       n       -       -       showq
error     unix  -       -       n       -       -       error
retry     unix  -       -       n       -       -       error
discard   unix  -       -       n       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       n       -       -       lmtp
anvil     unix  -       -       n       -       1       anvil
scache    unix  -       -       n       -       1       scache
dspam-retrain unix -    n       n       -       -       pipe
  flags=Rhq argv=/usr/local/bin/dspamc --client --mode=teft --class=${nexthop} --source=error --user ${sender}
```

System configuration:

/etc/rc.conf

```
hostname="mail.domain.com"
sshd_enable="YES"
postfix_enable="YES"
dspam_enable="YES"
dspam_pidfile="/var/run/dspam.pid"
dovecot_enable="YES"
syslogd_flags="-s -s"
sendmail_enable="NONE"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
```

/etc/group (important ones)

```
mail:*:6:postfix
virtual:*:2000:
dovecot:*:143:
postfix:*:125:
```

/etc/passwd (important ones)

```
virtual:*:2000:2000:virtual:/usr/mail:/usr/sbin/nologin
dovecot:*:143:143:Dovecot User:/var/empty:/usr/sbin/nologin
postfix:*:125:125:Postfix Mail System:/var/spool/postfix:/usr/sbin/nologin
```

My current concerns are:
-- *dspam(1)* daemon runs on root, it should run on its user (like dspam for example), any tips how to make the permissions?

Like I said before, any comments welcome.


----------



## vermaden (Aug 9, 2010)

_Reserved because of 10000 char limit per post for the future._


----------



## vermaden (Aug 11, 2010)

I assume that there were zero responses here because not many experienced mail server admins here?


----------



## graudeejs (Aug 11, 2010)

Why didn't you post this in HOWTO section?

Here's my howto
http://forums.freebsd.org/showthread.php?t=10728
a little more complex and probably more buggy  perhaps it can be of any help....
I will see If I can (and want to) integrate dspam in my setup 

I'd love to recommend you mail/spamd with pf (I had trouble getting it to work with ipfw. I gave up)
It saves server from lots of spam... especially with China etc blacklisted 
I don't expect any mail from China 

Thanks for posting your howto


----------



## vermaden (Aug 11, 2010)

killasmurf86 said:
			
		

> Why didn't you post this in HOWTO section?


Because I am not sure if this is well setup'ed mail server.



			
				killasmurf86 said:
			
		

> Here's my howto
> http://forums.freebsd.org/showthread.php?t=10728
> a little more complex and probably more buggy  perhaps it can be of any help....
> I will see If I can (and want to) integrate dspam in my setup


Nice mate, integrating *dspam(1)* should be relatively easy for your setup, You will only have to put *dspam(1)* between *postfix(1)* and *dovecot(1)*.



			
				killasmurf86 said:
			
		

> I'd love to recommend you mail/spamd with pf (I had trouble getting it to work with ipfw. I gave up)
> It saves server from lots of spam... especially with China etc blacklisted
> I don't expect any mail from China


Thanks for recommendations


----------



## graudeejs (Aug 11, 2010)

vermaden said:
			
		

> Because I am not sure if this is well setup'ed mail server.



Anyone using this kind of howtos MUST be prepared, that he/she will have to dig, debug, fix, read, search and improvise...

It took me more than week to get my mail server up and running from various howtos and documentations.... and I still improve it from time to time


----------



## graudeejs (Aug 11, 2010)

Also note on spamd.... emails from new IP's will be delayed.... and you need to manually white list google, because they use different IPs to retry sending mail

I can send you my google whitelist if you want


There is also postgray (google it), but I can't find it in ports....


----------



## graudeejs (Aug 11, 2010)

btw, are you planning to use spamassasin? (I recommend it very much)
and you should install and configure mail/dovecot-sieve

I use sieve to move spam to spam folder 


```
require "fileinto";

if anyof (  header :contains "X-Spam-Flag" "Yes",
            header :matches ["X-Spam-score", "X-Remote-Spam-score"]
                ["5.?", "6.?", "7.?", "8.?", "9.?", "1?.?", "2?.?", "3?.?", "4?.?", "5?.?", "6?.?", "7?.?"],    # 5.0 to 79.9
            header :contains ["To", "Cc"] ["undisclosed-recipients", "undisclosed recipients"]
        )
{ 
    fileinto "Junk";
    stop;
}

# http://www.okean.com/antispam/headers.html
if allof (  header :contains "Content-type" "text/html; charset",
            header :contains "Content-type" ["big5", "ks", "euc-kr", "gb2312", "euc-tw", "iso-2022-kr", "ks_c_5601-1987"]
        )
{
    fileinto "Junk";
    stop;
}
```

here's small part of my sieve script


----------



## vermaden (Aug 11, 2010)

killasmurf86 said:
			
		

> Also note on spamd.... emails from new IP's will be delayed.... and you need to manually white list google, because they use different IPs to retry sending mail. I can send you my google whitelist if you want



I will see how this setup will carry on and let You know, it will be used by only a few accounts.



			
				killasmurf86 said:
			
		

> There is also postgray (google it), but I can't find it in ports....



Its *postgrey*, and its in packages/ports:
http://www.freshports.org/mail/postgrey/

... but I also typed *postgrAy* in google 




			
				killasmurf86 said:
			
		

> btw, are you planning to use spamassasin? (I recommend it very much)


I have chosen dspam(1) to avoid using spamassassin, and have read that dspam is better (and less resources hungry at the same time),  but time will tell if I will use it.

Thanks for Your suggestions and feedback mate.


----------



## graudeejs (Aug 11, 2010)

some rough stats:
since *1st June* I received only 37 spams, of which only 3-4 were false negatives, 0 of many (some 2 hundred probably, maybe even more) false positives

since *Jun 23* spamd stopped 94 spams from china etc (with blacklist)
and god know how many spamd didn't pass gray list  every day it sops at least 3 spams

EDIT:
spamassasin ain't that resource hungry


----------



## graudeejs (Aug 11, 2010)

ahh, almost forgot
http://wiki.apache.org/spamassassin/OtherTricks

Fake MX recors, I don't know how much spam they prevent, but it's quite easy to implement and I'm using it....


----------



## DutchDaemon (Aug 11, 2010)

Fake MX records do help, though I've abandoned them in favour of greylisting now.

I used three MX records, and only the middle one was real. So for example:


```
IN     MX     100     fake.smtp
IN     MX     105     real.smtp
IN     MX     110     fake.smtp
```

The fake ones can be one and the same. Spammer and bots usually pick the best or the worst MX, without falling back to the 2nd one. You should make sure that the fake IPs deliver an immediate tcp reset on port 25, or all genuine mail will hang for about 75 seconds.

Again: greylisting is a more elegant option, but the above served me well before that.


----------



## graudeejs (Aug 11, 2010)

I use both fake MX and gray listing


DutchDaemon, what do you use spamd or postgrey, or something else?


----------



## DutchDaemon (Aug 11, 2010)

I use mail/milter-greylist. And it's still 'bo*th*'


----------



## Sylhouette (Aug 13, 2010)

Hello vermaden, thanks for the dspam part.

I am thinking of replacing MailScanner for dspam.
The only thing is the webinterface of dspam, i can not get it to work.

Do you have that enabled, and if so can you extend the HOW TO

regards,
Sylhouette


----------



## vermaden (Aug 13, 2010)

@Sylhouette

Welcome mate.

I havent 'done' the web interface part because that machine was intended to be small (or oven tiny) because it has 128MB RAM and needs only about 400MB for everything (it will be running in VMware ESX/vSphere virtual machine to be precise), I even replaced 'stock' ssh daemon with security/dropbear because *sshd* consumes a lot more memory then *dropbear*.

If I will be adding the web interface, I would definitely add that info here.


----------



## kpa (Aug 13, 2010)

You might want to use some of rfc-ignorant.org RHSBLs in postfix.

Basically you should block all messages that have sender or recipient address in bogusmx.rfc-ignorant.org because sending mail to those domains or bouncing those messages is not going to work and it's best just to reject them in smtpd_sender_restrictions and smtpd_recipient_restrictions.

The other useful rhsbl is dsn.rfc-ignorant.org, it blocks any email with domain name that does not accept NULL sender (<>) that a DSN (delivery status notification message) uses, making proper bouncing of undelivered mail very hard. You might come across some MTAs that are listed in dsn.rfc-ignorant.org but you'd still want to accept email from them, whitelist those in smtpd_client_restrictions (or smtpd_sender_restrictions or both).

I do not recommend using postmaster.rfc-ignorant.org rhsbl, there are some very big domains that just don't have a working postmaster address.

http://www.rfc-ignorant.org/how_to_domain.php


----------



## vermaden (Aug 14, 2010)

@kpa

Thanks for suggestion, I will read about it.


----------



## Werner (Jan 28, 2011)

Hi there,

first of all thanks for this quite nice tutorial. It fits almost all my needs 

Unfortunately I have some problems which I think could be solved one after another.


/var/log/maillog

```
[...]
Jan 28 17:24:09 mail2 postfix/master[54620]: warning: process /usr/local/libexec/postfix/smtpd pid 54788 exit status 1
Jan 28 17:24:09 mail2 postfix/master[54620]: warning: /usr/local/libexec/postfix/smtpd: bad command startup -- throttling
Jan 28 17:25:04 mail2 postfix/smtpd[54793]: fatal: open database /usr/mail/postfix_accounts.db: No such file or directory
Jan 28 17:25:05 mail2 postfix/master[54620]: warning: process /usr/local/libexec/postfix/smtpd pid 54793 exit status 1
[...]
```

How can I create this .db file (maybe postfix should create it itself at startup but it doesn't) and what does this "bad command startup" mean? 
These errors happen when I try connecting to postfix using thunderbird.

If needed:
/usr/local/etc/postfix/mail.cf

```
queue_directory      = /var/spool/postfix
command_directory    = /usr/local/sbin
daemon_directory     = /usr/local/libexec/postfix
data_directory       = /var/db/postfix
mail_owner           = postfix
mynetworks_style     = host
sendmail_path        = /usr/local/sbin/sendmail
newaliases_path      = /usr/local/bin/newaliases
mailq_path           = /usr/local/bin/mailq
setgid_group         = maildrop
html_directory       = /usr/local/share/doc/postfix
manpage_directory    = /usr/local/man
sample_directory     = /usr/local/etc/postfix
readme_directory     = /usr/local/share/doc/postfix
mailbox_command      = /usr/local/libexec/dovecot/deliver
unknown_local_recipient_reject_code = 550

myhostname = mail2
#mynetworks = 0.0.0.0/8,127.0.0.0/8,10.0.0.0/8
#Note: 10.0.0.0/8 is my subnet for ezjails

smtpd_use_tls = yes
smtp_use_tls = yes
smtp_tls_note_starttls_offer = yes
smtpd_tls_key_file = /etc/ssl/postfix/smtpd.pem
smtpd_tls_cert_file = /etc/ssl/postfix/smtpd.pem
smtpd_tls_CAfile = /etc/ssl/postfix/smtpd.pem
smtpd_tls_loglevel = 0
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom



smtpd_sasl_auth_enable = yes
smtpd_sasl_path        = private/auth
smtpd_sasl_type        = dovecot


smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks

smtpd_recipient_restrictions =
  permit_mynetworks,
  permit_sasl_authenticated,
  reject_non_fqdn_hostname,
  reject_non_fqdn_sender,
  reject_non_fqdn_recipient,
  reject_unauth_destination,
  reject_unauth_pipelining,
  reject_invalid_hostname,
  reject_rbl_client bl.spamcop.net


#smtpd_recipient_restrictions =
#  permit_mynetworks,
#  permit_sasl_authenticated,
#  reject_unauth_destination

broken_sasl_auth_clients = yes
strict_rfc821_envelopes = no

virtual_mailbox_domains = extraneous.for.this
virtual_mailbox_base    = /usr/mail
virtual_mailbox_maps    = hash:/usr/mail/postfix_accounts
virtual_minimum_uid     = 100
virtual_uid_maps        = static:2000
virtual_gid_maps        = static:2000
virtual_transport       = lmtp:unix:/var/run/dspam.sock
transport_maps          = hash:/usr/mail/dspam_transport
dspam_destination_recipient_limit = 1
```

/usr/local/etc/postfix/master.cf

```
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd
  -o content_filter=lmtp:unix:/var/run/dspam.sock

smtps     inet  n       -       n       -       -       smtpd
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o message_size_limit=26214400

pickup    fifo  n       -       n       60      1       pickup
cleanup   unix  n       -       n       -       0       cleanup
qmgr      fifo  n       -       n       300     1       qmgr
tlsmgr    unix  -       -       n       1000?   1       tlsmgr
rewrite   unix  -       -       n       -       -       trivial-rewrite
bounce    unix  -       -       n       -       0       bounce
defer     unix  -       -       n       -       0       bounce
trace     unix  -       -       n       -       0       bounce
verify    unix  -       -       n       -       1       verify
flush     unix  n       -       n       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       n       -       -       smtp
relay     unix  -       -       n       -       -       smtp
        -o smtp_fallback_relay=
showq     unix  n       -       n       -       -       showq
error     unix  -       -       n       -       -       error
retry     unix  -       -       n       -       -       error
discard   unix  -       -       n       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       n       -       -       lmtp
anvil     unix  -       -       n       -       1       anvil
scache    unix  -       -       n       -       1       scache
dspam-retrain unix -    n       n       -       -       pipe
  flags=Rhq argv=/usr/local/bin/dspamc --client --mode=teft --class=${nexthop} --source=error --user ${sender}
```

I added SSL support to dovecot and postfix using this tutorial (thanks too ) : http://forums.freebsd.org/showthread.php?t=10728

Greetings
Werner


----------



## vermaden (Jan 28, 2011)

Werner said:
			
		

> Hi there,
> 
> first of all thanks for this quite nice tutorial. It fits almost all my needs



Welcome mate.



> How can I create this .db file (maybe postfix should create it itself at startup but it doesn't) and what does this "bad command startup" mean?



Try that one:

```
# cd /usr/mail
# postmap postfix_accounts
```

... also, I have moved from DSPAM to SpamAssassin since DSPAM stopped working at non deterministic way, just hang without any significant error ...

I really liked DSPAM because of its small code written in C, it was really fast and low on memory, a great scanner ... but really unmaintained. I regret that SpamAssassin takes a lot more 'momentum' then DSPAM and that DSPAM has so little community.


----------



## Werner (Jan 29, 2011)

Hi there,

fast answer wow 

[CMD=""]postmap postfix_accounts[/CMD]
working very well. I did the same with dspam_transport, 'cause postfix wanted it .

Now everything seems working well, even SSL :h.

Would you edit your Howto and add Spamassassin?

Grettings
Werner


Update:

I tried to integrate sa and clamav using amavisd myself using a view tutorials found with google, but I wasn't successfull.

Postfix doesnt receive emails from outside and emails sent by myself being dropt by amavis:

```
Jan 29 09:39:15 mail2 amavis[58098]: (!)DENIED ACCESS from IP 10.0.0.3, policy bank ''
```

/etc/hosts

```
127.0.0.1               localhost localhost.localdomain
10.0.0.3                mail2   mail2.localdomain
```

I edited inet_interfaces and hosts based on this:
http://www.mail-archive.com/freebsd-questions@freebsd.org/msg05604.html

/usr/local/etc/amavisd.conf

```
use strict;

# a minimalistic configuration file for amavisd-new with all necessary settings
[...]

$max_servers = 2;            # num of pre-forked children (2..30 is common), -m
$daemon_user  = 'vscan';     # (no default;  customary: vscan or amavis), -u
$daemon_group = 'vscan';     # (no default;  customary: vscan or amavis), -g

$mydomain = 'mail2.localdomain';   # a convenient default for other settings

# $MYHOME = '/var/amavis';   # a convenient default for other settings, -H
$TEMPBASE = "$MYHOME/tmp";   # working directory, needs to exist, -T
$ENV{TMPDIR} = $TEMPBASE;    # environment variable TMPDIR, used by SA, etc.
$QUARANTINEDIR = '/var/virusmails';  # -Q
# $quarantine_subdir_levels = 1;  # add level of subdirs to disperse quarantine
# $release_format = 'resend';     # 'attach', 'plain', 'resend'
# $report_format  = 'arf';        # 'attach', 'plain', 'resend', 'arf'

# $daemon_chroot_dir = $MYHOME;   # chroot directory or undef, -R

# $db_home   = "$MYHOME/db";      # dir for bdb nanny/cache/snmp databases, -D
# $helpers_home = "$MYHOME/var";  # working directory for SpamAssassin, -S
# $lock_file = "$MYHOME/var/amavisd.lock";  # -L
# $pid_file  = "$MYHOME/var/amavisd.pid";   # -P
#NOTE: create directories $MYHOME/tmp, $MYHOME/var, $MYHOME/db manually

$log_level = 5;              # verbosity 0..5, -d
$log_recip_templ = undef;    # disable by-recipient level-0 log entries
$DO_SYSLOG = 1;              # log via syslogd (preferred)
$syslog_facility = 'mail';   # Syslog facility as a string
           # e.g.: mail, daemon, user, local0, ... local7
$syslog_priority = 'debug';  # Syslog base (minimal) priority as a string,
           # choose from: emerg, alert, crit, err, warning, notice, info, debug

$enable_db = 1;              # enable use of BerkeleyDB/libdb (SNMP and nanny)
$enable_global_cache = 1;    # enable use of libdb-based cache if $enable_db=1
$nanny_details_level = 2;    # nanny verbosity: 1: traditional, 2: detailed
$enable_dkim_verification = 1;  # enable DKIM signatures verification
$enable_dkim_signing = 1;    # load DKIM signing code, keys defined by dkim_key

@local_domains_maps = ( [".$mydomain"] );  # list of all local domains

@mynetworks = qw( 127.0.0.0/8 [::1] [FE80::]/10 [FEC0::]/10
                  10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 );

$unix_socketname = "$MYHOME/amavisd.sock";  # amavisd-release or amavis-milter
               # option(s) -p overrides $inet_socket_port and $unix_socketname

$inet_socket_port = 10024;   # listen on this local TCP port(s)
# $inet_socket_port = [10024,10026];  # listen on multiple TCP ports

$policy_bank{'MYNETS'} = {   # mail originating from @mynetworks
  originating => 1,  # is true in MYNETS by default, but let's make it explicit
  os_fingerprint_method => undef,  # don't query p0f for internal clients
};

# it is up to MTA to re-route mail from authenticated roaming users or
# from internal hosts to a dedicated TCP port (such as 10026) for filtering
$interface_policy{'10026'} = 'ORIGINATING';

$policy_bank{'ORIGINATING'} = {  # mail supposedly originating from our users
  originating => 1,  # declare that mail was submitted by our smtp client
  allow_disclaimers => 1,  # enables disclaimer insertion if available
  # notify administrator of locally originating malware
  virus_admin_maps => ["virusalert\@$mydomain"],
  spam_admin_maps  => ["virusalert\@$mydomain"],
  warnbadhsender   => 1,
  # forward to a smtpd service providing DKIM signing service
  forward_method => 'smtp:[127.0.0.1]:10027',
  # force MTA conversion to 7-bit (e.g. before DKIM signing)
  smtpd_discard_ehlo_keywords => ['8BITMIME'],
  bypass_banned_checks_maps => [1],  # allow sending any file names and types
  terminate_dsn_on_notify_success => 0,  # don't remove NOTIFY=SUCCESS option
};

$interface_policy{'SOCK'} = 'AM.PDP-SOCK'; # only applies with $unix_socketname

[...]
$path = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/usr/bin:/bin';
# $dspam = 'dspam';

$MAXLEVELS = 14;
$MAXFILES = 1500;
$MIN_EXPANSION_QUOTA =      100*1024;  # bytes  (default undef, not enforced)
$MAX_EXPANSION_QUOTA = 300*1024*1024;  # bytes  (default undef, not enforced)

$sa_spam_subject_tag = '***SPAM*** ';
$defang_virus  = 1;  # MIME-wrap passed infected mail
$defang_banned = 1;  # MIME-wrap passed mail containing banned name
# for defanging bad headers only turn on certain minor contents categories:
$defang_by_ccat{+CC_BADH.",3"} = 1;  # NUL or CR character in header
$defang_by_ccat{+CC_BADH.",5"} = 1;  # header line longer than 998 characters
$defang_by_ccat{+CC_BADH.",6"} = 1;  # header field syntax error


# OTHER MORE COMMON SETTINGS (defaults may suffice):

$myhostname = 'mail2.localdomain';  # must be a fully-qualified domain name!

# $notify_method  = 'smtp:[127.0.0.1]:10025';
# $forward_method = 'smtp:[127.0.0.1]:10025';  # set to undef with milter!

 $final_virus_destiny      = D_PASS;
# $final_banned_destiny     = D_DISCARD;
$final_spam_destiny       = D_PASS;
# $final_bad_header_destiny = D_PASS;
# $bad_header_quarantine_method = undef;

$os_fingerprint_method = 'p0f:*:2345';  # to query p0f-analyzer.pl


# SOME OTHER VARIABLES WORTH CONSIDERING (see amavisd.conf-default for all)
[...]
```

/usr/local/etc/postfix/main.cf

```
[...]
myhostname = mail2
mynetworks = 127.0.0.0/8, 10.0.0.0/8
inet_interfaces = $myhostname, 10.0.0.3
[...]
virtual_transport       = dovecot
#transport_maps          = hash:/usr/mail/dspam_transport
dovecot_destination_recipient_limit = 1
content_filter = smtp-amavis:[127.0.0.1]:10024
max_use = 10
```

/usr/local/etc/master.cf

```
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
#smtp      inet  n       -       n       -       -       smtpd

smtp-amavis unix - - y - 2 lmtp
        -o smtp_data_done_timeout=1200
        -o disable_dns_lookups=yes

127.0.0.1:10025 inet    n       -       y       -       -       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=10.0.0.0/8,127.0.0.0/8
        -o strict_rfc821_envelopes=yes

smtps     inet  n       -       n       -       -       smtpd
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o message_size_limit=26214400

pickup    fifo  n       -       n       60      1       pickup
cleanup   unix  n       -       n       -       0       cleanup
qmgr      fifo  n       -       n       300     1       qmgr
tlsmgr    unix  -       -       n       1000?   1       tlsmgr
rewrite   unix  -       -       n       -       -       trivial-rewrite
bounce    unix  -       -       n       -       0       bounce
defer     unix  -       -       n       -       0       bounce
trace     unix  -       -       n       -       0       bounce
verify    unix  -       -       n       -       1       verify
flush     unix  n       -       n       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       n       -       -       smtp
relay     unix  -       -       n       -       -       smtp
        -o smtp_fallback_relay=
showq     unix  n       -       n       -       -       showq
error     unix  -       -       n       -       -       error
retry     unix  -       -       n       -       -       error
discard   unix  -       -       n       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       n       -       -       lmtp
anvil     unix  -       -       n       -       1       anvil
scache    unix  -       -       n       -       1       scache
#dspam-retrain unix -    n       n       -       -       pipe
#  flags=Rhq argv=/usr/local/bin/dspamc --client --mode=teft --class=${nexthop} --source=error --user ${sender}
```

I omit some comments and unnessecary parts of these config files to fall below the 10000 character limit 

Werner


----------



## vermaden (Jan 29, 2011)

> Would you edit your Howto and add Spamassassin?



I would rather create new howto, but yes, I will add it some day


----------



## anigma (Feb 26, 2011)

Hey,

Did you set any special options when installing each package? Basically you didn't touch any of the other options in the config files when preparing your mail server? Also, what kind of port forwarding has to be done? Obviously the ports that you set in your dovecot.conf has to be forwarded... any others?


----------



## vermaden (Feb 26, 2011)

anigma said:
			
		

> Hey,
> 
> Did you set any special options when installing each package? Basically you didn't touch any of the other options in the config files when preparing your mail server? Also, what kind of port forwarding has to be done? Obviously the ports that you set in your dovecot.conf has to be forwarded... any others?



You need to compile *postfix* with one of these:

```
[ ] DOVECOT    Dovecot 1.x SASL authentication method
[ ] DOVECOT2   Dovecot 2.x SASL authentication method
```

I have used *dovecot* 1.2, but I have also read recently that *dovecot* 2.x has many good improvements:
http://wiki2.dovecot.org/Upgrading/2.0


----------



## oliverh (Feb 26, 2011)

vermaden said:
			
		

> I assume that there were zero responses here because not many experienced mail server admins here?



Well, I have to work with sendmail and most of the time I don't have many time because of this fact  ;-)


----------



## vermaden (Feb 28, 2011)

I haven't tried sendmail, I started 'mail experience' with postfix, but I have heard that sendmail has its 'downsides'


----------



## cbrace (Oct 8, 2012)

First, a *big thanks* for vermaden for this very useful how-to.

I have a working mailserver built along these lines (mail/postfix + mail/dovecot2 + mail/dspam). I would would like to add sieve support, with mail/dovecot2-pigeonhole.

This page: Exim + Dovecot + Sieve + Roundcube + ManageSieve supplies useful instructions on configuring dovecot2 for sieve and adding support to mail/roundcube.

This page details adding sieve to postfix: Dovecot LDA with Postfix. It sounds straightforward: adding this line to master.cf:

```
dovecot   unix  -       n       n       -       -       pipe
  flags=DRhu user=vmail:vmail argv=/usr/local/libexec/dovecot/dovecot-lda -f ${sender} -d ${recipient}
```
and this to main.cf:

```
dovecot_destination_recipient_limit = 1
virtual_transport = dovecot
```

I have now gotten to the point where roundcube now has a "filter" tab in the settings and can connect with the sieve server on port 4190. I can now create a test filter from the roundcube interface.

I am still missing a piece of the puzzle however. With this line enabled in main.cf: 


> virtual_transport = dovecot



an incoming message bounces with a "user unknown" error:

```
Oct  8 17:15:20 venus postfix/pipe[90375]: 21876A42C0: to=<cb@****.**>, orig_to=<colin>, relay=dovecot, delay=0.5, delays=0.4/0.02/0/0.08, dsn=5.1.1, status=bounced (user unknown)
```

when I comment out that line postfix delivers an incoming message normally but obviously misses the sieve step supplied by dovecot:

```
Oct  8 17:16:13 venus postfix/virtual[90497]: 77025A42C0: to=<cb@****.**>, orig_to=<colin>, relay=virtual, delay=0.04, delays=0.03/0/0/0, dsn=2.0.0, status=sent (delivered to maildir)
```

Any ideas on what I am missing here?

TIA


----------



## vermaden (Oct 15, 2012)

cbrace said:
			
		

> First, a *big thanks* for vermaden for this very useful how-to.



Welcome.



			
				cbrace said:
			
		

> It sounds straightforward: adding this line to master.cf:
> 
> ```
> dovecot   unix  -       n       n       -       -       pipe
> ...



I used this one:

```
dovecot    unix  -       n       n       -       -       pipe
  flags=DRhu user=virtual:virtual argv=/usr/local/libexec/dovecot/deliver -f ${sender} -d ${recipient}
```

... and after switching to *spamsassassin* (*dspam* made segmentation fault often) I use now something like that:

```
dovecot    unix  -       n       n       -       -       pipe
  flags=DRhu user=virtual:virtual argv=/usr/local/bin/spamc -u ${recipient} -e /usr/local/libexec/dovecot/deliver -f ${sender} -d ${recipient}
```


----------



## cbrace (Oct 16, 2012)

Hi Vermaden,

I've changed the line in master.cf to ../dovecot/deliver.

Incoming mails are no longer bounced, but are now accepted, but delivery is temporarily deferred. From maillog:


```
Oct 16 12:39:37 paz postfix/lmtp[514]: 320883BE2D: to=<cb@lim.nl>, relay=paz[/var/run/dspam.sock], delay=0.71, delays=0.02/0.01/0/0.67, dsn=2.6.0, status=sent (250 2.6.0 <cb@lim.nl> Message accepted for delivery)
Oct 16 12:39:37 paz postfix/qmgr[414]: 320883BE2D: removed
Oct 16 12:41:02 paz postfix/qmgr[414]: CD03E3BE5B: from=<cbrace@mail.#######.net>, size=1282, nrcpt=1 (queue active)
Oct 16 12:41:02 paz postfix/pipe[516]: CD03E3BE5B: to=<cb@lim.nl>, relay=dovecot, delay=583, delays=583/0.01/0/0.06, dsn=4.3.0, status=deferred (temporary failure)
```

I have switched on auth-debugging in dovecot, and this is what I see in /var/log/dovecot:

```
Oct 16 12:31:19 auth: Debug: auth client connected (pid=0)
Oct 16 12:31:20 auth: Debug: master in: USER	1	cb@lim.nl	service=lda
Oct 16 12:31:20 auth: Debug: passwd(cb@lim.nl): lookup
Oct 16 12:31:20 auth: Info: passwd(cb@lim.nl): unknown user
Oct 16 12:31:20 auth: Debug: passwd-file /usr/local/etc/dovecot-passwd: Read # users in 0 secs
Oct 16 12:31:20 auth: Debug: passwd-file(cb@lim.nl): lookup: user=cb@lim.nl file=/usr/local/etc/dovecot-passwd
Oct 16 12:31:20 auth: Debug: userdb out: USER	1	cb@lim.nl	uid=1001	gid=6	home=/var/db/vmail/lim.nl/cb
```

Up until now, using postfix virtual delivery, I have had all mail incoming to various virtual domains delivered to a single system user, in my case "colin". This line in dovecot-passwd 

```
colin:{PLAIN-MD5}516b38afeee70474b04881a633728b15
```
With these credentials my mail clients connect with IMAP. However, it appears from auth debug that dovecot delivery is looking for a user in the userdb (dovecot-passwd?), so I added an entry matching the actual recipient, like this:

```
cb@lim.nl:{SSHA}63a5fRaKfNcG2f8FPy3y4xC8Vz3o+D9e
```
This where I am stuck. Dovecot says USER UNKOWN, even though I have an entry. 

It appears to be determining a destination: 
	
	



```
home=/var/db/vmail/lim.nl/cb
```
This exists; it isn't the one IMAP when one logs in using a system name but that can be fixed. But something is still going wrong with delivery.

With my very limited knowledge of postfix and dovecot am wondering whether there is some config error between the system  and virtual users. I don't need virtual users on this mailserver, but I do need virtual domains.

Any ideas?


----------



## vermaden (Oct 18, 2012)

I do not have any ideas how to fix this one, but I can sent You my current configuration with postfix, dovecot and spamd.


----------



## cbrace (Oct 19, 2012)

Thanks, but first a quick question: are you currently using Dovecot1 or Dovecot2?


----------



## vermaden (Oct 19, 2012)

@cbrace  

dovecot-1.2.17


----------



## cbrace (Oct 20, 2012)

Ah, OK. I'm using v2.

I will go through your configuration line-by-line and see if I can figure out what you are doing that I'm not. If that fails, I'll ask on the dovecot ML.


----------



## cbrace (Nov 2, 2016)

vermaden said:


> My current concerns are:
> -- *dspam(1)* daemon runs on root, it should run on its user (like dspam for example), any tips how to make the permissions?


This appears to have been fixed with release v3.10.2_2 of mail/dspam which, if I am not mistaken, was released in May. From files/UPDATING:

```
# dspam-3.10.2_2
#

Port Changes:
- Runs as dspam:dspam instead of root:mail [1]
- Default run directory is now /var/run/dspam [1]
- Default daemon/client communication port is now 2424 [1]
- New SETUID option to enable old insecure behavior [1]

[1] Questionable ownership and security on mail/dspam (PR #115957)
```
However, I am unable to get this latest version to work. I see this error in maillog:

```
Nov  2 14:17:07 galatea dspam[94824]: Daemon process starting
Nov  2 14:17:07 galatea dspam[94824]: Creating local domain socket /var/run/dspam.sock
Nov  2 14:17:07 galatea dspam[94824]: Daemon mode failed to start
Nov  2 14:17:07 galatea dspam[94824]: Daemon process exiting
Nov  2 14:19:37 galatea dspam[94843]: Unable to determine the destination user
Nov  2 14:19:37 galatea dspam[94843]: DSPAM agent misconfigured: aborting
```
I have to revert to v3.10.2 to get dspam working again.

When dspam is run on the command line, for retraining, you feed it owner of the mail like this (from my roundcube config):

```
$rcmail_config['markasjunk2_spam_cmd'] = "/usr/local/bin/dspam --user %u  --class=spam --source=error --signature=%xds";
```
I have no idea though whether this is the "destination user" referred to in the error message above. In any case, the previous version doesn't complain about this.

Has anyone here gotten this version working? vermaden ?


----------



## vermaden (Nov 4, 2016)

I have created this mail server in 2010, 6 years ago and this mail server has been phased out of production in late 2011, 5 years ago.

Its ok if someone finds this HOWTO useful but I think its very outdated and would need some rework/update to make it usable in 2016.

Regards,
vermaden


----------

