Nastavení mail serveru: Porovnání verzí

Z ZděchovNET
Skočit na navigaci Skočit na vyhledávání
Bez shrnutí editace
Bez shrnutí editace
 
(Není zobrazeno 7 mezilehlých verzí od stejného uživatele.)
Řádek 1: Řádek 1:
Ruční instalace poštovního serveru na linuxu je velmi komplikovaná jelikož celý email server je tvořen mnoho různými komponentami, které je potřeba správně provázat. Při nastavování konfiguračních souborů je možné udělat opravdu mnoho různých zapeklitých chyb. Proto je mnohem lepší varianta šáhnout po nějakém již hotovém řešení nebo použít alespoň předchystaný instalátor. Jeden takový doporučený najdete zde: [https://mailinabox.email/ mailinabox.email]

=Úvod=

Návod popisuje instalace poštovního serveru s virtuálními účty v MySQL databázi.
Návod popisuje instalace poštovního serveru s virtuálními účty v MySQL databázi.


Řádek 8: Řádek 12:




=Instalační skript=
* Nainstalujte potřebné balíčky


Většina návodů je provedena jako dlouhý popis postupu s mnoha útržkovými částmi příkazů, které je potřeba provést. To je zdlouhavý proces kopírovat jednotlivé části povelů a po částech je provádět. Místo toho bychom rádi měli jednoduchou instalaci, kterou prostě spustíme, chvíli počkáme a máme hotovo. Zde je předložen skript, který se toto dle [https://www.exratione.com/2014/05/a-mailserver-on-ubuntu-1404-postfix-dovecot-mysql/ tohoto] návodu snaží docílit.
<pre>yum install postfix dovecot php-imap dovecot-mysql system-switch-mail roundcubemail</pre>


<source lang="php">
<?php


$MysqlRootPassword = 'MysqlRootPassword';
* Přidejte systémový účet pro virtuální schránky
$MysqlUserPassword = 'MysqlUserPassword';
$PostfixAdminName = 'PostfixAdminName';
$PostfixSetupPassword = 'PostfixSetupPassword';
$DomainName = 'domain.com';
$ServerDomain = 'mail.'.$DomainName;


function Execute($Command)
<pre># useradd vmail</pre>
{
echo('Executing: '.$Command."\n");
passthru($Command);
}


function InstallPackages()
{
// LAMP web server
Execute('apt-get update');
Execute('apt-get upgrade --assume-yes');
Execute('apt-get install --assume-yes lamp-server^');


Execute('apt-get install --assume-yes \
* Doplňte do souboru '''/etc/postfix/main.cf''' nastavení pro schránky:
php-apc \
php7.0-mcrypt \
php7.0-memcache \
php7.0-curl \
php7.0-gd \
php-xml-parser');


Execute('ln -sf ../../mods-available/mcrypt.ini /etc/php5/apache2/conf.d/20-mcrypt.ini');
<pre>virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
virtual_gid_maps = static:505
virtual_mailbox_base = /home/vmail
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_limit = 51200000
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_minimum_uid = 505
virtual_transport = virtual
virtual_uid_maps = static:505
</pre>


// Configure apache
Obsažené číslo UID upravte dle systémového UID uživatele vmail.
Execute('a2enmod rewrite ssl');
Execute('a2ensite default-ssl');


Execute('service apache2 restart');


// Memcached
* Pokud váš server musí předávat poštu přes zadaný SMTP server, doplňte také řádek pro nastavení SMTP předávacího serveru
Execute('apt-get install --assume-yes memcached');
<pre>relayhost = smtp.zdechov.net</pre>
// Mail packages
Execute('apt-get install --assume-yes mail-server^');


Execute('apt-get install --assume-yes \
postfix-mysql \
dovecot-mysql \
dovecot-imapd \
dovecot-pop3d \
postgrey \
amavis \
clamav \
clamav-daemon \
spamassassin \
php7.0-imap');


Execute('ln -sf ../../mods-available/imap.ini /etc/php5/apache2/conf.d/20-imap.ini');
* Dále vytvořte ve složce '''/etc/postfix''' soubory se zadaným obsahem a upravte přihlašovací pro váš MySQL server:


Execute('service apache2 restart');
'''Soubor mysql_relay_domains_maps.cf'''
<pre>user = postfix
password = heslo
hosts = localhost
dbname = postfix
table = domain
select_field = domain
where_field = domain
additional_conditions = and backupmx = '1'</pre>


Execute('apt-get install --assume-yes \
'''Soubor mysql_virtual_alias_maps.cf'''
pyzor \
<pre>user = postfix
razor \
password = heslo
arj \
hosts = localhost
cabextract \
dbname = postfix
lzop \
table = alias
nomarch \
select_field = goto
p7zip-full \
where_field = address</pre>
ripole \
rpm2cpio \
tnef \
unzip \
unrar-free \
zip \
zoo');
}


function PrepareDatabase()
'''Soubor mysql_virtual_domains_maps.cf'''
{
<pre>user = postfix
global $MysqlUserPassword, $MysqlRootPassword;
password = heslo
// Mail database
hosts = localhost
dbname = postfix
table = domain
select_field = domain
where_field = domain
#additional_conditions = and backupmx = '0' and active = '1'</pre>


Execute('mysql -uroot -p'.$MysqlRootPassword.' -Bse \
'''Soubor mysql_virtual_mailbox_limit_maps.cf'''
"drop database mail; create database mail;
<pre>user = postfix
grant all on mail.* to \'mail\'@\'localhost\' identified by \''.$MysqlUserPassword.'\';"');
password = heslo
}
hosts = localhost
dbname = postfix
table = mailbox
select_field = quota
where_field = username
#additional_conditions = and active = '1'</pre>


function UpdatePHPConfigFile($FileName, $BaseVariable, $Parameters)
'''Soubor mysql_virtual_mailbox_maps.cf'''
{
<pre>user = postfix
if(!file_exists($FileName.'_backup'))
password = heslo
file_put_contents($FileName.'_backup', file_get_contents($FileName));
hosts = localhost
$Content = explode("\n", file_get_contents($FileName.'_backup'));
dbname = postfix
foreach($Parameters as $Parameter)
table = mailbox
{
select_field = maildir
where_field = username
if(is_array($Parameter['name'])) {
#additional_conditions = and active = '1'</pre>
foreach($Content as $Num => $Line)
{
$Needle = '$'.$BaseVariable.'['."'".$Parameter['name'][0]."'] = array (";
if(substr($Line, 0, strlen($Needle)) == $Needle)
{
echo('Found group: '.$Parameter['name'][0]."\n");
$Needle = " '".$Parameter['name'][1]."' => ";
$I = 1;
while((($Num + $I) < count($Content)) and ($Content[$Num + $I] != ');'))
{
if(substr($Content[$Num + $I], 0, strlen($Needle)) == $Needle) {
echo('Found group: '.$Parameter['name'][1]."\n");
$Content[$Num + $I] = $Needle.$Parameter['value'].',';
}
$I++;
}
}
}
} else {
foreach($Content as $Num => $Line)
{
$Needle = '$'.$BaseVariable.'['."'".$Parameter['name']."'] = ";
if(substr($Line, 0, strlen($Needle)) == $Needle)
{
echo('Found: '.$Parameter['name']."\n");
$Content[$Num] = $Needle.$Parameter['value'].';';
}
}
}
}
file_put_contents($FileName, implode("\n", $Content));
}


function generate_setup_password_salt()
{
$salt = time().'*'.mt_rand(0,60000);
$salt = md5($salt);
return $salt;
}


function encrypt_setup_password($password, $salt)
* Konfigurační soubor '''/etc/dovecot.conf''' nastavte např. takto:
{
<pre>dovecot.conf 882/1668 UTF-8 52%
return $salt . ':' . sha1($salt . ':' . $password);
auth_debug_passwords = yes
}


function InstallPostfixAdmin()
# Log file to use for error messages, instead of sending them to syslog.
{
# /dev/stderr can be used to log into stderr.
global $ServerDomain, $PostfixAdminName, $MysqlUserPassword, $PostfixSetupPassword, $DomainName;
log_path = /var/log/dovecot.log

Execute('wget "http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/'.
# Log file to use for informational and debug messages.
$PostfixAdminName.'/'.$PostfixAdminName.'.tar.gz?r=&ts=1417890779&use_mirror=netcologne" -O '.
# Default is the same as log_path.
$PostfixAdminName.'.tar.gz');
info_log_path = /var/log/dovecot-info.log
Execute('tar -xf '.$PostfixAdminName.'.tar.gz');

Execute('rm -f '.$PostfixAdminName.'.tar.gz');

Execute('mv '.$PostfixAdminName.' /var/www/html/postfixadmin');
# More verbose logging. Useful for figuring out why authentication isn't
Execute('chown -R www-data:www-data /var/www/html/postfixadmin');
# working.
auth_verbose = yes


UpdatePHPConfigFile('/var/www/html/postfixadmin/config.inc.php', 'CONF', array(
# Even more verbose logging for debugging purposes. Shows for example SQL
array('name' => 'setup_password', 'value' => "'".encrypt_setup_password($PostfixSetupPassword, generate_setup_password_salt())."'"),
# queries.
array('name' => 'configured', 'value' => 'true'),
auth_debug = yes
array('name' => 'postfix_admin_url', 'value' => "'https://".$ServerDomain."/postfixadmin'"),
array('name' => 'database_type', 'value' => "'mysql'"),
array('name' => 'database_host', 'value' => "'localhost'"),
array('name' => 'database_user', 'value' => "'mail'"),
array('name' => 'database_password', 'value' => "'".$MysqlUserPassword."'"),
array('name' => 'database_name', 'value' => "'mail'"),
array('name' => 'admin_email', 'value' => "'admin@".$DomainName."'"),
array('name' => 'user_footer_link', 'value' => "'https://".$ServerDomain."/main.php'"),
array('name' => 'show_footer_text', 'value' => "'YES'"),
array('name' => 'footer_text', 'value' => "'Return to ".$ServerDomain."'"),
array('name' => 'footer_link', 'value' => "'https://".$ServerDomain."'"),
array('name' => array('default_aliases', 'abuse'), 'value' => "'abuse@".$DomainName."'"),
array('name' => array('default_aliases', 'hostmaster'), 'value' => "'hostmaster@".$DomainName."'"),
array('name' => array('default_aliases', 'postmaster'), 'value' => "'postmaster@".$DomainName."'"),
array('name' => array('default_aliases', 'webmaster'), 'value' => "'webmaster@".$DomainName."'"),
));



mail_location = maildir:~/Maildir

#mail_location = maildir:/home/vmail/%d/%u
first_valid_uid = 505
last_valid_uid = 505
maildir_copy_with_hardlinks = yes

protocol imap {
mail_plugins = quota imap_quota
imap_client_workarounds = outlook-idle delay-newmail
}
}


function VirtualMailUser()
protocol pop3 {
{
mail_plugins = quota
Execute('useradd -r -u 150 -g mail -d /var/vmail -s /sbin/nologin -c "Virtual maildir handler" vmail');
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
Execute('mkdir /var/vmail');
Execute('chmod 770 /var/vmail');
Execute('chown vmail:mail /var/vmail');
}
}


function UpdateDovecotConfigFile($FileName, $Parameters)
protocol lda {
{
postmaster_address = postmaster@domena.cz
if(!file_exists($FileName.'_backup'))
mail_plugins = quota
file_put_contents($FileName.'_backup', file_get_contents($FileName));
log_path = /var/log/dovecot-deliver.log
$Content = explode("\n", file_get_contents($FileName.'_backup'));
info_log_path = /var/log/dovecot-deliver.log
foreach($Parameters as $Parameter)
{
if(!is_array($Parameter['name']))
$Parameter['name'] = array($Parameter['name']);
// First find subgroup
$Num = 0;
$NestingLevel = 0;
while(count($Parameter['name']) > 1)
{
$Found = false;
$Needle = '#'.array_values($Parameter['name'])[0].' {';
$I = 0;
$StartNestingLevel = $NestingLevel;
while((($Num + $I) < count($Content)) and ($NestingLevel >= $StartNestingLevel))
{
if(substr(trim($Content[$Num + $I]), -1, 1) == '{') $NestingLevel++;
if(substr(trim($Content[$Num + $I]), -1, 1) == '}') $NestingLevel--;
if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle)
or (trim(substr(trim($Content[$Num + $I]), 0, strlen(substr($Needle, 1)))) == substr($Needle, 1)))
{
$Content[$Num + $I] = array_values($Parameter['name'])[0].' {';
$Num = $Num + $I + 1;
$Found = true;
echo('Found group: '.array_values($Parameter['name'])[0]."\n");
array_shift($Parameter['name']);
break;
}
$I++;
}
if(!$Found) break;
}
// Find and replace value
if(count($Parameter['name']) == 1)
{
if(!array_key_exists('value', $Parameter))
{
$Needle = array_values($Parameter['name'])[0];
$Parameter['value'] = '';
} else
$Needle = array_values($Parameter['name'])[0]." =";
$I = 0;
$StartNestingLevel = $NestingLevel;
$Found = false;
while((($Num + $I) < count($Content)) and ($NestingLevel >= $StartNestingLevel))
{
if(substr(trim($Content[$Num + $I]), -1, 1) == '{') $NestingLevel++;
if(substr(trim($Content[$Num + $I]), -1, 1) == '}')
{
if($NestingLevel == $StartNestingLevel) $Content[$Num + $I] = '}';
$NestingLevel--;
}
if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle)
or ((substr(trim($Content[$Num + $I]), 0, 1) == '#') and (substr(trim(substr(trim($Content[$Num + $I]), 1)), 0, strlen($Needle)) == $Needle)))
{
echo('Found: '.array_values($Parameter['name'])[0]."\n");
$Content[$Num + $I] = $Needle.' '.$Parameter['value'];
$Found = true;
break;
}
$I++;
}
// If not found then add new value
if($Found == false)
{
echo('Added new: '.array_values($Parameter['name'])[0]."\n");
array_splice($Content, $Num + $I - 1, 0, $Needle.' '.$Parameter['value']);
}
}
}
file_put_contents($FileName, implode("\n", $Content));
}
}


function ConfigureDovecot()
auth default {
{
# Having "login" also as a mechanism make sure outlook can use the auth smtpd as well
global $MysqlUserPassword, $DomainName;
# http://wiki.dovecot.org/Authentication/Mechanisms
mechanisms = plain login
passdb sql {
args = /etc/dovecot/sql.conf
}
UpdateDovecotConfigFile('/etc/dovecot/dovecot-sql.conf.ext', array(
userdb sql {
array('name' => 'driver', 'value' => 'mysql'),
args = /etc/dovecot/sql.conf
array('name' => 'connect', 'value' => 'host=localhost dbname=mail user=mail password='.$MysqlUserPassword),
}
array('name' => 'default_pass_scheme', 'value' => 'MD5-CRYPT'),
array('name' => 'password_query', 'value' => "SELECT username as user, password, '/var/vmail/%d/%n' as userdb_home, \\
'maildir:/var/vmail/%d/%n' as userdb_mail, 150 as userdb_uid, 8 as userdb_gid \\
FROM mailbox WHERE username = '%u' AND active = '1'"),
array('name' => 'user_query', 'value' => "SELECT '/var/vmail/%d/%n' as home, 'maildir:/var/vmail/%d/%n' as mail, \\
150 AS uid, 8 AS gid, concat('dirsize:storage=', quota) AS quota \\
FROM mailbox WHERE username = '%u' AND active = '1'"),
));
UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-auth.conf', array(
array('name' => 'disable_plaintext_auth', 'value' => 'yes'),
array('name' => 'auth_mechanisms', 'value' => 'plain login'),
array('name' => '!include auth-sql.conf.ext'),
));
UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-mail.conf', array(
array('name' => 'mail_location', 'value' => 'maildir:/var/vmail/%d/%n'),
array('name' => 'mail_uid', 'value' => 'vmail'),
array('name' => 'mail_gid', 'value' => 'mail'),
array('name' => 'first_valid_uid', 'value' => '150'),
array('name' => 'last_valid_uid', 'value' => '150'),
));
UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-ssl.conf', array(
array('name' => 'ssl_cert', 'value' => '</etc/ssl/certs/'.$DomainName.'.crt'),
array('name' => 'ssl_key', 'value' => '</etc/ssl/private/'.$DomainName.'.key'),
array('name' => 'ssl_ca', 'value' => '</etc/ssl/certs/ca-bundle.crt'),
array('name' => 'ssl_cipher_list', 'value' => 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'),
));
UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-master.conf', array(
array('name' => array('service auth', 'unix_listener auth-userdb', 'mode'), 'value' => '0666'),
array('name' => array('service auth', 'unix_listener auth-userdb', 'user'), 'value' => 'vmail'),
array('name' => array('service auth', 'unix_listener auth-userdb', 'group'), 'value' => 'mail'),
array('name' => array('service auth', 'unix_listener /var/spool/postfix/private/auth', 'mode'), 'value' => '0666'),
array('name' => array('service auth', 'unix_listener /var/spool/postfix/private/auth', 'user'), 'value' => 'postfix'),
array('name' => array('service auth', 'unix_listener /var/spool/postfix/private/auth', 'group'), 'value' => 'postfix'),
));
UpdateDovecotConfigFile('/etc/dovecot/conf.d/15-lda.conf', array(
array('name' => 'postmaster_address', 'value' => 'postmaster@'.$DomainName),
));
Execute('chown -R vmail:dovecot /etc/dovecot');
userdb prefetch {
Execute('chmod -R o-rwx /etc/dovecot');
}

function UpdateAmavisConfigFile($FileName, $Parameters)
{
if(!file_exists($FileName.'_backup'))
file_put_contents($FileName.'_backup', file_get_contents($FileName));
$Content = explode("\n", file_get_contents($FileName.'_backup'));
if(count($Content) > 0)
{
// Remove ending part
$I = count($Content) - 1;
while(($I >= 0))
{
if($Content[$I] != '#------------ Do not modify anything below this line -------------')
array_pop($Content);
else {
array_pop($Content);
break;
}
$I--;
}
}
}
foreach($Parameters as $Parameter)
user = nobody
{
socket listen {
$Parameter['name'] = array($Parameter['name']);
master {
$Num = 0;
path = /var/run/dovecot/auth-master
if(!array_key_exists('value', $Parameter))
mode = 0660
user = vmail
{
$Needle = array_values($Parameter['name'])[0];
group = mail
$Parameter['value'] = '';
} else
$Needle = array_values($Parameter['name'])[0]." =";
$I = 0;
$Found = false;
while((($Num + $I) < count($Content)))
{
if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle)
or ((substr(trim($Content[$Num + $I]), 0, 1) == '#') and (substr(trim(substr(trim($Content[$Num + $I]), 1)), 0, strlen($Needle)) == $Needle)))
{
echo('Found: '.array_values($Parameter['name'])[0]."\n");
$Content[$Num + $I] = $Needle.' '.$Parameter['value'];
$Found = true;
break;
}
$I++;
}
}
// If not found then add new value
client {
if($Found == false)
{
path = /var/spool/postfix/private/auth
echo('Added new: '.array_values($Parameter['name'])[0]."\n");
mode = 0660
array_splice($Content, $Num + $I - 1, 0, $Needle.' '.$Parameter['value']);
user = postfix
group = mail
}
}
$Content[] = '#------------ Do not modify anything below this line -------------';
$Content[] = '1; # ensure a defined return';
file_put_contents($FileName, implode("\n", $Content));
}

function UpdateDefaultConfigFile($FileName, $Parameters)
{
if(!file_exists($FileName.'_backup'))
file_put_contents($FileName.'_backup', file_get_contents($FileName));
$Content = explode("\n", file_get_contents($FileName.'_backup'));
foreach($Parameters as $Parameter)
{
if(!is_array($Parameter['name']))
$Parameter['name'] = array($Parameter['name']);
$Num = 0;
// Find and replace value
if(count($Parameter['name']) == 1)
{
if(!array_key_exists('value', $Parameter))
{
$Needle = array_values($Parameter['name'])[0];
$Parameter['value'] = '';
} else
$Needle = array_values($Parameter['name'])[0]."=";
$I = 0;
$Found = false;
while((($Num + $I) < count($Content)))
{
if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle)
or ((substr(trim($Content[$Num + $I]), 0, 1) == '#') and (substr(trim(substr(trim($Content[$Num + $I]), 1)), 0, strlen($Needle)) == $Needle)))
{
echo('Found: '.array_values($Parameter['name'])[0]."\n");
$Content[$Num + $I] = $Needle.$Parameter['value'];
$Found = true;
break;
}
$I++;
}
// If not found then add new value
if($Found == false)
{
echo('Added new: '.array_values($Parameter['name'])[0]."\n");
array_splice($Content, $Num + $I - 1, 0, $Needle.' '.$Parameter['value']);
}
}
}
}
}
file_put_contents($FileName, implode("\n", $Content));
}
}


function SpamVirus()
dict {
{
}</pre>
Execute('adduser clamav amavis');
Execute('adduser amavis clamav');
UpdateAmavisConfigFile('/etc/amavis/conf.d/15-content_filter_mode', array(
array('name' => '@bypass_virus_checks_maps', 'value' => '(\%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);'),
array('name' => '@bypass_spam_checks_maps', 'value' => '(\%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);'),
));
UpdateDefaultConfigFile('/etc/default/spamassassin', array(
array('name' => 'ENABLED', 'value' => '1'),
array('name' => 'CRON', 'value' => '1'),
));
UpdateAmavisConfigFile('/etc/amavis/conf.d/50-user', array(
array('name' => '$max_servers', 'value' => '3;'),
array('name' => '$sa_tag_level_deflt', 'value' => '-9999;'),
array('name' => '@lookup_sql_dsn', 'value' => "(
['DBI:mysql:database=mail;host=127.0.0.1;port=3306',
'mail',
'mailpassword']);"),
array('name' => '$sql_select_policy', 'value' => "'SELECT domain from domain WHERE CONCAT(\"@\",domain) IN (%k)';"),
));
Execute('freshclam');
Execute('service clamav-daemon restart');
Execute('service amavis restart');
Execute('service spamassassin restart');
}


function ConfigurePostfix()
{
file_put_contents('/etc/postfix/mysql_virtual_alias_domainaliases_maps.cf',
"user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
query = SELECT goto FROM alias,alias_domain
WHERE alias_domain.alias_domain = '%d'
AND alias.address=concat('%u', '@', alias_domain.target_domain)
AND alias.active = 1");
file_put_contents('/etc/postfix/mysql_virtual_alias_maps.cf',
"user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
table = alias
select_field = goto
where_field = address
additional_conditions = and active = '1'");
file_put_contents('/etc/postfix/mysql_virtual_domains_maps.cf',
"user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
table = domain
select_field = domain
where_field = domain
additional_conditions = and backupmx = '0' and active = '1'");
file_put_contents('/etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf',
"user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
query = SELECT maildir FROM mailbox, alias_domain
WHERE alias_domain.alias_domain = '%d'
AND mailbox.username=concat('%u', '@', alias_domain.target_domain )
AND mailbox.active = 1");
file_put_contents('/etc/postfix/mysql_virtual_mailbox_maps.cf',
"user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
table = mailbox
select_field = CONCAT(domain, '/', local_part)
where_field = username
additional_conditions = and active = '1'");
file_put_contents('/etc/postfix/header_checks',
"/^Received:/ IGNORE
/^User-Agent:/ IGNORE
/^X-Mailer:/ IGNORE
/^X-Originating-IP:/ IGNORE
/^x-cr-[a-z]*:/ IGNORE
/^Thread-Index:/
IGNORE");
if(!file_exists('/etc/postfix/main.cf_backup'))
file_put_contents('/etc/postfix/main.cf_backup', file_get_contents('/etc/postfix/main.cf'));
file_put_contents('/etc/postfix/main.cf',
'# See /usr/share/postfix/main.cf.dist for a commented, more complete version
# The first text sent to a connecting process.
smtpd_banner = $myhostname ESMTP $mail_name
biff = no
# appending .domain is the MUA\'s job.
append_dot_mydomain = no
readme_directory = no
# SASL parameters
# ---------------------------------
# Use Dovecot to authenticate.
smtpd_sasl_type = dovecot
# Referring to /var/spool/postfix/private/auth
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =
smtpd_sasl_authenticated_header = yes
# TLS parameters
# ---------------------------------
# The default snakeoil certificate. Comment if using a purchased
# SSL certificate.
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
# Uncomment if using a purchased SSL certificate.
# smtpd_tls_cert_file=/etc/ssl/certs/example.com.crt
# smtpd_tls_key_file=/etc/ssl/private/example.com.key
# The snakeoil self-signed certificate has no need for a CA file. But
# if you are using your own SSL certificate, then you probably have
# a CA certificate bundle from your provider. The path to that goes
# here.
# smtpd_tls_CAfile=/etc/ssl/certs/ca-bundle.crt
# Ensure we\'re not using no-longer-secure protocols.
smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
smtp_tls_note_starttls_offer = yes
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom
#smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
#smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# Note that forcing use of TLS is going to cause breakage - most mail servers
# don\'t offer it and so delivery will fail, both incoming and outgoing. This is
# unfortunate given what various governmental agencies are up to these days.
#
# Enable (but don\'t force) all incoming smtp connections to use TLS.
smtpd_tls_security_level = may
# Enable (but don\'t force) all outgoing smtp connections to use TLS.
smtp_tls_security_level = may
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
# SMTPD parameters
# ---------------------------------
# Uncomment the next line to generate \"delayed mail\" warnings
#delay_warning_time = 4h
# will it be a permanent error or temporary
unknown_local_recipient_reject_code = 450
# how long to keep message on queue before return as failed.
# some have 3 days, I have 16 days as I am backup server for some people
# whom go on holiday with their server switched off.
maximal_queue_lifetime = 7d
# max and min time in seconds between retries if connection failed
minimal_backoff_time = 1000s
maximal_backoff_time = 8000s
# how long to wait when servers connect before receiving rest of data
smtp_helo_timeout = 60s
# how many address can be used in one message.
# effective stopper to mass spammers, accidental copy in whole address list
# but may restrict intentional mail shots.
smtpd_recipient_limit = 16
# how many error before back off.
smtpd_soft_error_limit = 3
# how many max errors before blocking it.
smtpd_hard_error_limit = 12
# This next set are important for determining who can send mail and relay mail
# to other servers. It is very important to get this right - accidentally producing
# an open relay that allows unauthenticated sending of mail is a Very Bad Thing.
#
# You are encouraged to read up on what exactly each of these options accomplish.
# Requirements for the HELO statement
smtpd_helo_restrictions = permit_mynetworks, warn_if_reject reject_non_fqdn_hostname, reject_invalid_hostname, permit
# Requirements for the sender details
smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks, warn_if_reject reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining, permit
# Requirements for the connecting server
smtpd_client_restrictions = reject_rbl_client sbl.spamhaus.org, reject_rbl_client blackholes.easynet.nl, reject_rbl_client dnsbl.njabl.org
# Requirement for the recipient address. Note that the entry for
# \"check_policy_service inet:127.0.0.1:10023\" enables Postgrey.
smtpd_recipient_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, check_policy_service inet:127.0.0.1:10023, permit
smtpd_data_restrictions = reject_unauth_pipelining
# This is a new option as of Postfix 2.10, and is required in addition to
# smtpd_recipient_restrictions for things to work properly in this setup.
smtpd_relay_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, check_policy_service inet:127.0.0.1:10023, permit
# require proper helo at connections
smtpd_helo_required = yes
# waste spammers time before rejecting them
smtpd_delay_reject = yes
disable_vrfy_command = yes
# General host and delivery info
# ----------------------------------
myhostname = mail.example.com
myorigin = /etc/hostname
# Some people see issues when setting mydestination explicitly to the server
# subdomain, while leaving it empty generally doesn\'t hurt. So it is left empty here.
# mydestination = mail.example.com, localhost
mydestination =
# If you have a separate web server that sends outgoing mail through this
# mailserver, you may want to add its IP address to the space-delimited list in
# mynetworks, e.g. as 10.10.10.10/32.
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
mynetworks_style = host
# This specifies where the virtual mailbox folders will be located.
virtual_mailbox_base = /var/vmail
# This is for the mailbox location for each user. The domainaliases
# map allows us to make use of Postfix Admin\'s domain alias feature.
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf, mysql:/etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf
# and their user id
virtual_uid_maps = static:150
# and group id
virtual_gid_maps = static:8
# This is for aliases. The domainaliases map allows us to make
# use of Postfix Admin\'s domain alias feature.
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf, mysql:/etc/postfix/mysql_virtual_alias_domainaliases_maps.cf
# This is for domain lookups.
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
# Integration with other packages
# ---------------------------------------
# Tell postfix to hand off mail to the definition for dovecot in master.cf
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1
# Use amavis for virus and spam scanning
content_filter = amavis:[127.0.0.1]:10024
# Header manipulation
# --------------------------------------
# Getting rid of unwanted headers. See: https://posluns.com/guides/header-removal/
header_checks = regexp:/etc/postfix/header_checks
# getting rid of x-original-to
enable_original_recipient = no');


if(!file_exists('/etc/postfix/master.cf_backup'))
* Pak nastavení Dovecotu pro přípojení k MySQL serveru je potřeba vytvořit v souboru '''/etc/dovecot/sql.conf''' takto:
file_put_contents('/etc/postfix/master.cf_backup', file_get_contents('/etc/postfix/master.cf'));
<pre>driver = mysql
file_put_contents('/etc/postfix/master.cf',
connect = host=localhost dbname=postfix user=postfix password=heslo
'#
user_query = SELECT concat('/home/vmail/', maildir) as home, concat('maildir:/home/vmail/', maildir) as mail, 505 AS uid, 12
# Postfix master process configuration file. For details on the format
AS gid, concat('maildir:storage=', quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'
# of the file, see the master(5) manual page (command: \"man 5 master\").
# fast but now so nice:-)
#
#user_query = SELECT '/var/vmail/%d/%n' as home, 'maildir:/var/vmail/%d/%n' as mail, 101 AS uid, 12 AS gid, concat('dirsize:
# Do not forget to execute \"postfix reload\" after editing this file.
storage=', quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'
#
# Just in case you are using postfix the delimiter char "+", the above query will probably fail for the username '%n' or '%u
# ==========================================================================
' and result in a "5.5.1 user unknown" error
# service type private unpriv chroot wakeup maxproc command + args
#in this case, you will probalby want to use a separate user and domain part, whilst searching only for the destination user
# (yes) (yes) (yes) (never) (100)
part (user_query only):
# ==========================================================================
# SELECT ... WHERE username = substring_index('%n','+',1) AND userrealm = '%d'
# SMTP on port 25, unencrypted.
smtp inet n - - - - smtpd
#smtp inet n - - - 1 postscreen
#smtpd pass - - - - - smtpd
#dnsblog unix - - - - 0 dnsblog
#tlsproxy unix - - - - 0 tlsproxy
# SMTP with TLS on port 587. Currently commented.
#submission inet n - - - - smtpd
# -o syslog_name=postfix/submission
# -o smtpd_tls_security_level=encrypt
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_enforce_tls=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject
# -o smtpd_sasl_tls_security_options=noanonymous
# SMTP over SSL on port 465.
smtps inet n - - - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_tls_auth_only=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject
-o smtpd_sasl_security_options=noanonymous,noplaintext
-o smtpd_sasl_tls_security_options=noanonymous
#628 inet n - - - - qmqpd
pickup fifo n - - 60 1 pickup
-o content_filter=
-o receive_override_options=no_header_body_checks
cleanup unix n - - - 0 cleanup
qmgr fifo n - n 300 1 qmgr
#qmgr fifo n - n 300 1 oqmgr
tlsmgr unix - - - 1000? 1 tlsmgr
rewrite unix - - - - - trivial-rewrite
bounce unix - - - - 0 bounce
defer unix - - - - 0 bounce
trace unix - - - - 0 bounce
verify unix - - - - 1 verify
flush unix n - - 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - - - - smtp
relay unix - - - - - smtp
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq unix n - - - - showq
error unix - - - - - error
retry unix - - - - - error
discard unix - - - - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - - - - lmtp
anvil unix - - - - 1 anvil
scache unix - - - - 1 scache
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
#
# Many of the following services use the Postfix pipe(8) delivery
# agent. See the pipe(8) man page for information about ${recipient}
# and other message envelope options.
# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
maildrop unix - n n - - pipe
flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
#
# ====================================================================
#
# Recent Cyrus versions can use the existing \"lmtp\" master.cf entry.
#
# Specify in cyrus.conf:
# lmtp cmd=\"lmtpd -a\" listen=\"localhost:lmtp\" proto=tcp4
#
# Specify in main.cf one or more of the following:
# mailbox_transport = lmtp:inet:localhost
# virtual_transport = lmtp:inet:localhost
#
# ====================================================================
#
# Cyrus 2.1.5 (Amos Gouaux)
# Also specify in main.cf: cyrus_destination_recipient_limit=1
#
#cyrus unix - n n - - pipe
# user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
#
# ====================================================================
# Old example of delivery via Cyrus.
#
#old-cyrus unix - n n - - pipe
# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
#
# ====================================================================
#
# See the Postfix UUCP_README file for configuration details.
#
uucp unix - n n - - pipe
flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
#
# Other external delivery methods.
#/var/www/html/.htaccess
ifmail unix - n n - - pipe
flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp unix - n n - - pipe
flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix - n n - 2 pipe
flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman unix - n n - - pipe
flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
${nexthop} ${user}
# The next two entries integrate with Amavis for anti-virus/spam checks.
amavis unix - - - - 3 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
-o disable_dns_lookups=yes
-o max_use=20
127.0.0.1:10025 inet n - - - - smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-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 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
# Integration with Dovecot - hand mail over to it for local delivery, and
# run the process under the vmail user and mail group.
dovecot unix - n n - - pipe
flags=DRhu user=vmail:mail argv=/usr/lib/dovecot/dovecot-lda -d $(recipient)');
}


function RestartAll()
password_query = SELECT username as user, password, concat('/home/vmail/', maildir) as userdb_home, concat('maildir:/home/vm
{
ail/', maildir) as userdb_mail, 505 as userdb_uid, 12 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'
Execute('service postfix restart');
# fast but now so nice:-)
Execute('service spamassassin restart');
#password_query = SELECT username as user, password, '/var/vmail/%d/%n' as userdb_home, 'maildir:/var/vmail/%d/%n' as userdb
Execute('service clamav-daemon restart');
_mail, 101 as userdb_uid, 12 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'</pre>
Execute('service amavis restart');
Execute('service dovecot restart');
}


function InstallRoundCube()
{
Execute('apt-get install --assume-yes \
roundcube \
roundcube-plugins \
roundcube-plugins-extra');
UpdatePHPConfigFile('/etc/roundcube/main.inc.php', 'rcmail_config', array(
array('name' => 'default_host', 'value' => "'localhost'"),
array('name' => 'force_https', 'value' => 'true'),
array('name' => 'imap_cache', 'value' => "'memcache'"),
array('name' => 'session_storage', 'value' => "'memcache'"),
array('name' => 'memcache_hosts', 'value' => "array('localhost:11211')"),
));
Execute('ln -s /var/lib/roundcube /var/www/html/roundcube');
if(file_exists('/var/www/html/index.html'))
Execute('mv /var/www/html/index.html /var/www/html/index.bak.html');
file_put_contents('/var/www/html/.htaccess', 'RewriteEngine On
# Redirect all HTTP traffic to HTTPS.
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
# Send / to /roundcube.
RewriteRule ^/?$ /roundcube [L]');
}


function InstallMonit()
* Nastavit automatické spouštění potřebných služeb
{

Execute('apt-get install --assume-yes monit');
<pre>chkconfig dovecot on
file_put_contents('/etc/monit/conf.d/amavis',
chkconfig postfix on</pre>
'check process amavisd with pidfile /var/run/amavis/amavisd.pid

every 5 cycles
group mail
start program = "/etc/init.d/amavis start"
stop program = "/etc/init.d/amavis stop"
if failed port 10024 protocol smtp then restart
if 5 restarts within 25 cycles then timeout');
file_put_contents('/etc/monit/conf.d/apache2',
'check process apache2 with pidfile /var/run/apache2/apache2.pid
group www
start program = "/etc/init.d/apache2 start"
stop program = "/etc/init.d/apache2 stop"
if failed host localhost port 80 protocol http
with timeout 10 seconds
then restart
if 5 restarts within 5 cycles then timeout');
file_put_contents('/etc/monit/conf.d/dovecot',
'check process dovecot with pidfile /var/run/dovecot/master.pid
group mail
start program = "/sbin/start dovecot"
stop program = "/sbin/stop dovecot"
group mail
# We\'d like to use this line, but see:
# http://serverfault.com/questions/610976/monit-failing-to-connect-to-dovecot-over-ssl-imap
#if failed port 993 type tcpssl sslauto protocol imap for 5 cycles then restart
if failed port 993 for 5 cycles then restart
if 5 restarts within 25 cycles then timeout');
file_put_contents('/etc/monit/conf.d/mysql',
'check process mysqld with pidfile /var/run/mysqld/mysqld.pid
group database
start program = "/etc/init.d/mysql start"
stop program = "/etc/init.d/mysql stop"
if failed host localhost port 3306 protocol mysql then restart
if 5 restarts within 5 cycles then timeout');
file_put_contents('/etc/monit/conf.d/memcached',
'check process memcached with pidfile /var/run/memcached.pid
group www
start program = "/etc/init.d/memcached start"
stop program = "/etc/init.d/memcached stop"
if failed host localhost port 11211 then restart
if 5 restarts within 5 cycles then timeout');
file_put_contents('/etc/monit/conf.d/postfix',
'check process postfix with pidfile /var/spool/postfix/pid/master.pid
group mail
start program = "/etc/init.d/postfix start"
stop program = "/etc/init.d/postfix stop"
if failed port 25 protocol smtp then restart
if 5 restarts within 5 cycles then timeout');
file_put_contents('/etc/monit/conf.d/spamassassin',
'check process spamassassin with pidfile /var/run/spamd.pid
group mail
start program = "/etc/init.d/spamassassin start"
stop program = "/etc/init.d/spamassassin stop"
if 5 restarts within 5 cycles then timeout');
file_put_contents('/etc/monit/conf.d/sshd',
'check process sshd with pidfile /var/run/sshd.pid
start program "/etc/init.d/ssh start"
stop program "/etc/init.d/ssh stop"
if failed host 127.0.0.1 port 22 protocol ssh then restart
if 5 restarts within 5 cycles then timeout');
Execute('service monit restart');
}


InstallPackages();
* Stáhněte a nainstalujte [http://sourceforge.net/projects/postfixadmin/files/ Postfix Admin] např. do složky '''/var/www/html/postfixadmin/'''
PrepareDatabase();
InstallPostfixAdmin();
VirtualMailUser();
ConfigureDovecot();
SpamVirus();
ConfigurePostfix();
RestartAll();
InstallMonit();
InstallRoundCube();


</source>


* Prohlédněte a nastavte obsah souboru '''config.inc.php''' jako:
<pre>$CONF['configured'] = true;
$CONF['default_language'] = 'cs';
$CONF['database_type'] = 'mysql';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfix';
$CONF['database_password'] = 'heslo';
$CONF['database_name'] = 'postfix';
$CONF['database_prefix'] = '';
$CONF['encrypt'] = 'md5';
</pre>




=Vnější odkazy=
=Vnější odkazy=


* [https://www.exratione.com/2014/05/a-mailserver-on-ubuntu-1404-postfix-dovecot-mysql/ A Mailserver on Ubuntu 14.04: Postfix, Dovecot, MySQL]
* [https://wiki.archlinux.org/index.php/Virtual_user_mail_system Virtual user mail system]
* [http://www.howtoforge.com/virtual-users-and-domains-postfix-dovecot-mysql-centos4.5 How To Configure ISP Mail Server With Virtual Users/Domain On Centos 4.5 Using Postfix, Dovecot, MySQL, phpMyAdmin, TLS/SSL]
* [http://www.howtoforge.com/virtual-users-and-domains-postfix-dovecot-mysql-centos4.5 How To Configure ISP Mail Server With Virtual Users/Domain On Centos 4.5 Using Postfix, Dovecot, MySQL, phpMyAdmin, TLS/SSL]
* [https://help.ubuntu.com/community/Dovecot Dovecot on Ubuntu help]


[[Kategorie:Linux]]
[[Kategorie:Linux]]

Aktuální verze z 13. 12. 2016, 00:41

Ruční instalace poštovního serveru na linuxu je velmi komplikovaná jelikož celý email server je tvořen mnoho různými komponentami, které je potřeba správně provázat. Při nastavování konfiguračních souborů je možné udělat opravdu mnoho různých zapeklitých chyb. Proto je mnohem lepší varianta šáhnout po nějakém již hotovém řešení nebo použít alespoň předchystaný instalátor. Jeden takový doporučený najdete zde: mailinabox.email

Úvod

Návod popisuje instalace poštovního serveru s virtuálními účty v MySQL databázi.

  • Budou použity následují komponenty:
    • postfix - SMTP server
    • dovecot - IMAP server
    • roundcubemail - web mail klient
    • postfixadmin - správa schránek


Instalační skript

Většina návodů je provedena jako dlouhý popis postupu s mnoha útržkovými částmi příkazů, které je potřeba provést. To je zdlouhavý proces kopírovat jednotlivé části povelů a po částech je provádět. Místo toho bychom rádi měli jednoduchou instalaci, kterou prostě spustíme, chvíli počkáme a máme hotovo. Zde je předložen skript, který se toto dle tohoto návodu snaží docílit.

<?php

$MysqlRootPassword = 'MysqlRootPassword';
$MysqlUserPassword = 'MysqlUserPassword';
$PostfixAdminName = 'PostfixAdminName';
$PostfixSetupPassword = 'PostfixSetupPassword';
$DomainName = 'domain.com';
$ServerDomain = 'mail.'.$DomainName;

function Execute($Command)
{
  echo('Executing: '.$Command."\n");
  passthru($Command);
}

function InstallPackages()
{
  // LAMP web server
  Execute('apt-get update');
  Execute('apt-get upgrade --assume-yes');
  Execute('apt-get install --assume-yes lamp-server^');

  Execute('apt-get install --assume-yes \
  php-apc \
  php7.0-mcrypt \
  php7.0-memcache \
  php7.0-curl \
  php7.0-gd \
  php-xml-parser');

  Execute('ln -sf ../../mods-available/mcrypt.ini /etc/php5/apache2/conf.d/20-mcrypt.ini');

  // Configure apache
  Execute('a2enmod rewrite ssl');
  Execute('a2ensite default-ssl');

  Execute('service apache2 restart');

  // Memcached
  Execute('apt-get install --assume-yes memcached');
 
  // Mail packages
  Execute('apt-get install --assume-yes mail-server^');

  Execute('apt-get install --assume-yes \
  postfix-mysql \
  dovecot-mysql \
  dovecot-imapd \
  dovecot-pop3d \
  postgrey \
  amavis \
  clamav \
  clamav-daemon \
  spamassassin \
  php7.0-imap');

  Execute('ln -sf ../../mods-available/imap.ini /etc/php5/apache2/conf.d/20-imap.ini');

  Execute('service apache2 restart');

  Execute('apt-get install --assume-yes \
  pyzor \
  razor \
  arj \
  cabextract \
  lzop \
  nomarch \
  p7zip-full \
  ripole \
  rpm2cpio \
  tnef \
  unzip \
  unrar-free \
  zip \
  zoo');
}

function PrepareDatabase()
{
  global $MysqlUserPassword, $MysqlRootPassword;
  // Mail database

  Execute('mysql -uroot -p'.$MysqlRootPassword.' -Bse \
"drop database mail; create database mail;
grant all on mail.* to \'mail\'@\'localhost\' identified by \''.$MysqlUserPassword.'\';"');
}

function UpdatePHPConfigFile($FileName, $BaseVariable, $Parameters)
{
  if(!file_exists($FileName.'_backup'))
    file_put_contents($FileName.'_backup', file_get_contents($FileName));    
  $Content = explode("\n", file_get_contents($FileName.'_backup'));
  foreach($Parameters as $Parameter)
  {
    
    if(is_array($Parameter['name'])) {      
      foreach($Content as $Num => $Line)
      {
        $Needle = '$'.$BaseVariable.'['."'".$Parameter['name'][0]."'] = array (";      
        if(substr($Line, 0, strlen($Needle)) == $Needle)
        {          
          echo('Found group: '.$Parameter['name'][0]."\n");
          $Needle = "    '".$Parameter['name'][1]."' => ";      
          $I = 1;
          while((($Num + $I) < count($Content)) and ($Content[$Num + $I] != ');')) 
          {
            if(substr($Content[$Num + $I], 0, strlen($Needle)) == $Needle) {   
              echo('Found group: '.$Parameter['name'][1]."\n");
              $Content[$Num + $I] = $Needle.$Parameter['value'].',';              
            }
            $I++;
          }
        }
      }
    } else {
      foreach($Content as $Num => $Line)
      {
        $Needle = '$'.$BaseVariable.'['."'".$Parameter['name']."'] = ";      
        if(substr($Line, 0, strlen($Needle)) == $Needle)
        {
          echo('Found: '.$Parameter['name']."\n");
          $Content[$Num] = $Needle.$Parameter['value'].';';
        }
      }
    }
  }
  file_put_contents($FileName, implode("\n", $Content));
  
}

function generate_setup_password_salt() 
{
  $salt = time().'*'.mt_rand(0,60000);
  $salt = md5($salt);
  return $salt;
}

function encrypt_setup_password($password, $salt) 
{
  return $salt . ':' . sha1($salt . ':' . $password);
}

function InstallPostfixAdmin()
{
  global $ServerDomain, $PostfixAdminName, $MysqlUserPassword, $PostfixSetupPassword, $DomainName;
  
  Execute('wget "http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/'.
    $PostfixAdminName.'/'.$PostfixAdminName.'.tar.gz?r=&ts=1417890779&use_mirror=netcologne" -O '.
    $PostfixAdminName.'.tar.gz');
  Execute('tar -xf '.$PostfixAdminName.'.tar.gz');
  Execute('rm -f '.$PostfixAdminName.'.tar.gz');
  Execute('mv '.$PostfixAdminName.' /var/www/html/postfixadmin');
  Execute('chown -R www-data:www-data /var/www/html/postfixadmin');

  UpdatePHPConfigFile('/var/www/html/postfixadmin/config.inc.php', 'CONF', array(
    array('name' => 'setup_password', 'value' => "'".encrypt_setup_password($PostfixSetupPassword, generate_setup_password_salt())."'"),
    array('name' => 'configured', 'value' => 'true'),
    array('name' => 'postfix_admin_url', 'value' => "'https://".$ServerDomain."/postfixadmin'"),
    array('name' => 'database_type', 'value' => "'mysql'"),
    array('name' => 'database_host', 'value' => "'localhost'"),
    array('name' => 'database_user', 'value' => "'mail'"),
    array('name' => 'database_password', 'value' => "'".$MysqlUserPassword."'"),
    array('name' => 'database_name', 'value' => "'mail'"),
    array('name' => 'admin_email', 'value' => "'admin@".$DomainName."'"),
    array('name' => 'user_footer_link', 'value' =>  "'https://".$ServerDomain."/main.php'"),
    array('name' => 'show_footer_text', 'value' => "'YES'"),
    array('name' => 'footer_text', 'value' => "'Return to ".$ServerDomain."'"),
    array('name' => 'footer_link', 'value' => "'https://".$ServerDomain."'"),
    array('name' => array('default_aliases', 'abuse'), 'value'  => "'abuse@".$DomainName."'"),
    array('name' => array('default_aliases', 'hostmaster'), 'value' => "'hostmaster@".$DomainName."'"),
    array('name' => array('default_aliases', 'postmaster'), 'value' => "'postmaster@".$DomainName."'"),
    array('name' => array('default_aliases', 'webmaster'), 'value' => "'webmaster@".$DomainName."'"),
  ));

}

function VirtualMailUser()
{
  Execute('useradd -r -u 150 -g mail -d /var/vmail -s /sbin/nologin -c "Virtual maildir handler" vmail');
  Execute('mkdir /var/vmail');
  Execute('chmod 770 /var/vmail');
  Execute('chown vmail:mail /var/vmail');
}

function UpdateDovecotConfigFile($FileName, $Parameters)
{
  if(!file_exists($FileName.'_backup'))
    file_put_contents($FileName.'_backup', file_get_contents($FileName));    
  $Content = explode("\n", file_get_contents($FileName.'_backup'));
  foreach($Parameters as $Parameter)
  { 
    if(!is_array($Parameter['name'])) 
      $Parameter['name'] = array($Parameter['name']);
    // First find subgroup
    $Num = 0;
    $NestingLevel = 0;
    while(count($Parameter['name']) > 1)  
    {
      $Found = false;
      $Needle = '#'.array_values($Parameter['name'])[0].' {';
      $I = 0;
      $StartNestingLevel = $NestingLevel;     
      while((($Num + $I) < count($Content)) and ($NestingLevel >= $StartNestingLevel)) 
      {
        if(substr(trim($Content[$Num + $I]), -1, 1) == '{') $NestingLevel++;
        if(substr(trim($Content[$Num + $I]), -1, 1) == '}') $NestingLevel--;
        if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle)
        or (trim(substr(trim($Content[$Num + $I]), 0, strlen(substr($Needle, 1)))) == substr($Needle, 1)))
        {
          $Content[$Num + $I] = array_values($Parameter['name'])[0].' {';
          $Num = $Num + $I + 1;
          $Found = true;
          echo('Found group: '.array_values($Parameter['name'])[0]."\n");
          array_shift($Parameter['name']);
          break;
        }
        $I++;
      }
      if(!$Found) break;
    } 
    // Find and replace value
    if(count($Parameter['name']) == 1)
    {
      if(!array_key_exists('value', $Parameter)) 
      {
        $Needle = array_values($Parameter['name'])[0];      
        $Parameter['value'] = '';
      } else 
        $Needle = array_values($Parameter['name'])[0]." =";      
      $I = 0;
      $StartNestingLevel = $NestingLevel;
      $Found = false;
      while((($Num + $I) < count($Content)) and ($NestingLevel >= $StartNestingLevel))
      {
        if(substr(trim($Content[$Num + $I]), -1, 1) == '{') $NestingLevel++;
        if(substr(trim($Content[$Num + $I]), -1, 1) == '}')
        {
          if($NestingLevel == $StartNestingLevel) $Content[$Num + $I] = '}';
          $NestingLevel--;
        }
        if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle)
        or ((substr(trim($Content[$Num + $I]), 0, 1) == '#') and (substr(trim(substr(trim($Content[$Num + $I]), 1)), 0, strlen($Needle)) == $Needle)))
        {
          echo('Found: '.array_values($Parameter['name'])[0]."\n");
          $Content[$Num + $I] = $Needle.' '.$Parameter['value'];
          $Found = true;
          break;
        }
        $I++;
      }
      // If not found then add new value
      if($Found == false)
      {
        echo('Added new: '.array_values($Parameter['name'])[0]."\n");
        array_splice($Content, $Num + $I - 1, 0, $Needle.' '.$Parameter['value']);
      }
    }
  }
  file_put_contents($FileName, implode("\n", $Content));
}

function ConfigureDovecot()
{
  global $MysqlUserPassword, $DomainName;
  
  UpdateDovecotConfigFile('/etc/dovecot/dovecot-sql.conf.ext', array(
    array('name' => 'driver', 'value' => 'mysql'),
    array('name' => 'connect', 'value' => 'host=localhost dbname=mail user=mail password='.$MysqlUserPassword),
    array('name' => 'default_pass_scheme', 'value' => 'MD5-CRYPT'),
    array('name' => 'password_query', 'value' => "SELECT username as user, password, '/var/vmail/%d/%n' as userdb_home, \\
  'maildir:/var/vmail/%d/%n' as userdb_mail, 150 as userdb_uid, 8 as userdb_gid \\
  FROM mailbox WHERE username = '%u' AND active = '1'"),
    array('name' => 'user_query', 'value' => "SELECT '/var/vmail/%d/%n' as home, 'maildir:/var/vmail/%d/%n' as mail, \\
  150 AS uid, 8 AS gid, concat('dirsize:storage=', quota) AS quota \\
  FROM mailbox WHERE username = '%u' AND active = '1'"),
  ));
  UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-auth.conf', array(
    array('name' => 'disable_plaintext_auth', 'value' => 'yes'),
    array('name' => 'auth_mechanisms', 'value' => 'plain login'),
    array('name' => '!include auth-sql.conf.ext'),
  ));
  UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-mail.conf', array(
    array('name' => 'mail_location', 'value' => 'maildir:/var/vmail/%d/%n'),
    array('name' => 'mail_uid', 'value' => 'vmail'),
    array('name' => 'mail_gid', 'value' => 'mail'),
    array('name' => 'first_valid_uid', 'value' => '150'),
    array('name' => 'last_valid_uid', 'value' => '150'),
  ));
  UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-ssl.conf', array(
    array('name' => 'ssl_cert', 'value' => '</etc/ssl/certs/'.$DomainName.'.crt'),
    array('name' => 'ssl_key', 'value' => '</etc/ssl/private/'.$DomainName.'.key'),
    array('name' => 'ssl_ca', 'value' => '</etc/ssl/certs/ca-bundle.crt'),
    array('name' => 'ssl_cipher_list', 'value' => 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'),
  ));
  UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-master.conf', array(
    array('name' => array('service auth', 'unix_listener auth-userdb', 'mode'), 'value' => '0666'),
    array('name' => array('service auth', 'unix_listener auth-userdb', 'user'), 'value' => 'vmail'),
    array('name' => array('service auth', 'unix_listener auth-userdb', 'group'), 'value' => 'mail'),
    array('name' => array('service auth', 'unix_listener /var/spool/postfix/private/auth', 'mode'), 'value' => '0666'),
    array('name' => array('service auth', 'unix_listener /var/spool/postfix/private/auth', 'user'), 'value' => 'postfix'),
    array('name' => array('service auth', 'unix_listener /var/spool/postfix/private/auth', 'group'), 'value' => 'postfix'),
  ));
  UpdateDovecotConfigFile('/etc/dovecot/conf.d/15-lda.conf', array(
    array('name' => 'postmaster_address', 'value' => 'postmaster@'.$DomainName),
  ));
  
  Execute('chown -R vmail:dovecot /etc/dovecot');
  Execute('chmod -R o-rwx /etc/dovecot');
}

function UpdateAmavisConfigFile($FileName, $Parameters)
{
  if(!file_exists($FileName.'_backup'))
    file_put_contents($FileName.'_backup', file_get_contents($FileName));    
  $Content = explode("\n", file_get_contents($FileName.'_backup'));
  if(count($Content) > 0)
  {
    // Remove ending part
    $I = count($Content) - 1;
    while(($I >= 0))
    {  
      if($Content[$I] != '#------------ Do not modify anything below this line -------------')
        array_pop($Content);
        else {
          array_pop($Content);
          break;
        }
      $I--;
    }
  }
  
  foreach($Parameters as $Parameter)
  { 
    $Parameter['name'] = array($Parameter['name']);
    $Num = 0;
    if(!array_key_exists('value', $Parameter)) 
    {
      $Needle = array_values($Parameter['name'])[0];      
      $Parameter['value'] = '';
    } else 
      $Needle = array_values($Parameter['name'])[0]." =";      
    $I = 0;
    $Found = false;
    while((($Num + $I) < count($Content)))
    {
      if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle)
      or ((substr(trim($Content[$Num + $I]), 0, 1) == '#') and (substr(trim(substr(trim($Content[$Num + $I]), 1)), 0, strlen($Needle)) == $Needle)))
      {
        echo('Found: '.array_values($Parameter['name'])[0]."\n");
        $Content[$Num + $I] = $Needle.' '.$Parameter['value'];
        $Found = true;
        break;
      }
      $I++;
    }
    // If not found then add new value
    if($Found == false)
    {
      echo('Added new: '.array_values($Parameter['name'])[0]."\n");
      array_splice($Content, $Num + $I - 1, 0, $Needle.' '.$Parameter['value']);
    }  
  }
  $Content[] = '#------------ Do not modify anything below this line -------------';
  $Content[] = '1;  # ensure a defined return';
  file_put_contents($FileName, implode("\n", $Content));
}

function UpdateDefaultConfigFile($FileName, $Parameters)
{
  if(!file_exists($FileName.'_backup'))
    file_put_contents($FileName.'_backup', file_get_contents($FileName));    
  $Content = explode("\n", file_get_contents($FileName.'_backup'));
  foreach($Parameters as $Parameter)
  { 
    if(!is_array($Parameter['name'])) 
      $Parameter['name'] = array($Parameter['name']);
    $Num = 0;
    // Find and replace value
    if(count($Parameter['name']) == 1)
    {
      if(!array_key_exists('value', $Parameter)) 
      {
        $Needle = array_values($Parameter['name'])[0];      
        $Parameter['value'] = '';
      } else 
        $Needle = array_values($Parameter['name'])[0]."=";
      $I = 0;
      $Found = false;
      while((($Num + $I) < count($Content)))
      {
        if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle)
        or ((substr(trim($Content[$Num + $I]), 0, 1) == '#') and (substr(trim(substr(trim($Content[$Num + $I]), 1)), 0, strlen($Needle)) == $Needle)))
        {
          echo('Found: '.array_values($Parameter['name'])[0]."\n");
          $Content[$Num + $I] = $Needle.$Parameter['value'];
          $Found = true;
          break;
        }
        $I++;
      }
      // If not found then add new value
      if($Found == false)
      {
        echo('Added new: '.array_values($Parameter['name'])[0]."\n");
        array_splice($Content, $Num + $I - 1, 0, $Needle.' '.$Parameter['value']);
      }
    }
  }
  file_put_contents($FileName, implode("\n", $Content));  
}

function SpamVirus()
{
  Execute('adduser clamav amavis');
  Execute('adduser amavis clamav');
  UpdateAmavisConfigFile('/etc/amavis/conf.d/15-content_filter_mode', array(
    array('name' => '@bypass_virus_checks_maps', 'value' => '(\%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);'),
    array('name' => '@bypass_spam_checks_maps', 'value' => '(\%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);'),
  ));
  UpdateDefaultConfigFile('/etc/default/spamassassin', array(
    array('name' => 'ENABLED', 'value' => '1'),
    array('name' => 'CRON', 'value' => '1'),
  ));
  UpdateAmavisConfigFile('/etc/amavis/conf.d/50-user', array(
    array('name' => '$max_servers', 'value' => '3;'),
    array('name' => '$sa_tag_level_deflt', 'value' => '-9999;'),
    array('name' => '@lookup_sql_dsn', 'value' => "(
    ['DBI:mysql:database=mail;host=127.0.0.1;port=3306',
     'mail',
     'mailpassword']);"),     
    array('name' => '$sql_select_policy', 'value' => "'SELECT domain from domain WHERE CONCAT(\"@\",domain) IN (%k)';"),
  ));
  Execute('freshclam');
  Execute('service clamav-daemon restart');
  Execute('service amavis restart');
  Execute('service spamassassin restart');  
}

function ConfigurePostfix()
{
  file_put_contents('/etc/postfix/mysql_virtual_alias_domainaliases_maps.cf', 
  "user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
query = SELECT goto FROM alias,alias_domain
  WHERE alias_domain.alias_domain = '%d'
  AND alias.address=concat('%u', '@', alias_domain.target_domain)
  AND alias.active = 1");
  file_put_contents('/etc/postfix/mysql_virtual_alias_maps.cf', 
  "user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
table = alias
select_field = goto
where_field = address
additional_conditions = and active = '1'");
  file_put_contents('/etc/postfix/mysql_virtual_domains_maps.cf', 
  "user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
table = domain
select_field = domain
where_field = domain
additional_conditions = and backupmx = '0' and active = '1'");
  file_put_contents('/etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf',
  "user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
query = SELECT maildir FROM mailbox, alias_domain
  WHERE alias_domain.alias_domain = '%d'
  AND mailbox.username=concat('%u', '@', alias_domain.target_domain )
  AND mailbox.active = 1");
  file_put_contents('/etc/postfix/mysql_virtual_mailbox_maps.cf',
  "user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
table = mailbox
select_field = CONCAT(domain, '/', local_part)
where_field = username
additional_conditions = and active = '1'");
  file_put_contents('/etc/postfix/header_checks',
  "/^Received:/                 IGNORE
/^User-Agent:/               IGNORE
/^X-Mailer:/                 IGNORE
/^X-Originating-IP:/         IGNORE
/^x-cr-[a-z]*:/              IGNORE
/^Thread-Index:/     
        IGNORE");
  if(!file_exists('/etc/postfix/main.cf_backup'))
    file_put_contents('/etc/postfix/main.cf_backup', file_get_contents('/etc/postfix/main.cf'));
  file_put_contents('/etc/postfix/main.cf',
  '# See /usr/share/postfix/main.cf.dist for a commented, more complete version
 
# The first text sent to a connecting process.
smtpd_banner = $myhostname ESMTP $mail_name
biff = no
# appending .domain is the MUA\'s job.
append_dot_mydomain = no
readme_directory = no
 
# SASL parameters
# ---------------------------------
 
# Use Dovecot to authenticate.
smtpd_sasl_type = dovecot
# Referring to /var/spool/postfix/private/auth
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =
smtpd_sasl_authenticated_header = yes
 
# TLS parameters
# ---------------------------------
 
# The default snakeoil certificate. Comment if using a purchased
# SSL certificate.
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
 
# Uncomment if using a purchased SSL certificate.
# smtpd_tls_cert_file=/etc/ssl/certs/example.com.crt
# smtpd_tls_key_file=/etc/ssl/private/example.com.key
 
# The snakeoil self-signed certificate has no need for a CA file. But
# if you are using your own SSL certificate, then you probably have
# a CA certificate bundle from your provider. The path to that goes
# here.
# smtpd_tls_CAfile=/etc/ssl/certs/ca-bundle.crt
 
# Ensure we\'re not using no-longer-secure protocols.
smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
 
smtp_tls_note_starttls_offer = yes
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom
#smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
#smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
 
# Note that forcing use of TLS is going to cause breakage - most mail servers
# don\'t offer it and so delivery will fail, both incoming and outgoing. This is
# unfortunate given what various governmental agencies are up to these days.
#
# Enable (but don\'t force) all incoming smtp connections to use TLS.
smtpd_tls_security_level = may
# Enable (but don\'t force) all outgoing smtp connections to use TLS.
smtp_tls_security_level = may
 
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
 
# SMTPD parameters
# ---------------------------------
 
# Uncomment the next line to generate \"delayed mail\" warnings
#delay_warning_time = 4h
# will it be a permanent error or temporary
unknown_local_recipient_reject_code = 450
# how long to keep message on queue before return as failed.
# some have 3 days, I have 16 days as I am backup server for some people
# whom go on holiday with their server switched off.
maximal_queue_lifetime = 7d
# max and min time in seconds between retries if connection failed
minimal_backoff_time = 1000s
maximal_backoff_time = 8000s
# how long to wait when servers connect before receiving rest of data
smtp_helo_timeout = 60s
# how many address can be used in one message.
# effective stopper to mass spammers, accidental copy in whole address list
# but may restrict intentional mail shots.
smtpd_recipient_limit = 16
# how many error before back off.
smtpd_soft_error_limit = 3
# how many max errors before blocking it.
smtpd_hard_error_limit = 12
 
# This next set are important for determining who can send mail and relay mail
# to other servers. It is very important to get this right - accidentally producing
# an open relay that allows unauthenticated sending of mail is a Very Bad Thing.
#
# You are encouraged to read up on what exactly each of these options accomplish.
 
# Requirements for the HELO statement
smtpd_helo_restrictions = permit_mynetworks, warn_if_reject reject_non_fqdn_hostname, reject_invalid_hostname, permit
# Requirements for the sender details
smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks, warn_if_reject reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining, permit
# Requirements for the connecting server
smtpd_client_restrictions = reject_rbl_client sbl.spamhaus.org, reject_rbl_client blackholes.easynet.nl, reject_rbl_client dnsbl.njabl.org
# Requirement for the recipient address. Note that the entry for
# \"check_policy_service inet:127.0.0.1:10023\" enables Postgrey.
smtpd_recipient_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, check_policy_service inet:127.0.0.1:10023, permit
smtpd_data_restrictions = reject_unauth_pipelining
# This is a new option as of Postfix 2.10, and is required in addition to
# smtpd_recipient_restrictions for things to work properly in this setup.
smtpd_relay_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, check_policy_service inet:127.0.0.1:10023, permit
 
# require proper helo at connections
smtpd_helo_required = yes
# waste spammers time before rejecting them
smtpd_delay_reject = yes
disable_vrfy_command = yes
 
# General host and delivery info
# ----------------------------------
 
myhostname = mail.example.com
myorigin = /etc/hostname
# Some people see issues when setting mydestination explicitly to the server
# subdomain, while leaving it empty generally doesn\'t hurt. So it is left empty here.
# mydestination = mail.example.com, localhost
mydestination =
# If you have a separate web server that sends outgoing mail through this
# mailserver, you may want to add its IP address to the space-delimited list in
# mynetworks, e.g. as 10.10.10.10/32.
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
mynetworks_style = host
 
# This specifies where the virtual mailbox folders will be located.
virtual_mailbox_base = /var/vmail
# This is for the mailbox location for each user. The domainaliases
# map allows us to make use of Postfix Admin\'s domain alias feature.
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf, mysql:/etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf
# and their user id
virtual_uid_maps = static:150
# and group id
virtual_gid_maps = static:8
# This is for aliases. The domainaliases map allows us to make
# use of Postfix Admin\'s domain alias feature.
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf, mysql:/etc/postfix/mysql_virtual_alias_domainaliases_maps.cf
# This is for domain lookups.
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
 
# Integration with other packages
# ---------------------------------------
 
# Tell postfix to hand off mail to the definition for dovecot in master.cf
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1
 
# Use amavis for virus and spam scanning
content_filter = amavis:[127.0.0.1]:10024
 
# Header manipulation
# --------------------------------------
 
# Getting rid of unwanted headers. See: https://posluns.com/guides/header-removal/
header_checks = regexp:/etc/postfix/header_checks
# getting rid of x-original-to
enable_original_recipient = no');

  if(!file_exists('/etc/postfix/master.cf_backup'))
    file_put_contents('/etc/postfix/master.cf_backup', file_get_contents('/etc/postfix/master.cf'));
  file_put_contents('/etc/postfix/master.cf', 
  '#
# Postfix master process configuration file.  For details on the format
# of the file, see the master(5) manual page (command: \"man 5 master\").
#
# Do not forget to execute \"postfix reload\" after editing this file.
#
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
 
# SMTP on port 25, unencrypted.
smtp      inet  n       -       -       -       -       smtpd
#smtp      inet  n       -       -       -       1       postscreen
#smtpd     pass  -       -       -       -       -       smtpd
#dnsblog   unix  -       -       -       -       0       dnsblog
#tlsproxy  unix  -       -       -       -       0       tlsproxy
 
# SMTP with TLS on port 587. Currently commented.
#submission inet n       -       -       -       -       smtpd
#  -o syslog_name=postfix/submission
#  -o smtpd_tls_security_level=encrypt
#  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_enforce_tls=yes
#  -o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject
#  -o smtpd_sasl_tls_security_options=noanonymous
 
# SMTP over SSL on port 465.
smtps     inet  n       -       -       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_tls_auth_only=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject
  -o smtpd_sasl_security_options=noanonymous,noplaintext
  -o smtpd_sasl_tls_security_options=noanonymous
 
#628       inet  n       -       -       -       -       qmqpd
pickup    fifo  n       -       -       60      1       pickup
  -o content_filter=
  -o receive_override_options=no_header_body_checks
cleanup   unix  n       -       -       -       0       cleanup
qmgr      fifo  n       -       n       300     1       qmgr
#qmgr     fifo  n       -       n       300     1       oqmgr
tlsmgr    unix  -       -       -       1000?   1       tlsmgr
rewrite   unix  -       -       -       -       -       trivial-rewrite
bounce    unix  -       -       -       -       0       bounce
defer     unix  -       -       -       -       0       bounce
trace     unix  -       -       -       -       0       bounce
verify    unix  -       -       -       -       1       verify
flush     unix  n       -       -       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       -       -       -       smtp
relay     unix  -       -       -       -       -       smtp
#       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq     unix  n       -       -       -       -       showq
error     unix  -       -       -       -       -       error
retry     unix  -       -       -       -       -       error
discard   unix  -       -       -       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       -       -       -       lmtp
anvil     unix  -       -       -       -       1       anvil
scache    unix  -       -       -       -       1       scache
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
#
# Many of the following services use the Postfix pipe(8) delivery
# agent.  See the pipe(8) man page for information about ${recipient}
# and other message envelope options.
# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
maildrop  unix  -       n       n       -       -       pipe
  flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
#
# ====================================================================
#
# Recent Cyrus versions can use the existing \"lmtp\" master.cf entry.
#
# Specify in cyrus.conf:
#   lmtp    cmd=\"lmtpd -a\" listen=\"localhost:lmtp\" proto=tcp4
#
# Specify in main.cf one or more of the following:
#  mailbox_transport = lmtp:inet:localhost
#  virtual_transport = lmtp:inet:localhost
#
# ====================================================================
#
# Cyrus 2.1.5 (Amos Gouaux)
# Also specify in main.cf: cyrus_destination_recipient_limit=1
#
#cyrus     unix  -       n       n       -       -       pipe
#  user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
#
# ====================================================================
# Old example of delivery via Cyrus.
#
#old-cyrus unix  -       n       n       -       -       pipe
#  flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
#
# ====================================================================
#
# See the Postfix UUCP_README file for configuration details.
#
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
#
# Other external delivery methods.
#/var/www/html/.htaccess
ifmail    unix  -       n       n       -       -       pipe
  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp     unix  -       n       n       -       -       pipe
  flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix  -       n       n       -       2       pipe
  flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman   unix  -       n       n       -       -       pipe
  flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
  ${nexthop} ${user}
 
# The next two entries integrate with Amavis for anti-virus/spam checks.
amavis      unix    -       -       -       -       3       smtp
  -o smtp_data_done_timeout=1200
  -o smtp_send_xforward_command=yes
  -o disable_dns_lookups=yes
  -o max_use=20
127.0.0.1:10025 inet    n       -       -       -       -       smtpd
  -o content_filter=
  -o local_recipient_maps=
  -o relay_recipient_maps=
  -o smtpd_restriction_classes=
  -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 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
 
# Integration with Dovecot - hand mail over to it for local delivery, and
# run the process under the vmail user and mail group.
dovecot      unix   -        n      n       -       -   pipe
  flags=DRhu user=vmail:mail argv=/usr/lib/dovecot/dovecot-lda -d $(recipient)');
}

function RestartAll()
{
  Execute('service postfix restart');
  Execute('service spamassassin restart');
  Execute('service clamav-daemon restart');
  Execute('service amavis restart');
  Execute('service dovecot restart');
}

function InstallRoundCube()
{
  Execute('apt-get install --assume-yes \
  roundcube \
  roundcube-plugins \
  roundcube-plugins-extra');
  UpdatePHPConfigFile('/etc/roundcube/main.inc.php', 'rcmail_config', array(
    array('name' => 'default_host', 'value' => "'localhost'"),
    array('name' => 'force_https', 'value' => 'true'),
    array('name' => 'imap_cache', 'value' => "'memcache'"),
    array('name' => 'session_storage', 'value' => "'memcache'"),
    array('name' => 'memcache_hosts', 'value' => "array('localhost:11211')"),
  ));
  Execute('ln -s /var/lib/roundcube /var/www/html/roundcube');
  if(file_exists('/var/www/html/index.html'))
    Execute('mv /var/www/html/index.html /var/www/html/index.bak.html');
  file_put_contents('/var/www/html/.htaccess', 'RewriteEngine On
 
# Redirect all HTTP traffic to HTTPS.
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
 
# Send / to /roundcube.
RewriteRule ^/?$ /roundcube [L]');
}

function InstallMonit()
{
  Execute('apt-get install --assume-yes monit');
  file_put_contents('/etc/monit/conf.d/amavis', 
  'check process amavisd with pidfile /var/run/amavis/amavisd.pid
  every 5 cycles
  group mail
  start program = "/etc/init.d/amavis start"
  stop  program = "/etc/init.d/amavis stop"
  if failed port 10024 protocol smtp then restart
  if 5 restarts within 25 cycles then timeout');
  file_put_contents('/etc/monit/conf.d/apache2', 
  'check process apache2 with pidfile /var/run/apache2/apache2.pid
  group www
  start program = "/etc/init.d/apache2 start"
  stop program = "/etc/init.d/apache2 stop"
  if failed host localhost port 80 protocol http
    with timeout 10 seconds
    then restart
  if 5 restarts within 5 cycles then timeout');
  file_put_contents('/etc/monit/conf.d/dovecot',
  'check process dovecot with pidfile /var/run/dovecot/master.pid
  group mail
  start program = "/sbin/start dovecot"
  stop program = "/sbin/stop dovecot"
  group mail
  # We\'d like to use this line, but see:
  # http://serverfault.com/questions/610976/monit-failing-to-connect-to-dovecot-over-ssl-imap
  #if failed port 993 type tcpssl sslauto protocol imap for 5 cycles then restart
  if failed port 993 for 5 cycles then restart
  if 5 restarts within 25 cycles then timeout');
  file_put_contents('/etc/monit/conf.d/mysql',
  'check process mysqld with pidfile /var/run/mysqld/mysqld.pid
  group database
  start program = "/etc/init.d/mysql start"
  stop program = "/etc/init.d/mysql stop"
  if failed host localhost port 3306 protocol mysql then restart
  if 5 restarts within 5 cycles then timeout');
  file_put_contents('/etc/monit/conf.d/memcached',
  'check process memcached with pidfile /var/run/memcached.pid
  group www
  start program = "/etc/init.d/memcached start"
  stop program = "/etc/init.d/memcached stop"
  if failed host localhost port 11211 then restart
  if 5 restarts within 5 cycles then timeout');
  file_put_contents('/etc/monit/conf.d/postfix',
  'check process postfix with pidfile /var/spool/postfix/pid/master.pid
  group mail
  start program = "/etc/init.d/postfix start"
  stop  program = "/etc/init.d/postfix stop"
  if failed port 25 protocol smtp then restart
  if 5 restarts within 5 cycles then timeout');
  file_put_contents('/etc/monit/conf.d/spamassassin',
  'check process spamassassin with pidfile /var/run/spamd.pid
  group mail
  start program = "/etc/init.d/spamassassin start"
  stop  program = "/etc/init.d/spamassassin stop"
  if 5 restarts within 5 cycles then timeout');
  file_put_contents('/etc/monit/conf.d/sshd',
  'check process sshd with pidfile /var/run/sshd.pid
  start program "/etc/init.d/ssh start"
  stop program "/etc/init.d/ssh stop"
  if failed host 127.0.0.1 port 22 protocol ssh then restart
   if 5 restarts within 5 cycles then timeout');
  Execute('service monit restart');
}

InstallPackages();
PrepareDatabase();
InstallPostfixAdmin();
VirtualMailUser();
ConfigureDovecot();
SpamVirus();
ConfigurePostfix();
RestartAll();
InstallMonit();
InstallRoundCube();


Vnější odkazy