Postfix Tutorial

Contact | Services | Login

Postfix, Courier/POP, SASL & Spamassassin - with MySQL admin on Ubuntu LTS 22.04 (Jammy Jellyfish)



This tutorial uses the example of creating an email server for the domain name example-domain.com, under the subdomain mail.example-domain.com (you can use mx.example-domain.com or smtp.example-domain.com or pop.example-domain.com or any other subdomain), accessed with password. Change example-domain.com and password to your actual domain name and password.


1. DNS. Create an MX record in the primary zone file for the domains, with an A record pointing to the IP address of the mail server. You can proceed with the following installation and configuration, but your server will not test for your domain until your name server(s) are announcing DNS for it. Make sure you can see the A record IP address before testing the Postfix configuration:

dig mail.example-domain.com @name-server-for-example-domain.com

2. Package Installation - install the following packages:

sudo apt -y install apache2 php mysql-server php libapache2-mod-php php-mysql postfix mailutils courier-pop courier-imap vim courier-authlib-mysql libsasl2-2 libsasl2-modules libsasl2-modules-sql postfix-mysql sasl2-bin libpam-mysql opendkim

3. Postfix Configuration - enter the following at the command line:

sudo postconf -e 'home_mailbox = Maildir/'
sudo postconf -e 'mailbox_command = '
sudo postconf -e 'mydestination = localhost.localdomain, localhost'
sudo postconf -e 'mynetworks = 127.0.0.0/8, '
sudo postconf -e 'inet_interfaces = all'
sudo postconf -e 'inet_protocols = all'

4. Hostname - edit the file /etc/hostname/

vi /etc/hostname/

5. Restart Apache2

sudo /etc/init.d/apache2 reload

(Optional) Configure phpMyAdmin - add this line to the end of /etc/apache2/apache2.conf:

Include /etc/phpmyadmin/apache.conf

… then access phpMyAdmin at :

http://mailserver-domain-name/phpmyadmin/

6. Create MySQL Database - first login to MySQL at the command line: create the MySQL database 'mail':

mysql -u root -p

At the MySQL prompt, create the MySQL database 'mail':

CREATE DATABASE `mail` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_0900_ai_ci;
USE `mail`;

7. Create MySQL Tables - Create the following tables on the MySQL database 'mail':

a) `virtual_aliases` schema
… using the following SQL (insert directly into phpMyAdmin):

