<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>postfix &#8211; Blog of Kliment Andreev &#8211; A place so I won&#039;t forget things</title>
	<atom:link href="https://blog.andreev.it/tag/postfix/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.andreev.it</link>
	<description></description>
	<lastBuildDate>Sat, 31 Oct 2020 13:49:56 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>CentOS: Create disposable e-mail addresses using postfix, dovecot and squirrelmail</title>
		<link>https://blog.andreev.it/2020/01/centos-create-disposable-e-mail-addresses-using-postfix-dovecot-and-squirrelmail/</link>
					<comments>https://blog.andreev.it/2020/01/centos-create-disposable-e-mail-addresses-using-postfix-dovecot-and-squirrelmail/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Tue, 14 Jan 2020 19:51:37 +0000</pubDate>
				<category><![CDATA[CentOS]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[disposable e-mail]]></category>
		<category><![CDATA[dovecot]]></category>
		<category><![CDATA[postfix]]></category>
		<category><![CDATA[squirrelmail]]></category>
		<category><![CDATA[temp e-mail]]></category>
		<category><![CDATA[temporary e-maill]]></category>
		<guid isPermaLink="false">https://blog.andreev.it/?p=6425</guid>

					<description><![CDATA[There are many sites that offer this functionality (temp-mail.org, guerrillamail.org, throwawaymail.com), but if you&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>There are many sites that offer this functionality (temp-mail.org, guerrillamail.org, throwawaymail.com), but if you want to build your own solution from scratch, I&#8217;ll show how I managed to accomplish this. I have a CentOS 7 server running in a cloud with a public IP and a valid domain name. You won&#8217;t need any SSL certificates, but you can add them if you want. This is not a complete guide on how to create a valid postfix and dovecot e-mail solution. If you are looking for that, stop and look further. The solution described here uses just the basic functionalities to send and receive e-mails. I&#8217;ll create some small scripts to manage the temporary e-mail addresses and you can use <strong>squirrelmail </strong>to check your e-mails. Actually, if you want you can skip that part and use some other e-mail POP3/IMAP e-mail client to check your e-mails.</p>
<h1>Valid domain and MX records</h1>
<p>You will need a valid domain for this. The scripts cover multiple virtual domains, so if you have many domains, you can use them as well. In the DNS for your domain make sure you have a valid MX record that points to your server. I use Route 53 and this is how my records look like.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/01/P144-01.png"><img decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/01/P144-01.png" alt="" width="443" height="76" class="aligncenter size-full wp-image-6428" srcset="https://blog.andreev.it/wp-content/uploads/2020/01/P144-01.png 443w, https://blog.andreev.it/wp-content/uploads/2020/01/P144-01-300x51.png 300w" sizes="(max-width: 443px) 100vw, 443px" /></a><br />
Make sure you have the MX record set properly. Go to this <a href="https://mxtoolbox.com/" rel="noopener noreferrer" target="_blank">site </a>and type your domain name. I&#8217;ll use my domain called <strong>cloudranger.live</strong>. This is how it looks like.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/01/P144-02.png"><img fetchpriority="high" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/01/P144-02.png" alt="" width="1205" height="288" class="aligncenter size-full wp-image-6429" srcset="https://blog.andreev.it/wp-content/uploads/2020/01/P144-02.png 1205w, https://blog.andreev.it/wp-content/uploads/2020/01/P144-02-300x72.png 300w, https://blog.andreev.it/wp-content/uploads/2020/01/P144-02-1024x245.png 1024w, https://blog.andreev.it/wp-content/uploads/2020/01/P144-02-768x184.png 768w, https://blog.andreev.it/wp-content/uploads/2020/01/P144-02-1170x280.png 1170w, https://blog.andreev.it/wp-content/uploads/2020/01/P144-02-585x140.png 585w" sizes="(max-width: 1205px) 100vw, 1205px" /></a><br />
Don&#8217;t worry about the DMARC error, we won&#8217;t use that. As you can see from both screenshots above, the IPs from the DNS and the tool match, which means your e-mail server will be properly configured on the Internet to receive e-mails. </p>
<h1>Firewall and SELinux</h1>
<p>If you use firewall, make sure you have these ports opened: 25 for SMTP, 143 for IMAP or 110 for POP3 and 80 for squirrelmail/Apache.<br />
SELinux can stay as is, but if you use squirrelmail, you&#8217;ll have to disable it in <strong>/etc/selinux/config</strong>. Or temporarily, do:</p>
<pre class="brush: bash; title: ; notranslate">
setenforce 0
</pre>
<h1>postfix Part I</h1>
<p>We&#8217;ll use postfix as MTA. It comes preinstalled on CentOS, but it runs on the localhost interface only, so we have to make some changes. The postfix daemon is running under the postfix user, but later we&#8217;ll see that because this users UID is lower than 1000, we can&#8217;t use it with dovecot. Actually, we can, but it&#8217;s not recommended. We&#8217;ll create a user called <strong>vpostfix</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
groupadd vpostfix &amp;&amp; useradd vpostfix -g vpostfix -s /sbin/nologin -c &quot;Virtual postfix user&quot; -d /var/empty
</pre>
<p>This will create a user and a group called vpostfix. Let&#8217;s get the <strong>UID </strong>and <strong>GID</strong>.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
grep vpostfix /etc/passwd &amp;&amp; grep vpostfix /etc/group
vpostfix:x:1002:1002:Virtual postfix user:/var/empty:/sbin/nologin
vpostfix:x:1002:
</pre>
<p>The <strong>UID </strong>and the <strong>GID </strong>are 1002. Write down this number. Now, edit the main configuration file for postfix which is <strong>/etc/postfix/main.cf</strong>. Make a copy first for the config file in case something goes wrong.</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/postfix
cp main.cf main.cf.ORIG
</pre>
<p>Then edit <strong>main.cf</strong> and search for <strong>inet_interfaces</strong>. <strong>IMPORTANT</strong>! Uncomment <strong>inet_interfaces = all</strong> and add a comment for i<strong>net_interfaces = localhost</strong>. If you don&#8217;t put comment in front of &#8230;localhost it will override the &#8230;all.</p>
<pre class="brush: bash; title: ; notranslate">
inet_interfaces = all
#inet_interfaces = $myhostname
#inet_interfaces = $myhostname, localhost
#inet_interfaces = localhost
</pre>
<p>Find and uncomment this line.</p>
<pre class="brush: bash; title: ; notranslate">
#home_mailbox = Maildir/
</pre>
<p>Then add these lines at the end of the file.</p>
<pre class="brush: bash; title: ; notranslate">
# Virtual domains, users, and aliases
virtual_mailbox_domains = mysql:/etc/postfix/virtual_domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/virtual_users.cf
virtual_mailbox_base = /var/mail/virtual_domains
# Make sure you replace these UID:GID numbers
virtual_minimum_uid = 1002
virtual_uid_maps = static:1002
virtual_gid_maps = static:1002
virtual_transport = lmtp:unix:private/dovecot
</pre>
<p>So, we&#8217;ll use virtual domains that will be defined in a MySQL database, our temp/disposable e-mail addresses will be also stored in a MySQL database and we&#8217;ll have a directory <strong>/var/mail/virtual_domains</strong> where we&#8217;ll get the e-mails in a <strong>Maildir </strong>format. Make sure you replace those numbers that you got for the postfix user. The last line is used to override the actual postfix delivery and use dovecot for that.<br />
Let&#8217;s create the directory where e-mails will be stored.</p>
<pre class="brush: bash; title: ; notranslate">
mkdir /var/mail/virtual_domains
chown -R vpostfix:vpostfix /var/mail/virtual_domains
</pre>
<p>Leave postfix as is for now and let&#8217;s proceed with MySQL database.</p>
<h1>MySQL</h1>
<p>I prefer to use MariaDB, so we&#8217;ll install that first.</p>
<pre class="brush: bash; title: ; notranslate">
yum -y install mariadb-server
</pre>
<p>Enable the daemon on boot and start it.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl enable mariadb
systemctl start mariadb
</pre>
<p>Do an initial config.</p>
<pre class="brush: bash; title: ; notranslate">
mysql_secure_installation
</pre>
<p>Pretty much, accept the defaults with ENTER and just enter the new <strong>root </strong>database password.<br />
Now, we have to create the database and two tables for the virtual domains and the virtual users as specified in lines 2 and 3 in the <strong>main.cf</strong> file above. Copy and paste these lines but change the password in line 3. That is your password for the postfix database user. This DB user has nothing to do with postfix account in <strong>/etc/passwd </strong>that runs postfix. You can change the name if you want, but you have to remember it later when we do the scripts.</p>
<pre class="brush: bash; title: ; notranslate">
cat &lt;&lt; 'EOF' &gt; /tmp/temp.sql
CREATE DATABASE db_postfix;
GRANT ALL PRIVILEGES ON db_postfix.* TO &quot;postfix&quot;@&quot;localhost&quot; IDENTIFIED BY &quot;your_password&quot;;

use db_postfix;

CREATE TABLE virtual_domains (
  id INT(11) NOT NULL AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL,
  PRIMARY KEY (id),
  UNIQUE(name)
);

CREATE TABLE virtual_users (
  id int(11) NOT NULL AUTO_INCREMENT,
  domain_id INT(11) NOT NULL,
  password VARCHAR(106) NOT NULL,
  email VARCHAR(100) NOT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY email (email),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) DEFAULT CHARSET=utf8;
EOF
</pre>
<p>Run the script.</p>
<pre class="brush: bash; title: ; notranslate">
mysql -u root -p &lt; /tmp/temp.sql
</pre>
<p>You can check the tables. Log to the database as the postfix with the password you specified in line 3.</p>
<pre class="brush: bash; title: ; notranslate">
mysql -u postfix -p
</pre>
<p>Then switch to our new database <strong>db_postfix</strong> defined in line 2.</p>
<pre class="brush: bash; title: ; notranslate">
use db_postfix;
</pre>
<p>Show the tables.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
show tables;
+----------------------+
| Tables_in_db_postfix |
+----------------------+
| virtual_domains      |
| virtual_users        |
+----------------------+
2 rows in set (0.00 sec)
</pre>
<p>At this point, we are good with the database. Now we have to create the scripts that will manage the domains and users. You can (of course) use mysql commands to create domains and users, but I&#8217;ve made some scripts that will make this easier.</p>
<h1>Scripts</h1>
<p>These scripts are the backbone of how you&#8217;ll interact when creating domains and users. It simplifies everything for you. So, we&#8217;ll have a couple of scripts/commands and this is their syntax. I&#8217;ll put them under <strong>/usr/local/bin</strong> so if you run these commands as root, this directory is not in the path. But under CentOS, if you have any non-root user, <strong>/usr/local/bin</strong> is already in the <strong>$PATH</strong>. So, do <strong>echo $PATH</strong> and see if you can execute them without specifying the full path.<br />
There are 8 scripts in total. If you run them without any parameters, they&#8217;ll give you the syntax. This is a brief description.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/01/P144-03.png"><img decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/01/P144-03.png" alt="" width="719" height="181" class="aligncenter size-full wp-image-6438" srcset="https://blog.andreev.it/wp-content/uploads/2020/01/P144-03.png 719w, https://blog.andreev.it/wp-content/uploads/2020/01/P144-03-300x76.png 300w, https://blog.andreev.it/wp-content/uploads/2020/01/P144-03-585x147.png 585w" sizes="(max-width: 719px) 100vw, 719px" /></a><br />
Here is the kick. These scripts call the mysql utility and you have to provide a password for every interaction with the database. You can easily modify them and specify <strong>-p</strong> parameter in the script and type the password there, but that&#8217;s not recommended. So, you have to either specify the postfix DB user password all the time&#8230; or, my suggestion is to export the postfix password in a variable that only lasts for the duration of your session.<br />
So, before running any of the scripts, I recommend that you export your password like this. This is the password for the postfix DB user, not the root DB user.</p>
<pre class="brush: bash; title: ; notranslate">
export MYSQL_PWD=your_password
</pre>
<p>Once you do this, you can run any of the scripts without any prompts. Copy and paste the following scripts.<br />
<strong>IMPORTANT! </strong>If you modified the DB name or any table name from my script (<strong>/tmp/temp.sql</strong>), you have to modify these scripts as well.<br />
==================================================<br />
<strong>add_domain</strong></p>
<pre class="brush: bash; collapse: true; light: false; title: ; toolbar: true; notranslate">
cat &lt;&lt; 'EOF' &gt; /usr/local/bin/add_domain
#!/bin/bash
usage () {
    echo &quot;Usage: add_domain &lt;domain_name&gt;&quot;
}

if &#x5B; $# -ne 1 ] ; then
    usage
    exit 1
fi

if &#x5B; -z &quot;$MYSQL_PWD&quot; ] ; then
    OPTION=&quot;-p&quot;
else
    OPTION=&quot;&quot;
fi

/usr/bin/mysql -u postfix db_postfix $OPTION -e &quot;INSERT INTO db_postfix.virtual_domains (name) VALUES ('$1');&quot;
EOF
</pre>
<p><strong>add_user</strong></p>
<pre class="brush: bash; collapse: true; light: false; title: ; toolbar: true; notranslate">
cat &lt;&lt; 'EOF' &gt; /usr/local/bin/add_user
#!/bin/bash
if &#x5B; $# -ne 2 ] ; then
    echo &quot;Usage: add_user &lt;e-mail&gt; &lt;password&gt;&quot;
    exit 1
fi

if &#x5B; -z &quot;$MYSQL_PWD&quot; ] ; then
    OPTION=&quot;-p&quot;
else
    OPTION=&quot;&quot;
fi
regex=&quot;^&#x5B;a-z0-9!#\$%&amp;'*+/=?^_\`{|}~-]+(\.&#x5B;a-z0-9!#$%&amp;'*+/=?^_\`{|}~-]+)*@(&#x5B;a-z0-9](&#x5B;a-z0-9-]*&#x5B;a-z0-9])?\.)+&#x5B;a-z0-9](&#x5B;a-z0-9-]*&#x5B;a-z0-9])?\$&quot;

if &#x5B;&#x5B; $1 =~ $regex ]] ; then
    DOMAIN=`echo $1 | cut -d'@' -f2`
else
    echo &quot;Not a valid e-mail address.&quot;
    exit 1
fi
ID=$(/usr/bin/mysql -u postfix db_postfix -s $OPTION -N -e &quot;SELECT id from db_postfix.virtual_domains WHERE NAME='$DOMAIN';&quot;)
if &#x5B; -z &quot;$ID&quot; ] ; then
    echo &quot;The domain $DOMAIN is missing. Use add_domain $DOMAIN first.&quot;
else
   /usr/bin/mysql -u postfix db_postfix $OPTION -e &quot;INSERT INTO db_postfix.virtual_users (domain_id, email, password) VALUES ($ID, '$1', ENCRYPT('$2', CONCAT('\$6\$', SUBSTRING(SHA(RAND()), -16))));&quot;
fi
EOF
</pre>
<p><strong>ls_domains</strong></p>
<pre class="brush: bash; collapse: true; light: false; title: ; toolbar: true; notranslate">
cat &lt;&lt; 'EOF' &gt; /usr/local/bin/ls_domains
#!/bin/bash
if &#x5B; -z &quot;$MYSQL_PWD&quot; ] ; then
    OPTION=&quot;-p&quot;
else
    OPTION=&quot;&quot;
fi
/usr/bin/mysql -u postfix db_postfix $OPTION -e &quot;SELECT * FROM virtual_domains;&quot;
EOF
</pre>
<p><strong>ls_users</strong></p>
<pre class="brush: bash; collapse: true; light: false; title: ; toolbar: true; notranslate">
cat &lt;&lt; 'EOF' &gt; /usr/local/bin/ls_users
#!/bin/bash

if &#x5B; -z &quot;$MYSQL_PWD&quot; ] ; then
    OPTION=&quot;-p&quot;
else
    OPTION=&quot;&quot;
fi

/usr/bin/mysql -u postfix db_postfix $OPTION -e &quot;SELECT * FROM virtual_users;&quot;

EOF
</pre>
<p><strong>rmall_domains</strong></p>
<pre class="brush: bash; collapse: true; light: false; title: ; toolbar: true; notranslate">
cat &lt;&lt; 'EOF' &gt; /usr/local/bin/rmall_domains
#!/bin/bash
if &#x5B; -z &quot;$MYSQL_PWD&quot; ] ; then
    OPTION=&quot;-p&quot;
else
    OPTION=&quot;&quot;
fi

while true; do
    read -p &quot;All domain records will be deleted. Please confirm &#x5B;yn] &quot; yn
    case $yn in
        &#x5B;Yy]* ) /usr/bin/mysql -u postfix db_postfix $OPTION -e &quot;DELETE FROM db_postfix.virtual_domains&quot;; break;;
        &#x5B;Nn]* ) exit;;
        * ) echo &quot;Answer yes(y) or no(n).&quot;;;
    esac
done
EOF
</pre>
<p><strong>rmall_users</strong></p>
<pre class="brush: bash; collapse: true; light: false; title: ; toolbar: true; notranslate">
cat &lt;&lt; 'EOF' &gt; /usr/local/bin/rmall_users
#!/bin/bash
if &#x5B; -z &quot;$MYSQL_PWD&quot; ] ; then
    OPTION=&quot;-p&quot;
else
    OPTION=&quot;&quot;
fi

while true; do
    read -p &quot;All user records will be deleted. Please confirm &#x5B;yn] &quot; yn
    case $yn in
        &#x5B;Yy]* ) /usr/bin/mysql -u postfix db_postfix $OPTION -e &quot;DELETE FROM db_postfix.virtual_users&quot;; break;;
        &#x5B;Nn]* ) exit;;
        * ) echo &quot;Answer yes(y) or no(n).&quot;;;
    esac
done

EOF
</pre>
<p><strong>rm_domain</strong></p>
<pre class="brush: bash; collapse: true; light: false; title: ; toolbar: true; notranslate">
cat &lt;&lt; 'EOF' &gt; /usr/local/bin/rm_domain
#!/bin/bash
if &#x5B; $# -ne 1 ]
  then
    echo &quot;Usage: rm_domain &lt;domain_name&gt;&quot;
    exit
fi
if &#x5B; -z &quot;$MYSQL_PWD&quot; ] ; then
    OPTION=&quot;-p&quot;
else
    OPTION=&quot;&quot;
fi

/usr/bin/mysql -u postfix db_postfix $OPTION -e &quot;DELETE FROM db_postfix.virtual_domains WHERE name = '$1';&quot;

EOF
</pre>
<p><strong>rm_user</strong></p>
<pre class="brush: bash; collapse: true; light: false; title: ; toolbar: true; notranslate">
cat &lt;&lt; 'EOF' &gt; /usr/local/bin/rm_user
#!/bin/bash
if &#x5B; $# -ne 1 ]
  then
    echo &quot;Usage: rm_user &lt;e-mail&gt;&quot;
    exit
fi
if &#x5B; -z &quot;$MYSQL_PWD&quot; ] ; then
    OPTION=&quot;-p&quot;
else
    OPTION=&quot;&quot;
fi

