{"id":232,"date":"2007-03-08T10:11:33","date_gmt":"2007-03-08T09:11:33","guid":{"rendered":"http:\/\/tom.scholten.nu\/weblog\/?page_id=232"},"modified":"2013-02-10T20:56:28","modified_gmt":"2013-02-10T18:56:28","slug":"postfix_ldap_howto","status":"publish","type":"page","link":"https:\/\/tom.scholten.nu\/weblog\/postfix_ldap_howto","title":{"rendered":"Postfix LDAP Howto v2.1"},"content":{"rendered":"<p>Last updated on 05th of August 2007<\/p>\n<p><a href=\"http:\/\/tom.scholten.nu\/weblog\/en\/postfix_mysql_howto\">You can also check my newer page on Postfix MySQL over here\u00c2\u00a0http:\/\/tom.scholten.nu\/weblog\/en\/postfix_mysql_howto<\/a><\/p>\n<p>&nbsp;<\/p>\n<h2>Full-fledged Postfix using LDAP HOWTO<\/h2>\n<h3>Postfix, LDAP, IMAP, WebMail, Virus- and spamscanning\/checking mail system<\/h3>\n<h4>by Tom Scholten and authors of likewise documents<\/h4>\n<h3>v2.1<\/h3>\n<h4>Special thanks to Richard from UnixGuru.nl<\/h4>\n<table width=\"100%\" border=\"0\">\n<tbody>\n<tr>\n<td align=\"left\"><img loading=\"lazy\" decoding=\"async\" title=\"Postfix\" alt=\"Postfix\" src=\"http:\/\/tom.scholten.nu\/weblog\/wp-content\/uploads\/2007\/03\/postfix1.gif\" width=\"130\" height=\"91\" align=\"middle\" \/><\/td>\n<td align=\"right\"><img loading=\"lazy\" decoding=\"async\" title=\"OpenLDAP\" alt=\"OpenLDAP\" src=\"http:\/\/tom.scholten.nu\/weblog\/wp-content\/uploads\/2007\/03\/ldap1.gif\" width=\"305\" height=\"120\" align=\"middle\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<hr \/>\n<p>This document tens to provide a description of how to set up a &#8216;full fledge&#8217; mailserver using Postfix as it&#8217;s core. It will be extended using mailing list managers and webmail on the frontend side but will feature spam- and virus detection and avoidance software to handle the backend. There will also be a backend interface for mailhandling (web-based). All software used is available from the web and open source. The solution chosen will provide capabilities for multiple users and multiple domains, so you might use it for your small\/average ISP solutions. This document can be used as a HOWTO document on FreeBSD or likewise systems, but will also apply to generic Unices like Solaris or Linuces (e.g. RedHat\/Ubuntu\/Debian\/etc. There are other documents describing how to implement Postfix and LDAP, and this howto is based upon them, but is written as a &#8216;from-scratch&#8217; to &#8216;fully-operational&#8217; 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&#8217;re very own Postfix-LDAP mail system.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<hr \/>\n<p>This page describes how i installed and configured the solution on a FreeBSD 6.x system. There is no reason why this wouldn&#8217;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&#8217;t like either there OS nor their attitude. Ofcourse no responsibility or liability blah blah blah, to be continued<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<hr \/>\n<h2>Installed software (on FreeBSD)<\/h2>\n<p>Today, 05th of August 2007, I started updating this howto by building a complete new mailsystem. It should be fairly up to date and fully usable for you! Installing using the order provided might ensure you have all the packages required (due to their dependencies).<\/p>\n<ul>\n<li>lang\/perl58 v5.8.8 (either as additional package during install or usinig ports)<\/li>\n<li>mail\/p5-Mail-ClamAV and security\/p5-File-Scan-ClamAV<\/li>\n<li>databases\/p5-DBD-mysql50<\/li>\n<li>net\/openldap23-server v2.3.37 (check dependencies first, as v2.4 might become dependent instead of v2.3)<\/li>\n<li>www\/apache22 v2.2.4_2 (WITH_LDAP_MODULES=yes)<\/li>\n<li>mail\/postfix (using pcre, sasl, tls, mysql, openldap, vda and test) v2.54<\/li>\n<li>lang\/php5 v5.2.3 and lang\/php5-extensions (at least enable openldap, mysql and imap)<\/li>\n<li>databases\/mysql50-server v5.0.45<\/li>\n<li>mail\/dovecot v1.0.2 (with LDAP and MYSQL enabled)<\/li>\n<li>security\/clamav v0.91.1<\/li>\n<li>mail\/mailscanner v4.61.7<\/li>\n<li>net\/phpldapadmin<\/li>\n<li>mail\/roundcube<\/li>\n<li><em>Optionally you could install these packages:<\/em><\/li>\n<li>procmail<\/li>\n<li>phpldapadmin<\/li>\n<li>phpmyadmin<\/li>\n<\/ul>\n<hr \/>\n<h2>Assumptions<\/h2>\n<p>Assumptions made for this howto<\/p>\n<ul>\n<li>The example domain name will be &#8216;example.org&#8217;<\/li>\n<li>The virtual users (mail)directory store will live under \/usr\/virtual<\/li>\n<li>The virtual user used is vmail (group vmail) uid\/gid are both 2001<\/li>\n<li>The scanner runs as vscan\/vscan (2002\/2002)<\/li>\n<\/ul>\n<hr \/>\n<h2>OpenLDAP configuration<\/h2>\n<p>First edit \/usr\/local\/etc\/openldap\/slapd.conf, 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\u00e2\u20ac\u2122re 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!<\/p>\n<p>Also in the example below there are no acl\u00e2\u20ac\u2122s so anyone has access to you\u00e2\u20ac\u2122re information, consider RTFM on (Open)LDAP to secure you\u00e2\u20ac\u2122re LDAPtree some more.<em>\/usr\/local\/etc\/openldap\/slapd.conf <\/em><\/p>\n<p>[code]<\/p>\n<p>#<br \/>\n# See slapd.conf(5) for details on configuration options.<br \/>\n# This file should NOT be world readable.<br \/>\n#<\/p>\n<p>pidfile \/var\/run\/openldap\/slapd.pid<br \/>\nargsfile \/var\/run\/openldap\/slapd.args<\/p>\n<p># Load dynamic backend modules:<br \/>\nmodulepath \/usr\/local\/libexec\/openldap\/<br \/>\nmoduleload back_bdb<\/p>\n<p># Sample security restrictions<br \/>\n# Require integrity protection (prevent hijacking)<br \/>\n# Require 112-bit (3DES or better) encryption for updates<br \/>\n# Require 63-bit encryption for simple bind<br \/>\n# security ssf=1 update_ssf=112 simple_bind=64<\/p>\n<p># Sample access control policy:<br \/>\n# Root DSE: allow anyone to read it<br \/>\n# Subschema (sub)entry DSE: allow anyone to read it<br \/>\n# Other DSEs:<br \/>\n# Allow self write access<br \/>\n# Allow authenticated users read access<br \/>\n# Allow anonymous users to authenticate<br \/>\n# Directives needed to implement policy:<br \/>\n# access to dn.base=&#8221;&#8221; by * read<br \/>\n# access to dn.base=&#8221;cn=Subschema&#8221; by * read<br \/>\n# access to *<br \/>\n# by self write<br \/>\n# by users read<br \/>\n# by anonymous auth<br \/>\n#<br \/>\n# if no access controls are present, the default policy<br \/>\n# allows anyone and everyone to read anything but restricts<br \/>\n# updates to rootdn. (e.g., &#8220;access to * by * read&#8221;)<br \/>\n#<br \/>\n# rootdn can always read and write EVERYTHING!<\/p>\n<p>#######################################################################<br \/>\n# BDB database definitions<br \/>\n#######################################################################<\/p>\n<p># OpenLDAP configuration for example.org<\/p>\n<p># Core schema&#8217;s delivered with OpenLDAP<br \/>\ninclude \/usr\/local\/etc\/openldap\/schema\/core.schema<br \/>\ninclude \/usr\/local\/etc\/openldap\/schema\/cosine.schema<br \/>\ninclude \/usr\/local\/etc\/openldap\/schema\/inetorgperson.schema<br \/>\ninclude \/usr\/local\/etc\/openldap\/schema\/nis.schema<\/p>\n<p># Mailserver schema used with postfix<br \/>\ninclude \/usr\/local\/etc\/openldap\/schema\/mailserver.schema<\/p>\n<p>#<\/p>\n<p># ldbm database definitions<br \/>\n#<\/p>\n<p>database bdb<br \/>\nsuffix &#8220;dc=example,dc=org&#8221;<\/p>\n<p>rootdn &#8220;cn=Manager,dc=example,dc=org&#8221;<br \/>\nrootpw secret<\/p>\n<p>pidfile \/var\/run\/openldap\/slapd.pid<\/p>\n<p># The database directory MUST exist prior to running slapd AND<br \/>\n# should only be accessable by the slapd\/tools. Mode 700 recommended.<br \/>\ndirectory \/var\/db\/openldap-data<\/p>\n<p># Indices to maintain<br \/>\nindex objectClass pres,eq<br \/>\nindex mail,cn eq,sub<\/p>\n<p># logging<br \/>\nloglevel 256<\/p>\n<p>access to attrs=userPassword<br \/>\nby self write<br \/>\nby anonymous auth<br \/>\nby peername.ip=127.0.0.1 read<br \/>\nby dn=&#8221;cn=dovecot,dc=example,dc=org&#8221; read<br \/>\nby * none<\/p>\n<p>access to *<br \/>\nby dn=&#8221;cn=postfix,dc=example,dc=org&#8221; read<br \/>\nby dn=&#8221;cn=courier,dc=example,dc=org&#8221; read<br \/>\nby peername.ip=127.0.0.1 read<br \/>\nby * read<\/p>\n<p>[\/code]<\/p>\n<hr \/>\n<h2>OpenLDAP scheme for mailserver<\/h2>\n<p>Next, create the LDAPscheme to be used for our mailserver in \/usr\/local\/etc\/openldap\/schemaDownload <a href=\"http:\/\/www.tom.scholten.nu\/mailserver.schema\">mailserver.schema<\/a><\/p>\n<hr \/>\n<h2>Ready, Aim, OpenLDAP<\/h2>\n<p>Now start up you\u00e2\u20ac\u2122re OpenLDAP server either by hand or set slapd_enable=\u00e2\u20ac\u009dYES\u00e2\u20ac\u009d in \/etc\/rc.conf and use \/usr\/local\/etc\/rc.d\/slapd start and verify that slapd is running.If it\u00e2\u20ac\u2122s running were ready to fill \u00e2\u20ac\u00a6<\/p>\n<hr \/>\n<h2>Initial LDIF<\/h2>\n<p>OpenLDAP tree layout and initial ldif. You can load this to your serverusing<\/p>\n<p>[code] cat \/home\/user\/ldap\/initial.ldif | ldapadd -x -D &#8220;cn=Manager,dc=example,dc=org&#8221; -W<\/p>\n<p>[\/code]<\/p>\n<p>[code]<\/p>\n<p># example<br \/>\ndn: dc=example, dc=org<br \/>\nobjectClass: top<br \/>\nobjectClass: organization<br \/>\nobjectClass: dcObject<br \/>\no: example<br \/>\ndc: example<\/p>\n<p># MAnager<br \/>\ndn: cn=Manager,dc=example,dc=org<br \/>\nobjectClass: top<br \/>\nobjectClass: organizationalRole<br \/>\ncn: Manager<\/p>\n<p># mail, example<br \/>\ndn: dc=mail, dc=example, dc=org<br \/>\nobjectClass: top<br \/>\nobjectClass: organizationalunit<br \/>\nobjectClass: dcObject<br \/>\nou: mail<br \/>\ndc: mail<\/p>\n<p>dn: cn=postfix,dc=example,dc=org<br \/>\nobjectClass: top<br \/>\nobjectClass: simpleSecurityObject<br \/>\nobjectClass: organizationalRole<br \/>\nuserPassword:: secret<br \/>\ncn: postfix<\/p>\n<p>dn: cn=dovecot,dc=example,dc=org<br \/>\nobjectClass: top<br \/>\nobjectClass: simpleSecurityObject<br \/>\nobjectClass: organizationalRole<br \/>\nuserPassword:: secret<br \/>\ncn: dovecot<\/p>\n<p># example.org, mail, example<br \/>\ndn: dc=example.org, dc=mail, dc=example,dc=org<br \/>\naccountActive: TRUE<br \/>\neditPostmasters: TRUE<br \/>\neditAccounts: TRUE<br \/>\nobjectClass: top<br \/>\nobjectClass: mailDomain<br \/>\ndc: example.org<br \/>\ndelete: FALSE<br \/>\nlastChange: 111<br \/>\npostfixTransport: virtual:<\/p>\n<p># somenudomain.nu, mail, example<br \/>\ndn: dc=somenudomain.nu, dc=mail, dc=example,dc=org<br \/>\naccountActive: TRUE<br \/>\neditPostmasters: TRUE<br \/>\neditAccounts: TRUE<br \/>\nobjectClass: top<br \/>\nobjectClass: mailDomain<\/p>\n<p>dc: somenudomain.nu<br \/>\ndelete: FALSE<br \/>\nlastChange: 111<br \/>\npostfixTransport: virtual:<\/p>\n<p># someoldaccount.demon.org, mail, example<br \/>\ndn: dc=someoldaccount.demon.org, dc=mail, dc=example,dc=org<br \/>\naccountActive: TRUE<br \/>\neditPostmasters: TRUE<br \/>\neditAccounts: TRUE<br \/>\nobjectClass: top<br \/>\nobjectClass: mailDomain<br \/>\ndc: someoldaccount.demon.org<br \/>\ndelete: FALSE<br \/>\nlastChange: 111<br \/>\npostfixTransport: virtual:<\/p>\n<p># domain3.org, mail, example<br \/>\ndn: dc=domain3.org, dc=mail, dc=example,dc=org<br \/>\naccountActive: TRUE<br \/>\neditPostmasters: TRUE<br \/>\neditAccounts: TRUE<br \/>\nobjectClass: top<br \/>\nobjectClass: mailDomain<br \/>\ndc: domain3.org<br \/>\ndelete: FALSE<br \/>\nlastChange: 111<br \/>\npostfixTransport: virtual:<\/p>\n<p>[\/code]<\/p>\n<h2>Apache webserver<\/h2>\n<p>Add the following lines to your\/usr\/local\/etc\/apache22\/httpd.conf and make sure \u00e2\u20ac\u02dcDirectoryIndex\u00e2\u20ac\u2122 also contains index.php[code]AddType application\/x-httpd-php .phpAddType application\/x-httpd-php-source .phps[\/code]<\/p>\n<hr \/>\n<h2>phpLdapAdmin<\/h2>\n<p>Since not all people are keen on adding\/removing\/changing users by hand using scripts there is also \u00e2\u20ac\u02dcphpldapadmin\u00e2\u20ac\u2122 in the portstree that makes things a little easier, after installing the port (assuming apache+php are up and running!!!) add the following lines to a secure (https) instance of your webserver \/usr\/local\/etc\/apache22\/extra\/httpd-ssl.conf<\/p>\n<p>[code]<\/p>\n<p>Alias \/phpldapadmin &#8220;\/usr\/local\/www\/phpldapadmin\/&#8221;<\/p>\n<p>AllowOverride AuthConfig<\/p>\n<p>Allow from all<\/p>\n<p>[\/code]<\/p>\n<p>And put a .htaccess file in \/usr\/local\/www\/phpldapadmin containing<\/p>\n<p>[code]<\/p>\n<p>AuthUserFile \/usr\/local\/etc\/apache22\/htpasswd.admin<\/p>\n<p>AuthName &#8220;\/admin auth&#8221;<\/p>\n<p>AuthType Basicrequire valid-user[\/code]<\/p>\n<p>Next create the htpasswd file using \u00e2\u20ac\u0153htpasswd -cm \/usr\/local\/etc\/apache22\/htpasswd.admin {username}\u00e2\u20ac\u009d and any further users leaving the -c out.Next edit the \/usr\/local\/www\/phpldapadmin\/config\/config.php and change\/add the following lines<\/p>\n<p>[code]$ldapservers-&gt;SetValue($i,&#8217;server&#8217;,&#8217;host&#8217;,&#8217;127.0.0.1&#8242;);<\/p>\n<p>$ldapservers-&gt;SetValue($i,&#8217;server&#8217;,&#8217;port&#8217;,&#8217;389&#8242;);<\/p>\n<p>$ldapservers-&gt;SetValue($i,&#8217;server&#8217;,&#8217;auth_type&#8217;,&#8217;config&#8217;);<\/p>\n<p>$ldapservers-&gt;SetValue($i,&#8217;login&#8217;,&#8217;dn&#8217;,&#8217;cn=Manager,dc=example,dc=org&#8217;);<\/p>\n<p>$ldapservers-&gt;SetValue($i,&#8217;login&#8217;,&#8217;pass&#8217;,&#8217;secret&#8217;);<\/p>\n<p>$ldapservers-&gt;SetValue($i,&#8217;server&#8217;,&#8217;tls&#8217;,false);[\/code]<\/p>\n<p>Restart your webserver and test if everything works The reason i use plain htpasswd authentication instead of ldap authentication (that is possible by using the example .htaccess below) is that any FU in your ldap would knock yourself out of it.Example .htaccess using ldap authentication<\/p>\n<p>[code]AuthName &#8220;\/auth required&#8221;<\/p>\n<p>AuthType BasicAuthLDAPURL ldap:\/\/localhost\/dc=employees,dc=example,dc=org?name??<\/p>\n<p>require valid-user[\/code]<\/p>\n<hr \/>\n<h2>ClamAV, virusscanner<\/h2>\n<p>You might want to run it by enabling clamav_clamd_enable and clamav_freshclam_enable in \/etc\/rc.conf<\/p>\n<hr \/>\n<h2>DOVECOT imap server<\/h2>\n<p>Copy \/usr\/local\/etc\/dovecot-example to dovecot.conf and adjust the<br \/>\nfollowing lines<\/p>\n<p>[code]<br \/>\nprotocols = imaps pop3s<br \/>\ndisable_plaintext_auth = no<br \/>\nsyslog_facility = mail<br \/>\nssl_disable = no<br \/>\nssl_cert_file = \/etc\/ssl\/certs\/mailserver.pem<br \/>\nssl_key_file = \/etc\/ssl\/certs\/mailserver.pem<br \/>\nlogin_user = dovecot<br \/>\nmail_location = maildir:\/usr\/virtual\/%d\/%n\/Maildir<br \/>\nfirst_valid_uid = 500<br \/>\nlast_valid_uid = 0<br \/>\nlast_valid_gid = 0<br \/>\nvalid_chroot_dirs = \/usr\/virtual<br \/>\npassdb ldap {<br \/>\nargs = \/usr\/local\/etc\/dovecot-ldap.conf<br \/>\n}<br \/>\nuserdb ldap {<br \/>\nargs = \/usr\/local\/etc\/dovecot-ldap.conf<br \/>\n} [\/code]<br \/>\nCopy \/usr\/local\/etc\/dovecot-ldap-example.conf to dovecot-ldap.conf and<br \/>\nadjust the following lines<\/p>\n<p>[code]<br \/>\nhosts = localhost<br \/>\ndn=&#8221;cn=dovecot,dc=example,dc=org&#8221;<br \/>\ndnpass=&#8221;secret&#8221;<br \/>\ntls = no<br \/>\nauth_bind = no<br \/>\nldap_version = 3<br \/>\nbase = dc=mail,dc=example,dc=org<br \/>\nuser_filter =<br \/>\n(&amp;(objectClass=MailAccount)(accountActive=TRUE)(delete=FALSE))<br \/>\nuser_attrs = mail,homeDirectory,,,,<br \/>\npass_attrs = mail=user,userPassword=password<br \/>\npass_attrs = mail,userPassword<br \/>\npass_filter = (&amp;(objectClass=MailAccount)(mail=%u))<br \/>\ndefault_pass_scheme = CRYPT<br \/>\nuser_global_uid = 5000<br \/>\nuser_global_gid = 5000[\/code]<\/p>\n<p>Next start dovecot using \/usr\/local\/etc\/rc.d\/dovecot start<\/p>\n<hr \/>\n<h2>RoundCube Webmail<\/h2>\n<p>Make sure mysql is started (\/usr\/local\/etc\/rc.d\/mysql_server start) next issue<\/p>\n<p>mysql -uroot -p (depending on if you already secured your database)<\/p>\n<p>[code]&gt; create database roundcube;<\/p>\n<p>&gt; grant all on roundcube.* to roundcube@localhost identified by \u00e2\u20ac\u2122secret\u00e2\u20ac\u2122;<\/p>\n<p>[\/code]<\/p>\n<p>Issue cat \/usr\/ports\/mail\/roundcube\/work\/roundcube*\/SQL\/mysql5.initial.sql | mysql -u roundcube -psecret roundcube and add the following lines to your \/usr\/local\/etc\/apache22\/extra\/httpd-ssl.conf<\/p>\n<p>[code]Alias \/webmail \/usr\/local\/www\/roundcube&gt;<\/p>\n<p>&lt;Directory \u00e2\u20ac\u0153\/usr\/local\/www\/roundcube\u00e2\u20ac\u009d&gt;<\/p>\n<p>Allow from all<\/p>\n<p>&lt;\/Directory&gt; [\/code]<\/p>\n<hr \/>\n<h2>OpenLDAP scripts<\/h2>\n<p><del>Using the script provide below we can add users, according to the domain setup shown below using the following commands example\u00c2\u00b7 .\/ldapadduser.pl vivian example.org \u00e2\u20ac\u0153Secret123? mailbox | ldapadd -x -D \u00e2\u20ac\u02dccn=Manager,dc=example,dc=org\u00e2\u20ac\u2122 -w secret\u00c2\u00b7 .\/ldapadduser.pl alexander example.org \u00e2\u20ac\u0153Dog=Cr@zy\u00e2\u20ac\u009d mailbox | ldapadd -x -D \u00e2\u20ac\u02dccn=Manager,dc=example,dc=org\u00e2\u20ac\u2122 -w secret\u00c2\u00b7 .\/ldapadduser.pl roland_dg example.org \u00e2\u20ac\u0153a1zihw\u00e2\u20ac\u009d mailbox | ldapadd -x -D \u00e2\u20ac\u02dccn=Manager,dc=example,dc=org\u00e2\u20ac\u2122 -w secret\u00c2\u00b7 .\/ldapadduser.pl postmaster example.org alexander@example.org,vivian@example.org alias | ldapadd -x -D \u00e2\u20ac\u02dccn=Manager,dc=example,dc=org\u00e2\u20ac\u2122 -w secret\u00c2\u00b7 .\/ldapadduser.pl webmaster example.org john@webbuilders.com alias | ldapadd -x -D \u00e2\u20ac\u02dccn=Manager,dc=example,dc=org\u00e2\u20ac\u2122 -w secret\u00c2\u00b7 .\/ldapadduser.pl \u00e2\u20ac\u0153*\u00e2\u20ac\u009d example.org vivian@example.org alias | ldapadd -x -D \u00e2\u20ac\u02dccn=Manager,dc=example,dc=org\u00e2\u20ac\u2122 -w secretsomenudomain.nu\u00c2\u00b7 .\/ldapadduser.pl ian somenudomain.nu \u00e2\u20ac\u0153vivian\u00e2\u20ac\u009d mailbox | ldapadd -x -D \u00e2\u20ac\u02dccn=Manager,dc=example,dc=org\u00e2\u20ac\u2122 -w secret\u00c2\u00b7 .\/ldapadduser.pl postmaster somenudomain.nu alexander@example.org alias | ldapadd -x -D \u00e2\u20ac\u02dccn=Manager,dc=example,dc=org\u00e2\u20ac\u2122 -w secret\u00c2\u00b7 .\/ldapadduser.pl webmaster somenudomain.nu \u00e2\u20ac\u0153w3bs1t3? mailbox | ldapadd -x -D \u00e2\u20ac\u02dccn=Manager,dc=example,dc=org\u00e2\u20ac\u2122 -w secretsomeoldaccount.demon.org\u00c2\u00b7 .\/ldapadduser.pl \u00e2\u20ac\u0153*\u00e2\u20ac\u009d someoldaccount.demon.org @somenudomain.nu alias | ldapadd -x -D \u00e2\u20ac\u02dccn=Manager,dc=example,dc=org\u00e2\u20ac\u2122 -w secretdomain3.org\u00c2\u00b7 .\/ldapadduser.pl postmaster domain3.org alexander@example.org alias | ldapadd -x -D \u00e2\u20ac\u02dccn=Manager,dc=example,dc=org\u00e2\u20ac\u2122 -w secret\u00c2\u00b7 .\/ldapadduser.pl webmaster domain3.org alexander@example.org alias | ldapadd -x -D \u00e2\u20ac\u02dccn=Manager,dc=example,dc=org\u00e2\u20ac\u2122 -w secret<\/del>And so, we should have created a tree looking like this, with vivian@example.org receiving all \u00e2\u20ac\u02dcnon-existing-mailbox\u00e2\u20ac\u2122 mail from example.org and all mail from \u00e2\u20ac\u2122someoldaccount.demon.org\u00e2\u20ac\u2122 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\u00e2\u20ac\u2122s 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 \u00e2\u20ac\u02dcmaildrop\u00e2\u20ac\u2122s in the LDAP tree!<\/p>\n<hr \/>\n<h2>MailScanner<\/h2>\n<p>First of all, copy all .sample files to their respective realnames (and make changes if you like) in \/usr\/local\/etc\/MailScanner and subdirectories. Do the same for \/usr\/local\/share\/MailScanner\/reports\/en\/ (or other languages). To enable \u00e2\u20ac\u02dcautofinding\u00e2\u20ac\u2122 clamav, also issue acp \/usr\/local\/libexec\/MailScanner\/clamav-wrapper.sample \/usr\/local\/libexec\/MailScanner\/clamav-wrapper<\/p>\n<p>I recommend using clamavmodule however, this will save you overhead and time of seperate clamav processes on your precious system!<\/p>\n<p>Adjust \/usr\/local\/etc\/MailScanner\/MailScanner.conf with at least the following lines.<\/p>\n<p>[code]<\/p>\n<p>%org-name% = YourOrg<br \/>\n%org-long-name% = Your Full Organisation Name<br \/>\n%web-site% = www.example.org<br \/>\nRun As User = postfix<br \/>\nRun As Group = postfix<br \/>\nIncoming Queue Dir = \/var\/spool\/postfix\/hold<br \/>\nOutgoing Queue Dir = \/var\/spool\/postfix\/incoming<br \/>\nMTA = postfix<br \/>\nQuarantine User = postfix<br \/>\nQuarantine Group = www<br \/>\nDeliver Disinfected Files = yes<br \/>\nQuarantine Whole Message = yes<br \/>\nInformation Header Value = See you&#8217;re providers webpage or<br \/>\nwww.mailscanner.info for more information<br \/>\nNotify Senders = no<br \/>\nRequired SpamAssassin Score = 3<br \/>\nHigh SpamAssassin Score = 5<br \/>\nDepending on your choice you might change :<br \/>\n#High Scoring Spam Actions = deliver header &#8220;X-Spam-Status: Yes&#8221;<br \/>\nHigh Scoring Spam Actions = store<\/p>\n<p>Monitors for ClamAV Updates = \/var\/db\/clamav\/*.inc\/* \/var\/db\/clamav\/*.cvd<\/p>\n<p>[\/code]<\/p>\n<hr \/>\n<h2>MailWatch (MailScanner front-end)<\/h2>\n<p>Download the package from <a href=\"http:\/\/mailwatch.sf.net\">http:\/\/mailwatch.sf.net<\/a> and untar in \/tmp and change to the directory.<\/p>\n<p>[code]$ mysql -uroot -p &lt; create.sql[\/code]<\/p>\n<p>[code]$ mysql -uroot -p [\/code]<\/p>\n<p>[mysql]mysql&gt; GRANT ALL ON mailscanner.* TO mailwatch@localhost IDENTIFIED BY &#8216;secret&#8217;;<\/p>\n<p>mysql&gt; GRANT FILE ON *.* TO mailwatch@localhost IDENTIFIED BY &#8216;secret&#8217;;<\/p>\n<p>mysql&gt; FLUSH PRIVILEGES;<\/p>\n<p>mysql &gt; use mailscanner;<\/p>\n<p>mysql &gt; INSERT INTO users (username, password, fullname, type) VALUES (&#8216;&lt;username&#8217;&gt;,md5(&#8216;&lt;password&gt;&#8217;),'&lt;name&gt;&#8217;,&#8217;A&#8217;);[\/mysql]<\/p>\n<p>Edit the MailWatch.pm file and change the database configuration<\/p>\n<p>[code]my($db_user) = &#8216;mailwatch&#8217;;<\/p>\n<p>my($db_pass) = &#8216;secret&#8217;;[\/code]<\/p>\n<p>Next copy this file to the MailScanner directories : cp MailWatch.pm \/usr\/local\/lib\/MailScanner\/MailScanner\/CustomFunctions\/Move the mailscanner directory to your webroot and &#8220;chown www:www&#8221; it (i.e. \/usr\/local\/www\/mailscanner) and add the following lines to your apache configuration<\/p>\n<p>[code]Alias \/mailscanner \/usr\/local\/www\/mailscanner<\/p>\n<p>Directory \u00e2\u20ac\u0153\/usr\/local\/www\/mailscanner\u00e2\u20ac\u009d<\/p>\n<p>Allow from all<\/p>\n<p>\/Directory&lt;[\/code]<\/p>\n<p>Next restart your mailscanner (\/usr\/local\/etc\/rc.d\/mailscanner restart) and watch the \/var\/log\/maillog closely. If no obvious errors or warnings occur try to send yourself an email. If it all works (email received) just go ahead and browse to MailWatch to see some stats!<\/p>\n<hr \/>\n<h2>Configure postfix<\/h2>\n<p>Changes to postfix\u00e2\u20ac\u2122 main.cf, also change other settings to customize you\u00e2\u20ac\u2122re requirements. Setting \u00e2\u20ac\u2122soft_bounce=yes\u00e2\u20ac\u2122 for testing purposes while starting out using you\u00e2\u20ac\u2122re new mailserver would be a wise decision!We also need to change some things regarding to sending Postfix\u00e2\u20ac\u2122 incoming mail through MailScanner first in main.cf<br \/>\n[code]<\/p>\n<p>hash_queue_depth = 1<br \/>\nhash_queue_names = incoming,hold,deferred,defer<br \/>\ninet_protocols = all<br \/>\nheader_checks = regexp:\/usr\/local\/etc\/postfix\/header_checks<br \/>\nAnd add the following line to \/usr\/local\/etc\/postfix\/header_checks<br \/>\n\/^Received:\/ HOLD<br \/>\nFurther, change your main.cf to contain the following ldap-related stuff.<br \/>\nqueue_directory = \/var\/spool\/postfix<br \/>\ncommand_directory = \/usr\/local\/sbin<br \/>\ndaemon_directory = \/usr\/local\/libexec\/postfix<br \/>\nmail_owner = postfix<br \/>\nmyhostname = mail.example.org<br \/>\nmydomain = example.org<br \/>\nmyorigin = $mydomain<br \/>\nlocal_recipient_maps =<br \/>\nunknown_local_recipient_reject_code = 550<\/p>\n<p>debug_peer_level = 2<br \/>\ndebugger_command =<br \/>\nPATH=\/bin:\/usr\/bin:\/usr\/local\/bin:\/usr\/X11R6\/bin<br \/>\nxxgdb $daemon_directory\/$process_name $process_id &amp; sleep 5<br \/>\nsendmail_path = \/usr\/local\/sbin\/sendmail<br \/>\nnewaliases_path = \/usr\/local\/bin\/newaliases<br \/>\nmailq_path = \/usr\/local\/bin\/mailq<br \/>\nsetgid_group = maildrop<br \/>\nhtml_directory = no<br \/>\nmanpage_directory = \/usr\/local\/man<br \/>\nsample_directory = \/usr\/local\/etc\/postfix<br \/>\nreadme_directory = no<br \/>\ndomains_server_host = 127.0.0.1<br \/>\ndomains_search_base = dc=mail,dc=example,dc=org<br \/>\ndomains_query_filter =<br \/>\n(&amp;(dc=%s)(objectClass=mailDomain)(accountActive=TRUE)(delete=FALSE))<br \/>\ndomains_result_attribute = postfixTransport<br \/>\ndomains_bind = no<br \/>\ndomains_scope = one<br \/>\naliases_server_host = 127.0.0.1<br \/>\naliases_search_base = dc=mail,dc=example,dc=org<br \/>\naliases_query_filter =<br \/>\n(&amp;(objectClass=mailAlias)(mail=%s)(accountActive=TRUE))<br \/>\naliases_result_attribute = maildrop<br \/>\naliases_bind = no<br \/>\naliasalternates_server_host = 127.0.0.1<br \/>\naliasalternates_search_base = dc=mail,dc=example,dc=org<br \/>\naliasalternates_query_filter =<br \/>\n(&amp;(objectClass=mailAlias)(mailalternateaddress=%s)(accountActive=TRUE))<br \/>\naliasalternates_result_attribute = maildrop<br \/>\naliasalternates_bind = no<br \/>\naccounts_server_host = 127.0.0.1<br \/>\naccounts_search_base = dc=mail,dc=example,dc=org<br \/>\naccounts_query_filter =<br \/>\n(&amp;(objectClass=mailAccount)(mail=%s)(accountActive=TRUE)(delete=FALSE))<br \/>\naccounts_result_attribute = mailbox<br \/>\naccounts_bind = no<\/p>\n<p>accountsmap_server_host = 127.0.0.1<br \/>\naccountsmap_search_base = dc=mail,dc=example,dc=org<br \/>\naccountsmap_query_filter =<br \/>\n(&amp;(objectClass=mailAccount)(mail=%s)(accountActive=TRUE)(delete=FALSE))<br \/>\naccountsmap_result_attribute = mail<br \/>\naccountsmap_bind = no<br \/>\naccountalternates_server_host = 127.0.0.1<br \/>\naccountalternates_search_base = dc=mail,dc=example,dc=org<br \/>\naccountalternates_query_filter =<br \/>\n(&amp;(objectClass=mailAccount)(mailalternateaddress=%s)(accountActive=TRUE)(del<br \/>\nete=FALSE))<br \/>\naccountalternates_result_attribute = mail<br \/>\naccountalternates_bind = no<br \/>\ntransport_maps = ldap:domains<br \/>\nmasquerade_domains = ldap:domains<br \/>\nvirtual_maps = ldap:accountsmap, ldap:aliases, ldap:accountalternates,<br \/>\nldap:aliasalternates<br \/>\nvirtual_transport = local<br \/>\nvirtual_mailbox_base = \/usr\/virtual<br \/>\nvirtual_mailbox_maps = ldap:accounts<br \/>\nvirtual_mailbox_domains = ldap:domains<br \/>\nvirtual_minimum_uid = 5000<br \/>\nvirtual_uid_maps = static:5000<br \/>\nvirtual_gid_maps = static:5000<br \/>\nlocal_alias_maps = hash:\/etc\/mail\/aliases<br \/>\nlocal_transport = local<br \/>\nmailbox_command = \/usr\/local\/bin\/procmail<br \/>\nmydestination = localhost.example.org, localhost<br \/>\nrelay_domains = localhost<br \/>\nmynetworks = localhost, mail.example.org<\/p>\n<p>owner_request_special = no<br \/>\nrecipient_delimiter = +<br \/>\nunknown_local_recipient_reject_code = 550<br \/>\nsmtpd_client_restrictions = check_client_access<br \/>\nhash:\/usr\/local\/etc\/postfix\/access, permit<br \/>\nsmtpd_sender_restrictions = hash:\/usr\/local\/etc\/postfix\/access<br \/>\nheader_checks = regexp:\/usr\/local\/etc\/postfix\/header_checks<\/p>\n<p>hash_queue_depth = 1<br \/>\nhash_queue_names = incoming,hold,deferred,defer<\/p>\n<p>inet_protocols = all<br \/>\ndebug_peer_level = 9<\/p>\n<p>[\/code]<\/p>\n<p>And finally some code to protect your drive from flooding<\/p>\n<p>[code] # A maximum limit of a mailbox<br \/>\nvirtual_mailbox_limit = 1000000<\/p>\n<p># Limits only INBOX part (usefull when<br \/>\n# using when you have IMAP users)<br \/>\nvirtual_mailbox_limit_inbox = yes [\/code]<\/p>\n<p>You may want to add a few dnsbl statements to limit the amount of unwanted<br \/>\nmail in your main.cf using<\/p>\n<p>[code]smtpd_recipient_restrictions =<br \/>\npermit_mynetworks,<br \/>\nreject_unauth_destination,<br \/>\nreject_unknown_recipient_domain,<br \/>\nreject_invalid_hostname,<br \/>\nreject_non_fqdn_hostname,<br \/>\nreject_non_fqdn_sender,<br \/>\nreject_non_fqdn_recipient,<br \/>\nreject_unknown_sender_domain,<br \/>\nreject_rbl_client list.dsbl.org,<br \/>\nreject_rbl_client sbl.spamhaus.org,<br \/>\nreject_rbl_client cbl.abuseat.org,<br \/>\nreject_rbl_client dul.dnsbl.sorbs.net,<br \/>\npermit<\/p>\n<p>[\/code]<\/p>\n<h2>Starting you\u00e2\u20ac\u2122re mailserver<\/h2>\n<p>Next again edit \/etc\/rc.conf to disable sendmail and enable postfix Insert<\/p>\n<ul>\n<li>sendmail_enable=\u00e2\u20ac\u009dNONE\u00e2\u20ac\u009d<\/li>\n<\/ul>\n<p>Comment out\/remove<\/p>\n<ul>\n<li>sendmail_enable=\u00e2\u20ac\u009dYES\u00e2\u20ac\u009d<\/li>\n<li>sendmail_flags=\u00e2\u20ac\u009d-bd\u00e2\u20ac\u009d<\/li>\n<li>sendmail_pidfile=\u00e2\u20ac\u009d\/var\/spool\/postfix\/pid\/master.pid\u00e2\u20ac\u009d<\/li>\n<li>sendmail_outbound_enable=\u00e2\u20ac\u009dNO\u00e2\u20ac\u009d<\/li>\n<li>sendmail_submit_enable=\u00e2\u20ac\u009dNO\u00e2\u20ac\u009d<\/li>\n<li>sendmail_msp_queue_enable=\u00e2\u20ac\u009dNO\u00e2\u20ac\u009dNow 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\u00e2\u20ac\u2122s going on.First start mailscanner (\/usr\/local\/etc\/rc.d\/mailscanner start) but remember to add mailscanner_enable=\u00e2\u20ac\u009dYES\u00e2\u20ac\u009d to your \/etc\/rc.conf watch your logging for a while before proceeding with the next step.Now you\u00e2\u20ac\u2122re ready to start postfix simply by typing postfix start<br \/>\n<hr \/>\n<h2>Verify mail sending and receiving<\/h2>\n<p>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\u00e2\u20ac\u2122re 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 \u00e2\u20ac\u02dcwelcome\u00e2\u20ac\u2122 mail of some kind to let postfix create their \u00e2\u20ac\u02dchomedirectory\u00e2\u20ac\u2122 in \/usr\/virtual. When omitted the user will receive an error when checking mail (either via imap\/pop or when using webmail)<\/p>\n<hr \/>\n<h2>Documents and resources used<\/h2>\n<p>Besides RTFM on various packages used to install a number of special resources will be named below the packages linklist; (in no particular order)<\/li>\n<li>Postfix, MTA used<\/li>\n<li>Spam tagging software<\/li>\n<li>LDAP software<\/li>\n<li>Webmail software<\/li>\n<li>Mailinglist software (when done, you could add mailinglists, not captured in this document)<\/li>\n<li>ClamAV Antivirus software<\/li>\n<li>Short for [A] [MA]il [VI]rus [S]canner<\/li>\n<li>Apache webserver for webmail and admin (php) interface<\/li>\n<li>The admin interface was build using phpMost usefull to produce this document was :http:\/\/janus.errornet.de\/ with his pdf and schema ((mirrored here) pdf and schema)<br \/>\n<hr \/>\n<h2>Others resources used<\/h2>\n<ul>\n<li>http:\/\/jamm.sourceforge.net everything else seems to be based upon this<\/li>\n<li>http:\/\/www.vriesman.tk detailed enough for me<\/li>\n<\/ul>\n<hr \/>\n<p><a href=\"http:\/\/tom.scholten.nu\">Tom Scholten<\/a> is consultant with <a href=\"http:\/\/snow.nl\">Snow B.V.<\/a>, a Dutch Technical Consultancy Company supplying specialists in the fields of Storage, Networking and Unix<\/p>\n<table width=\"100%\" border=\"0\">\n<tbody>\n<tr>\n<td align=\"left\"><a href=\"http:\/\/www.snow.nl\"><img loading=\"lazy\" decoding=\"async\" title=\"Snow B.V.\" alt=\"Snow B.V.\" src=\"http:\/\/tom.scholten.nu\/weblog\/wp-content\/uploads\/2007\/03\/snow-logo1.jpg\" width=\"200\" height=\"67\" align=\"left\" \/><\/a><\/td>\n<td align=\"left\"><\/td>\n<td align=\"right\"><\/td>\n<td align=\"right\"><a href=\"http:\/\/www.freebsd.org\"><img loading=\"lazy\" decoding=\"async\" title=\"FreeBSD\" alt=\"FreeBSD\" src=\"http:\/\/tom.scholten.nu\/weblog\/wp-content\/uploads\/2007\/03\/fbsd-full1.png\" width=\"200\" height=\"72\" align=\"right\" \/><\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Last updated on 05th of August 2007 You can also check my newer page on Postfix MySQL over here\u00c2\u00a0http:\/\/tom.scholten.nu\/weblog\/en\/postfix_mysql_howto &nbsp; Full-fledged Postfix using LDAP HOWTO<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"class_list":["post-232","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/tom.scholten.nu\/weblog\/wp-json\/wp\/v2\/pages\/232","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tom.scholten.nu\/weblog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/tom.scholten.nu\/weblog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/tom.scholten.nu\/weblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tom.scholten.nu\/weblog\/wp-json\/wp\/v2\/comments?post=232"}],"version-history":[{"count":5,"href":"https:\/\/tom.scholten.nu\/weblog\/wp-json\/wp\/v2\/pages\/232\/revisions"}],"predecessor-version":[{"id":1953,"href":"https:\/\/tom.scholten.nu\/weblog\/wp-json\/wp\/v2\/pages\/232\/revisions\/1953"}],"wp:attachment":[{"href":"https:\/\/tom.scholten.nu\/weblog\/wp-json\/wp\/v2\/media?parent=232"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}