Nastavení mail serveru: Porovnání verzí
Skočit na navigaci
Skočit na vyhledávání
Bez shrnutí editace |
Bez shrnutí editace |
||
Řádek 956: | Řádek 956: | ||
* [https://wiki.archlinux.org/index.php/Virtual_user_mail_system Virtual user mail system] |
* [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]] |
Verze z 12. 12. 2016, 22:04
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();