Add mail roles

This commit is contained in:
Joshua Boniface 2020-11-21 20:22:14 -05:00
parent fe3b41e057
commit d01e99c3da
47 changed files with 1710 additions and 0 deletions

View File

@ -0,0 +1,37 @@
---
# Default configurations
# I populate these from external configs; I indicate what they are as inline comments
domain: "{{ blsedomains_admindomain }}" # Base domain name
postmaster: "root@{{ blsedomains_rootdomain }}" # Postmaster email address
# Roundcube
smtp_host: "{{ blsecluster_smtphost }}" # The hostname for SMTP access, usually the public name of your mail server
support_url: "https://www.{{ blsedomains_webdomain }}" # Some website address for Roundcube support
logo_filename: "bl-logo-roundcube.png" # The Roundcube logo under files/
roundcube_deskey: "{{ passwd_roundcube_deskey }}" # The Roundcube DES key
# Postfix
banner_hostname: "{{ ansible_hostname }}.{{ domain }}" # Public hostname of *this* mail host
myhostname: "{{ banner_hostname }}" # Hostname for Postfix myhostame
mydomain: "{{ domain }}" # Domain for Postfix mydomain
mynetworks: "{{ blsecluster_remote1v4 }} {{ blsecluster_remote2v4 }} {{ blsecluster_remote3v4 }} {{ blsecluster_hostsubnetv4 }}" # IP addresses for Postfix mynetworks
# Dovecot
# Note: SSL listeners aren't provided; HAProxy is expected to do SSL termination for us
trusted_networks: "{{ blsecluster_hostsubnetv4 }} {{ blsecluster_hostsubnetv6 }}" # Trusted network ranges for Dovecot
haproxy: yes # Enable HAProxy-specific (Proxy protocol) listeners on ports 10143 and 10110
# LDAP integration (Postfix, Dovecot, Roundcube)
ldap_host: "{{ blsecluster_ldaphost }}" # The hostname for LDAP access
ldap_port: 389 # The LDAP port (always non-SSL)
ldap_basedn: "o=domains,dc=bonilan,dc=net" # The LDAP base DN
ldap_bind_username: "{{ username_ldap_admin }}" # The LDAP bind user name (usually cn=admin)
ldap_bind_password: "{{ passwd_ldap_admin }}" # The LDAP bind user password
# MySQL integration (Roundcube)
mysql_host: "{{ blsecluster_sqlhost }}" # The hostname for MySQL access
mysql_port: "{{ mysql_client['mail'].port }}" # The port for MySQL access
mysql_database: "{{ mysql_client['mail'].database }}" # The database name
mysql_username: "{{ mysql_client['mail'].username }}" # The database user
mysql_password: "{{ mysql_client['mail'].passwd }}" # The database password

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -0,0 +1,23 @@
---
- name: postmap transport
command: "postmap /etc/postfix/transport"
- name: restart amavis
service:
name: "amavis"
state: "restarted"
- name: restart saslauthd
service:
name: "saslauthd"
state: "restarted"
- name: restart postfix
service:
name: "postfix"
state: "restarted"
- name: restart dovecot
service:
name: "dovecot"
state: "restarted"
- name: restart apache2
service:
name: "apache2"
state: "restarted"

View File

@ -0,0 +1,222 @@
---
- name: install filtering packages and monitoring components
apt:
name:
- postfix
- postfix-ldap
- postfix-pcre
- dovecot-core
- dovecot-imapd
- dovecot-pop3d
- dovecot-lmtpd
- dovecot-sieve
- dovecot-managesieved
- dovecot-ldap
- dovecot-mysql
- apache2
- libapache2-mod-php
- roundcube
- roundcube-plugins
- php-ldap
- php-net-sieve
- mailgraph
- amavis
- spamassassin
- clamav-daemon
- libnet-dns-perl
- libmail-spf-perl
- pyzor
- razor
- pfqueue
state: latest
- name: install compression algorithms for scanning
apt:
name:
- p7zip-full
- arj
- bzip2
- cabextract
- cpio
- file
- gzip
- lhasa
- liblz4-tool
- lrzip
- lzop
- nomarch
- pax
- rar
- rpm
- unrar-free
- unzip
- xz-utils
- zip
state: latest
# ClamAV
- name: ensure clamav is in amavis group
user:
name: "clamav"
append: "yes"
groups: "amavis"
- name: ensure amavis is in clamav group
user:
name: "amavis"
append: "yes"
groups: "clamav"
# Amavis
- name: install Amavis configs
template:
src: "{{ item }}.j2"
dest: "/etc/amavis/conf.d/{{ item }}"
notify:
- restart amavis
with_items:
- 15-content_filter_mode
- 50-user
# Postfix
- name: install Postfix main configs
template:
src: "{{ item }}.j2"
dest: "/etc/postfix/{{ item }}"
notify:
- restart postfix
with_items:
- main.cf
- master.cf
- helo_access.pcre
- transport
- name: map transport
command: postmap /etc/postfix/transport
- name: create LDAP config dir
file:
name: "/etc/postfix/ldap"
state: "directory"
- name: install Postfix LDAP configs
template:
src: "postfix-ldap/{{ item }}.j2"
dest: "/etc/postfix/ldap/{{ item }}"
mode: "640"
group: "postfix"
notify:
- restart postfix
with_items:
- catchall_maps.cf
- recipient_bcc_maps_domain.cf
- recipient_bcc_maps_user.cf
- relay_domains.cf
- sender_bcc_maps_domain.cf
- sender_bcc_maps_user.cf
- sender_login_maps.cf
- transport_maps_domain.cf
- transport_maps_user.cf
- virtual_alias_maps.cf
- virtual_group_maps.cf
- virtual_group_members_maps.cf
- virtual_mailbox_domains.cf
- virtual_mailbox_maps.cf
- name: link /etc/mailname to /etc/hostname
file:
dest: "/etc/mailname"
src: "/etc/hostname"
state: "link"
force: "yes"
# Dovecot
- name: install Dovecot main configs
template:
src: "{{ item }}.j2"
dest: "/etc/dovecot/{{ item }}"
notify:
- restart dovecot
with_items:
- dovecot.conf
- dovecot-ldap.conf
- name: add vmail group
group:
name: "vmail"
gid: "2000"
state: "present"
- name: add vmail user
user:
name: "vmail"
home: "/srv/vmail"
shell: "/bin/false"
uid: "2000"
group: "vmail"
state: "present"
- name: ensure log ownership
file:
dest: "/var/log/{{ item }}"
owner: "vmail"
group: "adm"
mode: "644"
state: "touch"
with_items:
- dovecot.log
- dovecot-lmtp.log
# Roundcube
- name: Install roundcube PHP configs
template:
src: "{{ item }}.j2"
dest: "/etc/roundcube/{{ item }}"
mode: "640"
group: "www-data"
with_items:
- debian-db.php
- config.inc.php
- name: Remove default apache2 config
file:
name: "/etc/apache2/sites-enabled/000-default.conf"
state: "absent"
notify:
- restart apache2
- name: Install roundcube ports config
template:
src: "ports.conf.j2"
dest: "/etc/apache2/ports.conf"
notify:
- restart apache2
- name: Install roundcube apache2 config
template:
src: "roundcube.conf.j2"
dest: "/etc/roundcube/apache.conf"
notify:
- restart apache2
- name: create logo dir
file:
dest: "/var/lib/roundcube/images"
state: "directory"
- name: install Roundcube logo
copy:
src: "{{ logo_filename }}"
dest: "/var/lib/roundcube/images/{{ logo_filename }}"
# General
- name: ensure services are running (and enabled at boot)
service:
name: "{{ item }}"
state: "started"
enabled: "yes"
with_items:
- postfix
- amavis
- clamav-daemon
- dovecot