/usr/bin/mysql -u postfix db_postfix $OPTION -e &quot;DELETE FROM db_postfix.virtual_users WHERE email = '$1';&quot;
EOF
</pre>
<p>==================================================<br />
Make the scripts executable.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/bin
chmod +x add_domain ls_domains rmall_domains rm_domain add_user ls_users rmall_users rm_user
</pre>
<p>Now that we have the scripts let&#8217;s create our first domain and first disposable e-mail address. It&#8217;s very easy.<br />
Log as regular user or add <strong>/usr/local/bin</strong> in the PATH if you run these as root.</p>
<pre class="brush: bash; title: ; notranslate">
export MYSQL_PWD=pwd_for_postfix_user
add_domain cloudranger.live
add_user klimenta@cloudranger.live some_pwd
</pre>
<p>Check what you did.</p>
<pre class="brush: bash; highlight: [1,7]; title: ; notranslate">
ls_domains
+----+------------------+
| id | name             |
+----+------------------+
|  1 | cloudranger.live |
+----+------------------+
ls_users
+----+-----------+----------------------------------------------------------+---------------------------+
| id | domain_id | password                                                 | email                     |
+----+-----------+----------------------------------------------------------+---------------------------+
|  1 |         1 | $6$4asdfasdfadsfasdfasdfadsfasdfadsfasdfasdfadsfa3qw8sF/ | klimenta@cloudranger.live |
+----+-----------+----------------------------------------------------------+---------------------------+
</pre>
<p>The password is hashed. Use the other commands if you want to remove a domain, user, all domains or all users. </p>
<h1>postfix Part II</h1>
<p>Now that we have MySQL ready, you should create two files that will tell postfix how to tie with MySQL. If you look at the postfix <strong>main.cf</strong> file, lines 2 and 3 specify exactly that info. Here are the files. Just copy and paste these, but make sure you change the password in line 2. Log as root or sudo.</p>
<pre class="brush: bash; title: ; notranslate">
cat &lt;&lt; 'EOF' &gt; /etc/postfix/virtual_domains.cf
user = postfix
password = password_for_db_user_postfix
hosts = 127.0.0.1
dbname = db_postfix
query = SELECT 1 from virtual_domains WHERE name='%s'
EOF
</pre>
<p>And the same file for the e-mails.</p>
<pre class="brush: bash; title: ; notranslate">
cat &lt;&lt; 'EOF' &gt; /etc/postfix/virtual_users.cf
user = postfix
password = password_for_db_user_postfix
hosts = 127.0.0.1
dbname = db_postfix
query = SELECT 1 from virtual_users WHERE email='%s'
EOF
</pre>
<h1>dovecot</h1>
<p>We&#8217;ll use dovecot so we can get the received e-mails as POP3 or IMAP. I&#8217;ll enable both protocols but I&#8217;ll use IMAP later with the squirrelmail. We need to install it first and enable it to boot.</p>
<pre class="brush: bash; title: ; notranslate">
yum -y install dovecot dovecot-mysql
systemctl enable dovecot
</pre>
<p>Now, we&#8217;ll configure it. dovecot has one main config file which <strong>/etc/dovecot/dovecot.conf</strong> and separate config files for each functionality under <strong>/etc/dovecot/conf.d</strong> directory. Make a copy of both.</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/dovecot
cp dovecot.conf dovecot.conf.ORIG
cp -R conf.d conf.d.ORIG
</pre>
<p>Edit <strong>/etc/dovecot/dovecot.conf</strong> and uncomment the following line.</p>
<pre class="brush: bash; title: ; notranslate">
protocols = imap pop3 lmtp
</pre>
<p>Then, copy the template dovecot-sql file. You might have to check the directory where this file is, because the dovecot version number is part of the name.</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/dovecot
cp /usr/share/doc/dovecot-2.2.36/example-config/dovecot-sql.conf.ext .
</pre>
<p>Edit this file and search for these directives, uncomment them and configure them properly.</p>
<pre class="brush: bash; title: ; notranslate">
#driver =
</pre>
<p>&#8230;should become</p>
<pre class="brush: bash; title: ; notranslate">
driver = mysql
</pre>
<p>Then&#8230;</p>
<pre class="brush: bash; title: ; notranslate">
#connect =
</pre>
<p>&#8230;should become</p>
<pre class="brush: bash; title: ; notranslate">
connect = host=127.0.0.1 dbname=db_postfix user=postfix password=pwd_for_db_postfix_user
</pre>
<p>Again&#8230;</p>
<pre class="brush: bash; title: ; notranslate">
#default_pass_scheme = MD5
</pre>
<p>&#8230;should become</p>
<pre class="brush: bash; title: ; notranslate">
default_pass_scheme = SHA512-CRYPT
</pre>
<p>Scroll down and finally change this.</p>
<pre class="brush: bash; title: ; notranslate">
#password_query = \
#  SELECT username, domain, password \
#  FROM users WHERE username = '%n' AND domain = '%d'
</pre>
<p>&#8230;to this.</p>
<pre class="brush: bash; title: ; notranslate">
password_query = \
  SELECT email as user, password \
  FROM virtual_users WHERE email = '%u'
</pre>
<p>But it&#8217;s not over. We have to make some changes in the other files as well.<br />
Edit each of these files and make these changes under <strong>/etc/dovecot/conf.d</strong>.<br />
====================================================<br />
<strong>10-master.conf</strong><br />
Look for this snippet and make sure&#8230;</p>
<pre class="brush: bash; title: ; notranslate">
service lmtp {
  unix_listener lmtp {
    #mode = 0666
  }
</pre>
<p>&#8230;it&#8217;s like this. The first occurrence for user/group is postfix, the rest are vpostfix. It&#8217;s not a typo.</p>
<pre class="brush: bash; title: ; notranslate">
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot {
    #mode = 0666
    mode = 0600
    user = postfix
    group = postfix
  }
</pre>
<p>Same further down. </p>
<pre class="brush: bash; title: ; notranslate">
  unix_listener auth-userdb {
    #mode = 0666
    #user =
    #group =
  }

  # Postfix smtp-auth
  #unix_listener /var/spool/postfix/private/auth {
  #  mode = 0666
  #}
</pre>
<p>Should look like this.</p>
<pre class="brush: bash; title: ; notranslate">
  unix_listener auth-userdb {
    mode = 0600
    user = vpostfix
    group =  vpostfix
  }

  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = vpostfix
    group = vpostfix
  }
</pre>
<p><strong>10-auth.conf</strong><br />
Uncomment these 3 lines.</p>
<pre class="brush: bash; title: ; notranslate">
disable_plaintext_auth = yes
auth_mechanisms = plain
!include auth-sql.conf.ext
</pre>
<p>Then modify <strong>auth_mechanisms = plain</strong> and add <strong>login </strong>so it looks like this.</p>
<pre class="brush: bash; title: ; notranslate">
auth_mechanisms = plain login
</pre>
<p><strong>auth-sql.conf.ext</strong><br />
Comment these lines.</p>
<pre class="brush: bash; title: ; notranslate">
userdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
</pre>
<p>So it&#8217;s like this.</p>
<pre class="brush: bash; title: ; notranslate">
#userdb {
#  driver = sql
#  args = /etc/dovecot/dovecot-sql.conf.ext
#}
</pre>
<p>&#8230;and all the way at the bottom.</p>
<pre class="brush: bash; title: ; notranslate">
#userdb {
  #driver = static
  #args = uid=vmail gid=vmail home=/var/vmail/%u
#}
</pre>
<p>should be&#8230;Don&#8217;t just uncomment. Change the <strong>args </strong>line.</p>
<pre class="brush: bash; title: ; notranslate">
userdb {
  driver = static
  args = uid=vpostfix gid=vpostfix home=/var/mail/virtual_domains/%d/%n
}
</pre>
<p><strong>10-logging.conf</strong><br />
Uncomment the <strong>log_path</strong> line and specify a log file for dovecot.</p>
<pre class="brush: bash; title: ; notranslate">
log_path = /var/log/dovecot.log
</pre>
<p><strong>10-mail.conf</strong><br />
Uncomment the <strong>mail_location</strong> and specify where the e-mails will be stored. <strong>%d/%n</strong> means the domain name and the login name, so the path will be something like <strong>/var/mail/virtual_domains/cloudranger.live/klimenta</strong>. dovecot will take care of the directory creation, so don&#8217;t worry about that.</p>
<pre class="brush: bash; title: ; notranslate">
mail_location = maildir:/var/mail/virtual_domains/%d/%n
</pre>
<p>====================================================</p>
<h1>Test e-mail delivery</h1>
<p>At this point we should be able to test our solution. Restart both daemons, so all the changes take effect.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl restart mariadb
systemctl restart postfix
systemctl restart dovecot
</pre>
<p>Check the logs for both postfix and dovecot. They should look similar to this.</p>
<pre class="brush: bash; title: ; notranslate">
tail /var/log/maillog
Jan 13 16:21:08 ip-172-31-72-148 postfix/postfix-script&#x5B;27817]: stopping the Postfix mail system
Jan 13 16:21:08 ip-172-31-72-148 postfix/master&#x5B;2774]: terminating on signal 15
Jan 13 16:21:08 ip-172-31-72-148 postfix/postfix-script&#x5B;27897]: starting the Postfix mail system
Jan 13 16:21:08 ip-172-31-72-148 postfix/master&#x5B;27899]: daemon started -- version 2.10.1, configuration /etc/postfix
</pre>
<p>&#8230;and</p>
<pre class="brush: bash; title: ; notranslate">
tail /var/log/dovecot.log
Jan 13 16:21:14 master: Info: Dovecot v2.2.36 (1f10bfa63) starting up for imap, pop3, lmtp (core dumps disabled)
</pre>
<p>From another computer send an e-mail to your disposable e-mail account. You&#8217;ll see that it&#8217;s recorded in the postfix log.<br />
This is my <strong>/var/log/maillog</strong>.</p>
<pre class="brush: bash; highlight: [6]; title: ; notranslate">
Jan 13 23:34:26 ip-172-31-86-23 postfix/smtpd&#x5B;23108]: connect from something.domain.com&#x5B;114.102.113.201]
Jan 13 23:34:26 ip-172-31-86-23 postfix/smtpd&#x5B;23108]: ACB334065F8: client=something.domain.com&#x5B;114.102.113.201]
Jan 13 23:34:26 ip-172-31-86-23 postfix/cleanup&#x5B;23116]: ACB334065F8: message-id=&lt;000701d5ca69$fe8e8eb0$fbabac10$@heythere.com&gt;
Jan 13 23:34:26 ip-172-31-86-23 postfix/smtpd&#x5B;23108]: disconnect from something.domain.com&#x5B;114.102.113.201]
Jan 13 23:34:26 ip-172-31-86-23 postfix/qmgr&#x5B;23052]: ACB334065F8: from=&lt;user@heythere.com&gt;, size=2814, nrcpt=1 (queue active)
Jan 13 23:34:26 ip-172-31-86-23 postfix/lmtp&#x5B;23117]: ACB334065F8: to=&lt;klimenta@cloudranger.live&gt;, relay=ip-172-31-86-23.ec2.internal&#x5B;private/dovecot], delay=0.09, delays=0.02/0.01/0.01/0.04, dsn=2.0.0, status=sent (250 2.0.0 &lt;klimenta@cloudranger.live&gt; gDpGLIL+HF5OWgAAbmziKA Saved)
Jan 13 23:34:26 ip-172-31-86-23 postfix/qmgr&#x5B;23052]: ACB334065F8: removed
</pre>
<p>Look at line 6 (scroll to the right). SMTP code 250 means all went well.<br />
And if you go to <strong>/var/mail/virtual_domains/your_domain/your_email</strong>, you&#8217;ll see a bunch of folders created. The e-mail that just arrived is under <strong>new </strong>directory. You can <strong>cat </strong>the file and see your e-mail.</p>
<pre class="brush: bash; highlight: [1,3]; title: ; notranslate">
pwd
/var/mail/virtual_domains/cloudranger.live/klimenta/new
ls -l
total 4
-rw-------. 1 vpostfix vpostfix 2993 Jan 13 23:34 1578958466.M778127P23118.ip-172-31-86-23.ec2.internal,S=2993,W=3076
</pre>
<p>At this point, you can use some IMAP/POP3 client to get the e-mail (see notes at the end). Specify the hostname of the server as your mail server, if asked for port, put 110 for POP and 143 for IMAP and your disposable e-mail/password as username and password. In my case, I don&#8217;t want to deal with constant e-mail client configuration for these temp e-mails, so I installed <strong>squirrelmail</strong>. You can use <strong>Roundcube Mail</strong> if you like sleeker interface, but there is more configuration involved.</p>
<h1>squirrelmail (optional)</h1>
<p>In order to install squirrelmail, you have to install epel-release repo. It also installs Apache and PHP for you. Bear this in mind and if you are not comfortable, stop.</p>
<pre class="brush: bash; title: ; notranslate">
yum -y install epel-release
</pre>
<p>Then install squirrelmail.</p>
<pre class="brush: bash; title: ; notranslate">
yum -y install squirrelmail
</pre>
<p>Enable Apache on boot.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl enable httpd
</pre>
<p>Go to <strong>/etc/httpd/conf.d</strong> and replace the <strong>squirrelmail.conf</strong> file. Keep the original file. Just copy and paste.</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/httpd/conf.d
mv squirrelmail.conf squirrelmail.conf.ORIG
cat &lt;&lt; 'EOF' &gt; /etc/httpd/conf.d/squirrelmail.conf
#
# SquirrelMail is a webmail package written in PHP.
#

Alias /webmail /usr/share/squirrelmail

&lt;Directory &quot;/usr/share/squirrelmail&quot;&gt;
        Options None
        AllowOverride none
        Require all granted