CREATE TABLE IF NOT EXISTS `virtual_aliases` (
  `id` int NOT NULL auto_increment,
  `alias` varchar(255) character set utf8mb4 collate utf8mb4_0900_ai_ci NOT NULL,
  `virtual_user_email` text collate utf8mb4_0900_ai_ci,
  PRIMARY KEY (`id`),
  FULLTEXT KEY `aliases` (`alias`,`virtual_user_email`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Postfix virtual recipient aliases' AUTO_INCREMENT=1 ;

b) `virtual_mailbox_domains` schema

CREATE TABLE IF NOT EXISTS `virtual_mailbox_domains` (
  `id` int NOT NULL auto_increment,
  `domain` varchar(255) collate utf8mb4_0900_ai_ci default NULL,
  PRIMARY KEY (`id`),
  FULLTEXT KEY `domains` (`domain`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Postfix virtual domains' AUTO_INCREMENT=1 ;

c) `virtual_users` schema

CREATE TABLE IF NOT EXISTS `virtual_users` (
  `id` int NOT NULL auto_increment,
  `username` varchar(255) collate utf8mb4_0900_ai_ci NOT NULL default '0',
  `userrealm` varchar(255) collate utf8mb4_0900_ai_ci NOT NULL,
  `userpassword` varchar(255) collate utf8mb4_0900_ai_ci NOT NULL,
  `auth` int default '1',
  `active` int default '1',
  `email` varchar(255) collate utf8mb4_0900_ai_ci NOT NULL default '',
  `virtual_uid` int default '1007',
  `virtual_gid` int default '1007',
  `virtual_mailbox` varchar(255) collate utf8mb4_0900_ai_ci default NULL,
  PRIMARY KEY (`id`),
  FULLTEXT KEY `recipient` (`email`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='SMTP AUTH and virtual mailbox users' AUTO_INCREMENT=1 ;

8. Create MySQL User - create MySQL user for Postfix. Run the SQL Query below (either from phpMyAdmin or Terminal), replacing password with your own password (note there is an excellent password generator in phpMyAdmin under Privileges then “Add a new User”):

CREATE USER 'postfix'@'localhost' IDENTIFIED BY 'password'
GRANT USAGE ON * . * TO 'postfix'@'localhost';
GRANT SELECT, INSERT, UPDATE ,DELETE, CREATE, DROP, RELOAD, SHUTDOWN,
PROCESS, FILE, REFERENCES, INDEX, ALTER ON * . * TO 'postfix'@'localhost';
FLUSH PRIVILEGES;

9. Grant User Privileges. The postfix user should not be able to alter or create tables, but should be restricted to read-only (SELECT) access. Run the SQL Query below (either from phpMyAdmin or Terminal), replacing password with your own password (note there is an excellent password generator in phpMyAdmin under Privileges then “Add a new User”):

GRANT USAGE ON *.* TO 'postfix'@'localhost';
GRANT SELECT ON mail.virtual_aliases TO 'postfix'@'localhost';
GRANT SELECT ON mail.virtual_users TO 'postfix'@'localhost';
GRANT SELECT ON mail.virtual_mailbox_domains TO 'postfix'@'localhost';
FLUSH PRIVILEGES;

10. Postfix Configuration Files. Create the /etc/postfix/sql directory, then create the following 6 files inside the sql directory, changing password in each file to the actual MySQL password for the user postfix. Alternatively, you can download all 6 files here. Finally, apply appropriate permissions to the directory.

a) Create the /etc/postfix/sql directory:

sudo mkdir -p /etc/postfix/sql && cd /etc/postfix/sql

b) Create the file sender_check.cf inside the sql directory, with the contents:

user = postfix
password = password
dbname = mail
table = virtual_users
hosts = 127.0.0.1
query = SELECT email FROM virtual_users WHERE email ='%s' and active=1

c) Create the file virtual_alias_maps.cf inside the sql directory, with the contents:

user = postfix
password = password
dbname = mail
table = virtual_aliases
select_field = virtual_user_email
where_field = alias
hosts = 127.0.0.1

d) Create the file virtual_gid_maps.cf inside the sql directory, with the contents:

user = postfix
password = password
dbname = mail
table = virtual_users
select_field = virtual_gid
where_field = email
hosts = 127.0.0.1

e) Create the file virtual_mailbox_domains.cf inside the sql directory, with the contents:

user = postfix
password = password
dbname = mail
table = virtual_mailbox_domains
select_field = domain
where_field = domain
hosts = 127.0.0.1

f) Create the file virtual_mailbox_recipients.cf inside the sql directory, with the contents:

user = postfix
password = password
dbname = mail
table = virtual_users
select_field = virtual_mailbox
where_field = email
additional_conditions = and active = '1'
hosts = 127.0.0.1

g) Create the file virtual_uid_maps.cf inside the sql directory, with the contents:

user = postfix
password = password
dbname = mail
table = virtual_users
select_field = virtual_uid
where_field = email
hosts = 127.0.0.1

h) Apply appropriate persmissions of the sql directory:

chown postfix /etc/postfix/sql
chgrp root /etc/postfix/sql
chmod 500 /etc/postfix/sql

11. SASL Configuration. Create the /etc/postfix/sasl directory, and apply appropriate permissions to it:

a) Create the /etc/postfix/sasl directory if it does not already exist (otherwise change directory to it):

sudo mkdir -p /etc/postfix/sasl && cd /etc/postfix/sasl

b) Create the smtpd.conf file inside the sasl directory, with the following contents:

log_level: 1
pwcheck_method: saslauthd
mech_list: plain login
allow_plaintext: true