View File

@ -0,0 +1,12 @@
use strict;
# Amavis filter configuration
# {{ ansible_managed }}
@bypass_virus_checks_maps = (
\%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
@bypass_spam_checks_maps = (
\%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);
1; # ensure a defined return

View File

@ -0,0 +1,12 @@
use strict;
@local_domains_acl = ( "." );
$sa_tag_level_deflt = -9999;
$sa_tag2_level_deflt = 4.5;
$sa_kill_level_deflt = 4.5;
$sa_spam_subject_tag = '*** SPAM *** ';
$forward_method = 'smtp:[::1]:10025';
#------------ Do not modify anything below this line -------------
1; # ensure a defined return

View File

@ -0,0 +1,111 @@
<?php
/* Local configuration for Roundcube Webmail */
/* {{ ansible_managed }} */
$config['imap_auth_type'] = 'LOGIN';
$config['imap_delimiter'] = '/';
// ----------------------------------
// SMTP
// ----------------------------------
$config['smtp_server'] = '{{ smtp_host }}';
$config['smtp_auth_type'] = 'LOGIN';
$config['support_url'] = '{{ support_url }}';
array(
"elastic:login[small]" => "/images/logo_login_small.png",
"elastic:login" => "/images/logo_login.png",
"elastic:*[small]" => "/images/logo_small.png",
"larry:*" => "/images/larry.png",
"login" => "/images/logo_login.png",
"[print]" => "/images/logo_print.png",
);
$config['skin_logo'] = 'images/{{ logo_filename }}';
$config['des_key'] = '{{ roundcube_deskey }}';
// ----------------------------------
// PLUGINS
// ----------------------------------
$config['plugins'] = array('managesieve');
$config['create_default_folders'] = true;
$config['quota_zero_as_unlimited'] = true;
$config['ldap_public'] = array (
'global_ldap_abook' =>
array (
'name' => 'Global LDAP Address Book',
'hosts' =>
array (
0 => '{{ ldap_host }}',
),
'port' => {{ ldap_port }},
'use_tls' => false,
'ldap_version' => '3',
'network_timeout' => 10,
'user_specific' => true,
'base_dn' => '{{ ldap_basedn }}',
'bind_dn' => 'mail=%u@%d,ou=Users,domainName=%d,{{ ldap_basedn }}',
'hidden' => false,
'searchonly' => false,
'writable' => false,
'search_fields' =>
array (
0 => 'mail',
1 => 'cn',
2 => 'sn',
3 => 'givenName',
4 => 'street',
5 => 'telephoneNumber',
6 => 'mobile',
7 => 'stree',
8 => 'postalCode',
),
'fieldmap' =>
array (
'name' => 'cn',
'surname' => 'sn',
'firstname' => 'givenName',
'title' => 'title',
'email' => 'mail:*',
'phone:work' => 'telephoneNumber',
'phone:mobile' => 'mobile',
'street' => 'street',
'zipcode' => 'postalCode',
'locality' => 'l',
'department' => 'departmentNumber',
'notes' => 'description',
'phone:workfax' => 'facsimileTelephoneNumber',
'photo' => 'jpegPhoto',
),
'sort' => 'cn',
'scope' => 'sub',
'filter' => '(&(enabledService=mail)(enabledService=deliver)(enabledService=displayedInGlobalAddressBook)(|(objectClass=mailList)(objectClass=mailAlias)(objectClass=mailUser)))',
'fuzzy_search' => true,
'vlv' => false,
'sizelimit' => '0',
'timelimit' => '0',
'referrals' => false,
'group_filters' =>
array (
'departments' =>
array (
'name' => 'Mailing Lists',
'scope' => 'sub',
'base_dn' => '{{ ldap_basedn }}',
'filter' => '(&(objectclass=mailList)(accountStatus=active)(enabledService=displayedInGlobalAddressBook))',
'name_attr' => 'cn',
'email' => 'mail',
),
),
),
);
$config['autocomplete_addressbooks'] = array('sql', 'global_ldap_abook');
$config['skin'] = 'elastic';
$config['addressbook_sort_col'] = 'name';
$config['draft_autosave'] = 60;
$config['check_all_folders'] = true;
$config['autoexpand_threads'] = 2;
include_once("/etc/roundcube/debian-db-roundcube.php");

View File

@ -0,0 +1,9 @@
<?php
/* {{ ansible_managed }} */
$dbuser='{{ mysql_username }}';
$dbpass='{{ mysql_password }}';
$basepath='';
$dbname='{{ mysql_database }}';
$dbserver='{{ mysql_host }}';
$dbport='{{ mysql_port }}';
$dbtype='mysql';

View File

@ -0,0 +1,21 @@
# Dovecot LDAP interface configuration
# {{ ansible_managed }}
hosts = {{ ldap_host }}:{{ ldap_port }}
ldap_version = 3
auth_bind = yes
dn = {{ ldap_bind_username }}
dnpass = {{ ldap_bind_password }}
base = {{ ldap_basedn }}
scope = subtree
deref = never
# Below two are required by command 'doveadm mailbox ...'
iterate_attrs = mail=user
iterate_filter = (&(objectClass=mailUser)(accountStatus=active)(enabledService=mail))
user_filter = (&(objectClass=mailUser)(accountStatus=active)(enabledService=mail)(enabledService=%Ls%Lc)(|(mail=%u)(&(enabledService=shadowaddress)(shadowAddress=%u))))
user_attrs = mail=user,homeDirectory=home,=mail=maildir:~/Maildir/,mailQuota=quota_rule=*:bytes=%$
pass_filter = (&(objectClass=mailUser)(accountStatus=active)(enabledService=mail)(enabledService=%Ls%Lc)(|(mail=%u)(&(enabledService=shadowaddress)(shadowAddress=%u))))
pass_attrs = mail=user,userPassword=password
default_pass_scheme = SSHA

View File

@ -0,0 +1,177 @@
# Dovecot main configuration
# {{ ansible_managed }}
listen = *, [::]
mail_plugins = quota
protocols = pop3 imap sieve lmtp
mail_uid = 2000
mail_gid = 2000
first_valid_uid = 2000
last_valid_uid = 2000
log_path = /var/log/dovecot.log
mail_debug = no
auth_verbose = no
auth_debug = no
auth_debug_passwords = no
auth_verbose_passwords = no
ssl = no
mailbox_list_index = yes
disable_plaintext_auth = no
mail_location = maildir:/%Lh/Maildir/:INDEX=/%Lh/Maildir/:VOLATILEDIR=/tmp/dovecot-volatile/%d/%u
auth_default_realm = {{ domain }}
auth_mechanisms = PLAIN LOGIN
haproxy_trusted_networks = {{ trusted_networks }}
haproxy_timeout = 5s
service auth {
unix_listener /var/spool/postfix/private/dovecot-auth {
user = postfix
group = postfix
mode = 0666
}
unix_listener auth-master {
user = vmail
group = vmail
mode = 0666
}
unix_listener auth-userdb {
user = vmail
group = vmail
mode = 0660
}
}
service lmtp {
user = vmail
process_min_avail = 5
executable = lmtp -L
unix_listener /var/spool/postfix/private/dovecot-lmtp {
user = postfix
group = postfix
mode = 0600
}
inet_listener lmtp {
port = 24
}
}
service stats {
unix_listener stats-reader {
user = dovecot
group = postfix
mode = 0660
}
unix_listener stats-writer {
user = dovecot
group = postfix
mode = 0660
}
}
userdb {
args = /etc/dovecot/dovecot-ldap.conf
driver = ldap
}
passdb {
args = /etc/dovecot/dovecot-ldap.conf
driver = ldap
}
plugin {
auth_socket_path = /var/run/dovecot/auth-master
acl = vfile
acl_shared_dict = proxy::acl
sieve_dir = /%Lh/sieve
sieve = /%Lh/sieve/dovecot.sieve
sieve_global_dir = /srv/vmail/sieve
sieve_default = /srv/vmail/sieve/dovecot.sieve
}
service dict {
unix_listener dict {
mode = 0660
user = vmail
group = vmail
}
}
protocol lda {
mail_plugins = $mail_plugins sieve
auth_socket_path = /run/dovecot/auth-master
log_path = /var/log/dovecot.log
lda_mailbox_autocreate = yes
postmaster_address = {{ postmaster }}
}
protocol lmtp {
info_log_path = /var/log/dovecot-lmtp.log
mail_plugins = quota sieve
postmaster_address = {{ postmaster }}
lmtp_save_to_detail_mailbox = yes
recipient_delimiter = +
}
protocol imap {
mail_plugins = $mail_plugins imap_quota
imap_client_workarounds = tb-extra-mailbox-sep
}
protocol pop3 {
mail_plugins = $mail_plugins
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
pop3_uidl_format = %08Xu%08Xv
}
service imap-login {
service_count = 1
process_limit = 500
inet_listener imap {
port = 143
}
{% if haproxy %}
inet_listener imap-haproxy {
port = 10143
haproxy = yes
}
{% endif %}
}
service pop3-login {
service_count = 1
process_limit = 500
inet_listener pop3 {
port = 110
}
{% if haproxy %}
inet_listener pop3-haproxy {
port = 10110
haproxy = yes
}
{% endif %}
}
namespace {
type = private
separator = /
prefix =
inbox = yes
mailbox Sent {
auto = subscribe
special_use = \Sent
}
mailbox "Sent Messages" {
auto = no
special_use = \Sent
}
mailbox Drafts {
auto = subscribe
special_use = \Drafts
}
mailbox Trash {
auto = subscribe
special_use = \Trash
}
mailbox Junk {
auto = subscribe
special_use = \Junk
}
mailbox Spam {
auto = no
special_use = \Junk
}
}
namespace {
type = shared
separator = /
prefix = Shared/%%u/
location = maildir:/%%Lh/Maildir/:INDEX=/%%Lh/Maildir/Shared/%%u:VOLATILEDIR=/tmp/dovecot-volatile/Shared/%%u
subscriptions = yes
list = children
}

View File

@ -0,0 +1,143 @@
# Main Postfix configuration
# {{ ansible_managed }}
# No one will use these in helo command.
/^(localhost)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/^(localhost.localdomain)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(\.local)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
# Reject who use IP address as helo.
# Correct: [xxx.xxx.xxx.xxx]
# Incorrect: xxx.xxx.xxx.xxx
/^([0-9\.]+)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server sent non RFC compliant HELO identity (${1})
#
# This is the real HELO identify of these ISPs:
# sohu.com websmtp.sohu.com relay2nd.mail.sohu.com
# 126.com m15-78.126.com
# 163.com m31-189.vip.163.com m13-49.163.com
# sina.com mail2-209.sinamail.sina.com.cn
# gmail.com xx-out-NNNN.google.com
/^(126\.com)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server seems to be impersonating another mail server (${1})
/^(163\.com)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server seems to be impersonating another mail server (${1})
/^(163\.net)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server seems to be impersonating another mail server (${1})
/^(sohu\.com)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server seems to be impersonating another mail server (${1})
/(gmail\.com)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server seems to be impersonating another mail server (${1})
/^(google\.com)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server seems to be impersonating another mail server (${1})
/^(yahoo\.com\.cn)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server seems to be impersonating another mail server (${1})
/^(yahoo\.co\.jp)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server seems to be impersonating another mail server (${1})
#
# Spammers.
#
/^(728154EA470B4AA\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(taj-co\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(CF8D3DB045C1455\.net)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(dsgsfdg\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(se\.nit7-ngbo\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(mail\.goo\.ne\.jp)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(n-ong_an\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(meqail\.teamefs-ine5tl\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(zzg\.jhf-sp\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(din_glo-ng\.net)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(fda-cnc\.ie\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(yrtaj-yrco\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(m\.am\.biz\.cn)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(xr_haig\.roup\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(hjn\.cn)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(we_blf\.com\.cn)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(netvigator\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(mysam\.biz)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(mail\.teams-intl\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(seningbo\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(nblf\.com\.cn)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(kdn\.ktguide\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(zzsp\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(nblongan\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(dpu\.cn)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(nbalton\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(cncie\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(xinhaigroup\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(wz\.com)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/(\.zj\.cn)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/(\.kornet)$/ REJECT ACCESS DENIED. Your email was rejected because it appears to come from a known spamming mail server (${1})
/^(dsldevice\.lan)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/^(system\.mail)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/^(speedtouch\.lan)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/^(dsldevice\.lan)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
#
# Reject adsl spammers.
#
/(adsl)/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(dynamic)/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(\d{1,3}-\d{1,3}-\d{1,3}-\d{1,3})/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(pppoe)/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(dsl\.brasiltelecom\.net\.br)/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(dsl\.optinet\.hr)/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(dsl\.telesp\.net\.br)/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(dialup)/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(dhcp)/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(pool-)/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/^(cpe-)/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(\.cpe\.)/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(speedy\.com\.ar)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(speedyterra\.com\.br)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(static\.sbb\.rs)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(static\.vsnl\.net\.in)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
/(advance\.com\.ar)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(airtelbroadband\.in)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(bb\.netvision\.net\.il)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(bezeqint\.net)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(broadband3\.iol\.cz)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(cable\.net\.co)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(catv\.broadband\.hu)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(chello\.nl)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(chello\.sk)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(client\.mchsi\.com)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(comunitel\.net)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(coprosys\.cz)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(dclient\.hispeed\.ch)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(dip0\.t-ipconnect\.de)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(domain\.invalid)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(dyn\.centurytel\.net)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(embarqhsd\.net)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(emcali\.net\.co)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(epm\.net\.co)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(eutelia\.it)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(fastwebnet\.it)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(fibertel\.com\.ar)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(freedom2surf\.net)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(hgcbroadband\.com)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(HINET-IP\.hinet\.net)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(infonet\.by)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(is74\.ru)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(kievnet\.com\.ua)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(metrotel\.net\.co)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(nw\.nuvox\.net)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(pldt\.net)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(pool\.invitel\.hu)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(pool\.ukrtel\.net)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(pools\.arcor-ip\.net)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(pppoe\.avangarddsl\.ru)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(retail\.telecomitalia\.it)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(revip2\.asianet\.co\.th)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(tim\.ro)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(tsi\.tychy\.pl)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(ttnet\.net\.tr)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(tttmaxnet\.com)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(user\.veloxzone\.com\.br)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(utk\.ru)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(veloxzone\.com\.br)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(virtua\.com\.br)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(wanamaroc\.com)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(wbt\.ru)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(wireless\.iaw\.on\.ca)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(business\.telecomitalia\.it)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(cotas\.com\.bo)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(marunouchi\.tokyo\.ocn\.ne\.jp)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(amedex\.com)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})
/(aageneva\.com)$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server does not identify itself correctly (${1})

View File

@ -0,0 +1,89 @@
# Main Postfix configuration
# {{ ansible_managed }}
smtpd_banner = {{ banner_hostname }} ESMTP $mail_name (Debian/GNU)
biff = no
append_dot_mydomain = no
delay_warning_time = 48h
maximal_queue_lifetime = 14d
bounce_queue_lifetime = 14d
readme_directory = no
compatibility_level = 2
smtp_use_tls=yes
smtp_tls_cert_file=/etc/ssl/{{ banner_hostname }}.crt
smtp_tls_key_file=/etc/ssl/{{ banner_hostname }}.key
smtpd_tls_cert_file=/etc/ssl/letsencrypt/infrastructure.pem
smtpd_tls_key_file=/etc/ssl/letsencrypt/infrastructure.pem
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
myhostname = {{ myhostname }}
mydomain = {{ mydomain }}
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = localhost
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 {{ mynetworks }}
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
swap_bangpath = no
mynetworks_style = host
smtpd_data_restrictions = reject_unauth_pipelining
smtpd_reject_unlisted_recipient = yes
smtpd_reject_unlisted_sender = yes
smtp_tls_security_level = may
smtp_tls_CAfile = $smtpd_tls_CAfile
smtp_tls_loglevel = 0
smtp_tls_note_starttls_offer = yes
proxy_read_maps = $canonical_maps $lmtp_generic_maps $local_recipient_maps $mydestination $mynetworks $recipient_bcc_maps $recipient_canonical_maps $relay_domains $relay_recipient_maps $relocated_maps $sender_bcc_maps $sender_canonical_maps $smtp_generic_maps $smtpd_sender_login_maps $transport_maps $virtual_alias_domains $virtual_alias_maps $virtual_mailbox_domains $virtual_mailbox_maps $smtpd_sender_restrictions
smtp_data_init_timeout = 240s
smtp_data_xfer_timeout = 600s
smtpd_helo_required = yes
smtpd_helo_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_helo_hostname, reject_invalid_helo_hostname, check_helo_access pcre:/etc/postfix/helo_access.pcre
queue_run_delay = 300s
minimal_backoff_time = 300s
maximal_backoff_time = 4000s
enable_original_recipient = no
disable_vrfy_command = yes
home_mailbox = Maildir/
allow_min_user = no
message_size_limit = 52428800
virtual_minimum_uid = 2000
virtual_uid_maps = static:2000
virtual_gid_maps = static:2000
virtual_mailbox_base = /srv/vmail
transport_maps = proxy:ldap:/etc/postfix/ldap/transport_maps_user.cf, proxy:ldap:/etc/postfix/ldap/transport_maps_domain.cf, hash:/etc/postfix/transport
virtual_alias_maps = proxy:ldap:/etc/postfix/ldap/virtual_alias_maps.cf, proxy:ldap:/etc/postfix/ldap/virtual_group_maps.cf, proxy:ldap:/etc/postfix/ldap/virtual_group_members_maps.cf, proxy:ldap:/etc/postfix/ldap/catchall_maps.cf
virtual_mailbox_domains = proxy:ldap:/etc/postfix/ldap/virtual_mailbox_domains.cf
virtual_mailbox_maps = proxy:ldap:/etc/postfix/ldap/virtual_mailbox_maps.cf
sender_bcc_maps = proxy:ldap:/etc/postfix/ldap/sender_bcc_maps_user.cf, proxy:ldap:/etc/postfix/ldap/sender_bcc_maps_domain.cf
recipient_bcc_maps = proxy:ldap:/etc/postfix/ldap/recipient_bcc_maps_user.cf, proxy:ldap:/etc/postfix/ldap/recipient_bcc_maps_domain.cf
smtpd_sender_login_maps = proxy:ldap:/etc/postfix/ldap/sender_login_maps.cf
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain =
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_tls_auth_only = no
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
smtpd_relay_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
smtpd_tls_security_level = may
smtpd_tls_loglevel = 0
tls_random_source = dev:/dev/urandom
command_time_limit = 12h
ipc_timeout = 12h
mailbox_command = /usr/lib/dovecot/deliver
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/dovecot-auth
smtp-amavis_destination_recipient_limit = 1
virtual_alias_domains =

View File

@ -0,0 +1,73 @@
# Postfix master process configuration file
# {{ ansible_managed }}
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - y - - smtpd
pickup unix n - y 60 1 pickup
-o content_filter=
-o receive_override_options=no_header_body_checks
cleanup unix n - y - 0 cleanup
qmgr unix n - n 300 1 qmgr
tlsmgr unix - - y 1000? 1 tlsmgr
rewrite unix - - y - - trivial-rewrite
bounce unix - - y - 0 bounce
defer unix - - y - 0 bounce
trace unix - - y - 0 bounce
verify unix - - y - 1 verify
flush unix n - y 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - y - - smtp
smtp-ipv4 unix - - y - - smtp
-o inet_protocols=ipv4
relay unix - - y - - smtp
showq unix n - y - - showq
error unix - - y - - error
retry unix - - y - - error
discard unix - - y - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - y - - lmtp
anvil unix - - y - 1 anvil
scache unix - - y - 1 scache
submission inet n - n - - smtpd
-o smtpd_enforce_tls=no
-o smtpd_sasl_auth_enable=yes
-o smtpd_upstream_proxy_protocol=haproxy
-o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
-o content_filter=smtp-amavis:[::1]:10024
dovecot unix - n n - - pipe
-o soft_bounce=yes
flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${user}@${domain} -m ${extension}
smtp-amavis unix - - y - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
-o disable_dns_lookups=yes
-o max_use=20
[::1]:10025 inet n - y - - smtpd
-o inet_protocols=ipv6
-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,[::1]/128
-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

View File

@ -0,0 +1,4 @@
# Roundcube custom port configuration
# {{ ansible_managed }}
Listen 81

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
version = 3
bind = yes
start_tls = no
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = {{ ldap_basedn }}
scope = sub
query_filter = (&(objectClass=mailUser)(accountStatus=active)(|(mail=@%d)(shadowAddress=@%d)))
result_attribute= mailForwardingAddress
debuglevel = 0

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
version = 3
bind = yes
start_tls = no
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = {{ ldap_basedn }}
scope = one
query_filter = (&(objectClass=mailDomain)(|(domainName=%d)(domainAliasName=%d))(accountStatus=active)(enabledService=mail)(enabledService=recipientbcc))
result_attribute= domainRecipientBccAddress
debuglevel = 0

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
version = 3
bind = yes
start_tls = no
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = ou=Users,domainName=%d,{{ ldap_basedn }}
scope = one
query_filter = (&(|(mail=%s)(&(enabledService=shadowaddress)(shadowAddress=%s)))(objectClass=mailUser)(accountStatus=active)(enabledService=mail)(enabledService=recipientbcc))
result_attribute= userRecipientBccAddress
debuglevel = 0

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
bind = yes
start_tls = no
version = 3
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = {{ ldap_basedn }}
scope = one
query_filter = (&(objectClass=mailDomain)(|(domainName=%s)(&(enabledService=domainalias)(domainAliasName=%s)))(domainBackupMX=yes)(accountStatus=active)(enabledService=mail))
result_attribute= domainName
debuglevel = 0

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
version = 3
bind = yes
start_tls = no
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = {{ ldap_basedn }}
scope = one
query_filter = (&(objectClass=mailDomain)(|(domainName=%d)(domainAliasName=%d))(accountStatus=active)(enabledService=mail)(enabledService=senderbcc))
result_attribute= domainSenderBccAddress
debuglevel = 0

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
version = 3
bind = yes
start_tls = no
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = ou=Users,domainName=%d,{{ ldap_basedn }}
scope = one
query_filter = (&(|(mail=%s)(&(enabledService=shadowaddress)(shadowAddress=%s)))(objectClass=mailUser)(accountStatus=active)(enabledService=mail)(enabledService=senderbcc))
result_attribute= userSenderBccAddress
debuglevel = 0

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
version = 3
bind = yes
start_tls = no
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = {{ ldap_basedn }}
scope = sub
query_filter = (&(objectClass=mailUser)(accountStatus=active)(enabledService=mail)(enabledService=smtp)(|(mail=%s)(&(enabledService=shadowaddress)(shadowAddress=%s))))
result_attribute= mail
debuglevel = 0

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
version = 3
bind = yes
start_tls = no
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = {{ ldap_basedn }}
scope = one
query_filter = (&(objectClass=mailDomain)(accountStatus=active)(enabledService=mail)(|(domainName=%s)(domainAliasName=%s)))
result_attribute= mtaTransport
debuglevel = 0

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
version = 3
bind = yes
start_tls = no
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = ou=Users,domainName=%d,{{ ldap_basedn }}
scope = one
query_filter = (&(objectClass=mailUser)(mail=%s)(accountStatus=active)(enabledService=mail))
result_attribute= mtaTransport
debuglevel = 0

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
version = 3
bind = yes
start_tls = no
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = {{ ldap_basedn }}
scope = sub
query_filter = (&(|(mail=%s)(shadowAddress=%s))(accountStatus=active)(enabledService=mail)(enabledService=deliver)(|(objectClass=mailAlias)(&(objectClass=mailUser)(enabledService=forward))))
result_attribute= mailForwardingAddress
debuglevel = 0

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
version = 3
bind = yes
start_tls = no
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = {{ ldap_basedn }}
scope = sub
query_filter = (&(accountStatus=active)(enabledService=mail)(enabledService=deliver)(|(&(|(memberOfGroup=%s)(shadowAddress=%s))(objectClass=mailUser))(&(memberOfGroup=%s)(!(shadowAddress=%s))(|(objectClass=mailExternalUser)(objectClass=mailList)(objectClass=mailAlias)))))
result_attribute= mail
debuglevel = 0

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
version = 3
bind = yes
start_tls = no
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = {{ ldap_basedn }}
scope = sub
query_filter = (&(objectClass=mailUser)(accountStatus=active)(enabledService=mail)(enabledService=deliver)(|(mail=%s)(&(enabledService=shadowaddress)(shadowAddress=%s))))
result_attribute= mail
debuglevel = 0

View File

@ -0,0 +1,13 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
bind = yes
start_tls = no
version = 3
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = {{ ldap_basedn }}
scope = one
query_filter = (&(objectClass=mailDomain)(|(domainName=%s)(&(enabledService=domainalias)(domainAliasName=%s)))(!(domainBackupMX=yes))(accountStatus=active)(enabledService=mail))
result_attribute= domainName
debuglevel = 0

View File

@ -0,0 +1,14 @@
# {{ ansible_managed }}
server_host = {{ ldap_host }}
server_port = {{ ldap_port }}
version = 3
bind = yes
start_tls = no
bind_dn = {{ username_ldap_admin }}
bind_pw = {{ passwd_ldap_admin }}
search_base = {{ ldap_basedn }}
scope = sub
query_filter = (&(objectClass=mailUser)(|(mail=%s)(&(enabledService=shadowaddress)(shadowAddress=%s)))(accountStatus=active)(enabledService=mail)(enabledService=deliver))
result_attribute= mailMessageStore
result_format = %s/Maildir/
debuglevel = 0

View File

@ -0,0 +1,47 @@
DocumentRoot /var/lib/roundcube
Alias /mail /var/lib/roundcube
<Directory /var/lib/roundcube/>
Options +FollowSymLinks
# This is needed to parse /var/lib/roundcube/.htaccess. See its
# content before setting AllowOverride to None.
AllowOverride All
<IfVersion >= 2.3>
Require all granted
</IfVersion>
<IfVersion < 2.3>
Order allow,deny
Allow from all
</IfVersion>
</Directory>
# Protecting basic directories:
<Directory /var/lib/roundcube/config>
Options -FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/lib/roundcube/temp>
Options -FollowSymLinks
AllowOverride None
<IfVersion >= 2.3>
Require all denied
</IfVersion>
<IfVersion < 2.3>
Order allow,deny
Deny from all
</IfVersion>
</Directory>
<Directory /var/lib/roundcube/logs>
Options -FollowSymLinks
AllowOverride None
<IfVersion >= 2.3>
Require all denied
</IfVersion>
<IfVersion < 2.3>
Order allow,deny
Deny from all
</IfVersion>
</Directory>

View File

@ -0,0 +1,3 @@
# Gmail-specific transfer policy
# {{ ansible_managed }}
gmail.com smtp-ipv4:

View File

@ -0,0 +1,35 @@
---
# Default configurations
# I populate these from external configs; I indicate what the are as inline comments
# Postfix
# A list of relay domains and their target (square-bracked hostname/IP + port); examples follow
relay_domains: "{{ blse_relaydomains }}"
# - domain: "some.domain.tld"
# relay: "[mail.domain.tld]"
# - domain: "other.domain.tld"
# relay: "[secure.domain.tld]:465"
# A list of RBLs to check for rejecting incoming mail
remote_block_lists:
- bl.spamcop.net
- zen.spamhaus.org
- cbl.abuseat.org
# Enable TLS (literal yes/no only) and, if yes, the cert and key files
tls_enabled: yes
tls_cert: "/etc/ssl/{{ ansible_fqdn }}.crt"
tls_key: "/etc/ssl/{{ ansible_fqdn }}.key"
# Virtual address maps
virtual_maps:
- regex: "/^postmaster@/"
map: "root@{{ blsedomains_admindomain }}"
# SpamAssassin
notify_admin: "joshua@boniface.me" # Administrative address to notify
notify_method: "smtp:{{ blsecluster_smtphost }}:25"
custom_sender_scores:
- [qr'^(offers)@'i => 1.0]
- [qr'^.*@pizzanova.com'i => 1.0]

View File

@ -0,0 +1,2 @@
Populate me with spam-tagged legit emails.
Then `tar -cvJf ham-sample.txz ham-sample/` in the parent directory.

View File

@ -0,0 +1,2 @@
Populate me with spam-tagged legit emails.
Then `tar -cvJf ham-sample.txz ham-sample/` in the parent directory.

View File

@ -0,0 +1,19 @@
---
- name: postmap transport
command: "postmap /etc/postfix/transport"
- name: restart amavis
service:
name: "amavis"
state: "restarted"
- name: restart saslauthd
service:
name: "saslauthd"
state: "restarted"
- name: restart postfix
service:
name: "postfix"
state: "restarted"
- name: restart spamassassin
service:
name: "spamassassin"
state: "restarted"

View File

@ -0,0 +1,220 @@
---
#
# Install role packages
#
- name: install filtering packages and monitoring components
apt:
name:
- postfix
- postfix-pcre
- mailgraph
- amavis
- spamassassin
- clamav-daemon
- libnet-dns-perl
- libmail-spf-perl
- postfix-policyd-spf-python
- pfqueue
state: latest
- name: install compression algorithms for scanning
apt:
name:
- p7zip-full
- arj
- bzip2
- cabextract
- cpio
- file
- gzip
- lhasa
- liblz4-tool
- lrzip
- lzop
- nomarch
- pax
- rar
- rpm
- unrar-free
- unzip
- xz-utils
- zip
state: latest
#
# ClamAV
#
- name: ensure clamav is in amavis group
user:
name: "clamav"
append: "yes"
groups: "amavis"
- name: ensure amavis is in clamav group
user:
name: "amavis"
append: "yes"
groups: "clamav"
#
# policyd SPF
#
- name: install policyd-spf config
template:
src: "{{ item }}.j2"
dest: "/etc/postfix-policyd-spf-python/{{ item }}"
notify:
- restart postfix
with_items:
- "policyd-spf.conf"
#
# SpamAssassin
#
- name: install SpamAssassin config
template:
src: "{{ item }}.j2"
dest: "/etc/spamassassin/{{ item }}"
notify:
- restart spamassassin
- restart amavis
with_items:
- "local.cf"
- "90_customrules.cf"
#
# Amavis
#
- name: install Amavis configs
template:
src: "{{ item }}.j2"
dest: "/etc/amavis/conf.d/{{ item }}"
notify:
- restart amavis
with_items:
- "15-content_filter_mode"
- "50-user"
#
# Postfix
#
- name: create the Postfix local config dir
file:
state: directory
dest: "/etc/postfix/local"
- name: install the Postfix main configs
template:
src: "{{ item }}.j2"
dest: "/etc/postfix/{{ item }}"
notify:
- restart postfix
with_items:
- "main.cf"
- "master.cf"
- name: install the Postfix local configs
template:
src: "{{ item }}.j2"
dest: "/etc/postfix/local/{{ item }}"
notify:
- restart postfix
with_items:
- helo_access
- recipient_access
- relay_domains
- transport
- virtual
- name: link /etc/mailname to /etc/hostname
file:
dest: "/etc/mailname"
src: "/etc/hostname"
state: "link"
force: "yes"
#
# Verify and enable services
#
- name: verify and enable services
service:
name: "{{ item }}"
state: "started"
enabled: "yes"
with_items:
- "postfix"
- "amavis"
- "clamav-daemon"
#
# SpamAssassin training
#
- name: download spam sample archive
copy:
src: "spam-sample.txz"
dest: "/var/cache/spam-sample.txz"
owner: "root"
group: "root"
mode: "400"
register: spamsample
- name: make temporary directory
command: "mktemp -d"
register: tempdirspam
when: spamsample.changed
- name: extract spam sample archive to temporary directory
unarchive:
remote_src: "yes"
src: "/var/cache/spam-sample.txz"
dest: "{{ tempdirspam.stdout }}/"
when: spamsample.changed
- name: sa-learn from the spam sample
command: "sa-learn --spam {{ tempdirspam.stdout }}/spam-sample/"
when: spamsample.changed
- name: remove temporary directory
file:
dest: "{{ tempdirspam.stdout }}"
state: "absent"
when: spamsample.changed
- name: download ham sample archive
copy:
src: "ham-sample.txz"
dest: "/var/cache/ham-sample.txz"
owner: "root"
group: "root"
mode: "400"
register: hamsample
- name: make temporary directory
command: "mktemp -d"
register: tempdirham
when: hamsample.changed
- name: extract ham sample archive to temporary directory
unarchive:
remote_src: "yes"
src: "/var/cache/ham-sample.txz"
dest: "{{ tempdirham.stdout }}/"
when: hamsample.changed
- name: sa-learn from the ham sample
command: "sa-learn --ham {{ tempdirham.stdout }}/ham-sample/"
when: hamsample.changed
- name: remove temporary directory
file:
dest: "{{ tempdirham.stdout }}"
state: "absent"
when: hamsample.changed

View File

@ -0,0 +1,12 @@
use strict;
# Amavis filter configuration
# {{ ansible_managed }}
@bypass_virus_checks_maps = (
\%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
@bypass_spam_checks_maps = (
\%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);
1; # ensure a defined return

View File

@ -0,0 +1,40 @@
use strict;
@local_domains_acl = ( "." );
$sa_tag_level_deflt = -9999;
$sa_tag2_level_deflt = 5;
$sa_kill_level_deflt = 9999;
$sa_spam_subject_tag = '*** SPAM *** ';
$final_spam_destiny = 'D_PASS';
$bad_header_quarantine_method = undef;
$notify_method = '{{ notify_method }}';
$newvirus_admin = '{{ notify_admin }}';
$virus_admin = '{{ notify_admin }}';
$spam_admin = '{{ notify_admin }}';
$banned_admin = \@virus_admin_maps; # for compatibility with pre-2.2.1
$bad_header_admin = \@virus_admin_maps; # for compatibility with pre-2.2.1
@newvirus_admin_maps = (\$newvirus_admin);
@virus_admin_maps = (\%virus_admin, \$virus_admin);
@spam_admin_maps = (\%spam_admin, \$spam_admin);
@banned_admin_maps = (\$banned_admin);
@bad_header_admin_maps= (\$bad_header_admin);
{% if custom_sender_scores is defined %}
# Custom sender_map scores
@score_sender_maps = ({
'.' => [
new_RE(
{% for score in custom_sender_scores %}
{{ score }},
{% endfor %}
),
],
});
{% endif %}
#------------ Do not modify anything below this line -------------
1; # ensure a defined return

View File

@ -0,0 +1,7 @@
# Adjustments to default SpamAssassin scoring
# {{ ansible_managed }}
score RCVD_IN_PSBL 3.5 # Increase default score significantly
score URIBL_BLACK 3.5 # Increase default score significantly
score LOTS_OF_MONEY 2 # Increase default score a little
score ADVANCE_FEE_4_NEW 2 # Increase default score a little
score RDNS_NONE 0.5 # Decrease default score a little

View File

@ -0,0 +1,2 @@
/^\[[0-9]{1,3}(\.[0-9]{1,3}){3}\]$/ DUNNO announced self using an address literal
/^[0-9]{1,3}(\.[0-9]{1,3}){3}$/ REJECT announced self with an IP address instead of a domain name

View File

@ -0,0 +1,27 @@
# SpamAssassin local config
# {{ ansible_managed }}
report_safe 1
required_score 4.5
use_bayes 1
bayes_auto_learn 1
bayes_auto_learn_threshold_nonspam -0.1
bayes_auto_learn_threshold_spam 9.0
score BAYES_00 -4
score BAYES_05 -2
score BAYES_80 2
score BAYES_95 6
score BAYES_99 8
bayes_ignore_header X-Bogosity
bayes_ignore_header X-Spam-Flag
bayes_ignore_header X-Spam-Status
bayes_path /var/spamassassin/bayes_db/bayes
bayes_file_mode 0777
skip_rbl_checks 0
ok_languages all
ok_locales all

View File

@ -0,0 +1,91 @@
# Main Postfix configuration
# {{ ansible_managed }}
myorigin = /etc/mailname
myhostname = {{ ansible_fqdn }}
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
message_size_limit = 26214400
mailbox_size_limit = 0
default_process_limit = 1000
recipient_delimiter = +
inet_interfaces = all
smtpd_banner = {{ ansible_fqdn }} ESMTP $mail_name (Debian/GNU)
biff = no
append_dot_mydomain = no
delay_warning_time = 48h
maximal_queue_lifetime = 14d
bounce_queue_lifetime = 14d
readme_directory = no
compatibility_level = 2
smtpd_use_tls={{ tls_enabled }}
smtpd_tls_dh1024_param_file = /etc/ssl/dhparams.pem
smtpd_tls_cert_file={{ tls_cert }}
smtpd_tls_key_file={{ tls_key }}
smtpd_tls_ask_ccert = yes
smtpd_tls_received_header = yes
smtpd_tls_loglevel = 1
smtpd_tls_session_cache_database = btree:$data_directory/smtpd_scache
smtpd_tls_security_level = may
smtpd_tls_protocols = !SSLv2,!SSLv3
smtpd_tls_ciphers = medium
smtpd_tls_exclude_ciphers = RC4, CAMELLIA, SEED, 3DES
smtp_use_tls={{ tls_enabled }}
smtp_tls_cert_file={{ tls_cert }}
smtp_tls_key_file={{ tls_key }}
smtp_tls_session_cache_database = btree:$data_directory/smtp_scache
smtp_tls_loglevel = 1
smtp_tls_security_level = may
smtp_tls_protocols = $smtpd_tls_protocols
smtp_tls_ciphers = $smtpd_tls_ciphers
smtp_tls_exclude_ciphers = $smtpd_tls_exclude_ciphers
mydestination =
local_recipient_maps =
alias_maps =
alias_database =
virtual_alias_maps = pcre:$config_directory/local/virtual
local_transport = error:local mail delivery is disabled
transport_maps = pcre:$config_directory/local/transport
relay_domains = $config_directory/local/relay_domains
content_filter = smtp-amavis:[127.0.0.1]:10024
smtpd_client_recipient_rate_limit = 250
strict_rfc821_envelopes = yes
receive_override_options = no_address_mappings
policyd-spf_time_limit = 3600
smtpd_relay_restrictions =
permit_mynetworks
reject_unauth_destination
check_policy_service unix:private/policyd-spf
{% for rbl in remote_block_lists %}
reject_rbl_client {{ rbl }}
{% endfor %}
warn_if_reject reject_unknown_client
smtpd_helo_required = yes
smtpd_helo_restrictions =
check_helo_access pcre:$config_directory/local/helo_access
reject_invalid_hostname
smtpd_sender_restrictions =
check_sender_mx_access cidr:$config_directory/local/mx_access
reject_unknown_sender_domain
reject_non_fqdn_sender
check_sender_access pcre:$config_directory/local/sender_access
smtpd_recipient_restrictions =
reject_unknown_recipient_domain
reject_non_fqdn_recipient
reject_unauth_pipelining
reject_unauth_destination
check_policy_service unix:private/policyd-spf
check_recipient_access pcre:$config_directory/local/recipient_access
reject_unverified_recipient
smtpd_data_restrictions =
reject_multi_recipient_bounce
reject_unauth_pipelining

View File

@ -0,0 +1,62 @@
# Postfix master process configuration file
# {{ ansible_managed }}
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - y - - smtpd
pickup unix n - y 60 1 pickup
-o content_filter=
-o receive_override_options=no_header_body_checks
cleanup unix n - y - 0 cleanup
qmgr unix n - n 300 1 qmgr
tlsmgr unix - - y 1000? 1 tlsmgr
rewrite unix - - y - - trivial-rewrite
bounce unix - - y - 0 bounce
defer unix - - y - 0 bounce
trace unix - - y - 0 bounce
verify unix - - y - 1 verify
flush unix n - y 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - y - - smtp
relay unix - - y - - smtp
showq unix n - y - - showq
error unix - - y - - error
retry unix - - y - - error
discard unix - - y - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - y - - lmtp
anvil unix - - y - 1 anvil
scache unix - - y - 1 scache
policyd-spf unix - n n - 0 spawn
user=policyd-spf argv=/usr/bin/policyd-spf
smtp-amavis unix - - y - 2 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 - y - - 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

View File

@ -0,0 +1,12 @@
# policyd SPF config
# {{ ansible_managed }}
debugLevel = 1
HELO_reject = False
Mail_From_reject = False
PermError_reject = False
TempError_Defer = False
skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1

View File

@ -0,0 +1,4 @@
/[%!@].*[%!@]/ REJECT sender-specified routing in recipient address
/&.*@/ REJECT invalid user
/^(daemon|bin|sys|sync|games|man|lp|news|uucp|proxy|www-data|backup|list|irc|gnats|nobody)@/ REJECT reserved system user
/^(ntp|sshd|munin|postfix|clamav|sqlgrey|policyd-spf|bind|statd|freerad|mysql|smokeping|systemd-.+|)@/ REJECT reserved system user

View File

@ -0,0 +1,3 @@
{% for domain in relay_domains %}
{{ domain.domain }}
{% endfor %}

View File

@ -0,0 +1,3 @@
{% for domain in relay_domains %}
/@{{ domain.domain }}$/ relay:{{ domain.relay }}
{% endfor %}

View File

@ -0,0 +1,3 @@
{% for map in virtual_maps %}
{{ map.regex }} {{ map.map }}
{% endfor %}