&lt;/Directory&gt;
EOF
</pre>
<p>Let&#8217;s configure it.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/share/squirrelmail/config/
./conf.pl
</pre>
<p>Go to #2, then #3. Switch to #2 (SMTP). Go back with <strong>R</strong> and then go to option <strong>D</strong> and type <strong>dovecot</strong>. Finally type <strong>S</strong> to Save data. <strong>Q</strong> to quit.<br />
Start Apache.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl start httpd
</pre>
<p>&#8230;and go to your server&#8217;s IP or hostname if you have it in DNS as <em>http://ip_or_hostname/webmail</em>. Log with the disposable e-mail and you&#8217;ll see your mailbox. </p>
<h1>Note about POP3/IMAP clients</h1>
<p>If you want to access your mailbox from a GUI client from another computer, you won&#8217;t be able to do so because of the dovecot configuration. That&#8217;s because dovecot considers localhost connections secure, but any other subnet rather than that is considered unsecure.<br />
In order to make this work, you&#8217;ll have to make changes. But mind that if you make these changes, your password will be sent as a plain text across the network. If you are fine with this, proceed.<br />
Change this line to  <strong>= no</strong> in <strong>/etc/dovecot/conf.d/10-auth.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
disable_plaintext_auth = yes
</pre>
<p>Change <strong>ssl = required</strong> in <strong>/etc/dovecot/conf.d/10-ssl.conf</strong> to <strong>ssl = no</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
ssl = no
</pre>
<p>Restart dovecot and you should be able to access your mailbox remotely.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2020/01/centos-create-disposable-e-mail-addresses-using-postfix-dovecot-and-squirrelmail/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>General: Relay client e-mails using SASL and TLS in postfix</title>
		<link>https://blog.andreev.it/2018/03/124-postfix-relay-client-e-mails-using-sasl-and-tls/</link>
					<comments>https://blog.andreev.it/2018/03/124-postfix-relay-client-e-mails-using-sasl-and-tls/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Sun, 11 Mar 2018 03:20:33 +0000</pubDate>
				<category><![CDATA[CentOS]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[OpenBSD]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[e-mail]]></category>
		<category><![CDATA[postfix]]></category>
		<category><![CDATA[relay]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=3729</guid>

					<description><![CDATA[I have a bunch of test CentOS/FreeBSD servers and I wanted to get all&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>I have a bunch of test CentOS/FreeBSD servers and I wanted to get all the notifications sent to my e-mail instead of logging to each server and check the status of each one of them. Some of my servers are behind my home network where outbound port 25 (SMTP) is blocked by the ISP. So, I decided to use my main postfix server which is already configured to use port 587 for SMTP using TLS. In this post, I&#8217;ll explain how I configured my test servers to relay e-mails.<br />
Use the following links to see how I configured the postfix main server for <a href="https://blog.andreev.it/?p=1975" rel="noopener noreferrer" target="_blank">CentOS </a>and <a href="https://blog.andreev.it/?p=1604" rel="noopener noreferrer" target="_blank">FreeBSD</a>. </p>
<h1>CentOS 7</h1>
<p>There are some prerequisites for CentOS 7. It comes with postfix installed and it has built-in Cyrus SASL already, but we need another Cyrus SASL package for login support. In addition, CentOS doesn&#8217;t come up with the mail command, so we have to install that as well.</p>
<h2>Prerequisites</h2>
<p>Install Cyrus SASL package and the mail client.</p>
<pre class="brush: bash; title: ; notranslate">
yum install cyrus-sasl-plain mailx
</pre>
<h2>postfix main config file</h2>
<p>Edit <strong>/etc/postfix/main.cf</strong> and add these lines at the end.</p>
<pre class="brush: bash; title: ; notranslate">
relayhost = &#x5B;server.domain.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_use_tls = yes
smtp_tls_CAfile = /etc/ssl/certs/server.domain.com.crt
</pre>
<p>The first line is your main postfix server that will receive the e-mail from the client servers, the 4th line is the file where you are going to store the username and password for the user that&#8217;s able to login to the main postfix server and the 6th line is the certificate of the main postfix server. </p>
<h2>SASL Authentication</h2>
<p>Edit <strong>/etc/postfix/sasl_passwd</strong> and add this line.</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;server.domain.com]:587 mail@domain.com:YourPassword
</pre>
<p>You have to specify your main postfix server, the username and the password for a valid user that&#8217;s able to login to that server and receive e-mails. Once completed, execute postmap.</p>
<pre class="brush: bash; title: ; notranslate">
postmap /etc/postfix/sasl_passwd
</pre>
<h2>e-mails to relay</h2>
<p>I wanted to send all of my root e-mails to my main server, so what you have to do is edit <strong>/etc/aliases</strong> and scroll all the way down at the bottom. Un-comment the root line and specify where do you want your root emails to be forwarded.</p>
<pre class="brush: bash; title: ; notranslate">
root: mail@domain.com
</pre>
<p>If you have some cron jobs that run under some other username, specify them in this file, e.g. someuser: some-email@email.com.<br />
After you are done, type newaliases.</p>
<pre class="brush: bash; title: ; notranslate">
newaliases
</pre>
<h2>Public certificate</h2>
<p>You will also need the public certificate of your e-mail server. Get the certificate in a PEM format and paste it into a new file <strong>/etc/ssl/certs/server.domain.com.crt</strong>. Or, in my case, I have a wildcard certificate for my domain, so I can get it using this command.</p>
<pre class="brush: bash; title: ; notranslate">
openssl s_client -connect server.domain.com:443 &lt; /dev/null | \
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' &gt; /etc/ssl/certs/server.domain.com.crt
</pre>
<h2>Final step</h2>
<p>Restart the postfix server on the client server, send a test e-mail and check the result.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl restart postfix
echo &quot;This is a test.&quot; | mail -s &quot;Test e-mail&quot; root
tail /var/log/maillog
</pre>
<h1>FreeBSD 11</h1>
<p>Unlike CentOS, FreeBSD doesn&#8217;t come up with postfix, instead it uses sendmail. So, we have to remove sendmail, install postfix and follow similar config as with CentOS.</p>
<h2>Prerequisites</h2>
<p>We have to install postfix from the ports because it doesn&#8217;t come up with Cyrus SASL. It comes with dovecot SASL, but I am not sure if it works in a client config. On the other hand, FreeBSD comes with mail installed. Install the postfix port, not the package. </p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/ports
</pre>
<p>If you get an error that there is no such file or directory, get the ports tree. If you can cd to that folder, skip the step below to install the ports tree.</p>
<pre class="brush: bash; title: ; notranslate">
portsnap fetch
portsnap extract
</pre>
<p>Install postfix.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/ports/mail/postfix
make all install clear
</pre>
<p>When this dialog box pops-up, select <strong>BDB </strong>and <strong>SASL </strong>as highlighted.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P101-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P101-01.png" alt="" width="537" height="324" class="aligncenter size-full wp-image-8191" /></a><br />
Execute these lines so you replace sendmail with postfix.</p>
<pre class="brush: bash; title: ; notranslate">
sysrc postfix_enable=&quot;YES&quot;
sysrc sendmail_enable=&quot;NONE&quot;
mv /usr/local/etc/mail/mailer.conf /usr/local/etc/mail/mailer.conf.old
install -m 0644 /usr/local/share/postfix/mailer.conf.postfix /usr/local/etc/mail/mailer.conf
</pre>
<p>Add the following lines to <strong>/etc/defaults/periodic.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
daily_clean_hoststat_enable=&quot;NO&quot;
daily_status_mail_rejects_enable=&quot;NO&quot;
daily_status_include_submit_mailq=&quot;NO&quot;
daily_submit_queuerun=&quot;NO&quot;
</pre>
<p>Make sure Cyrus SASL is installed.</p>
<pre class="brush: bash; title: ; notranslate">
postconf -a
</pre>
<p>You should see cyrus and dovecot there.</p>
<h2>postfix main config file</h2>
<p>Edit <strong>/usr/local/etc/postfix/main.cf</strong> and add these lines at the end.</p>
<pre class="brush: bash; title: ; notranslate">
relayhost = &#x5B;server.domain.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/usr/local/etc/postfix/sasl_passwd
smtp_use_tls = yes
smtp_tls_CAfile = /usr/local/etc/ssl/server.domain.com.crt
</pre>
<p>The first line is your main postfix server that will receive the e-mail from the client servers, the 4th line is the file where you are going to store the username and password for the user that’s able to login to the main postfix server and the 6th line is the certificate of the main postfix server.</p>
<h2>SASL Authentication</h2>
<p>Edit <strong>/usr/local/etc/postfix/sasl_passwd</strong> and add this line.</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;server.domain.com]:587 mail@domain.com:YourPassword
</pre>
<p>You have to specify your main postfix server, the username and the password for a valid user that’s able to login to that server and receive e-mails. Once completed, execute postmap.</p>
<pre class="brush: bash; title: ; notranslate">
postmap /usr/local/etc/postfix/sasl_passwd
</pre>
<h2>e-mails to relay</h2>
<p>I wanted to send all of my root e-mails to my main server, so what you have to do is edit <strong>/etc/aliases</strong> and scroll a little bit way down. Un-comment the root line and specify where do you want your root emails to be forwarded.</p>
<pre class="brush: bash; title: ; notranslate">
root: mail@domain.com
</pre>
<p>If you have some cron jobs that run under some other username, specify them in this file, e.g. <strong>someuser: some-email@email.com.</strong><br />
After you are done, type <strong>newaliases</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
newaliases
</pre>
<h2>Public certificate</h2>
<p>You will also need the public certificate of your e-mail server. Get the certificate in a PEM format and paste it into a new file <strong>/usr/local/etc/ssl/server.domain.com.crt</strong>. Or, in my case, I have a wildcard certificate for my domain, so I can get it using this command.</p>
<pre class="brush: bash; title: ; notranslate">
openssl s_client -connect server.domain.com:443 &lt; /dev/null | \
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' &gt; /usr/local/etc/ssl/server.domain.com.crt
</pre>
<h2>Final step</h2>
<p>Restart the postfix server on the client server, send a test e-mail and check the result.</p>
<pre class="brush: bash; title: ; notranslate">
service postfix restart
echo &quot;This is a test.&quot; | mail -s &quot;Test e-mail&quot; root
tail /var/log/maillog
</pre>
<p>You will notice that the e-mails that come from FreeBSD are always sent by Charlie Root. If you have multiple FreeBSD boxes, the e-mails from various FreeBSD servers will come as Charlie Root which might be a bit confusing. So do a <strong>chpass </strong>and change the line <strong>Full Name</strong>, so instead of <strong>Full Name: Charlie &#038;</strong>, do something like <strong>Full Name: servername Charlie &#038;</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
chpass
</pre>
<p><a href="https://blog.andreev.it/wp-content/uploads/2018/03/P101-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P101-02.png" alt="" width="565" height="253" class="aligncenter size-full wp-image-8192" /></a><br />
Do <strong><ESC>:wq</strong> if your default editor is vi to save the changes.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2018/03/124-postfix-relay-client-e-mails-using-sasl-and-tls/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CentOS: postfix, dovecot, Roundcube, amavisd-new, spamassassin, clamav on CentOS 7</title>
		<link>https://blog.andreev.it/2015/06/centos-7-postfix-dovecot-roundcube-amavisd-new-spamassassin-clamav-pigeonhole/</link>
					<comments>https://blog.andreev.it/2015/06/centos-7-postfix-dovecot-roundcube-amavisd-new-spamassassin-clamav-pigeonhole/#comments</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Thu, 04 Jun 2015 16:14:47 +0000</pubDate>
				<category><![CDATA[CentOS]]></category>
		<category><![CDATA[amavisd-new]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[clamav]]></category>
		<category><![CDATA[dovecot]]></category>
		<category><![CDATA[postfix]]></category>
		<category><![CDATA[Roundcube]]></category>
		<category><![CDATA[spamassassin]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=1975</guid>

					<description><![CDATA[In one of my previous posts I&#8217;ve described how to run a postfix and&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>In one of my previous <a href="https://blog.andreev.it/?p=849" target="_blank" rel="noopener noreferrer">posts</a> I&#8217;ve described how to run a postfix and dovecot on CentOS 6. This time, we&#8217;ll go a step further and after the installation of <a href="http://www.postfix.org/" target="_blank" rel="noopener noreferrer">postfix</a> and <a href="http://www.dovecot.org/" target="_blank" rel="noopener noreferrer">dovecot</a>, we&#8217;ll talk about mail filtering, spam and anti-virus protection. </p>
<h1>Pre install</h1>
<p>The post described below uses:</p>
<ul>
<li> CentOS 7.1.1503 (fresh install)</li>
<li> Kernel 3.10.0-229.4.2.e17.x86_64
<li> postfix 2.10.1
<li> dovecot 2.2.10
<li> amavisd-new 2.10.1
<li> spamassasin 3.4.0
<li> clamav 0.98.7
<li> pigeonhole 0.4.3</li>
</ul>
<p>and will allow you to use virtual e-mail domains and users.</p>
<h1>postfix</h1>
<p>CentOS 7 comes with postfix preinstalled, so there is no need to install it first. Verify that postfix is installed and enabled to run on boot.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
systemctl status postfix | grep enabled
   Loaded: loaded (/usr/lib/systemd/system/postfix.service; enabled)
</pre>
<p><strong>NOTE: Highlighted numbers are what you type. The rest is the response from the server.</strong></p>
<p>The configuration files for postfix are in <strong>/etc/postfix</strong>. There are two main files, <strong>main.cf</strong> and <strong>master.cf</strong>. Make a copy of both these files.</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/postfix
cp main.cf main.cf.ORIG
cp master.cf master.cf.ORIG
</pre>
<p>On CentOS postfix also comes with a postfix username and postfix group that are used to run the daemon, but we&#8217;ll need a separate user and group. Technically we can use postfix user but it&#8217;s not recommended to use any UID that&#8217;s lower than 500. So, let&#8217;s create a new user and a group.</p>
<pre class="brush: bash; title: ; notranslate">
groupadd vpostfix &amp;&amp; useradd vpostfix -g vpostfix -s /sbin/nologin -c &quot;Virtual postfix user&quot; -d /var/empty
</pre>
<p>Ignore the warning that the home directory exists, that&#8217;s fine.<br />
Get the UID and GID because we will need these numbers for the configuration. </p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
grep vpostfix /etc/passwd &amp;&amp; grep vpostfix /etc/group
vpostfix:x:1001:1001:Virtual postfix user:/var/empty:/sbin/nologin
vpostfix:x:1001:
</pre>
<p>In my case the output was this, which means the <strong>UID is 1001</strong> and <strong>GID is 1001</strong>.<br />
Now, edit <strong>main.cf</strong> and change the following values:</p>
<pre class="brush: bash; title: ; notranslate">
myhostname = www.example.com
mydomain = example.com
myorigin = $mydomain
inet_interfaces = all
home_mailbox = Maildir/
</pre>
<p>Replace <strong>www.example.com</strong> with whatever your FQDN of the server is. Also, note that by default <strong>inet_interfaces = localhost</strong> is enabled by default. You have to comment this line. We will also use Maildir format instead of mbox because it&#8217;s much better.<br />
While editing <strong>main.cf</strong>, add these lines at the end of the file. Make sure you replace UID and GID. Don&#8217;t just blindly copy &#038; paste.</p>
<pre class="brush: bash; title: ; notranslate">
# Virtual domain config
virtual_mailbox_domains = /etc/postfix/virtual_domains
virtual_mailbox_base = /var/mail/vhosts
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
# Make sure you replace these UID:GID numbers
virtual_minimum_uid = 1001
virtual_uid_maps = static:1001
virtual_gid_maps = static:1001
virtual_alias_maps = hash:/etc/postfix/virtual
</pre>
<p>Now, create a new file called <strong>/etc/postfix/virtual_domains</strong>. This is the file where all of your domains will be listed. Of course, you’ll have to make sure that MX records of your domains point to the IP of the CentOS box.</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/postfix/
touch virtual_domains
</pre>
<p>The format looks like this.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
#  Put each domain in a separate line.
domain-one.com
domain-two.net
domain-three.org
</pre>
<p>Create the mail directory, sub-directories for the domains and assign the proper permissions. This is where the mail will be stored for all virtual domains.</p>
<pre class="brush: bash; title: ; notranslate">
mkdir /var/mail/vhosts
chgrp -R vpostfix /var/mail
cd /var/mail/vhosts
mkdir domain-one.com
mkdir domain-two.net
mkdir domain-three.org
cd ..
chown -R vpostfix:vpostfix vhosts
</pre>
<p>Once you do that, postfix will create the <strong>“Maildir”</strong> directories automatically and assign the proper permissions once an e-mail hits these destinations. Finally, create a file <strong>/etc/postfix/vmailbox</strong> and add all of the users that will receive e-mails. Here is an example:</p>
<pre class="brush: plain; gutter: false; title: ; notranslate">
joe@domain-one.com        domain-one.com/joe/
bill@domain-one.com       domain-one.com/bill/
@domain-one.com           domain-one.com/catch-all/
joe@domain-two.net        domain-two.net/joe/
</pre>
<p><strong>NOTE: Make sure you end up each line with “/”, otherwise mail won’t be delivered.</strong></p>
<p>Virtual user “joe@domain-one.com” (mind that there is no CentOS login for this user, these are all virtual users) will have his email delivered under <strong>/var/mail/vhosts/domain-one.com/joe</strong> directory. You don’t have to create these sub-directories. Once everything is up and running, postfix will take care of creating the Maildir structure (cur, new, tmp).</p>
<p>If you want you can create a <strong>catch-all</strong> address, see the example above (<strong>catch-all</strong>). This line tells postfix to get all the emails for the non-existing users in that domain (domain-one.com), which means a lot of spam. This is definitely not a recommended practice.</p>
<p>But what if you have a valid CentOS user named bill? Where that email goes? In this case, nowhere. If we want this OS user to receive an email, we’ll have to treat him as a virtual user and add him to a virtual domain. It’s much easier to maintain one list of virtual users and hosts than deal with separate configuration files.</p>
<p>Maybe you’ve noticed that the file with the e-mail addresses (vmailbox) has a <strong>hash:</strong> prefix in the config file. This is to speed-up lookups. Postfix can use <strong>hash:</strong> (Berkeley-DB), mySQL or PostgreSQL databases to store the e-mail accounts. Check the postfix howto if you want to use mySQL or PostgreSQL. We’ll be dealing with Berkeley DB.</p>
<p>Create the virtual aliases file and create a local aliases file.</p>
<pre class="brush: bash; title: ; notranslate">
touch /etc/postfix/virtual
cd /etc
postalias aliases
</pre>
<p>Once we are done with editing these files, do the following to create the hashed files (extension .db). </p>
<p><strong>NOTE: You should execute these lines anytime you make a change to these files (virtual_domains and vmailbox).</strong></p>
<pre class="brush: bash; title: ; notranslate">
postmap /etc/postfix/virtual
postmap /etc/postfix/vmailbox
</pre>
<p>At this point you can restart postfix so all changes that we made will take effect.:</p>
<pre class="brush: bash; title: ; notranslate">
systemctl restart postfix
</pre>
<p>Check the log file with:</p>
<pre class="brush: bash; title: ; notranslate">
tail /var/log/maillog
</pre>
<p>You should see that the daemon is started.</p>
<p>Check if postfix runs and listens on port 25.</p>
<pre class="brush: bash; highlight: [1,8]; title: ; notranslate">
ps -eaf | grep postfix
root      1627     1  0 Jun01 ?        00:00:00 /usr/libexec/postfix/master -w
postfix   1647  1627  0 Jun01 ?        00:00:00 qmgr -l -t unix -u
postfix  19407  1627  0 10:53 ?        00:00:00 pickup -l -t unix -u
postfix  19853  1627  0 12:05 ?        00:00:00 smtpd -n smtp -t inet -u -s 2
postfix  19854  1627  0 12:05 ?        00:00:00 proxymap -t unix -u
root     19862 19748  0 12:06 pts/0    00:00:00 grep --color=auto postfix
ss -l | grep smtp
u_str  LISTEN     0      100       private/smtp 14560                 * 0
tcp    LISTEN     0      100          127.0.0.1:smtp                  *:*
tcp    LISTEN     0      100                ::1:smtp                 :::*
</pre>
<p><strong>NOTE: </strong>You can stop and restart postfix with <strong>systemctl start postfix</strong> and <strong>systemctl stop postfix</strong> or reload the configuration files with <strong>systemctl reload postfix</strong>. </p>
<p>From another domain (e.g. your hotmail or gmail account) send an e-mail to joe@domain-one.com or whatever your domain is and watch the log file.</p>
<pre class="brush: bash; title: ; notranslate">
tail -f /var/log/maillog
</pre>
<p>You should see something like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/06/P056-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/06/P056-01.png" alt="" width="645" height="273" class="aligncenter size-full wp-image-7393" srcset="https://blog.andreev.it/wp-content/uploads/2015/06/P056-01.png 645w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-01-300x127.png 300w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-01-585x248.png 585w" sizes="(max-width: 645px) 100vw, 645px" /></a><br />
If you don&#8217;t see anything in the log and you verified that postfix is listening on port 25 from the server itself, most likely it&#8217;s a firewall issue. Open the SMTP port.</p>
<pre class="brush: bash; highlight: [1,3]; title: ; notranslate">
firewall-cmd --add-service=smtp --permanent
success
firewall-cmd --reload
success
</pre>
<p>If you check <strong>/var/mail/vhosts/domain-one/joe/new</strong> directory you’ll see a file with some gibberish name. This is your e-mail that you just sent to joe. But, how will this virtual user retrieve this e-mail? There is a login (the e-mail address), but what’s the password? </p>
<h1>dovecot</h1>
<p>In order to retrieve the e-mails, we’ll configure dovecot. Dovecot is an open-source POP and IMAP client.<br />
As of version 2.0, there are multiple configuration files for dovecot. The main file is <strong>/etc/dovecot/dovecot.conf</strong>, but you’ll see a lot of include directives there that point to <strong>/etc/dovecot/conf.d</strong> directory where we have multiple configuration files. CentOS doesn&#8217;t come up with dovecot installed, so we have to install it first.</p>
<pre class="brush: bash; title: ; notranslate">
yum install dovecot
</pre>
<p>Make a copy of <strong>/etc/dovecot/dovecot.conf</strong> and remove the comment from this line.</p>
<pre class="brush: bash; title: ; notranslate">
protocols = imap pop3 lmtp
</pre>
<p>Then, go to <strong>conf.d </strong>directory and change the following lines in the following files.</p>
<p><strong>10-auth.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
disable_plaintext_auth = no
#!include auth-system.conf.ext
!include auth-passwdfile.conf.ext
</pre>
<p><strong>10-logging.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
log_path = /var/log/dovecot.log
auth_verbose = no
auth_debug = no
verbose_ssl = no
</pre>
<p><strong>10-mail.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
mail_home = /var/mail/vhosts/%d/%n
mail_location = maildir:~
mail_uid = 1001    # These are the GID and UID numbers for postfix
mail_gid = 1001    # Don't just put random numbers here. Check above.
mail_privileged_group = vpostfix
</pre>
<p><strong>10-master.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
unix_listener auth-userdb {
  mode = 0600
  user = vpostfix
  group =  vpostfix
}
# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
  mode = 0666
  user = vpostfix
  group = vpostfix
}
</pre>
<p><strong>10-ssl.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
ssl = no
# ssl_cert = &lt;/etc/ssl/certs/dovecot.pem
# ssl_key = &lt;/etc/ssl/private/dovecot.pem
</pre>
<p>If you look at <strong>10-auth.conf</strong>, we commented the line <strong>#!include auth-system.conf.ext</strong> and uncommented the <strong>!include auth-passwdfile.conf.ext</strong>. Take a look at this file (<strong>auth-passwdfile.conf.ext</strong>) and you’ll see:</p>
<pre class="brush: bash; title: ; notranslate">
passdb {
  driver = passwd-file
  args = scheme=CRYPT username_format=%u /etc/dovecot/users
}
 
userdb {
  driver = passwd-file
  args = username_format=%u /etc/dovecot/users
}
</pre>
<p>This tells us that our username/password database will be in the file <strong>/etc/dovecot/users</strong>. To generate a password with SHA512-CRYPT password scheme do:</p>
<pre class="brush: bash; title: ; notranslate">
doveadm pw -s SHA512-CRYPT
</pre>
<p>You’ll be prompted to enter a password twice and the output will be similar to this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/06/P056-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/06/P056-02.png" alt="" width="647" height="100" class="aligncenter size-full wp-image-7394" srcset="https://blog.andreev.it/wp-content/uploads/2015/06/P056-02.png 647w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-02-300x46.png 300w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-02-585x90.png 585w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-02-640x100.png 640w" sizes="(max-width: 647px) 100vw, 647px" /></a><br />
If you want to use a different password scheme, take a look at this <a href="http://wiki2.dovecot.org/Authentication/PasswordSchemes" target="_blank" rel="noopener noreferrer">link</a>.<br />
Now, create or open <strong>/etc/dovecot/users</strong> and copy and paste the password after the username. In my case, I have <strong>joe@domain-one.com</strong> with some password that I just generated. So the line will be like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/06/P056-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/06/P056-03.png" alt="" width="643" height="43" class="aligncenter size-full wp-image-7395" srcset="https://blog.andreev.it/wp-content/uploads/2015/06/P056-03.png 643w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-03-300x20.png 300w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-03-585x39.png 585w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-03-640x43.png 640w" sizes="(max-width: 643px) 100vw, 643px" /></a><br />
Don’t forget to add 4 colons after the password <strong>“::::”</strong>. Even if you use the same password for the users, they’ll be encrypted differently.</p>
<p>The problem with this scenario is that the end users won’t have the ability to change their passwords. So, you’ll have to provide them with the password and they won’t be able to reset them. But, there are plenty of perl scripts that can take care of this or you can write your own.</p>
<p>Start dovecot, enable it to start on boot and check for any errors. At this point, we should have dovecot running and listening for pop and imap connections. </p>
<pre class="brush: bash; title: ; notranslate">
systemctl start dovecot
systemctl enable dovecot
tail /var/log/dovecot.log
ss -l | grep pop3
ss -l | grep imap
</pre>
<p>Now, let’s check our e-mail. You can do that from the server using the telnet command.</p>
<p><strong>NOTE: Highlighted numbers are what you type. The rest is the response from the server. </strong></p>
<pre class="brush: bash; highlight: [1,6,8,10,12,17]; title: ; notranslate">
telnet localhost 110
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
+OK Dovecot ready.
user joe@domain-one.com
+OK
pass topsecret
+OK Logged in.
stat
+OK 2 2037
list
+OK 2 messages:
1 1027
2 1010
.
quit
+OK Logging out.
Connection closed by foreign host.
</pre>
<p>In the above example, I am testing POP3. For IMAP, do the following.</p>
<pre class="brush: bash; highlight: [1,6,8,11]; title: ; notranslate">
telnet localhost 143
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
* OK &#x5B;CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN] Dovecot ready.
? login joe@domain-one.com topsecret
? OK &#x5B;CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPECIAL-USE BINARY MOVE] Logged in
? list &quot;&quot; &quot;*&quot;
* LIST (\HasNoChildren) &quot;.&quot; INBOX
? OK List completed.
? logout
* BYE Logging out
? OK Logout completed.
Connection closed by foreign host.
</pre>
<p>If you want you can test retrieving these emails from a mail client such as Outlook, Opera Mail or any MUA of your preference. At this point the server can receive e-mails from others and you can retrieve those e-mails from outside using POP and IMAP. What we need to do now is to be able to reply to those e-mails from outside (using MUA of your choice). Nowadays port 25 is blocked at some major providers (Verizon, Comcast for example), so we’ll use SASL in Postfix and we’ll use Dovecot to authenticate the users using the same username/password combination. In addition, we’ll use certificates, so instead of POP3 and IMAP, we’ll use their secure equivalents, POP3s and IMAPs running on ports 995 and 993 respectively. At this point you can open ports 993 and 995 if you want and close 110 and 143 on the firewall. We won&#8217;t be using these ports (POP3 and IMAP).</p>
<h1>postfix and TLS</h1>
<p>Edit <strong>/etc/postfix/main.cf</strong> and add the following lines at the end.</p>
<pre class="brush: bash; title: ; notranslate">
# TLS
smtpd_use_tls = yes
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_key_file = /etc/postfix/myserver.key
smtpd_tls_cert_file = /etc/postfix/server.crt
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom
 
# SASL
smtpd_sasl_type = dovecot
broken_sasl_auth_clients = yes
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
smtpd_relay_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
</pre>
<p><strong>NOTE: </strong>As of postfix 2.10 the last line is needed. See this <a href="http://www.postfix.org/SMTPD_ACCESS_README.html" target="_blank" rel="noopener noreferrer">link</a>.<br />
Then, edit <strong>/etc/postfix/master.cf</strong> and remove the comments from the submission part. </p>
<pre class="brush: bash; title: ; notranslate">
submission inet n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
</pre>
<p>Restart postfix after these changes. </p>
<pre class="brush: bash; title: ; notranslate">
systemctl restart postfix
</pre>
<p>For information of what these values mean, check the links at the end of this post. If you do</p>
<pre class="brush: bash; title: ; notranslate">
ss -l | grep submission
grep submission /etc/services
</pre>
<p>you’ll see that postfix is also listening on port 587. Allow this port on the firewall if you don&#8217;t have it enabled, but don’t close port 25. This port is used for server to server communication. </p>
<pre class="brush: bash; title: ; notranslate">
firewall-cmd --add-port=587/tcp
firewall-cmd --reload
</pre>
<p>If you do <strong>telnet localhost 587</strong> and type <strong>EHLO something.com</strong> you should see that postfix replies with STARTTLS.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
telnet localhost 587
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 master.iandreev.us ESMTP Postfix
EHLO asdf.com
250-master.iandreev.us
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
</pre>
<p>Exit by pressing <strong>CTRL-]</strong> and then type quit.</p>
<h1>dovecot and SSL</h1>
<p>Edit <strong>10-auth.conf</strong> and change:</p>
<pre class="brush: bash; title: ; notranslate">
disable_plaintext_auth = yes
</pre>
<p>Then, edit <strong>10-ssl.conf</strong> and change:</p>
<pre class="brush: bash; title: ; notranslate">
ssl = yes
ssl_cert = &lt;/etc/postfix/server.crt
ssl_key = &lt;/etc/postfix/myserver.key
</pre>
<p>We’ll use self-signed certificates, but check <a href="http://www.startssl.com" target="_blank" rel="noopener noreferrer">http://www.startssl.com</a> for free certificates. Self-signed certificates are fake, so you’ll get a prompt to accept a fake certificate when you try to send/receive an email, but the goal is to show you how to use them, not to be a 100% compliant.</p>
<p>Unlike virtual Apache domains, you don’t need multiple certificates for each virtual domain. </p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/postfix
openssl genrsa -out myserver.key 1024
openssl req -new -key myserver.key -out myserver.csr
</pre>
<p>You have to answer some questions for the certificate request.</p>
<pre class="brush: plain; highlight: [8,9,10,11,13,14]; title: ; notranslate">
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) &#x5B;AU]:US
State or Province Name (full name) &#x5B;Some-State]:NJ
Locality Name (eg, city) &#x5B;]:Lawrenceville
Organization Name (eg, company) &#x5B;Internet Widgits Pty Ltd]:Joe's Plumbing
Organizational Unit Name (eg, section) &#x5B;]:
Common Name (e.g. server FQDN or YOUR name) &#x5B;]:www.domain-one.com
Email Address &#x5B;]:joe@domain-one.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password &#x5B;]:
An optional company name &#x5B;]:
</pre>
<p>Sign the certificate.</p>
<pre class="brush: bash; title: ; notranslate">
openssl x509 -req -days 3650 -in myserver.csr -signkey myserver.key -out server.crt
</pre>
<p>The certificate files should be under <strong>/etc/postfix</strong> now. Restart both postfix and dovecot.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl restart postfix
systemctl restart dovecot
</pre>
<p>You can test SMTP SSL/TLS on submission port 587.</p>
<pre class="brush: bash; title: ; notranslate">
openssl s_client -starttls smtp -connect localhost:587
</pre>
<p>Then type <strong>ehlo something.com</strong> , hit ENTER and then <strong>mail from:joe@domain-one.com</strong>. If these steps work, you should be OK. To test SASL with postfix and dovecot, type:</p>
<pre class="brush: bash; title: ; notranslate">
doveadm auth test -a /var/spool/postfix/private/auth joe@domain-one.com secret
passdb: joe@domain-one.com auth succeeded
extra fields:
  user=joe@domain-one.com
</pre>
<p>If you want you can open the firewall for IMAPs and POP3s. </p>
<pre class="brush: bash; title: ; notranslate">
firewall-cmd --add-port=993/tcp
firewall-cmd --add-port=995/tcp
firewall-cmd --reload
</pre>
<p>At this point, you should be able to send e-mails from your favorite MUA, but you’ll have to make some changes in order to send and receive. For example, in Outlook, you should use these settings.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/06/P056-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/06/P056-04.png" alt="" width="381" height="179" class="aligncenter size-full wp-image-7396" srcset="https://blog.andreev.it/wp-content/uploads/2015/06/P056-04.png 381w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-04-300x141.png 300w" sizes="(max-width: 381px) 100vw, 381px" /></a><br />
So, no more port 110 and 143. Instead use 995 for POP3s, 587 for SMPT (SASL) and 993 for IMAPs. The username is your e-mail address and the password is the one that you generated with <strong>doveadm pw</strong> command.</p>
<p>Mind that if you use a web client like Roundcube and Roundcube is installed on the server where postfix and dovecot reside, you don&#8217;t have to open any port except 25. </p>
<h1>Roundcube IMAP webmail client</h1>
<p>In order to send/receive e-mails using a web client, you can use Roundcube. Please follow these guides to install it. </p>
<p><a href="https://blog.andreev.it/?p=1962" target="_blank" rel="noopener noreferrer">CentOS 7: Install LAMP (Linux, Apache, MySQL, PHP) + WordPress</a><br />
<a href="https://blog.andreev.it/?p=2004" target="_blank" rel="noopener noreferrer">CentOS 7: Install RoundCube Web Mail Client</a></p>
<h1>Amavisd, Spamassassin and clamav</h1>
<p>This software trio is used to fight spam messages and e-mails with virus attachments. Amavisd is used as an interface between postfix as MTA (mail transfer agent) and the content checkers (spamassassin and clamav). Clamav and spamassassin will be installed automatically once you install amavisd-new.</p>
<pre class="brush: bash; title: ; notranslate">
yum install amavisd-new
yum install clamav-udpate
</pre>
<p>First, let&#8217;s configure amavisd. The configuration file is <strong>/etc/amavisd/amavisd.conf</strong>. Edit this file and make sure that these values are correct. </p>
<pre class="brush: bash; title: ; notranslate">
# @bypass_virus_checks_maps = (1);  # controls running of anti-virus code
# @bypass_spam_checks_maps  = (1);  # controls running of anti-spam code
# $bypass_decode_parts = 1;         # controls running of decoders&amp;dearchivers
$daemon_user  = 'amavis';     # (no default;  customary: vscan or amavis), -u
$daemon_group = 'amavis';     # (no default;  customary: vscan or amavis), -g
$mydomain = 'example.com';   # a convenient default for other settings (change it)
$MYHOME = '/var/spool/amavisd';   # a convenient default for other settings, -H (remove the comment in front)
@local_domains_maps = ( &#x5B;&quot;.$mydomain&quot;,&quot;myotherdomain.net&quot;] );  # list of all local domains. If you have multiple domains, add the here.
$myhostname = 'host.example.com';  # must be a fully-qualified domain name! (remove the comment in front)
</pre>
<p>There are a lot of changes that you can configure, but these are the basic ones. See the <a href="http://www.ijs.si/software/amavisd/" target="_blank" rel="noopener noreferrer">official page</a> for more information.<br />
Finally, let&#8217;s make sure that amavisd and clamav know about each other. Go to line 383 and see if this is correct (383G in vi). </p>
<div style="border:1px solid red; padding:16px;">
<p style="text-align:center;"><strong><span style="color:#800000;">NOTE ABOUT MEMORY</span> </strong></p>
<p>Clamav eats up a lot of memory. You won&#8217;t be able to run it on a server with less than 2GB RAM. If you feel comfortable, you can disable it. Don&#8217;t uncomment the lines below, remove the comment from # @bypass_virus_checks_maps = (1);  # controls running of anti-virus code and </p>
</div>
<pre class="brush: bash; title: ; notranslate">
# ### http://www.clamav.net/
&#x5B;'ClamAV-clamd',
  \&amp;ask_daemon, &#x5B;&quot;CONTSCAN {}\n&quot;, &quot;/var/run/clamav/clamd.sock.sock&quot;],
  qr/\bOK$/m, qr/\bFOUND$/m,
  qr/^.*?: (?!Infected Archive)(.*) FOUND$/m ],
# # NOTE: run clamd under the same user as amavisd - or run it under its own
# #   uid such as clamav, add user clamav to the amavis group, and then add
# #   AllowSupplementaryGroups to clamd.conf;
# # NOTE: match socket name (LocalSocket) in clamav.conf to the socket name in
# #   this entry; when running chrooted one may prefer a socket under $MYHOME.
</pre>
<p>Now, let&#8217;s tie everything together with postfix. Edit <strong>/etc/postfix/master.cf</strong> and add these lines at the end.</p>
<pre class="brush: bash; title: ; notranslate">
# Amavisd
amavisfeed unix - - n - 2 lmtp
        -o lmtp_data_done_timeout=1200
        -o lmtp_send_xforward_command=yes
127.0.0.1:10025 inet n - n - - smtpd
        -o content_filter=
        -o smtpd_delay_reject=no
        -o smtpd_client_restrictions=permit_mynetworks,reject
        -o smtpd_helo_restrictions=
        -o smtpd_sender_restrictions=
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
        -o smtpd_data_restrictions=reject_unauth_pipelining
        -o smtpd_end_of_data_restrictions=
        -o smtpd_restriction_classes=
        -o mynetworks=127.0.0.0/8
        -o smtpd_error_sleep_time=0
        -o smtpd_soft_error_limit=1001
        -o smtpd_hard_error_limit=1000
        -o smtpd_client_connection_count_limit=0
        -o smtpd_client_connection_rate_limit=0
        -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters,no_address_mappings
        -o local_header_rewrite_clients=
        -o smtpd_milters=
        -o local_recipient_maps=
        -o relay_recipient_maps=
</pre>
<p>Edit <strong>/usr/local/etc/postfix/main.cf</strong> and add these lines at the end.</p>
<pre class="brush: bash; title: ; notranslate">
# Amavisd
content_filter = amavisfeed:&#x5B;127.0.0.1]:10024
</pre>
<p>Before we start these three daemons, let&#8217;s make some changes. First, edit <strong>/etc/freshclam.conf</strong> and remove or comment the <strong>Example </strong>line. </p>
<pre class="brush: bash; title: ; notranslate">
# Comment or remove the line below.
Example
</pre>
<p>Then, edit <strong>/etc/sysconfig/freshclam </strong>and remove all 4 lines at the bottom.</p>
<pre class="brush: bash; title: ; notranslate">
### !!!!! REMOVE ME !!!!!!
### REMOVE ME: By default, the freshclam update is disabled to avoid
### REMOVE ME: network access without prior activation
FRESHCLAM_DELAY=disabled-warn   # REMOVE ME
</pre>
<p>Once you do that, update the antivirus definitions by executing:</p>
<pre class="brush: bash; title: ; notranslate">
freshclam
</pre>
<p>Then update spamassassins&#8217;s signatures.</p>
<pre class="brush: bash; title: ; notranslate">
sa-update -D
</pre>
<p>The &#8220;-D&#8221; option is to run in debug mode so you can see what&#8217;s going on. If there is an update available, spamassassin&#8217;s exit code is 0, if not the exit code is 1. In case there is an update, we&#8217;ll have to restart the spamassassin&#8217;s daemon.<br />
Check the cron folder and make sure you see both calamav-update and sa-update files. </p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/cron.d
ls -l clamav-update sa-update
</pre>
<p>Now, we can start everything.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl start amavisd
systemctl enable amavisd
systemctl start spamassassin
systemctl enable spamassassin
</pre>
<p>Once you start amavisd, clamd starts as well.<br />
Finally, let&#8217;s restart postfix.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl restart postfix
</pre>
<p>Check the connection between amavisd and postfix.</p>
<pre class="brush: bash; title: ; notranslate">
telnet localhost 10024
</pre>
<p>Type <strong>ehlo localhost</strong> and check the ouput. In my case it looks like this.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
250-&#x5B;127.0.0.1]
250-VRFY
250-PIPELINING
250-SIZE
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 XFORWARD NAME ADDR PORT PROTO HELO IDENT SOURCE
</pre>
<p>Then do.</p>
<pre class="brush: bash; title: ; notranslate">
telnet localhost 10025
</pre>
<p>Again, type <strong>ehlo localhost</strong> and check the ouput. In my case it looks like this.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
250-www.testcloudserver.org
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
</pre>
<p>And finally, some real tests. First, check the mail log file.</p>
<pre class="brush: bash; title: ; notranslate">
tail -f /var/log/maillog
</pre>
<p>Then, from another e-mail account, send a text (not HTML) e-mail with this in the body.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
X5O!P%@AP&#x5B;4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
</pre>
<p>You should see something like this in the logs.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/06/P056-05.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/06/P056-05.jpg" alt="" width="809" height="206" class="aligncenter size-full wp-image-7397" srcset="https://blog.andreev.it/wp-content/uploads/2015/06/P056-05.jpg 809w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-05-300x76.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-05-768x196.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-05-585x149.jpg 585w" sizes="(max-width: 809px) 100vw, 809px" /></a><br />
Leave the log file open and let&#8217;s send another test e-mail, same text format, but this time put this line in the body of the message.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
</pre>
<p>You should see something like this in the log file.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/06/P056-06.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/06/P056-06.jpg" alt="" width="807" height="215" class="aligncenter size-full wp-image-7398" srcset="https://blog.andreev.it/wp-content/uploads/2015/06/P056-06.jpg 807w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-06-300x80.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-06-768x205.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/06/P056-06-585x156.jpg 585w" sizes="(max-width: 807px) 100vw, 807px" /></a></p>
<h1>Stress test</h1>
<p>From another server with postfix installed, do:</p>
<pre class="brush: bash; title: ; notranslate">
time /usr/sbin/smtp-source -s 40 -l 10120 -m 5000 -c -f user@whatsup.com -t joe@domain-one.com mail.domain-one.com:25
</pre>
<p>On your server do:</p>
<pre class="brush: bash; title: ; notranslate">
tail -f /var/log/maillog
</pre>
<p>Make sure that the server where you run <strong>smtp-source</strong> is a legit server, otherwise your postfix will just reject all messages.<br />
Watch how your log file gets bombarded with messages. You can also watch the queue real-time with:</p>
<pre class="brush: bash; title: ; notranslate">
postqueue -p
</pre>
<p>If you are satisfied with the results after 5-10 mins, empty the postfix queue with:</p>
<pre class="brush: bash; title: ; notranslate">
postsuper -d ALL
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2015/06/centos-7-postfix-dovecot-roundcube-amavisd-new-spamassassin-clamav-pigeonhole/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
		<item>
		<title>FreeBSD 10: postfix, dovecot, Roundcube, amavisd-new, spamassassin, clamav, pigeonhole</title>
		<link>https://blog.andreev.it/2014/11/freebsd-10-postfix-dovecot-amavisd-new-spamassassin-clamav-pigeonhole/</link>
					<comments>https://blog.andreev.it/2014/11/freebsd-10-postfix-dovecot-amavisd-new-spamassassin-clamav-pigeonhole/#comments</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Fri, 07 Nov 2014 20:39:49 +0000</pubDate>
				<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[amavisd-new]]></category>
		<category><![CDATA[clamav]]></category>
		<category><![CDATA[dovecot]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[pigeonhole]]></category>
		<category><![CDATA[postfix]]></category>
		<category><![CDATA[Roundcube]]></category>
		<category><![CDATA[spamassassin]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=1604</guid>

					<description><![CDATA[In one of my previous posts I&#8217;ve described how to run a postfix and&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>In one of my previous <a href="https://blog.andreev.it/?p=936" target="_blank" rel="noopener noreferrer">posts</a> I&#8217;ve described how to run a postfix and dovecot servers on FreeBSD 9. This time, we&#8217;ll go a step further and after the installation of <a href="http://www.postfix.org/" target="_blank" rel="noopener noreferrer">postfix</a> and <a href="http://www.dovecot.org/" target="_blank" rel="noopener noreferrer">dovecot</a>, we&#8217;ll talk about mail filtering, spam and anti-virus protection. </p>
<h1>Pre install</h1>
<p>The post described below uses:</p>
<ul>
<li> FreeBSD 10.0-p12 (fresh install)</li>
<li> postfix 2.11.3
<li> dovecot 2.2.15
<li> amavisd-new 2.9.1
<li> spamassasin 3.4.0
<li> clamav 0.98.4
<li> pigeonhole 0.4.3</li>
</ul>
<p>and will allow you to use virtual e-mail domains and users.</p>
<p>FreeBSD comes with sendmail preinstalled, so we need to remove it first. Edit <strong>/etc/rc.conf</strong> and add these lines.</p>
<pre class="brush: bash; title: ; notranslate">
# Disable sendmail
sendmail_enable=&quot;NO&quot;
sendmail_submit_enable=&quot;NO&quot;
sendmail_outbound_enable=&quot;NO&quot;
sendmail_msp_queue_enable=&quot;NO&quot;
</pre>
<p>Then terminate all sendmail processes.</p>
<pre class="brush: bash; title: ; notranslate">
killall sendmail
</pre>
<h1>postfix</h1>
<p>We&#8217;ll install postfix from the ports. The packaged install doesn&#8217;t come up with some prerequisites.<br />
<strong>NOTE</strong>: Recently, I got an e-mail saying that if you install the postfix-sasl package, you don&#8217;t have to deal with the ports. Try <strong>pkg install postfix-sasl</strong> instead and see if it works. </p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/ports/mail/postfix
make all install clean
</pre>
<p>Make sure that <strong>BDB, PCRE, TLS</strong> and <strong>DOVECOT2</strong> are selected and <strong>INST_BASE</strong> is not selected. <strong>OPTIONAL:</strong> Select <strong>TEST</strong> if you want to do a stress test (see below). I am using Berkeley DB as a back-end database. If you want to use MySQL or PostgreSQL, the scenario below won&#8217;t apply for postfix. The rest (dovecot, amavisd&#8230;) configs should be fine. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2014/11/P048-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2014/11/P048-01.png" alt="" width="665" height="421" class="aligncenter size-full wp-image-7153" srcset="https://blog.andreev.it/wp-content/uploads/2014/11/P048-01.png 665w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-01-300x190.png 300w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-01-585x370.png 585w" sizes="(max-width: 665px) 100vw, 665px" /></a><br />
<a href="https://blog.andreev.it/wp-content/uploads/2014/11/P048-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2014/11/P048-02.png" alt="" width="671" height="425" class="aligncenter size-full wp-image-7154" srcset="https://blog.andreev.it/wp-content/uploads/2014/11/P048-02.png 671w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-02-300x190.png 300w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-02-585x371.png 585w" sizes="(max-width: 671px) 100vw, 671px" /></a><br />
You should accept the defaults for <strong>perl5, pcre, db5, gmake, gettext</strong> and <strong>dovecot2</strong>. Once completed you&#8217;ll see this message.</p>
<pre class="brush: plain; gutter: false; title: ; notranslate">
Would you like to activate Postfix in /etc/mail/mailer.conf &#x5B;n]?
</pre>
<p>Say <strong>y</strong>, edit <strong>/etc/rc.conf</strong> and add these two lines to start <strong>postfix</strong> and <strong>dovecot</strong> automatically on boot.</p>
<pre class="brush: bash; title: ; notranslate">
postfix_enable=&quot;YES&quot;
dovecot_enable=&quot;YES&quot;
</pre>
<p>The configuration files for postfix are in <strong>/usr/local/etc/postfix</strong>. There are two main files, <strong>main.cf</strong> and <strong>master.cf</strong>. Make a copy of both these files.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/etc/postfix
cp main.cf main.cf.ORIG
cp master.cf master.cf.ORIG
</pre>
<p>Create a user that will have access to the mailboxes and get its <strong>UID</strong> and <strong>GID</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
pw groupadd vpostfix &amp;&amp; pw useradd vpostfix -g vpostfix -s /usr/sbin/nologin -c &quot;Virtual Postfix user&quot; -d /var/empty
grep vpostfix /etc/passwd
</pre>
<p>In my case the output was this, which means the <strong>UID is 1002</strong> and <strong>GID is 1001</strong>.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
vpostfix:*:1002:1001:Virtual Postfix user:/var/empty:/usr/sbin/nologin
</pre>
<p>Now, edit <strong>main.cf</strong> and change the following values:</p>
<pre class="brush: bash; title: ; notranslate">
myhostname = www.example.com
mydomain = example.com
myorigin = $mydomain
inet_interfaces = all
home_mailbox = Maildir/
</pre>
<p>Replace <strong>www.example.com</strong> with whatever your FQDN of the server is. While editing <strong>main.cf</strong>, add these lines at the end of the file.</p>
<pre class="brush: bash; title: ; notranslate">
# Virtual domain config
virtual_mailbox_domains = /usr/local/etc/postfix/virtual_domains
virtual_mailbox_base = /var/mail/vhosts
virtual_mailbox_maps = hash:/usr/local/etc/postfix/vmailbox
# Make sure you replace these UID:GID numbers
virtual_minimum_uid = 1002
virtual_uid_maps = static:1002
virtual_gid_maps = static:1001
virtual_alias_maps = hash:/usr/local/etc/postfix/virtual
</pre>
<p>Now, create a new file called <strong>/usr/local/etc/postfix/virtual_domains</strong>. This is the file where all of your domains will be listed. Of course, you’ll have to make sure that MX records of your domains point to the IP of the FreeBSD box.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/etc/postfix/
touch virtual_domains
</pre>
<p>The format looks like this.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
#  Put each domain in a separate line.
domain-one.com
domain-two.net
domain-three.org
</pre>
<p>Create the mail directory, sub-directories for the domains and assign the proper permissions. This is where the mail will be stored for all virtual domains.</p>
<pre class="brush: bash; title: ; notranslate">
mkdir /var/mail/vhosts
chgrp -R vpostfix /var/mail
cd /var/mail/vhosts
mkdir domain-one.com
mkdir domain-two.net
mkdir domain-three.org
cd ..
chown -R vpostfix:vpostfix vhosts
</pre>
<p>Once you do that, postfix will create the <strong>“Maildir”</strong> directories automatically and assign the proper permissions once an e-mail hits these destinations. Finally, create a file <strong>/usr/local/etc/postfix/vmailbox</strong> and add all of the users that will receive e-mails. Here is an example:</p>
<pre class="brush: plain; gutter: false; title: ; notranslate">
joe@domain-one.com        domain-one.com/joe/
bill@domain-one.com       domain-one.com/bill/
@domain-one.com           domain-one.com/catch-all/
joe@domain-two.net        domain-two.net/joe/
</pre>
<p><strong>NOTE: Make sure you end up each line with “/”, otherwise mail won’t be delivered.</strong></p>
<p>Virtual user “joe@domain-one.com” (mind that there is no FreeBSD login for this user, these are all virtual users) will have his email delivered under <strong>/var/mail/vhosts/domain-one.com/joe</strong> directory. You don’t have to create these sub-directories. Once everything is up and running, postfix will take care of creating the Maildir structure (cur, new, tmp).</p>
<p>If you want you can create a <strong>catch-all</strong> address, see the example above (<strong>catch-all</strong>). This line tells postfix to get all the emails for the non-existing users in that domain (domain-one.com), which means a lot of spam.</p>
<p>But what if you have a valid FreeBSD user named bill? Where that email goes? In this case, nowhere. If we want this OS user to receive an email, we’ll have to treat him as a virtual user and add him to a virtual domain. It’s much easier to maintain one list of virtual users and hosts than deal with separate configuration files.</p>
<p>Maybe you’ve noticed that the file with the e-mail addresses (vmailbox) has a <strong>hash:</strong> prefix in the config file. This is to speed-up lookups. Postfix can use <strong>hash:</strong> (Berkeley-DB), mySQL or PostgreSQL database to store the e-mail accounts. Check the postfix howto if you want to use mySQL or PostgreSQL. We’ll be dealing with Berkeley DB.</p>
<p>Create the virtual aliases file and create a local aliases file.</p>
<pre class="brush: bash; title: ; notranslate">
touch /usr/local/etc/postfix/virtual
cd /etc
postalias aliases
</pre>
<p>Once we are done with editing these files, do the following to create the hashed files (extension .db). </p>
<p><strong>NOTE: You should execute these lines anytime you make a change to these files.</strong></p>
<pre class="brush: bash; title: ; notranslate">
postmap /usr/local/etc/postfix/virtual
postmap /usr/local/etc/postfix/vmailbox
</pre>
<p>Postfix can be started with:</p>
<pre class="brush: bash; title: ; notranslate">
service postfix start
</pre>
<p>Check the log file with:</p>
<pre class="brush: bash; title: ; notranslate">
tail /var/log/maillog
</pre>
<p>In my case I saw these lines in the log file.</p>
<pre class="brush: plain; gutter: false; title: ; notranslate">
Nov  6 17:57:04 www postfix/postfix-script&#x5B;76814]: starting the Postfix mail system
Nov  6 17:57:04 www postfix/master&#x5B;76816]: daemon started -- version 2.11.3, configuration /usr/local/etc/postfix
</pre>
<p>Check if postfix runs and listens on port 25.</p>
<pre class="brush: bash; title: ; notranslate">
ps -waux | grep postfix
sockstat -4 | grep :25
</pre>
<p><strong>NOTE: </strong>You can stop and restart postfix with <strong>service postfix stop</strong> and <strong>service postfix restart</strong> or reload the configuration files with <strong>service postfix reload</strong>. </p>
<p>From another domain (e.g. your hotmail or gmail account) send an e-mail to joe@domain-one.com or whatever your domain is and watch the log file.</p>
<pre class="brush: bash; title: ; notranslate">
tail -f /var/log/maillog
</pre>
<p>You should see something like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2014/11/P048-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2014/11/P048-03.png" alt="" width="726" height="250" class="aligncenter size-full wp-image-7155" srcset="https://blog.andreev.it/wp-content/uploads/2014/11/P048-03.png 726w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-03-300x103.png 300w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-03-585x201.png 585w" sizes="(max-width: 726px) 100vw, 726px" /></a></p>
<p>If you check <strong>/var/mail/vhosts/domain-one/joe/new</strong> directory you’ll see a file with some gibberish name. This is your e-mail that you just sent to joe. But, how will this virtual user retrieve this e-mail? There is a login (the e-mail address), but what’s the password? </p>
<h1>dovecot</h1>
<p>In order to retrieve the e-mails, we’ll configure dovecot. Dovecot is an open-source POP and IMAP client.<br />
As of version 2.0, there are multiple configuration files for dovecot. The main file is <strong>/usr/local/etc/dovecot/dovecot.conf</strong>, but you’ll see a lot of include directives there that point to <strong>/usr/local/etc/dovecot/conf.d</strong> directory where we have multiple configuration files. FreeBSD comes with these files under a different directory, so we’ll have to copy them to their proper location.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/etc/dovecot
cp -R /usr/local/share/doc/dovecot/example-config/ .
</pre>
<p>Make a copy of <strong>dovecot.conf</strong> and remove the comment from this line.</p>
<pre class="brush: bash; title: ; notranslate">
protocols = imap pop3 lmtp
</pre>
<p>Then, go to <strong>conf.d </strong>directory and change the following lines in the following files.</p>
<p><strong>10-auth.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
disable_plaintext_auth = no
#!include auth-system.conf.ext
!include auth-passwdfile.conf.ext
</pre>
<p><strong>10-logging.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
log_path = /var/log/dovecot.log
auth_verbose = no
auth_debug = no
verbose_ssl = no
</pre>
<p><strong>10-mail.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
mail_home = /var/mail/vhosts/%d/%n
mail_location = maildir:~
mail_uid = 1002    # These are the GID and UID numbers for vpostfix
mail_gid = 1001    # Don't just put these numbers here
mail_privileged_group = vpostfix
</pre>
<p><strong>10-master.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
unix_listener auth-userdb {
  mode = 0600
  user = postfix
  group =  postfix
}
# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
  mode = 0666
  user = postfix
  group = postfix
}
</pre>
<p><strong>10-ssl.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
ssl = no
# ssl_cert = &lt;/etc/ssl/certs/dovecot.pem
# ssl_key = &lt;/etc/ssl/private/dovecot.pem
</pre>
<p>If you look at <strong>10-auth.conf</strong>, we commented the line <strong>#!include auth-system.conf.ext</strong> and uncommented the <strong>!include auth-passwdfile.conf.ext</strong>. Take a look at this file (<strong>auth-passwdfile.conf.ext</strong>) and you’ll see:</p>
<pre class="brush: bash; title: ; notranslate">
passdb {
  driver = passwd-file
  args = scheme=CRYPT username_format=%u /usr/local/etc/dovecot/users
}
 
userdb {
  driver = passwd-file
  args = username_format=%u /usr/local/etc/dovecot/users
}
</pre>
<p>This tells us that our username/password database will be in the file <strong>/usr/local/etc/dovecot/users</strong>. To generate a password with SHA512-CRYPT password scheme do:</p>
<pre class="brush: bash; title: ; notranslate">
doveadm pw -s SHA512-CRYPT
</pre>
<p>You’ll be prompted to enter a password twice and the output will be similar to this.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2014/11/P048-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2014/11/P048-04.png" alt="" width="726" height="141" class="aligncenter size-full wp-image-7156" srcset="https://blog.andreev.it/wp-content/uploads/2014/11/P048-04.png 726w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-04-300x58.png 300w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-04-585x114.png 585w" sizes="(max-width: 726px) 100vw, 726px" /></a><br />
If you want to use a different password scheme, take a look at this <a href="http://wiki2.dovecot.org/Authentication/PasswordSchemes" target="_blank" rel="noopener noreferrer">link</a>.<br />
Now, create or open <strong>/usr/local/etc/dovecot/users</strong> and copy and paste the password after the username. In my case, I have <strong>joe@domain-one.com</strong> with some password that I just generated. So the line will be like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2014/11/P048-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2014/11/P048-05.png" alt="" width="728" height="97" class="aligncenter size-full wp-image-7157" srcset="https://blog.andreev.it/wp-content/uploads/2014/11/P048-05.png 728w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-05-300x40.png 300w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-05-585x78.png 585w" sizes="(max-width: 728px) 100vw, 728px" /></a><br />
Don’t forget to add 4 colons after the password <strong>“::::”</strong>. Even if you use the same password for the users, they’ll be encrypted differently.</p>
<p>The problem with this scenario is that the end users won’t have the ability to change their passwords. So, you’ll have to provide them with the password and they won’t be able to reset them. But, there are plenty of perl scripts that can take care of this or you can write your own.</p>
<p>Start dovecot and check for any errors. At this point, we should have dovecot running and listening for pop and imap connections. </p>
<pre class="brush: bash; title: ; notranslate">
service dovecot start
tail /var/log/dovecot.log
sockstat -4 | grep :110
sockstat -4 | grep :143
</pre>
<p>Now, let’s check our e-mail. You can do that from the server using the telnet command.</p>
<p><strong>NOTE: Highlighted numbers are what you type. The rest is the response from the server. </strong></p>
<pre class="brush: bash; highlight: [1,6,8,10,12,17]; title: ; notranslate">
telnet localhost 110
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
+OK Dovecot ready.
user joe@domain-one.com
+OK
pass topsecret
+OK Logged in.
stat
+OK 2 2037
list
+OK 2 messages:
1 1027
2 1010
.
quit
+OK Logging out.
Connection closed by foreign host.
</pre>
<p>In the above example, I am testing POP3. For IMAP, do the following.</p>
<pre class="brush: bash; highlight: [1,6,8,11]; title: ; notranslate">
telnet localhost 143
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
* OK &#x5B;CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN] Dovecot ready.
? login joe@domain-one.com topsecret
? OK &#x5B;CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPECIAL-USE BINARY MOVE] Logged in
? list &quot;&quot; &quot;*&quot;
* LIST (\HasNoChildren) &quot;.&quot; INBOX
? OK List completed.
? logout
* BYE Logging out
? OK Logout completed.
Connection closed by foreign host.
</pre>
<p>If you want you can test retrieving these emails from a mail client such as Outlook, Opera Mail or any MUA of your preference. At this point the server can receive e-mails from others and you can retrieve those e-mails from outside using POP and IMAP. What we need to do now is to be able to reply to those e-mails from outside (using MUA of your choice). Nowadays port 25 is blocked at some major providers (Verizon, Comcast for example), so we’ll use SASL in Postfix and we’ll use Dovecot to authenticate the users using the same username/password combination. In addition, we’ll use certificates, so instead of POP3 and IMAP, we’ll use their secure equivalents, POP3s and IMAPs running on ports 995 and 993 respectively. Dovecot should already listen on these ports, so you can allow these ports on the firewall and close 110 and 143. </p>
<h1>postfix and TLS</h1>
<p>Edit <strong>/usr/local/etc/postfix/main.cf</strong> and add the following lines at the end.</p>
<pre class="brush: bash; title: ; notranslate">
# TLS
smtpd_use_tls = yes
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_key_file = /usr/local/etc/postfix/myserver.key
smtpd_tls_cert_file = /usr/local/etc/postfix/server.crt
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom
 
# SASL
smtpd_sasl_type = dovecot
broken_sasl_auth_clients = yes
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
smtpd_relay_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
</pre>
<p><strong>NOTE: </strong>As of postfix 2.10 the last line is needed. See this <a href="http://www.postfix.org/SMTPD_ACCESS_README.html" target="_blank" rel="noopener noreferrer">link</a>.<br />
Then, edit <strong>/usr/local/etc/postfix/master.cf</strong> and remove the comments from the submission part. </p>
<pre class="brush: bash; title: ; notranslate">
submission inet n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
</pre>
<p>Restart postfix after these changes. </p>
<pre class="brush: bash; title: ; notranslate">
service postfix restart
</pre>
<p>For information of what these values mean, check the links at the end of this post. If you do</p>
<pre class="brush: bash; title: ; notranslate">
sockstat -4 
</pre>
<p>you’ll see that postfix is also listening on port 587. Allow this port on the firewall if you have it enabled, but don’t close port 25. This port is used for server to server communication. If you do <strong>telnet localhost 587</strong> and type <strong>EHLO something.com</strong> you should see that postfix replies with STARTTLS.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2014/11/P048-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2014/11/P048-06.png" alt="" width="408" height="336" class="aligncenter size-full wp-image-7158" srcset="https://blog.andreev.it/wp-content/uploads/2014/11/P048-06.png 408w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-06-300x247.png 300w" sizes="(max-width: 408px) 100vw, 408px" /></a></p>
<h1>dovecot and SSL</h1>
<p>Edit <strong>10-auth.conf</strong> and change:</p>
<pre class="brush: bash; title: ; notranslate">
disable_plaintext_auth = yes
</pre>
<p>Then, edit <strong>10-ssl.conf</strong> and change:</p>
<pre class="brush: bash; title: ; notranslate">
ssl = yes
ssl_cert = &lt;/usr/local/etc/postfix/server.crt
ssl_key = &lt;/usr/local/etc/postfix/myserver.key
</pre>
<p>We’ll use self-signed certificates, but check <a href="http://www.startssl.com" target="_blank" rel="noopener noreferrer">http://www.startssl.com</a> for free certificates. Unlike virtual Apache domains, you don’t need multiple certificates for each virtual domain. Self-signed certificates are fake, so you’ll get a prompt to accept a fake certificate when you try to send/receive an email, but the goal is to show you how to use them, not to be a 100% compliant.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/etc/postfix
openssl genrsa -out myserver.key 1024
openssl req -new -key myserver.key -out myserver.csr
</pre>
<p>You have to answer some questions for the certificate request.</p>
<pre class="brush: plain; highlight: [8,9,10,11,13,14]; title: ; notranslate">
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) &#x5B;AU]:US
State or Province Name (full name) &#x5B;Some-State]:NJ
Locality Name (eg, city) &#x5B;]:Lawrenceville
Organization Name (eg, company) &#x5B;Internet Widgits Pty Ltd]:Joe's Plumbing
Organizational Unit Name (eg, section) &#x5B;]:
Common Name (e.g. server FQDN or YOUR name) &#x5B;]:www.domain-one.com
Email Address &#x5B;]:joe@domain-one.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password &#x5B;]:
An optional company name &#x5B;]:
</pre>
<p>Sign the certificate.</p>
<pre class="brush: bash; title: ; notranslate">
openssl x509 -req -days 3650 -in myserver.csr -signkey myserver.key -out server.crt
</pre>
<p>Copy <strong>server.crt</strong> and <strong>myserver.key</strong> under <strong>/usr/local/etc/postfix</strong> and restart both postfix and dovecot.</p>
<pre class="brush: bash; title: ; notranslate">
service postfix restart
service dovecot restart
</pre>
<p>You can test SMTP SSL/TLS on submission port 587.</p>
<pre class="brush: bash; title: ; notranslate">
openssl s_client -starttls smtp -connect localhost:587
</pre>
<p>Then type <strong>ehlo something.com</strong> , hit ENTER and then <strong>mail from:joe@domain-one.com</strong>. If these steps work, you should be OK. To test SASL with postfix and dovecot, type:</p>
<pre class="brush: bash; title: ; notranslate">
doveadm auth test -a /var/spool/postfix/private/auth joe@domain-one.com joe's_passwd
</pre>
<p>You should receive <strong>passdb: joe@domain-one.com auth succeeded.</strong></p>
<p>At this point, you should be able to send e-mails from your favorite MUA, but you’ll have to make some changes in order to send and receive. For example, in Outlook, you should use these settings.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2014/11/P048-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2014/11/P048-07.png" alt="" width="381" height="179" class="aligncenter size-full wp-image-7159" srcset="https://blog.andreev.it/wp-content/uploads/2014/11/P048-07.png 381w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-07-300x141.png 300w" sizes="(max-width: 381px) 100vw, 381px" /></a></p>
<p>So, no more port 110 and 143. Instead use 995 for POP3s, 587 for SMPT (SASL) and 993 for IMAPs. The username is your e-mail address and the password is the one that you generated with <strong>doveadm pw</strong> command.</p>
<h1>Roundcube IMAP webmail client</h1>
<p>In order to send/receive e-mails using a web client, you can use Roundcube. Please follow these guides to install it. </p>
<p><a href="https://blog.andreev.it/?p=1309" target="_blank" rel="noopener noreferrer">FreeBSD 10: Apache, PHP and MySQL</a><br />
<a href="https://blog.andreev.it/?p=1339" target="_blank" rel="noopener noreferrer">FreeBSD 10: Install Roundcube Web Mail Client</a></p>
<h1>Amavisd, Spamassassin and clamav</h1>
<p>This software trio is used to fight spam messages and e-mails with virus attachments. Amavisd is used as an interface between postfix as MTA (mail transfer agent) and the content checkers (spamassassin and clamav). There are no specific configurations, so we&#8217;ll install them from the packages. </p>
<pre class="brush: bash; title: ; notranslate">
pkg install amavisd-new
pkg install clamav
</pre>
<p>Spamassassin is a dependency for amavisd so it will be installed automatically. First, let&#8217;s configure amavisd. The configuration file is <strong>/usr/local/etc/amavisd.conf</strong>. Edit this file and make sure that these values are correct. </p>
<pre class="brush: bash; title: ; notranslate">
# @bypass_virus_checks_maps = (1);  # controls running of anti-virus code
# @bypass_spam_checks_maps  = (1);  # controls running of anti-spam code
# $bypass_decode_parts = 1;         # controls running of decoders&amp;dearchivers
$daemon_user  = 'vscan';     # (no default;  customary: vscan or amavis), -u
$daemon_group = 'vscan';     # (no default;  customary: vscan or amavis), -g
$mydomain = 'example.com';   # a convenient default for other settings (change it)
$MYHOME = '/var/amavis';   # a convenient default for other settings, -H (remove the comment in front)
@local_domains_maps = ( &#x5B;&quot;.$mydomain&quot;,&quot;myotherdomain.net&quot;] );  # list of all local domains
$myhostname = 'host.example.com';  # must be a fully-qualified domain name! (remove the comment in front)
</pre>
<p>There are a lot of changes that you can configure, but these are the basic ones. See the <a href="http://www.ijs.si/software/amavisd/" target="_blank" rel="noopener noreferrer">official page</a> for more information.<br />
Finally, let&#8217;s make another change in this file, so amavisd and clamav know about each other. Remove the comments from lines 2 to 5.</p>
<div style="border:1px solid red; padding:16px;">
<p style="text-align:center;"><strong><span style="color:#800000;">NOTE ABOUT MEMORY</span> </strong></p>
<p>Clamav eats up a lot of memory. You won&#8217;t be able to run it on a server with less than 2GB RAM. If you feel comfortable, you can disable it. Don&#8217;t uncomment the lines below, remove the comment from # @bypass_virus_checks_maps = (1);  # controls running of anti-virus code and remove it from rc.conf if you already installed it. </p>
</div>
<pre class="brush: bash; highlight: [2,3,4,5]; title: ; notranslate">
# ### http://www.clamav.net/
&#x5B;'ClamAV-clamd',
  \&amp;ask_daemon, &#x5B;&quot;CONTSCAN {}\n&quot;, &quot;/var/run/clamav/clamd.sock.sock&quot;],
  qr/\bOK$/m, qr/\bFOUND$/m,
  qr/^.*?: (?!Infected Archive)(.*) FOUND$/m ],
# # NOTE: run clamd under the same user as amavisd - or run it under its own
# #   uid such as clamav, add user clamav to the amavis group, and then add
# #   AllowSupplementaryGroups to clamd.conf;
# # NOTE: match socket name (LocalSocket) in clamav.conf to the socket name in
# #   this entry; when running chrooted one may prefer a socket under $MYHOME.
</pre>
<p>The default <strong>amavisd.conf</strong> file comes with &#8220;sock.sock&#8221; in line 3. Remove it, so line 3 looks like</p>
<pre class="brush: bash; first-line: 3; title: ; notranslate">
  \&amp;ask_daemon, &#x5B;&quot;CONTSCAN {}\n&quot;, &quot;/var/run/clamav/clamd.sock&quot;],
</pre>
<p>Now, edit <strong>/etc/group</strong> and add <strong>clamav</strong> as a member of <strong>vscan</strong> group so it looks like this.</p>
<pre class="brush: bash; title: ; notranslate">
vscan:*:110:clamav 
</pre>
<p>Then check the configuration file for clamav (<strong>/usr/local/etc/clamd.conf</strong>) and make sure that this line exists.</p>
<pre class="brush: bash; title: ; notranslate">
AllowSupplementaryGroups yes 
</pre>
<p>Now, let&#8217;s tie everything together with postfix. Edit <strong>/usr/local/etc/postfix/master.cf</strong> and add these lines at the end.</p>
<pre class="brush: bash; title: ; notranslate">
# Amavisd
amavisfeed unix - - n - 2 lmtp
        -o lmtp_data_done_timeout=1200
        -o lmtp_send_xforward_command=yes
127.0.0.1:10025 inet n - n - - smtpd
        -o content_filter=
        -o smtpd_delay_reject=no
        -o smtpd_client_restrictions=permit_mynetworks,reject
        -o smtpd_helo_restrictions=
        -o smtpd_sender_restrictions=
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
        -o smtpd_data_restrictions=reject_unauth_pipelining
        -o smtpd_end_of_data_restrictions=
        -o smtpd_restriction_classes=
        -o mynetworks=127.0.0.0/8
        -o smtpd_error_sleep_time=0
        -o smtpd_soft_error_limit=1001
        -o smtpd_hard_error_limit=1000
        -o smtpd_client_connection_count_limit=0
        -o smtpd_client_connection_rate_limit=0
        -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters,no_address_mappings
        -o local_header_rewrite_clients=
        -o smtpd_milters=
        -o local_recipient_maps=
        -o relay_recipient_maps=
</pre>
<p>Edit <strong>/usr/local/etc/postfix/main.cf</strong> and add these lines at the end.</p>
<pre class="brush: bash; title: ; notranslate">
# Amavisd
content_filter = amavisfeed:&#x5B;127.0.0.1]:10024
</pre>
<p>Let&#8217;s make sure that our trio starts on each reboot. Edit <strong>/etc/rc.conf</strong> and add these lines.</p>
<pre class="brush: bash; title: ; notranslate">
amavisd_enable=&quot;YES&quot;
clamav_clamd_enable=&quot;YES&quot;
clamav_freshclam_enable=&quot;YES&quot;
spamd_enable=&quot;YES&quot; 
</pre>
<p>The <strong>clamav_freshclam</strong> daemon part is to update the anti-virus signatures. For updating spamassassin&#8217;s definitions and signatures, we&#8217;ll have to run a cron job. First, let&#8217;s do an initial run for spamassassin.</p>
<pre class="brush: bash; title: ; notranslate">
sa-update -D
</pre>
<p>The &#8220;-D&#8221; option is to run in debug mode so you can see what&#8217;s going on. If there is an update available, spamassassin&#8217;s exit code is 0, if not the exit code is 1. In case there is an update, we&#8217;ll have to restart the spamassassin&#8217;s daemon. So, let&#8217;s create a cron job that runs once a day and checks for updates. </p>
<pre class="brush: bash; title: ; notranslate">
crontab -e
</pre>
<p>Add this line so the updates start 1 minute after midnight.</p>
<pre class="brush: bash; title: ; notranslate">
1 0 * * * /usr/local/bin/sa-update &amp;&amp; /usr/local/sbin/service sa-spamd restart
</pre>
<p>Once we took care of the updates part, let&#8217;s start spamassassin.</p>
<pre class="brush: bash; title: ; notranslate">
service sa-spamd start
</pre>
<p>Let&#8217;s do an initial run for clamav.</p>
<pre class="brush: bash; title: ; notranslate">
freshclam
</pre>
<p>You&#8217;ll see a warning, but ignore that. clamav daemon is still not started.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
ClamAV update process started at Sun Nov 2 18:49:06 2014
main.cvd is up to date (version: 55, sigs: 2424225, f-level: 60, builder: neo)
daily.cvd is up to date (version: 19576, sigs: 1244373, f-level: 63, builder: neo)
bytecode.cvd is up to date (version: 242, sigs: 46, f-level: 63, builder: dgoddard)
WARNING: Clamd was NOT notified: Can't connect to clamd through /var/run/clamav/clamd.sock: No such file or directory 
</pre>
<p>Finally, let&#8217;s start the services and restart postfix.</p>
<pre class="brush: bash; title: ; notranslate">
service clamav-clamd start
service clamav-freshclam start
service amavisd start 
service postfix restart
</pre>
<p>Check the connection between amavisd and postfix.</p>
<pre class="brush: bash; title: ; notranslate">
telnet localhost 10024
</pre>
<p>Type <strong>ehlo localhost</strong> and check the ouput. In my case it looks like this.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
250-&#x5B;127.0.0.1]
250-VRFY
250-PIPELINING
250-SIZE
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 XFORWARD NAME ADDR PORT PROTO HELO IDENT SOURCE
</pre>
<p>Then do.</p>
<pre class="brush: bash; title: ; notranslate">
telnet localhost 10025
</pre>
<p>Again, type <strong>ehlo localhost</strong> and check the ouput. In my case it looks like this.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
250-www.testcloudserver.org
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
</pre>
<p>And finally, some real tests. First, check the mail log file.</p>
<pre class="brush: bash; title: ; notranslate">
tail -f /var/log/maillog
</pre>
<p>Then, from another e-mail account, send a text (not HTML) e-mail with this in the body.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
X5O!P%@AP&#x5B;4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
</pre>
<p>You should see something like this in the logs.</p>
<pre class="brush: plain; gutter: false; title: ; notranslate">
Nov  7 17:33:02 www amavis&#x5B;966]: (00966-01) Blocked INFECTED (Eicar-Test-Signature) {DiscardedInbound,Quarantined}, &#x5B;104.207.128.32]:28661 &#x5B;104.207.128.32] &lt;klimenta@iandreev.com&gt; -&gt; &lt;klimenta@testcloudserver.us&gt;, quarantine: virus-G9s83IyyvqaS, Queue-ID: 130DDFA76, Message-ID: &lt;fbaa61e9ca8c994b4f0278f258652140@iandreev.com&gt;, mail_id: G9s83IyyvqaS, Hits: -, size: 952, 172 ms
Nov  7 17:33:02 www postfix/lmtp&#x5B;1167]: 130DDFA76: to=&lt;klimenta@testcloudserver.us&gt;, relay=127.0.0.1&#x5B;127.0.0.1]:10024, delay=0.21, delays=0.03/0.01/0.01/0.17, dsn=2.7.0, status=sent (250 2.7.0 Ok, discarded, id=00966-01 - INFECTED: Eicar-Test-Signature)
Nov  7 17:33:02 www postfix/qmgr&#x5B;1063]: 130DDFA76: removed
Nov  7 17:33:02 www postfix/qmgr&#x5B;1063]: 43707FA84: from=&lt;virusalert@testcloudserver.us&gt;, size=2765, nrcpt=1 (queue active)
Nov  7 17:33:02 www postfix/virtual&#x5B;1170]: 43707FA84: to=&lt;virusalert@testcloudserver.us&gt;, relay=virtual, delay=0.02, delays=0.01/0.01/0/0, dsn=2.0.0, status=sent (delivered to maildir)
Nov  7 17:33:02 www postfix/qmgr&#x5B;1063]: 43707FA84: removed
</pre>
<p>The e-mail won&#8217;t be delivered to the recipient, instead the message will be forwarded to the <strong>virusalert</strong> account. I don&#8217;t have this account created as virtual account, but I have a <strong>catch-all</strong> virtual account, so this is what I&#8217;ve received in Roundcube.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2014/11/P048-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2014/11/P048-08.png" alt="" width="580" height="650" class="aligncenter size-full wp-image-7160" srcset="https://blog.andreev.it/wp-content/uploads/2014/11/P048-08.png 580w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-08-268x300.png 268w" sizes="(max-width: 580px) 100vw, 580px" /></a><br />
Leave the log file open and let&#8217;s send another test e-mail, same text format, but this time put this line in the body of the message.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
</pre>
<p>You should see something like this in the log file.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
Nov  7 17:41:44 www amavis&#x5B;965]: (00965-01) Passed SPAM {RelayedTaggedInbound,Quarantined}, &#x5B;104.207.128.32]:57855 &#x5B;104.207.128.32] &lt;klimenta@iandreev.com&gt; -&gt; &lt;klimenta@testcloudserver.us&gt;, quarantine: spam-hPo7Kn_vhzBm.gz, Queue-ID: 3A733FA72, Message-ID: &lt;fce64236c0e9432da776553dba2f6ba2@iandreev.com&gt;, mail_id: hPo7Kn_vhzBm, Hits: 999.407, size: 947, queued_as: 98A9AFA76, 364 ms
</pre>
<p>If you check your e-mail, you&#8217;ll see this in your inbox.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2014/11/P048-09.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2014/11/P048-09.png" alt="" width="526" height="143" class="aligncenter size-full wp-image-7161" srcset="https://blog.andreev.it/wp-content/uploads/2014/11/P048-09.png 526w, https://blog.andreev.it/wp-content/uploads/2014/11/P048-09-300x82.png 300w" sizes="(max-width: 526px) 100vw, 526px" /></a><br />
Now that we have spam and anti-virus covered, we&#8217;ll discuss another topic. And that&#8217;s e-mail filtering and sorting.</p>
<h1>dovecot pigeonhole</h1>
<p>There are many other options that can be used for e-mail filtering and sorting, but <a href="http://pigeonhole.dovecot.org/" target="_blank" rel="noopener noreferrer">pigeonhole</a> uses <a href="http://sieve.info/" target="_blank" rel="noopener noreferrer">Sieve language</a> and it&#8217;s very powerful.<br />
Let&#8217;s install it from the packages. </p>
<pre class="brush: bash; title: ; notranslate">
pkg install dovecot-pigeonhole
cd /usr/local/etc/dovecot/conf.d
cp /usr/local/share/doc/dovecot-pigeonhole/example-config/conf.d/* .
</pre>
<p>This will copy three files to the existing configuration files (<strong>20-managesieve.conf, 90-sieve-extprograms.conf</strong> and <strong>90-sieve.conf</strong>). Let&#8217;s make the following changes.<br />
In <strong>/usr/local/etc/postfix/main.cf</strong> add these lines at the end.</p>
<pre class="brush: bash; title: ; notranslate">
# LMTP
virtual_transport = lmtp:unix:private/dovecot-lmtp
</pre>
<div style="border:1px solid red; padding:16px;">
<p style="text-align:center;"><strong><span style="color:#800000;">NOTE ABOUT VIRTUAL USERS</span> </strong></p>
<p>Once you enable virtual_transport in main.cf, postfix virutal users won&#8217;t have any effect. All virtual users are defined in /usr/local/etc/dovecot/users file from now on and dovecot will take care of mail delivery.</p>
</div>
<p>Then edit the following files under <strong>/usr/local/etc/dovecot/conf.d/</strong> and make sure that these parameters are as below.<br />
<strong>10-mail.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
mail_home = /var/mail/vhosts/%d/%n
mail_location = maildir:~
mail_privileged_group = vpostfix
</pre>
<p><strong>10-master.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
</pre>
<p><strong>15-lda.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
recipient_delimiter = +
mail_plugins = $mail_plugins sieve
</pre>
<p><strong>20-lmtp.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
lmtp_save_to_detail_mailbox = yes
protocol lmtp {
  # Space separated list of plugins to load (default is global mail_plugins).
  postmaster_address = joe@whatsup.com
  mail_plugins = $mail_plugins sieve
}
</pre>
<p><strong>90-sieve.com</strong></p>
<pre class="brush: bash; title: ; notranslate">
recipient_delimiter = +
</pre>
<p>Now, go to the mail directory of one of the virtual users.</p>
<pre class="brush: bash; title: ; notranslate">
cd /var/mail/vhosts/domain-one.com/joe
</pre>
<p>and create this file <strong>.dovecot.sieve</strong> with the following Sieve commands inside.</p>
<pre class="brush: bash; title: ; notranslate">
require &quot;fileinto&quot;;
if header :comparator &quot;i;ascii-casemap&quot; :contains &quot;Subject&quot; &quot;***Spam***&quot;  {
        fileinto &quot;Junk&quot;;
        stop;
}
</pre>
<p>This means that if an e-mail arrives flagged with &#8220;<strong>***Spam***</strong>&#8221; in the subject (as we configured Spamassassin), then move it to the &#8220;<strong>Junk</strong>&#8221; folder (make sure that you have Junk IMAP folder created).<br />
Restart both postfix and dovecot and you are all set.</p>
<pre class="brush: bash; title: ; notranslate">
service postfix restart
service dovecot restart
</pre>
<h1>Stress test</h1>
<p>From another server with postfix installed, do:</p>
<pre class="brush: bash; title: ; notranslate">
time /usr/sbin/smtp-source -s 40 -l 10120 -m 5000 -c -f user@whatsup.com -t joe@domain-one.com mail.domain-one.com:25
</pre>
<p>On your server do:</p>
<pre class="brush: bash; title: ; notranslate">
tail -f /var/log/maillog
</pre>
<p><strong>smtp-source</strong> comes up with FreeBSD only if you select <strong>TEST</strong> during the install, but it comes with CentOS in the default install.<br />
Make sure that the server where you run <strong>smtp-source</strong> is a legit server, otherwise your postfix will just reject all messages.<br />
Watch how your log file gets bombarded with messages. You can also watch the queue real-time with:</p>
<pre class="brush: bash; title: ; notranslate">
postqueue -p
</pre>
<p>If you are satisfied with the results after 5-10 mins, empty the postfix queue with:</p>
<pre class="brush: bash; title: ; notranslate">
postsuper -d ALL
</pre>
<h1>Issues with clamav</h1>
<p>I was testing the whole scenario on a 768MB RAM server. For some reason, clamav eats up a lot of memory.<br />
You might see this in <strong>/var/log/messages</strong> when you try to start the daemon.</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
Nov  7 22:04:03 www kernel: pid 997 (clamd), uid 106, was killed: out of swap space
</pre>
<p>My <a href="http://www.vultr.com" target="_blank" rel="noopener noreferrer">VPS</a> had no swap space when purchased. From what I see, clamav is memory hungry and while there are some workarounds, the easiest way is to create a swap partition. FreeBSD 10 has a wonderful option to create a swap without a dedicated partition. You just create a file that will be used as a swap. So, if you have a server with less than 4GB RAM and no swap partition, do the <a href="https://www.freebsd.org/doc/handbook/adding-swap-space.html" target="_blank" rel="noopener noreferrer">following</a>.</p>
<pre class="brush: bash; title: ; notranslate">
dd if=/dev/zero of=/usr/swap0 bs=1m count=1024
</pre>
<p>where <strong>1024</strong> means 1GB file. Then, change the permissions. </p>
<pre class="brush: bash; title: ; notranslate">
chmod 0600 /usr/swap0
</pre>
<p>Edit <strong>/etc/fstab</strong> and add this line.</p>
<pre class="brush: bash; title: ; notranslate">
md99	none	swap	sw,file=/usr/swap0	0	0
</pre>
<p>Reboot after this. You can do <strong>&#8220;swapon -aq&#8221;</strong> without a reboot, but it didn&#8217;t work for me.<br />
Anyway, type:</p>
<pre class="brush: bash; title: ; notranslate">
swapinfo
</pre>
<p>to see the swap usage.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2014/11/freebsd-10-postfix-dovecot-amavisd-new-spamassassin-clamav-pigeonhole/feed/</wfw:commentRss>
			<slash:comments>29</slash:comments>
		
		
			</item>
		<item>
		<title>FreeBSD: postfix, dovecot, MUA – virtual domains, virtual users</title>
		<link>https://blog.andreev.it/2013/12/freebsd-postfix-dovecot-mua-virtual-domains-virtual-users/</link>
					<comments>https://blog.andreev.it/2013/12/freebsd-postfix-dovecot-mua-virtual-domains-virtual-users/#comments</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Thu, 12 Dec 2013 19:02:49 +0000</pubDate>
				<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[dovecot]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[postfix]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=936</guid>

					<description><![CDATA[In my previous post I&#8217;ve described how to configure postfix and dovecot to serve&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>In my <a href="https://blog.andreev.it/?p=849" target="_blank" rel="noopener noreferrer">previous post</a> I&#8217;ve described how to configure postfix and dovecot to serve virtual domains and virtual users using POP3s, IMAPs, SMTP SSL/TLS and SASL under CentOS Linux. This time we&#8217;ll do the same for FreeBSD.</p>
<p>We&#8217;ll be using FreeBSD 9.2, postfix 2.10.0 and dovecot 2.2.5. </p>
<p><strong>Pre install</strong></p>
<p>FreeBSD comes with sendmail preinstalled, so we need to remove it first. Edit <em>/etc/rc.conf</em> and add these lines. </p>
<pre class="brush: bash; title: ; notranslate">
# Disable sendmail
sendmail_enable=&quot;NO&quot;
sendmail_submit_enable=&quot;NO&quot;
sendmail_outbound_enable=&quot;NO&quot;
sendmail_msp_queue_enable=&quot;NO&quot;
</pre>
<p>Then do:</p>
<pre class="brush: bash; title: ; notranslate">
killall sendmail
</pre>
<p><strong>Postfix and Dovecot install</strong></p>
<p>First, install postfix.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/ports/mail/postfix
make all install clean
</pre>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P033-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P033-01.png" alt="" width="660" height="385" class="aligncenter size-full wp-image-6778" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P033-01.png 660w, https://blog.andreev.it/wp-content/uploads/2013/12/P033-01-300x175.png 300w, https://blog.andreev.it/wp-content/uploads/2013/12/P033-01-585x341.png 585w" sizes="(max-width: 660px) 100vw, 660px" /></a></p>
<p>Select BDB, PCRE, TLS and DOVECOT2. Do not select INST_BASE. If you get a build error code 2, just repeat <em>make all install clean</em>. If you don&#8217;t see a dialog to prompt what to install, type <em>make rmconfig</em>. Accept the defaults for perl and pcre when the dialogs show up. Accept the defaults for dovecot and libiconv as well. Since we are installing from the source, it might take about 20 minutes depending on your hardware. Unlike CentOS, postfix and dovecot will be installed at the same time, because we specified dovecot when installing postfix.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P033-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P033-02.png" alt="" width="671" height="371" class="aligncenter size-full wp-image-6779" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P033-02.png 671w, https://blog.andreev.it/wp-content/uploads/2013/12/P033-02-300x166.png 300w, https://blog.andreev.it/wp-content/uploads/2013/12/P033-02-585x323.png 585w" sizes="(max-width: 671px) 100vw, 671px" /></a><br />
At the end of the install you&#8217;ll be prompted to activate postfix in <em>/etc/mail/mailer.conf</em>. Say yes. Finally, edit <em>/etc/rc.conf</em> and make sure that both postfix and dovecot start on boot.</p>
<pre class="brush: bash; title: ; notranslate">
postfix_enable=&quot;YES&quot;
dovecot_enable=&quot;YES&quot;
</pre>
<p>The configuration files for postfix are in <em>/usr/local/etc/postfix</em>. There are two main files, <em>main.cf</em> and <em>master.cf</em>. Make a copy of both these files. Usually I do:</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/etc/postfix
cp main.cf main.cf.20131124
cp master.cf master.cf.20131124
</pre>
<p>20131124 represents the date the copy was taken.</p>
<p>Now, edit <em>main.cf</em> and change the following values:</p>
<pre class="brush: bash; title: ; notranslate">
myhostname = www.example.com
mydomain = example.com
myorigin = $mydomain
inet_interfaces = all
home_mailbox = Maildir/
</pre>
<p>Create a user that will have access to the mailboxes.</p>
<pre class="brush: bash; title: ; notranslate">
adduser vpostfix
tail /etc/passwd
</pre>
<p>Make sure to change the login shell to <em>/usr/sbin/nologin</em> using <em>vipw</em>. </p>
<p>Look at the UID:GUID for the vpostfix user. In my case it&#8217;s 1002:1002.</p>
<p>Add the following lines at the end of main.cf and replace the UID:GUID under <em>virtual_minimum_uid</em>, <em>virtual_uid_maps</em> and <em>virtual_gid_maps</em> with the values that you got from <em>tail /etc/passwd</em> or <em>grep vpostfix /etc/passwd</em>.</p>
<pre class="brush: bash; title: ; notranslate">
# Virtual domain config
virtual_mailbox_domains = /usr/local/etc/postfix/virtual_domains
virtual_mailbox_base = /var/mail/vhosts
virtual_mailbox_maps = hash:/usr/local/etc/postfix/vmailbox
# Make sure you replace these UID:GUID numbers
virtual_minimum_uid = 1002
virtual_uid_maps = static:1002
virtual_gid_maps = static:1002
virtual_alias_maps = hash:/usr/local/etc/postfix/virtual
</pre>
<p>Edit or create <em>/usr/local/etc/postfix/virtual_domains</em>. This is a file where all of your domains will be listed. Of course, you&#8217;ll have to make sure that MX records of your domains point to the IP of the FreeBSD box.</p>
<pre class="brush: bash; title: ; notranslate">
#  Put each domain in a separate line.
domain-one.com
domain-two.net
domain-three.org
</pre>
<p>As you can see, we have three virtual domains, but the <em>myhostname</em> points to <em>www.example.com</em>. If you put one of these three domains as <em>myhostname</em> and <em>mydomain</em> values, you&#8217;ll get a warning that the local domain is already listed in the virtual domains list. In addition, if you keep e.g. <em>domain-one.com</em> as a local domain and remove it from the virtual domains list, then you can&#8217;t treat <em>domain-one.com</em> as a virtual domain and deliver its mail to <em>/var/mail/vhosts</em>. Don&#8217;t use <em>myhostname = localhost</em> either, because if some other mail server has the same config, you&#8217;ll get an error that the destination loops back and the mail won&#8217;t be delivered. Don&#8217;t use <em>www.example.com</em> either, because you won&#8217;t be able to send to <em>www.example.com</em> or any other server that have <em>www.example.com</em> as <em>myhostname</em>. So, pick something that&#8217;s unique even if you don&#8217;t own that domain or that domain is not registered. Mind that if you send an email from this server and analyze the headers, you&#8217;ll see that <em>www.example.com</em> is in the headers. Most e-mail servers won&#8217;t complain and treat this e-mail as spam, as long as you have a valid MX record for the virtual domains that point to that IP. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P033-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P033-03.png" alt="" width="637" height="73" class="aligncenter size-full wp-image-6780" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P033-03.png 637w, https://blog.andreev.it/wp-content/uploads/2013/12/P033-03-300x34.png 300w, https://blog.andreev.it/wp-content/uploads/2013/12/P033-03-585x67.png 585w" sizes="(max-width: 637px) 100vw, 637px" /></a></p>
<p>Create the mail folder, subfolders for the domains and assign the proper permissions.</p>
<pre class="brush: bash; title: ; notranslate">
mkdir /var/mail/vhosts
chgrp -R vpostfix /var/mail
cd /var/mail/vhosts
mkdir domain-one.com
mkdir domain-two.net
mkdir domain-three.org
cd ..
chown -R vpostfix:vpostfix vhosts
</pre>
<p>Once you do that, <em>postfix</em> will create the &#8220;Maildir&#8221; folders automatically and assign the proper permissions once an e-mail hits these detinations. Finally, create a file <em>/usr/local/etc/postfix/vmailbox</em> and add all of the users that will receive e-mails. Here is an example:</p>
<pre class="brush: bash; title: ; notranslate">
joe@domain-one.com        domain-one.com/joe/
bill@domain-one.com       domain-one.com/bill/
@domain-one.com           domain-one.com/catch-all/
joe@domain-two.net        domain-two.net/joe/
</pre>
<p>Make sure you end up each line with &#8220;/&#8221;, otherwise mail won&#8217;t be delivered.<br />
Virtual user <em>&#8220;joe@domain-one.com&#8221;</em> (mind that there is no FreeBSD login for this user, these are all virtual users) will have his email delivered under <em>/var/mail/vhosts/domain-one.com/joe</em> folder. You don&#8217;t have to create these subfolders. Once everything is up and running, postfix will take care of creating the Maildir structure (cur, new, tmp).</p>
<p>If you want you can create a catch-all address, see the example above (catch-all). This line tells postfix to get all the emails for the non-existing users in that domain (<em>domain-one.com</em>), which means a lot of spam. </p>
<p>But what if you have a valid FreeBSD user named <em>bill</em>? Where that email goes? In this case, nowhere. If we want this OS user to receive an email, we&#8217;ll have to treat him as a virtual user and add him to a virtual domain. It&#8217;s much easier to maintain one list of virtual users and hosts than deal with separate configuration files. </p>
<p>Maybe you&#8217;ve noticed that the file with the e-mail addresses (<em>vmailbox</em>) has a <em>hash:</em> prefix in the config file. This is to speed-up lookups. Postfix can use hash: (Berkeley-DB), mySQL or PostgreSQL database to store the e-mail accounts. Check the postfix howto if you want to use mySQL or PostgreSQL. We&#8217;ll be dealing with Berkeley DB.</p>
<p>Create the virtual aliases file and create a local aliases file</p>
<pre class="brush: bash; title: ; notranslate">
touch /usr/local/etc/postfix/virtual
cd /etc
postalias aliases
</pre>
<p>Once we are done with the editing of these files, do the following to create the hashed files (extension .db). You should execute these lines anytime you make a change to these files. </p>
<pre class="brush: bash; title: ; notranslate">
postmap /usr/local/etc/postfix/virtual
postmap /usr/local/etc/postfix/vmailbox
</pre>
<p>Now, everything is ready for postfix to receive an email. Make sure that postfix is running and that it actually listens on port 25. Also make sure that port 25 is opened on the firewall.</p>
<pre class="brush: bash; title: ; notranslate">
ps -waux | grep postfix
sockstat -4 | grep :25
tail /var/log/maillog
</pre>
<p>You can restart postfix with <em>postfix stop</em> and <em>postfix start</em> or reload the configuration files with <em>postfix reload</em>. </p>
<p>From another domain (e.g. your hotmail or gmail account) send an e-mail to <em>joe@domain-one.com</em> or whatever your domain is. Do :</p>
<pre class="brush: bash; title: ; notranslate">
tail -f /var/log/maillog
</pre>
<p>You should see something like this.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P033-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P033-04.png" alt="" width="726" height="250" class="aligncenter size-full wp-image-6781" /></a></p>
<p>If you check <em>/var/mail/vhosts/domain-one/joe/new</em> folder you&#8217;ll see a file with some gibberish name. This is your e-mail that you just sent to joe. But, how will this virtual user retrieve this e-mail? There is a login (the e-mail address), but what&#8217;s the password? </p>
<p><strong>Dovecot</strong></p>
<p>In order to retrieve the e-mails, we&#8217;ll configure Dovecot. Dovecot is an open-source POP and IMAP client. </p>
<p>As of version 2.0, there are multiple configuration files for Dovecot. The main file is <em>/usr/local/etc/dovecot/dovecot.conf</em>, but you&#8217;ll see a lot of include directives there that point to <em>/usr/local/etc/dovecot/conf.d</em> folder where we have about 22 configuration files. FreeBSD comes with these files under a different folder, so we&#8217;ll have to copy them to their proper location.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/etc/dovecot
cp -R /usr/local/share/doc/dovecot/example-config/ .
</pre>
<p>Make a copy of <em>dovecot.conf</em> and change only one line.</p>
<pre class="brush: bash; title: ; notranslate">
protocols = imap pop3
</pre>
<p>Then, go to <em>conf.d</em> folder and change the following lines in the following files.</p>
<p><strong>10-auth.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
disable_plaintext_auth = no
#!include auth-system.conf.ext
!include auth-passwdfile.conf.ext
</pre>
<p><strong>10-logging.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
log_path = /var/log/dovecot.log
auth_verbose = no
auth_debug = no
verbose_ssl = no
</pre>
<p><strong>10-mail.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
mail_location = maildir:/var/mail/vhosts/%d/%n
mail_uid = 1002
mail_gid = 1002
mail_privileged_group = vpostfix
</pre>
<p><strong>10-master.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
  unix_listener auth-userdb {
    mode = 0600
    user = postfix
    group =  postfix
  }
  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
</pre>
<p><strong>10-ssl.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
ssl = no
# ssl_cert = &lt;/etc/ssl/certs/dovecot.pem
# ssl_key = &lt;/etc/ssl/private/dovecot.pem
</pre>
<p>If you look at <em>10-auth.conf</em>, we commented the line <em>#!include auth-system.conf.ext</em> and uncommented the <em>!include auth-passwdfile.conf.ext</em>. Take a look at this file and you&#8217;ll see:</p>
<pre class="brush: bash; title: ; notranslate">
passdb {
  driver = passwd-file
  args = scheme=CRYPT username_format=%u /usr/local/etc/dovecot/users
}

userdb {
  driver = passwd-file
  args = username_format=%u /usr/local/etc/dovecot/users
}
</pre>
<p>This describes how our username/password database will be in the file <em>/usr/local/etc/dovecot/users</em>. To generate a password with SHA512-CRYPT password scheme do:</p>
<pre class="brush: bash; title: ; notranslate">
doveadm pw -s SHA512-CRYPT
</pre>
<p>You&#8217;ll be prompted to enter a password twice and the output will be similar to this:<br />
<a href="https://blog.andreev.it/wp-content/uploads/2013/12/P033-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P033-05.png" alt="" width="726" height="141" class="aligncenter size-full wp-image-6782" /></a></p>
<p>If you want to use a different password scheme, take a look at this <a href="http://wiki2.dovecot.org/Authentication/PasswordSchemes" target="_blank" rel="noopener noreferrer">link</a>.</p>
<p>Now, create or open <em>/usr/local/etc/dovecot/users</em> and copy and paste the password after the username. In my case, I have <em>joe@domain-one.com</em> with some password that I just generated. So the line will be like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2013/12/P033-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P033-06.png" alt="" width="728" height="97" class="aligncenter size-full wp-image-6783" /></a><br />
Don&#8217;t forget to add 4 colons after the password &#8220;::::&#8221;. Even if you use the same password for the users, they&#8217;ll be encrypted differently. </p>
<p>The problem with this scenario is that the end users won&#8217;t have the ability to change their passwords. So, you&#8217;ll have to provide them with the password and they won&#8217;t be able to reset them. But, there are plenty of perl scripts that can take care of this or you can write your own.</p>
<p>Start dovecot, by simply typing <em>dovecot</em> and check for any errors with <em>tail -f /var/log/dovecot.log</em>. At this point, we should have dovecot running and listening for pop and imap connections. </p>
<pre class="brush: bash; title: ; notranslate">
sockstat -4 | grep :110
sockstat -4 | grep :143
</pre>
<p>Now, let&#8217;s check our e-mail. You can do that from the server using the telnet command. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P033-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P033-07.png" alt="" width="577" height="481" class="aligncenter size-full wp-image-6784" /></a></p>
<p>In the above example, I am testing POP3. For IMAP, do the following.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P033-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P033-08.png" alt="" width="732" height="400" class="aligncenter size-full wp-image-6785" /></a><br />
If you want you can test retrieving these emails with a mail client such as Outlook, Opera Mail or any <a href="http://en.wikipedia.org/wiki/Email_client" target="_blank" rel="noopener noreferrer">MUA</a> of your preference. </p>
<p>At this point the server can receive e-mails from others and you can retrieve those e-mails from outside using POP and IMAP. What we need to do now is to be able to reply to those e-mails from outside (using MUA of your choice). Nowadays port 25 is blocked at some major providers (Verizon, Comcast for example), so we&#8217;ll use SASL in Postfix and we&#8217;ll use Dovecot to authenticate the users using the same username/password combination. In addition, we&#8217;ll use certificates, so instead of POP3 and IMAP, we&#8217;ll use their secure equivalents, POP3s and IMAPs running on ports 995 and 993 respectively. Dovecot should already listen on these ports, so you can allow these ports on the firewall and close 110 and 143. </p>
<p><strong>Postfix</strong></p>
<p>Edit <em>/usr/local/etc/postfix/main.cf</em> and add the following lines at the end.</p>
<pre class="brush: bash; title: ; notranslate">
# TLS
smtpd_use_tls = yes
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_key_file = /usr/local/etc/postfix/myserver.key
smtpd_tls_cert_file = /usr/local/etc/postfix/server.crt
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom

# SASL
smtpd_sasl_type = dovecot
broken_sasl_auth_clients = yes
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
smtpd_relay_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
</pre>
<p>NOTE: As of postfix 2.10 the last line is needed. See this <a href="http://www.postfix.org/SMTPD_ACCESS_README.html" target="_blank" rel="noopener noreferrer">link</a>.</p>
<p>Then, edit <em>/usr/local/etc/postfix/master.cf</em> and remove the comments from the submission part. </p>
<pre class="brush: bash; title: ; notranslate">
submission inet n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
</pre>
<p>Restart postfix after these changes. For information of what these values mean, check the links at the end of this post. If you do <em>sockstat -4</em>, you&#8217;ll see that postfix is also listening on port 587. Allow this port on the firewall if you have it enabled, but don&#8217;t close port 25. This port is used for server to server communication. If you do <em>telnet localhost 587</em> and type <em>EHLO something.com</em> you should see that postfix replies with STARTTLS.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P033-09.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P033-09.png" alt="" width="408" height="336" class="aligncenter size-full wp-image-6786" /></a></p>
<p><strong>Dovecot</strong></p>
<p>Edit <em>10-auth.conf</em> and change <em>disable_plaintext_auth = no</em> to <em>disable_plaintext_auth = yes</em>. Then, edit <em>10-ssl.conf</em> (you did a backup of this file, didn&#8217;t you?) and change the following values.</p>
<pre class="brush: bash; title: ; notranslate">
ssl = yes
ssl_cert = &lt;/usr/local/etc/postfix/server.crt
ssl_key = &lt;/usr/local/etc/postfix/myserver.key
</pre>
<p>We&#8217;ll use self-signed certificates, but check <a href="http://startssl.com" target="_blank" rel="noopener noreferrer">www.startssl.com</a> for free certificates. Unlike virtual Apache domains, you don&#8217;t need multiple certificates for each virtual domain. Self-signed certificates are fake, so you&#8217;ll get a prompt to accept a fake certificate when you try to send/receive an email, but the goal is to show you how to use them, not to be a 100% compliant. </p>
<pre class="brush: bash; title: ; notranslate">
openssl genrsa -out myserver.key 1024
openssl req -new -key myserver.key -out myserver.csr
openssl x509 -req -days 3650 -in myserver.csr -signkey myserver.key -out server.crt
</pre>
<p>Coopy <em>server.crt</em> and <em>myserver.key</em> under <em>/usr/local/etc/postfix</em> and restart both postfix and dovecot.</p>
<p>You can test SMTP SSL/TLS on submission port 587.</p>
<pre class="brush: bash; title: ; notranslate">
openssl s_client -starttls smtp -connect localhost:587
</pre>
<p>Then type <em>ehlo something.com </em>, hit ENTER and then <em>mail from:joe@domain-one.com</em>. If these steps work, you should be OK. To test SASL with postfix and dovecot, type:</p>
<pre class="brush: bash; title: ; notranslate">
doveadm auth -a /var/spool/postfix/private/auth joe@domain-one.com joe'spasswd
</pre>
<p>You should receive <em>passdb: joe@domain-one.com auth succeeded.</em></p>
<p>At this point, you should be able to send e-mails from your favorite MUA, but you&#8217;ll have to make some changes in order to send and receive. For example, in Outlook, you should use these settings.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P033-10.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P033-10.png" alt="" width="381" height="179" class="aligncenter size-full wp-image-6787" /></a><br />
<a href="https://blog.andreev.it/wp-content/uploads/2013/12/P033-11.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P033-11.png" alt="" width="379" height="151" class="aligncenter size-full wp-image-6831" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P033-11.png 379w, https://blog.andreev.it/wp-content/uploads/2013/12/P033-11-300x120.png 300w" sizes="(max-width: 379px) 100vw, 379px" /></a></p>
<p>So, no more port 110 and 143. Instead use 995 for POP3s, 587 for SMPT (SASL) and 993 for IMAPs. The username is your e-mail address and the password is the one that you generated with <em>doveadm pw</em> command.</p>
<p>References:</p>
<p><a href="http://www.postfix.org/VIRTUAL_README.html#virtual_mailbox" target="_blank" rel="noopener noreferrer">http://www.postfix.org/VIRTUAL_README.html#virtual_mailbox</a><br />
<a href="http://www.postfix.org/SASL_README.html" target="_blank" rel="noopener noreferrer">http://www.postfix.org/SASL_README.html</a><br />
<a href="http://wiki2.dovecot.org/HowTo/PostfixAndDovecotSASL" target="_blank" rel="noopener noreferrer">http://wiki2.dovecot.org/HowTo/PostfixAndDovecotSASL</a><br />
<a href="http://mxtoolbox.com/" target="_blank" rel="noopener noreferrer">http://mxtoolbox.com/</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2013/12/freebsd-postfix-dovecot-mua-virtual-domains-virtual-users/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			</item>
		<item>
		<title>CentOS: postfix, dovecot, MUA &#8211; virtual domains, virtual users</title>
		<link>https://blog.andreev.it/2013/12/centos-postfix-dovecot-mua-virtual-domains-virtual-users/</link>
					<comments>https://blog.andreev.it/2013/12/centos-postfix-dovecot-mua-virtual-domains-virtual-users/#comments</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Mon, 09 Dec 2013 04:30:32 +0000</pubDate>
				<category><![CDATA[CentOS]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[dovecot]]></category>
		<category><![CDATA[postfix]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=849</guid>

					<description><![CDATA[The goal of this post is to have postfix (SMTP, SSL/TLS and SASL) and&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>The goal of this post is to have <a href="http://www.postfix.org/" target="_blank" rel="noopener noreferrer">postfix</a> (SMTP, SSL/TLS and SASL) and <a href="http://www.dovecot.org/" target="_blank" rel="noopener noreferrer">dovecot</a> (POP3s, IMAPs) serving multiple non-U*ix users in multiple e-mail domains on one <a href="http://www.centos.org/" target="_blank" rel="noopener noreferrer">CentOS</a> box. I am using CentOS 6.3, postfix 2.6.6 and dovecot 2.0.9. The configuration files shouldn&#8217;t be different on any other Linux distro but there might be some slight differences in how things get accomplished. </p>
<p><strong>Postfix</strong></p>
<p>First, install postfix and configure it to start on boot with:</p>
<pre class="brush: bash; title: ; notranslate">
yum install postfix
chkconfig postfix on
</pre>
<p>You might get a notice that postfix is already installed and that&#8217;s fine. The configuration files for postfix are in <em>/etc/postfix</em>. There are two main files, <em>main.cf</em> and <em>master.cf</em>. Make a copy of both these files. Usually I do:</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/postfix
cp main.cf main.cf.20131124
cp master.cf master.cf.20131124
</pre>
<p>20131124 represents the date the copy was taken.</p>
<p>Now, edit <em>main.cf</em> and change the following values:</p>
<pre class="brush: bash; title: ; notranslate">
myhostname = www.example.com
mydomain = example.com
myorigin = $mydomain
inet_interfaces = all
home_mailbox = Maildir/
</pre>
<p>Create a user that will have access to the mailboxes.</p>
<pre class="brush: bash; title: ; notranslate">
adduser vpostfix
tail /etc/passwd
</pre>
<p>Make sure to change the login shell to <em>/sbin/nologin</em>. </p>
<pre class="brush: bash; title: ; notranslate">
usermod -s /sbin/nologin vpostfix. 
</pre>
<p>Look at the UID:GUID for the vpostfix user. In my case it&#8217;s 502:502.</p>
<p>Add the following lines at the end of main.cf and replace the UID:GUID under <em>virtual_minimum_uid</em>, <em>virtual_maximum_uid</em>, <em>virtual_uid_maps</em> and <em>virtual_gid_maps</em> with the values that you got from <em>tail /etc/passwd</em> or <em>grep vpostfix /etc/passwd</em>.</p>
<pre class="brush: bash; title: ; notranslate">
# Virtual domain config
virtual_mailbox_domains = /etc/postfix/virtual_domains
virtual_mailbox_base = /var/mail/vhosts
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
# Make sure you replace these UID:GUID numbers
virtual_minimum_uid = 502
virtual_maximum_uid = 502
virtual_uid_maps = static:502
virtual_gid_maps = static:502
virtual_alias_maps = hash:/etc/postfix/virtual
</pre>
<p>Edit or create <em>/etc/postfix/virtual_domains</em>. This is a file where all of your domains will be listed. Of course, you&#8217;ll have to make sure that MX records of your domains point to the IP of the CentOS box.</p>
<pre class="brush: bash; title: ; notranslate">
#  Put each domain in a separate line.
domain-one.com
domain-two.net
domain-three.org
</pre>
<p>As you can see, we have three virtual domains, but the <em>myhostname</em> points to <em>www.example.com</em>. If you put one of these three domains as <em>myhostname</em> and <em>mydomain</em> values, you&#8217;ll get a warning that the local domain is already listed in the virtual domains list. In addition, if you keep e.g. <em>domain-one.com</em> as a local domain and remove it from the virtual domains list, then you can&#8217;t treat <em>domain-one.com</em> as a virtual domain and deliver its mail to <em>/var/mail/vhosts</em>. Don&#8217;t use <em>myhostname = localhost</em> either, because if some other mail server has the same config, you&#8217;ll get an error that the destination loops back and the mail won&#8217;t be delivered. Don&#8217;t use <em>www.example.com</em> either, because you won&#8217;t be able to send to <em>www.example.com</em> or any other server that have <em>www.example.com</em> as <em>myhostname</em>. So, pick something that&#8217;s unique even if you don&#8217;t own that domain or that domain is not registered. Mind that if you send an email from this server and analyze the headers, you&#8217;ll see that <em>www.example.com</em> is in the headers. Most e-mail servers won&#8217;t complain and treat this e-mail as spam, as long as you have a valid MX record for the virtual domains that point to that IP. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P032-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P032-01.png" alt="" width="637" height="73" class="aligncenter size-full wp-image-6763" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P032-01.png 637w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-01-300x34.png 300w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-01-585x67.png 585w" sizes="(max-width: 637px) 100vw, 637px" /></a></p>
<p>Create the mail folder, subfolders for the domains and assign the proper permissions.</p>
<pre class="brush: bash; title: ; notranslate">
mkdir /var/mail/vhosts
chgrp -R vpostfix /var/mail
cd /var/mail/vhosts
mkdir domain-one.com
mkdir domain-two.net
mkdir domain-three.org
cd ..
chown -R vpostfix:vpostfix vhosts
</pre>
<p>Once you do that, <em>postfix</em> will create the &#8220;Maildir&#8221; folders automatically and assign the proper permissions. Finally, create a file <em>/etc/postfix/vmailbox</em> and add all of the users that will receive e-mails. Here is an example:</p>
<pre class="brush: bash; title: ; notranslate">
joe@domain-one.com        domain-one.com/joe/
bill@domain-one.com       domain-one.com/bill/
@domain-one.com           domain-one.com/catch-all/
joe@domain-two.net        domain-two.net/joe/
</pre>
<p>Make sure you end up each line with &#8220;/&#8221;, otherwise mail won&#8217;t be delivered.<br />
Virtual user <em>&#8220;joe@domain-one.com&#8221;</em> (mind that there is no CentOS login for this user, these are all virtual users) will have his email delivered under <em>/var/mail/vhosts/domain-one.com/joe</em> folder. You don&#8217;t have to create these subfolders. Once everything is up and running, postfix will take care of creating the Maildir structure (cur, new, tmp).</p>
<p>If you want you can create a catch-all address, see the example above (catch-all). This line tells postfix to get all the emails for the non-existing users in that domain (<em>domain-one.com</em>), which means a lot of spam. </p>
<p>But what if you have a valid CentOS user named <em>bill</em>? Where that email goes? In this case, nowhere. If we want this OS user to receive an email, we&#8217;ll have to treat him as a virtual user and add him to a virtual domain. It&#8217;s much easier to maintain one list of virtual users and hosts than deal with separate configuration files. </p>
<p>Maybe you&#8217;ve noticed that the file with the e-mail addresses (<em>vmailbox</em>) has a <em>hash:</em> prefix in the config file. This is to speed-up lookups. Postfix can use hash: (Berkeley-DB), mySQL or PostgreSQL database to store the e-mail accounts. Check the postfix howto if you want to use mySQL or PostgreSQL. We&#8217;ll be dealing with Berkeley DB.</p>
<p>Once we are done with the editing of these files, do the following to create the hashed files (extension .db). You should execute these lines anytime you make a change to these files. </p>
<pre class="brush: bash; title: ; notranslate">
postmap /etc/postfix/virtual
postmap /etc/postfix/vmailbox
</pre>
<p>Now, everything is ready for postfix to receive an email. Make sure that postfix is running and that it actually listens on port 25. Also make sure that port 25 is opened on the firewall.</p>
<pre class="brush: bash; title: ; notranslate">
ps -eaf | grep postfix
netstat -an | grep :25
iptables --list | grep smtp
</pre>
<p>You can restart postfix with <em>postfix stop</em> and <em>postfix start</em> or reload the configuration files with <em>postfix reload</em>. </p>
<p>From another domain (e.g. your hotmail or gmail account) send an e-mail to <em>joe@domain-one.com</em> or whatever your domain is. Do :</p>
<pre class="brush: bash; title: ; notranslate">
tail -f /var/log/maillog
</pre>
<p>You should see something like this.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P032-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P032-02.png" alt="" width="726" height="250" class="aligncenter size-full wp-image-6764" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P032-02.png 726w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-02-300x103.png 300w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-02-585x201.png 585w" sizes="(max-width: 726px) 100vw, 726px" /></a></p>
<p>If you check <em>/var/mail/vhosts/domain-one/joe/new</em> folder you&#8217;ll see a file with some gibberish name. This is your e-mail that you just sent to joe. But, how will this virtual user retrieve this e-mail? There is a login (the e-mail address), but what&#8217;s the password? </p>
<p><strong>Dovecot</strong></p>
<p>In order to retrieve the e-mails, we&#8217;ll install Dovecot. Dovecot is an open-source POP and IMAP client. </p>
<pre class="brush: bash; title: ; notranslate">
yum install dovecot
chkconfig dovecot on
</pre>
<p>As of version 2.0, there are multiple configuration files for Dovecot. The main file is <em>/etc/dovecot/dovecot.conf</em>, but you&#8217;ll see a lot of include directives there that point to <em>/etc/dovecot/conf.d</em> folder where we have about 22 configuration files. </p>
<p>Make a copy of <em>dovecot.conf</em> and change only one line.</p>
<pre class="brush: bash; title: ; notranslate">
protocols = imap pop3
</pre>
<p>Then, go to <em>conf.d</em> folder and change the following lines in the following files.</p>
<p><strong>10-auth.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
disable_plaintext_auth = no
#!include auth-system.conf.ext
!include auth-passwdfile.conf.ext
</pre>
<p><strong>10-logging.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
log_path = /var/log/dovecot.log
auth_verbose = no
auth_debug = no
verbose_ssl = no
</pre>
<p><strong>10-mail.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
mail_location = maildir:/var/mail/vhosts/%d/%n
mail_uid = 502
mail_gid = 502
mail_privileged_group = vpostfix
</pre>
<p><strong>10-master.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
  unix_listener auth-userdb {
    mode = 0600
    user = postfix
    group =  postfix
  }
  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
</pre>
<p><strong>10-ssl.conf</strong></p>
<pre class="brush: bash; title: ; notranslate">
ssl = no
# ssl_cert = &lt;/etc/ssl/certs/dovecot.pem
# ssl_key = &lt;/etc/ssl/private/dovecot.pem
</pre>
<p>If you look at <em>10-auth.conf</em>, we commented the line <em>#!include auth-system.conf.ext</em> and uncommented the <em>!include auth-passwdfile.conf.ext</em>. Take a look at this file and you&#8217;ll see:</p>
<pre class="brush: bash; title: ; notranslate">
passdb {
  driver = passwd-file
  args = scheme=CRYPT username_format=%u /etc/dovecot/users
}

userdb {
  driver = passwd-file
  args = username_format=%u /etc/dovecot/users
}
</pre>
<p>This describes how our username/password database will be in the file <em>/etc/dovecot/users</em>. To generate a password with SHA512-CRYPT password scheme do:</p>
<pre class="brush: bash; title: ; notranslate">
doveadm pw -s SHA512-CRYPT
</pre>
<p>You&#8217;ll be prompted to enter a password twice and the output will be similar to this:</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P032-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P032-03.png" alt="" width="726" height="141" class="aligncenter size-full wp-image-6765" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P032-03.png 726w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-03-300x58.png 300w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-03-585x114.png 585w" sizes="(max-width: 726px) 100vw, 726px" /></a><br />
If you want to use a different password scheme, take a look at this <a href="http://wiki2.dovecot.org/Authentication/PasswordSchemes" target="_blank" rel="noopener noreferrer">link</a>.</p>
<p>Now, create or open /<em>etc/dovecot/users</em> and copy and paste the password after the username. In my case, I have <em>joe@domain-one.com</em> with some password that I just generated. So the line will be like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2013/12/P032-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P032-04.png" alt="" width="728" height="97" class="aligncenter size-full wp-image-6766" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P032-04.png 728w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-04-300x40.png 300w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-04-585x78.png 585w" sizes="(max-width: 728px) 100vw, 728px" /></a></p>
<p>Don&#8217;t forget to add 4 colons after the password &#8220;::::&#8221;. Even if you use the same password for the users, they&#8217;ll be encrypted differently. </p>
<p>The problem with this scenario is that the end users won&#8217;t have the ability to change their passwords. So, you&#8217;ll have to provide them with the password and they won&#8217;t be able to reset them. But, there are plenty of perl scripts that can take care of this or you can write your own.</p>
<p>Start dovecot, by simply typing <em>dovecot</em> and check for any errors with <em>tail -f /var/log/dovecot.log</em>. At this point, we should have dovecot running and listening for pop and imap connections. </p>
<pre class="brush: bash; title: ; notranslate">
netstat -an | grep :110
netstat -an | grep :143
</pre>
<p>If needed, open the firewall for these two ports and let&#8217;s check our e-mail. You can do that from the server using the telnet command (<em>yum install telnet</em> if it&#8217;s not installed). </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P032-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P032-05.png" alt="" width="577" height="481" class="aligncenter size-full wp-image-6767" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P032-05.png 577w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-05-300x250.png 300w" sizes="(max-width: 577px) 100vw, 577px" /></a></p>
<p>In the above example, I am testing POP3. For IMAP, do the following.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2013/12/P032-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P032-06.png" alt="" width="732" height="400" class="aligncenter size-full wp-image-6768" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P032-06.png 732w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-06-300x164.png 300w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-06-585x320.png 585w" sizes="(max-width: 732px) 100vw, 732px" /></a></p>
<p>If you want you can test retrieving these emails with a mail client such as Outlook, Opera Mail or any <a href="http://en.wikipedia.org/wiki/Email_client" target="_blank" rel="noopener noreferrer">MUA</a> of your preference. </p>
<p>At this point the server can receive e-mails from others and you can retrieve those e-mails from outside using POP and IMAP. What we need to do now is to be able to reply to those e-mails from outside (using MUA of your choice). Nowadays port 25 is blocked at some major providers (Verizon, Comcast for example), so we&#8217;ll use SASL in Postfix and we&#8217;ll use Dovecot to authenticate the users using the same username/password combination. In addition, we&#8217;ll use certificates, so instead of POP3 and IMAP, we&#8217;ll use their secure equivalents, POP3s and IMAPs running on ports 995 and 993 respectively. Dovecot should already listen on these ports, so you can allow these ports on the firewall and close 110 and 143. </p>
<p><strong>Postfix</strong></p>
<p>Edit <em>/etc/postfix/main.cf</em> and add the following lines at the end.</p>
<pre class="brush: bash; title: ; notranslate">
# TLS
smtpd_use_tls = yes
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_key_file = /etc/postfix/myserver.key
smtpd_tls_cert_file = /etc/postfix/server.crt
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom

# SASL
smtpd_sasl_type = dovecot
broken_sasl_auth_clients = yes
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
</pre>
<p>Then, edit <em>master.cf</em> and remove the comments from the submission part. </p>
<pre class="brush: bash; title: ; notranslate">
submission inet n       -       n       -       -       smtpd
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
</pre>
<p>Restart postfix after these changes. For information of what these values mean, check the links at the end of this post. If you do <em>netstat -an</em>, you&#8217;ll see that postfix is also listening on port 587. Allow this port on the firewall, but don&#8217;t close port 25. This port is used for server to server communication.<br />
If you do <em>telnet localhost 587</em> and type <em>EHLO something.com</em> you should see that postfix replies with STARTTLS.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P032-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P032-07.png" alt="" width="408" height="336" class="aligncenter size-full wp-image-6769" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P032-07.png 408w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-07-300x247.png 300w" sizes="(max-width: 408px) 100vw, 408px" /></a></p>
<p><strong>Dovecot</strong></p>
<p>Edit <em>10-auth.conf</em> and change <em>disable_plaintext_auth = no</em> to <em>disable_plaintext_auth = yes</em>. Then, edit <em>10-ssl.conf</em> (you did a backup of this file, didn&#8217;t you?) and change the following values.</p>
<pre class="brush: bash; title: ; notranslate">
ssl = yes
ssl_cert = &lt;/etc/postfix/server.crt
ssl_key = &lt;/etc/postfix/myserver.key
</pre>
<p>We&#8217;ll use self-signed certificates, but check <a href="http://startssl.com" target="_blank" rel="noopener noreferrer">www.startssl.com</a> for free certificates. Unlike virtual Apache domains, you don&#8217;t need multiple certificates for each virtual domain. Self-signed certificates are fake, so you&#8217;ll get a prompt to accept a fake certificate when you try to send/receive an email, but the goal is to show you how to use them, not to be a 100% compliant. </p>
<pre class="brush: bash; title: ; notranslate">
openssl genrsa -out myserver.key 1024
openssl req -new -key myserver.key -out myserver.csr
openssl x509 -req -days 3650 -in myserver.csr -signkey myserver.key -out server.crt
</pre>
<p>Coopy <em>server.crt</em> and <em>myserver.key</em> under <em>/etc/postfix</em> and restart both postfix and dovecot.</p>
<p>You can test SMTP SSL/TLS on submission port 587.</p>
<pre class="brush: bash; title: ; notranslate">
openssl s_client -starttls smtp -connect localhost:587
</pre>
<p>Then type <em>ehlo something.com </em>, hit ENTER and then <em>mail from:joe@domain-one.com</em>. If these steps work, you should be OK. To test SASL with postfix and dovecot, type:</p>
<pre class="brush: bash; title: ; notranslate">
doveadm auth -a /var/spool/postfix/private/auth joe@domain-one.com joe'spasswd
</pre>
<p>You should receive <em>passdb: joe@domain-one.com auth succeeded.</em></p>
<p>At this point, you should be able to send e-mails from your favorite MUA, but you&#8217;ll have to make some changes in order to send and receive. For example, in Outlook, you should use these settings.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2013/12/P032-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P032-08.png" alt="" width="381" height="179" class="aligncenter size-full wp-image-6770" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P032-08.png 381w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-08-300x141.png 300w" sizes="(max-width: 381px) 100vw, 381px" /></a><br />
<a href="https://blog.andreev.it/wp-content/uploads/2013/12/P032-09.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2013/12/P032-09.png" alt="" width="379" height="151" class="aligncenter size-full wp-image-6771" srcset="https://blog.andreev.it/wp-content/uploads/2013/12/P032-09.png 379w, https://blog.andreev.it/wp-content/uploads/2013/12/P032-09-300x120.png 300w" sizes="(max-width: 379px) 100vw, 379px" /></a></p>
<p>So, no more port 110 and 143. Instead use 995 for POP3s, 587 for SMPT (SASL) and 993 for IMAPs. The username is your e-mail address and the password is the one that you generated with <em>doveadm pw</em> command.</p>
<p>References:</p>
<p><a href="http://www.postfix.org/VIRTUAL_README.html#virtual_mailbox" target="_blank" rel="noopener noreferrer">http://www.postfix.org/VIRTUAL_README.html#virtual_mailbox</a><br />
<a href="http://www.postfix.org/SASL_README.html" target="_blank" rel="noopener noreferrer">http://www.postfix.org/SASL_README.html</a><br />
<a href="http://wiki2.dovecot.org/HowTo/PostfixAndDovecotSASL" target="_blank" rel="noopener noreferrer">http://wiki2.dovecot.org/HowTo/PostfixAndDovecotSASL</a><br />
<a href="http://mxtoolbox.com/" target="_blank" rel="noopener noreferrer">http://mxtoolbox.com/</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2013/12/centos-postfix-dovecot-mua-virtual-domains-virtual-users/feed/</wfw:commentRss>
			<slash:comments>18</slash:comments>
		
		
			</item>
		<item>
		<title>General: postfix relay for another domain</title>
		<link>https://blog.andreev.it/2012/01/postfix-relay-for-other-domain/</link>
					<comments>https://blog.andreev.it/2012/01/postfix-relay-for-other-domain/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Wed, 18 Jan 2012 19:30:36 +0000</pubDate>
				<category><![CDATA[AIX]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[postfix]]></category>
		<category><![CDATA[relay]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=235</guid>

					<description><![CDATA[I have two registered domains both pointing to my FreeBSD external IP. The first&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>I have two registered domains both pointing to my FreeBSD external IP. The first one is chombe.org and I receive these e-mails on my FreeBSD using postfix. The second domain is klimentandreev.com and I use Exchange 2003 to receive e-mails for this domain. Since Exchange is on the internal network, I have to configure postfix to relay all e-mails for klimentandreev.com to the Exchange box.</p>
<p>First, I made sure that I can ping klimentandreev.com from FreeBSD box and that it will resolve to my internal IP. Next, I edited <strong>main.cf</strong> and changed <strong>relay_domains</strong> to be like this.</p>
<pre class="brush: bash; title: ; notranslate">
relay_domains = $mydestionation, /usr/local/etc/postfix/relay-domains 
</pre>
<p>Then, I created that file and added the following lines.</p>
<pre class="brush: bash; title: ; notranslate">
# Relay domains
klimentandreev.com
other-domain-that-i-will-probably-buy.com
</pre>
<p>After that, I reloaded postfix with <strong>/usr/local/etc/rc.d/postfix reload</strong> and I verified that postfix is relaying OK. I didn’t have to configure anything on the Exchange box.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2012/01/postfix-relay-for-other-domain/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>FreeBSD: postfix mail server</title>
		<link>https://blog.andreev.it/2012/01/postfix-and-freebsd/</link>
					<comments>https://blog.andreev.it/2012/01/postfix-and-freebsd/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Wed, 18 Jan 2012 19:27:47 +0000</pubDate>
				<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[postfix]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=228</guid>

					<description><![CDATA[A newer and more detailed version -> here. When I replaced my old desktop&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>A newer and more detailed version -> <a href="http://blog.andreev.it/?p=1604" target="_blank" rel="noopener noreferrer">here</a>.<span id="more-228"></span></p>
<p>When I replaced my old desktop FreeBSD router/gateway, I also decided to replace the MTA (mail transport agent). I was using qmail for a while and never had any problems. I figured it’s time to replace qmail because it’s no longer supported by its author and there are some fetaures that I might need in near future that qmail doesn’t support (IPv6 for example).</p>
<p>FreeBSD comes with sendmail installed but I think that this is the most difficult program to work with. The configuration file is cryptic and very confusing. So I decided to go with postfix. Installation and configuration is very easy. First, let’s install it.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/ports/mail/postfix
make all install clean
</pre>
<p>Then, edit <strong>/etc/rc.conf</strong> and add the following lines:</p>
<pre class="brush: bash; title: ; notranslate">postfix
postfix_enable=&quot;yes&quot;
sendmail_enable=&quot;NO&quot;
sendmail_submit_enable=&quot;NO
sendmail_outbound_enable=&quot;NO&quot;
</pre>
<p>We should remove some periodic processes that were part of sendmail as well. Edit <strong>/etc/periodic.conf</strong> and add the following lines:</p>
<pre class="brush: bash; title: ; notranslate">
# postfix &amp; sendmail maintenance
daily_clean_hoststat_enable=&quot;NO&quot;
daily_status_mail_rejects_enable=&quot;NO&quot;
daily_status_include_submit_mailq=&quot;NO&quot;
daily_submit_queuerun=&quot;NO&quot;
</pre>
<p>I also want root’s email to be forwarded to my other account, so I edited <strong>/etc/aliases</strong>, uncommented the line that says <strong>root: you</strong> and replaced <strong>you</strong> with my login name. Remember to update the aliases database with <strong>/usr/local/bin/newaliases</strong>. postfix comes with a configuration file in <strong>/usr/local/etc/postfix/main.cf</strong>. The only thing that I changed were the following lines:</p>
<pre class="brush: bash; title: ; notranslate">
myhostname = tripnotic.chombe.org
mydomain = chombe.org
myorigin = $mydomain
mynetworks = 127.0.0.1/8, 192.168.1.0/24, 172.16.0.0/16, 10.1.0.0/8
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
</pre>
<p>You can read the meanings of these lines in the comments in the file. They are very self-explanatory. Once I am done with postfix, let’s get rid of running sendmail and start postfix.</p>
<pre class="brush: bash; title: ; notranslate">
killall sendmail
sh /usr/local/etc/rc.d/postfix start
</pre>
<p>If you make any changes in <strong>main.cf</strong> use <strong>postfix reload</strong> instead of <strong>postfix stop &#038;&#038; postfix start</strong>. When you send or receive e-mails, you can check if everything is OK with </p>
<pre class="brush: bash; title: ; notranslate">tail -f /var/log/maillog. </pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2012/01/postfix-and-freebsd/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
