.
.
.
.
.
.
Â
Â
 Â
Full-fledged Postfix using LDAP HOWTOPostfix, LDAP, IMAP, WebMail, Virus- and spamscanning/checking mail systemby Tom Scholten and author of likewise documentsSpecial thanks to Richard from UnixGuru.nl  |
Â
Â
The document provides a description or howto if you will to build a unix-based postfix mailserver capable of multiple virtual domains and users based upon LDAP. There are other documents describing how to implement Postfix and LDAP, and this howto is based upon them, but is written as a 'from-scratch' to 'fully-operational' manual, as i found a great tutorial on Postfix-Mysql including a nice PHP admin frontend besides the great JAMM approach which has also a nice, but in java (server pages), admin tool. Plans for now are to deliver both a perl/cgi interface AND a PHP interface to administrate you're very own Postfix-LDAP mail system.
Â
This page aims at describing how i installed and configured Postfix with virtual domains, ldap and virusscanning on a FreeBSD 5.x system
There is no reason why this wouldn’t work on any other UN*X system, including all flavors of linux, *bsd, hpux, tru64, solaris or aix. Maybe on SCO but i don’t like either there OS nor their attitude.
Ofcourse no responsibility or liability blah blah blah, to be continued
Â
Â
Heads up : The proposed mailserver in this document is using amavis for content scanning, i’m working on a second version of this document using MailScanner instead of amavis, hopefully with user-specific SpamAssassin rules in LDAP (using SA 3.x)
Â
Installed software (on FreeBSD)
Installed packages from the portstree (in no particular order, let alone dependancy order)
- procmail (3.22)
- postfix (2.2.1)
- courier-imap (3.0.4,1)
- squirrelmail (1.4.3a)
- apache2 (2.0.50)
- php (4.3.7)
- openldap (2.0.25)
- clamav (0.74)
- amavisd-new (20030616)
- p5-SpamAssassin (2.63)
Assumptions
Assumptions made for this howto
- The example domain name will be ‘example.org’
- The virtual users (mail)directory store will live under /usr/virtual
- The virtual user used is vmail (group vmail) uid/gid are both 2001
- The scanner runs as vscan/vscan (2002/2002)
OpenLDAP configuration
First edit slapd.conf in /usr/local/etc/openldap, the example below does NOT have a safe password (secret), which you should create using slappasswd from the commandline. It asks you to type you’re password twice and then prints out the string to be used. You can use another (than SSHA, the default) algorythm, man slappasswd for more information! Also in the example below there are NO acl’s so anyone has access to you’re information, consider RTFM on (Open)LDAP to secure you’re LDAPtree some more.
slapd.conf
include /usr/local/etc/openldap/schema/core.schema include /usr/local/etc/openldap/schema/cosine.schema include /usr/local/etc/openldap/schema/nis.schema include /usr/local/etc/openldap/schema/mailserver.schema ####################################################################### # ldbm database definitions ####################################################################### database ldbm suffix "dc=example,dc=org" rootdn "cn=Manager,dc=example,dc=org" #rootpw secret rootpw {SSHA}FyQuk6XJK4aYcz1fh6RhbG2g/CtvCtz3 # The database directory MUST exist prior to running slapd AND # should only be accessable by the slapd/tools. Mode 700 recommended. directory /var/db/openldap-data # Indices to maintain index objectClass pres,eq index mail,cn eq,sub # logging loglevel 256
OpenLDAP scheme for mailserver
Next, create the LDAPscheme to be used for our mailserver in /usr/local/etc/openldap/schema
The used mailserver.schema
# # OID prefix: 1.3.6.1.4.1.12461 # # Attributes: 1.3.6.1.4.1.12461.1.1 # attributetype ( 1.3.6.1.4.1.12461.1.1.1 NAME 'postfixTransport' DESC 'A string directing postfix which transport to use' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{20} SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.12461.1.1.2 NAME 'accountActive' DESC 'A boolean telling whether an account is active or not' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.12461.1.1.3 NAME 'lastChange' DESC 'Time in unix time of last change in entry' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) #attributetype ( 1.3.6.1.4.1.12461.1.1.4 NAME 'jvd' # DESC 'A virtual domain managed by Jamm' # EQUALITY caseIgnoreIA5Match # SUBSTR caseIgnoreIA5SubstringsMatch # SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) # The following attributes are borrowed from Courier's schema so that # the Jamm Schema can live on its own. attributetype ( 1.3.6.1.4.1.12461.1.1.5 NAME 'mailbox' DESC 'The absolute path to the mailbox for a mail account in a non-default location' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.12461.1.1.6 NAME 'quota' DESC 'A string that represents the quota on a mailbox' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.12461.1.1.7 NAME 'clearPassword' DESC 'A separate text that stores the mail account password in clear text' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128}) attributetype ( 1.3.6.1.4.1.12461.1.1.8 NAME 'maildrop' DESC 'RFC822 Mailbox - mail alias' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) attributetype ( 1.3.6.1.4.1.12461.1.1.9 NAME 'mailsource' DESC 'Message source' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) # Back to more of Jamm specific attributes attributetype ( 1.3.6.1.4.1.12461.1.1.10 NAME 'editAliases' DESC 'A boolean telling whether a domain manager can edit Aliases' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.12461.1.1.11 NAME 'editAccounts' DESC 'A boolean telling whether a domain manager can edit Accounts' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.12461.1.1.12 NAME 'editPostmasters' DESC 'A boolean telling whether a domain manager can edit Postmasters' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.12461.1.1.13 NAME 'editCatchAlls' DESC 'A boolean telling whether a domain manager can edit CatchAlls' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.12461.1.1.14 NAME 'delete' DESC 'A boolean telling whether this item is marked for deletion' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) # # Objects: 1.3.6.1.4.1.12461.1.2 # objectclass ( 1.3.6.1.4.1.12461.1.2.1 NAME 'mailAccount' SUP top STRUCTURAL DESC 'Mail account objects' MUST ( mail $ homeDirectory $ mailbox $ accountActive $ lastChange $ delete ) MAY ( uidNumber $ gidNumber $ uid $ cn $ description $ quota $ userPassword $ clearPassword ) ) objectclass ( 1.3.6.1.4.1.12461.1.2.2 NAME 'mailAlias' SUP top STRUCTURAL DESC 'Mail aliasing/forwarding entry' MUST ( name $ mail $ maildrop $ accountActive $ lastChange ) MAY ( mailsource $ cn $ description $ userPassword ) ) objectclass ( 1.3.6.1.4.1.12461.1.2.3 NAME 'mailDomain' SUP domain STRUCTURAL DESC 'Virtual Domain entry to be used with postfix transport maps' MUST ( dc $ accountActive $ lastChange $ delete $ editAccounts $ editPostmasters ) MAY ( postfixTransport $ description ) ) # SUP top STRUCTURAL # MUST ( jvd $ accountActive $ lastChange $ delete $ editAccounts $ objectClass ( 1.3.6.1.4.1.12461.1.2.4 NAME 'mailPostmaster' SUP top AUXILIARY DESC 'Added to a mailAlias to create a postmaster entry' MUST roleOccupant )
Ready, Aim, OpenLDAP
Now start up you’re OpenLDAP server either by hand or use /usr/local/etc/rc.d/slapd.sh start and verify that slapd is running (ps ax | egrep slap[d]). If it’s running were ready to fill …
OpenLDAP tree layout and initial ldif
This initial ldif will create you’re domains, so if you have many, just stick to one or two at the time to test out, were creating the following tree.
Â
org | example----------Manager | | +----------------------------------+-----------------------------+----------------------------+ example.org somenudomain.nu someoldaccount.demon.org domain3.org |
Â
setup ldif file
warning! if you have openldap22 or above, you should add to the primary dc= objects the following lines (whatever is the dc declared, for the first entry below it becomes ‘example’ for the other (mail) object it becomes mail
Â
objectClass: dcObject dc: whatever
# example dn: dc=example, dc=org objectClass: top objectClass: organization objectClass: dcObject o: example dc: example # MAnager dn: cn=Manager,dc=example,dc=org objectClass: top objectClass: organizationalRole cn: Manager # mail, example dn: dc=mail, dc=example, dc=org objectClass: top objectClass: organizationalunit objectClass: dcObject ou: mail dc: mail # example.org, mail, example dn: dc=example.org, dc=mail, dc=example,dc=org accountActive: TRUE editPostmasters: TRUE editAccounts: TRUE objectClass: top objectClass: mailDomain dc: example.org delete: FALSE lastChange: 111 postfixTransport: virtual: # somenudomain.nu, mail, example dn: dc=somenudomain.nu, dc=mail, dc=example,dc=org accountActive: TRUE editPostmasters: TRUE editAccounts: TRUE objectClass: top objectClass: mailDomain dc: somenudomain.nu delete: FALSE lastChange: 111 postfixTransport: virtual: # someoldaccount.demon.org, mail, example dn: dc=someoldaccount.demon.org, dc=mail, dc=example,dc=org accountActive: TRUE editPostmasters: TRUE editAccounts: TRUE objectClass: top objectClass: mailDomain dc: someoldaccount.demon.org delete: FALSE lastChange: 111 postfixTransport: virtual: # domain3.org, mail, example dn: dc=domain3.org, dc=mail, dc=example,dc=org accountActive: TRUE editPostmasters: TRUE editAccounts: TRUE objectClass: top objectClass: mailDomain dc: domain3.org delete: FALSE lastChange: 111 postfixTransport: virtual:
cat FILENAME | ldapadd -x -D ‘cn=Manager,dc=example,dc=org’ -w secret to add the information to your LDAP server
OpenLDAP scripts
Using the script provide below we can add users, according to the domain setup shown below using the following commands
example
- ./ldapadduser.pl vivian example.org "Secret123" mailbox | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret
- ./ldapadduser.pl alexander example.org "Dog=Cr@zy" mailbox | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret
- ./ldapadduser.pl roland_dg example.org "a1zihw" mailbox | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret
- ./ldapadduser.pl postmaster example.org alexander@example.org,vivian@example.org alias | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret
- ./ldapadduser.pl webmaster example.org john@webbuilders.com alias | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret
- ./ldapadduser.pl "*" example.org vivian@example.org alias | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret
somenudomain.nu
- ./ldapadduser.pl ian somenudomain.nu "vivian" mailbox | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret
- ./ldapadduser.pl postmaster somenudomain.nu alexander@example.org alias | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret
- ./ldapadduser.pl webmaster somenudomain.nu "w3bs1t3" mailbox | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret
someoldaccount.demon.org
- ./ldapadduser.pl "*" someoldaccount.demon.org @somenudomain.nu alias | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret
domain3.org
- ./ldapadduser.pl postmaster domain3.org alexander@example.org alias | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret
- ./ldapadduser.pl webmaster domain3.org alexander@example.org alias | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret
And so, we should have created a tree looking like this, with vivian@example.org receiving all ‘non-existing-mailbox’ mail from example.org and all mail from ‘someoldaccount.demon.org’ delivered to somenudomain.nu (so you can email ian@someoldaccount.demon.org and still reach ian, whom (ofcourse) should have procmail or so set up to warn people about his changed domain name, but that’s outside the scope of this document). Also mind that postmaster@example.org is delivered to BOTH alexander AND vivian. The add-script just makes to ‘maildrop’s in the LDAP tree!
Â
Â
org | example----------Manager | | +----------------------------------+-----------------------------+----------------------------+ example.org somenudomain.nu someoldaccount.demon.org domain3.orgVivian ian *@ -> somenudomain.nu postmaster Alexander postmaster webmaster Roland_dG webmaster postmaster webmaster *@ -> vivian@example.org |
Â
perl script to generate ldif for changing/adding users (just use ldapmodify instead of the suggested ldapadd)
Â
#!/usr/local/bin/perl # ldapadduser.pl # # AddUser-LDAP: Generate User entry for adding in LDAP # Author: Raymond Ho # History: Modify from genuser.pl from # MacGyver aka Habeeb J. Dihu # 20040601 Tom Scholten, modified to do much more than just adding # Copyright (C) 2002, He Zhi Qiang Raymond.Ho use Carp; croak "Usage: $0 [accountname] [example.org] [cleartext-password|foo@bar.com{,bar@foo.com,com@foo.bar}] [mailbox|alias] accountname being everything before the @ or if you would like a 'fallthrough/wildcard' match "*" (don't let shell interpret the *!!!) examples Create new mailbox for user132@domain1.org using password MySecretPw $0 user132 domain1.org MySecretPw mailbox Map whole domain4.org to domain5.org $0 "*" domain4.org @domain5.org alias Create fallthough catch for domain6.org to postmaster@domain6.org $0 "*" domain6.org postmaster@domain6.org alias Create a webmaster@domain3.org alias which expands to the scriptmanager and contentmanager addresses $0 webmaster domain3.org scriptmanager@domain3.org,contentmanager@domain3.org alias " unless $#ARGV == 3; # Random salt. $salt = join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]; # output list $dn = "dn: mail=$ARGV[0]@$ARGV[1],dc=$ARGV[1], dc=mail,dc=example, dc=orgn"; $change = "lastChange: 1n"; $obj1 = "objectClass: topn"; if ( $ARGV[3] eq "mailbox" ) { $obj2 = "objectClass: mailAccountn"; $mailbox = "mailbox: $ARGV[1]/$ARGV[0]/Maildir/n"; $home = "homeDirectory: /usr/virtualn"; $clearpwd = "clearPassword: $ARGV[2]n"; $userpwd = "userPassword: {crypt}".crypt($ARGV[2], $salt)."n"; $uid = "uid: $ARGV[0]n"; $del = "delete: FALSEn"; } elsif ( $ARGV[3] eq "alias" ) { $obj2 = "objectClass: mailAliasn"; @aliases = split(/,/,$ARGV[2]); foreach $alias (@aliases) { $maildrop .= "maildrop: $aliasn"; } if ( $ARGV[0] eq "*" ) { $uid = "name: @$ARGV[1]n"; } else { $uid = "name: $ARGV[0]n"; } } else { croak "Cannot continue, choose either mailbox or aliasn"; } $at = "accountActive: TRUEn"; #if ( $ARGV[0] eq "*" ) { # $mail = "mail: @$ARGV[1]n"; #} else { $mail = "mail: $ARGV[0]@$ARGV[1]n"; #} # output to stdin print "$dn$change$uid$obj1$obj2$at$del$mail$home$mailbox$maildrop$clearpwd$userpwd"; print "n# pipe this throug -> | ldapadd -x -D 'cn=Manager,dc=example,dc=org' -w secret <- to insert into ldapn";
OpenLDAP searching
Now let’s try to find our entries in LDAP Search domains in the tree
# ldapsearch -x -wsecret -D "cn=Manager, dc=example, dc=org" -s sub -b "dc=mail,dc=example,dc=org" "(&(objectClass=mailDomain)(accountActive=TRUE))" Search accounts in the tree
# ldapsearch -x -wsecret -D "cn=Manager, dc=example, dc=org" -s sub -b "dc=mail,dc=example,dc=org" "(&(objectClass=mailAccount)(accountActive=TRUE))" Search aliases in the tree
# ldapsearch -x -wsecret -D "cn=Manager, dc=example, dc=org" -s sub -b "dc=mail,dc=example,dc=org" "(&(objectClass=mailAlias)(accountActive=TRUE))"
ClamAV, virusscanner
ClamAV uses /usr/local/etc/clamav.conf for configuration, the only changes made were
- changed localsocket to /var/amavis/clamd
- changed user to vscan
AMaViS, contentscanner
AMaViS uses /usr/local/etc/amavis.conf for configuration,
- changed MyDomain to example
- changed user/group to vscan
- Also change the settings described below;
-- replaced the lines containing $final_virus_destiny = D_BOUNCE; # (defaults to D_BOUNCE) $final_banned_destiny = D_BOUNCE; # (defaults to D_BOUNCE) $final_spam_destiny = D_BOUNCE; # (defaults to D_REJECT) $final_bad_header_destiny = D_PASS; # (defaults to D_PASS), D_BOUNCE suggested -- with the following lines $final_virus_destiny = D_DISCARD; # (defaults to D_BOUNCE) $final_banned_destiny = D_DISCARD; # (defaults to D_BOUNCE) $final_spam_destiny = D_DISCARD; # (defaults to D_REJECT) $final_bad_header_destiny = D_PASS; # (defaults to D_PASS), D_BOUNCE suggested -- uncommented the following lines and the second was changed to /var/amavis/clamd ['Clam Antivirus-clamd', &ask_daemon, ["CONTSCAN {}n", "/var/amavis/clamd"], 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"],
Starting the content scanner
Now startup clamav using /usr/local/etc/rc.d/clamav-clamd.sh start after updating /etc/rc.conf with a line
- clamav_clamd_enable="YES"
- clamav_freshclam_enable="YES"
- amavisd_enable="YES"
The last being optional but recommended since it will update you’re database, so consider using it and also running /usr/local/etc/rc.d/clamav-freshclam.sh start. After making sure /var/amavis/clamd exists and (ofcourse) ps ax | egrep clam[d] returns a running process, start AMAVIS using /usr/local/etc/rc.d/amavisd.sh start and verify we can use it to send mail, as taken from the README from Amavis/Postfix.
--> $ 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: 250 2.1.0 Sender test@example.com OK --> RCPT TO: 250 2.1.5 Recipient postmaster OK --> DATA 354 End data with . --> Subject: test1 --> --> test1 --> .*** 250 2.6.0 Ok, id=31859-01, from MTA: 250 Ok: queued as 90B7F16F--> MAIL FROM: 250 2.1.0 Sender test@example.com OK --> RCPT TO:250 2.1.5 Recipient postmaster OK --> DATA 354 End data with . --> Subject: test2 - virus test pattern --> --> X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* --> .you should get one of the following replies (or similar), depending on your $final_virus_destiny and *virus_lovers* settings in amavisd.conf: *** 550 5.7.1 Message content rejected, id=16968-01 - VIRUS: EICAR-AV-Test *** 250 2.5.0 Ok, but 1 BOUNCE *** 250 2.7.1 Ok, discarded, id=16984-01 - VIRUS: EICAR-AV-Test *** 250 2.6.0 Ok, id=17041-01, from MTA: 250 Ok: queued as 3F1841A5F5--> QUIT 221 2.0.0 [127.0.0.1] (amavisd) closing transmission channel Connection closed by foreign host. |
Configure postfix
Changes to postfix’ main.cf, also change other settings to customize you’re requirements. Setting ‘soft_bounce=yes’ for testing purposes while starting out using you’re new mailserver would be a wise decision!
# Transports transport_server_host = localhost transport_search_base = dc=mail,dc=example,dc=org transport_query_filter = (&(dc=%s)(objectClass=mailDomain)(accountActive=TRUE)(delete=FALSE)) transport_result_attribute = postfixTransport #transport_cache = yes transport_bind = no transport_scope = one # Aliases aliases_server_host = localhost aliases_search_base = dc=mail,dc=example,dc=org aliases_query_filter = (&(objectClass=mailAlias)(mail=%s)(accountActive=TRUE)) aliases_result_attribute = maildrop aliases_bind = no #aliases_cache = yes # Accounts accounts_server_host = localhost accounts_search_base = dc=mail,dc=example,dc=org accounts_query_filter = (&(objectClass=mailAccount)(mail=%s)(accountActive=TRUE)(delete=FALSE)) accounts_result_attribute = mailbox accounts_bind = no #accounts_cache = yes accountsmap_server_host = localhost accountsmap_search_base = dc=mail,dc=example,dc=org accountsmap_query_filter = (&(objectClass=mailAccount)(mail=%s)(accountActive=TRUE)(delete=FALSE)) accountsmap_result_attribute = mail accountsmap_bind = no #accountsmap_cache = yes # Transport map transport_maps = ldap:transport mydestination = $myhostname, localhost.$mydomain, $mydomain, mail.$mydomain, $transport_maps # Virtual maps virtual_maps = ldap:aliases, ldap:accountsmap # Virtual accounts virtual_mailbox_base = /usr/virtual virtual_mailbox_maps = ldap:accounts virtual_minimum_uid = 2000 virtual_uid_maps = static:2000 virtual_gid_maps = static:2000 # Local accounts local_alias_maps = hash:/etc/aliases local_recipient_maps = $local_alias_maps unix:passwd.byname # local_transport should set to "virtual" to deliver mail to local VirtualAccount # 's $HOME direcotry . or not set here, mail delivery would be failure local_transport = virtual local_recipient_maps = $alias_maps unix:passwd.byname $virtual_mailbox_maps # AMAVIS content_filter = smtp-amavis:[127.0.0.1]:10024
Changes to postfix’ master.cf (optionally replace the ‘y’ with ‘n’ depending on you’re chroot wishes). Make sure ‘virtual’ and ‘maildrop’ also exist in master.cf
smtp-amavis unix - - y - 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 - 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=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
Starting you’re mailserver
Next again edit /etc/rc.conf to disable sendmail and enable postfix
Insert
- sendmail_enable="NONE"
Comment out/remove
- sendmail_enable="YES"
- sendmail_flags="-bd"
- sendmail_pidfile="/var/spool/postfix/pid/master.pid"
- sendmail_outbound_enable="NO"
- sendmail_submit_enable="NO"
- sendmail_msp_queue_enable="NO"
Now would be a great time to start postfix, but before you do touch /var/log/maillog and open a second terminal, screen or whatever and do a tail -f /var/log/maillog there (as well as maybe a tail on /var/log/messages) to see what’s going on. Now you’re ready to start postfix simply by typing postfix start
Verify mail sending and receiving
Verify that you can send mail by sending yourself mail. If using an address@example.org which is an alias (pointing outside one of the domains for wich your new postfix server receives mail) please check you’re headers and confirm their ok. If receiving on a mailbox address (at your new postfix server), look in /usr/virtual and confirm you have a new directory named example.org (depending on the recipient). Below that directory your mailbox name (as a directory) should emerge, containing various maildir files. Besides checking that your mail was received also check the headers!
Note that users of a mailbox should have received at least one email to have their directory (and maildir files) in place When you create a new mailbox (not alias), you should send the new user a ‘welcome’ mail of some kind to let postfix create their ‘homedirectory’ in /usr/virtual. When omitted the user will receive an error when checking mail (either via imap/pop or when using webmail)
Webmail, a web frontend to mail
In this howto we choose squirrelmail. Why? Because it’s a good, safe and easy to install webmail application. When using FreeBSD we can install squirrelmail from ports, but i decided to just download the package and do everything by hand. Either way you’ll end up with a squirrelmail directory (/usr/local/www/data/squirrelmail) which contains a file called configure. Run ./configure in the squirrelmail directory and a menu will appear. For our sample setup the following defaults were changed
2 - Server Settings 1 - Domain example.org 3 - Sendmail or SMTP SMTP A - Update IMAP settings (reveals new options) 4 - IMAP server localhost 5 - IMAP port 993 6 - Authentication type login 7 - Secure IMAP (TLS) true 8 - Server software courier B - Update SMTP settings (reveals new options)) 4 - SMTP server localhost 5 - SMTP port 25 R - Return to main menu
You can change more options if you like, and even install some nice plugins from the squirrelmail website but this will do for now. Point your webbrowser to http://www.example.org/squirrelmail and login as one of your mailbox users. Happy webmailing!
Documents and resources used
Besides RTFM on various packages used to install a number of special resources will be named below the packages linklist; (in no particular order)
- Postfix, MTA used
- Spam tagging software
- LDAP software
- Webmail software
- Mailinglist software (when done, you could add mailinglists, not captured in this document)
- ClamAV Antivirus software
- Short for [A] [MA]il [VI]rus [S]canner
- Apache webserver for webmail and admin (php) interface
- The admin interface was build using php
Most usefull to produce this document was :http://janus.errornet.de/ with his pdf and schema
((mirrored here) pdf and schema)
Others resources used
- http://jamm.sourceforge.net everything else seems to be based upon this
- http://www.vriesman.tk detailed enough for me
Â
Â
Tom Scholten is Unix specialist with Snow B.V., a Dutch Technical Consultancy Company supplying specialists in the field of Networking and Unix
Â
Â
 |  |  |  |