#auxilary plugin properties
#auxprop_plugin: sql
#sql_engine: mysql
#sql_hostnames: 127.0.0.1
#sql_user: postfix
#sql_passwd: password
#sql_database: mail
#sql_select: select userpassword as %p from virtual_users where username = '%u' AND active = 1

c) Apply appropriate permissions:

adduser postfix sasl
chmod -R g+wrx /etc/postfix/sasl/

12. Configure authdaemonrc. Edit /etc/courier/authdaemonrc - and change: authmodulelist='' to: authmodulelist='authmysql'

13. Configure authmysqlrc. Edit the /etc/courier/authmysqlrc and change to the following (Change the password in the file to the actual MySQL password for the user postfix):

MYSQL_SERVER 127.0.0.1
MYSQL_USERNAME postfix
MYSQL_PASSWORD password
MYSQL_DATABASE mail
MYSQL_USER_TABLE virtual_users
MYSQL_LOGIN_FIELD email
#MYSQL_CRYPT_PWFIELD crypt
MYSQL_CLEAR_PWFIELD userpassword
MYSQL_MAILDIR_FIELD virtual_mailbox
MYSQL_HOME_FIELD '/var/spool/virtual_mailboxes'
MYSQL_UID_FIELD 1007
MYSQL_GID_FIELD 1007

Comment out MYSQL_CRYPT_PWFIELD and MYSQL_NAME_FIELD options

… there must be NO SPACES / TABS / ANYTHING at beginning or end of line.
This is how courier connects to mysql - it should effectively replicate the information in the /etc/postfix/sql/virtual_mailbox_recipients.cf file - mysql username, table and field names for mysql, etc.

14. Restart the daemons for changes to take effect:

/etc/init.d/courier-authdaemon restart
/etc/init.d/courier-pop restart
/etc/init.d/postfix restart

15. Enter MySQL Data. Enter you user data through phpMyAdmin (or alternative GUI) in the following format:

INSERT INTO `virtual_aliases` (`alias`, `virtual_user_email`) VALUES
('postmaster@example-domain.com', 'forward-to-this-user@example-domain.com'),
('abuse@example-domain.com', 'forward-to-this-user@example-domain.com');

INSERT INTO `virtual_mailbox_domains` (`domain`) VALUES
('example-domain.com'),
('another-domain.com');

INSERT INTO `virtual_users` (`username`, `userrealm`, `userpassword`, `auth`, `active`, `email`, `virtual_uid`, `virtual_gid`, `virtual_mailbox`) VALUES
('username-1', 'mail.example-domain.com', 'password', 1, 1, 'username-1@example-domain.com', 1007, 1007, 'example-domain.com/username-1/'),
('username-2', 'mail.another-domain.com', 'password', 1, 1, 'username-2@another-domain.com', 1007, 1007, 'anotherdomain.com/username-2/');

16. Configure /etc/postfix/main.cf :

# MySQL Setup for Virtual Mailbox Domains as per postfix-book.com

virtual_mailbox_base = /var/spool/virtual_mailboxes
virtual_mailbox_domains = mysql:/etc/postfix/sql/virtual_mailbox_domains.cf
virtual_uid_maps = mysql:/etc/postfix/sql/virtual_uid_maps.cf
virtual_gid_maps = mysql:/etc/postfix/sql/virtual_gid_maps.cf
virtual_mailbox_maps = mysql:/etc/postfix/sql/virtual_mailbox_recipients.cf
virtual_alias_maps = mysql:/etc/postfix/sql/virtual_alias_maps.cf

# SASL authentication
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_authenticated_header = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =

17. Create the file: /etc/pam.d/smtp … with the contents:

auth required pam_mysql.so user=postfix passwd=password host=127.0.0.1 db=mail table=virtual_users usercolumn=email passwdcolumn=userpassword crypt=0 verbose=1
password host=127.0.0.1 db=mail table=virtual_users usercolumn=email passwdcolumn=userpassword crypt=0 verbose=1

18. Create the file : /etc/default/saslauthd ... with the contents:

START=yes
MECHANISMS='pam'
MECH_OPTIONS=''
THREADS=5
OPTIONS='-c -m /var/spool/postfix/var/run/saslauthd -r'

19. Create the directories :

mkdir -p /var/spool/postfix/var/run/saslauthd/
mkdir /var/spool/virtual_mailboxes

20. Add /etc/passwd to vuser:x:1007:1008::/home/vuser:/bin/sh

groupadd vuser -g 1008
useradd -m vuser -u 1007 -g 1008
chown -R vuser: /var/spool/virtual_mailboxes/

21. DomainKeys Identified Mail (DKIM)

Install OpenDKIM (which replaced the dkim-filter package in Ubuntu as of 2011-12-13):

sudo apt -y install opendkim

Configure opendkim using instructions from http://opendkim.org/opendkim-README

22. Create restartmail

vi ~/.bashrc
alias restartmail='/etc/init.d/courier-authdaemon restart; /etc/init.d/courier-pop restart; /etc/init.d/postfix restart; /etc/init.d/saslauthd restart'

Then restart the various daemons using restartmail as a handy alias to restart courier, postfix, and saslauthd

23. Test. Insert your domains, users and aliases into the MySQL tables. You will need to send a message to each user account, before the account will work, as this is what creates the /var/spool/ directory for that user. Also, make sure on your email client that you enter 'username@example-domain.com' as the username and not just 'username'.

If you have any problems, try increasing logging to a higher, more verbose level, and then check the error logs.

Add -v to 'smtpd' in /etc/postfix/master.cf for verbose logging.

/etc/postfix/sasl/smtpd.conf log_level: 5

verbose courier debugging: /etc/courier/authdaemonrc DEBUG_LOGIN=2

Running the saslauthd as a foreground process attached to the terminal (so you get all login attempts displayed directly to terminal): saslauthd -d -a pam -c -m /var/spool/postfix/var/run/saslauthd -r
To test an account: testsaslauthd -s smtp -f /var/spool/postfix/var/run/saslauthd/mux -u -p


24. Spamassassin. Once you have Postfix up and running, as an option you can filter spam using this configuration of Spamassassin.

a) Install the packages:

sudo apt-get install spamassassin spamc

b) Create a specific user and group for spamassassin:

groupadd -g 5001 spamd
useradd -u 5001 -g spamd -s /sbin/nologin -d /var/lib/spamassassin spamd
mkdir /var/lib/spamassassin
chown spamd:spamd /var/lib/spamassassin

c) Configure /etc/default/spamassassin

ENABLED=1
SAHOME='/var/lib/spamassassin/'
OPTIONS='--create-prefs --max-children 5 --username spamd --helper-home-dir ${SAHOME} -s ${SAHOME}spamd.log'
PIDFILE='${SAHOME}spamd.pid'

d) Configure /etc/spamassassin/local.cf

rewrite_header Subject [***** SPAM _SCORE_ *****]
required_score 2.0
#to be able to use _SCORE_ we need report_safe set to 0
#If this option is set to 0, incoming spam is only modified by adding some 'X-Spam-' headers and no changes will be made to the body.
report_safe 0

# Enable the Bayes system
use_bayes 1
use_bayes_rules 1
# Enable Bayes auto-learning
bayes_auto_learn 1

# Enable or disable network checks
skip_rbl_checks 0
use_razor2 0
use_dcc 0
use_pyzor 0

e) Start spamassassin with /etc/init.d/spamassassin start

f) Configure Postfix /etc/postfix/master.cf

Change the line:
smtp inet n - - - - smtpd
… to …
smtp inet n - - - - smtpd
-o content_filter=spamassassin

g) Add the following at the end of /etc/init.d/spamassassin start

spamassassin unix - n n - - pipe
user=spamd argv=/usr/bin/spamc -f -e
/usr/sbin/sendmail -oi -f ${sender} ${recipient}

h) Reload Postfix with restartmail


References

https://help.ubuntu.com/community/PostfixBasicSetupHowto
http://www.postfix.org/STANDARD_CONFIGURATION_README.html#backup
http://www.debuntu.org/postfix-and-pamassassin-how-to-filter-spam



Powered by Embode

Leave a Comment