From 23a9ea4219dc8f6a4e0ef3a9d393c8ccf2f8f4f9 2017-08-03 12:02:34 From: Branko Majic Date: 2017-08-03 12:02:34 Subject: [PATCH] MAR-113: Added option for specifying relay port to mail_forwarder: - Introduced new option "smtp_relay_host_port". - Updated the test playbook and tests to make sure new functionality works as expected. - Update role reference documentation. - Updated usage instructions. --- diff --git a/docs/rolereference.rst b/docs/rolereference.rst index 0310c555d38c0a5617daa0112b96f2c8d5169c1f..68af373fba627fde71e08d398f3d34d87ceabf68 100644 --- a/docs/rolereference.rst +++ b/docs/rolereference.rst @@ -1241,6 +1241,9 @@ Parameters **smtp_relay_host** (string, optional, ``None``) SMTP server via which the mails are sent out for non-local recipients. +**smtp_relay_host_port** (integer, optional, ``None``) + Port to use when connecting to the SMTP relay host. + **smtp_relay_truststore** (string, optional, ``{{ lookup('file', tls_certificate_dir + '/truststore.pem') }}``) X.509 certificate chain used for issuing certificate for the SMTP relay service. The file will be stored in location @@ -1272,6 +1275,8 @@ Here is an example configuration for setting-up the mail forwarder: smtp_relay_host: mail.example.com + smtp_relay_host_port: 27 + smtp_from_relay_allowed: False smtp_relay_truststore: /etc/ssl/certs/example_ca_chain.pem diff --git a/docs/usage.rst b/docs/usage.rst index 3a432d064ad27e6912dfbd635d795174228b823e..12ce92a573686c906e5d9d0975106aea61adfa25 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -637,7 +637,10 @@ servers relay their mails to the mail server host). .. note:: Should you ever need to deploy the forwarder role on a laptop or machine - behind NAT, make sure to look at ``smtp_from_relay_allowed`` parameter. + behind NAT, make sure to look at ``smtp_from_relay_allowed`` parameter. In + case you need to connect to the SMTP relay via non-standard port (for example + to work-around ISP blocks), have a look at ``smtp_relay_host_port`` + parameter. The mail server role looks-up available mail domains, users, and aliases in the LDAP directory. This has already been set-up on the server diff --git a/roles/mail_forwarder/defaults/main.yml b/roles/mail_forwarder/defaults/main.yml index 50426184d36507fb14078c1d1360e93c1425cdbf..9aff8c79653f0a08fcfe6f90e58a3df916df6f63 100644 --- a/roles/mail_forwarder/defaults/main.yml +++ b/roles/mail_forwarder/defaults/main.yml @@ -4,3 +4,4 @@ local_mail_aliases: {} smtp_from_relay_allowed: True smtp_relay_host: "" smtp_relay_truststore: "{{ lookup('file', tls_certificate_dir + '/truststore.pem') }}" +smtp_relay_host_port: null diff --git a/roles/mail_forwarder/playbook.yml b/roles/mail_forwarder/playbook.yml index 3d0a337a35a9dcd0998d7aa48cc6eeede28170e5..2fc2b90126a3d8f4c6577b754c8667258ae2fd54 100644 --- a/roles/mail_forwarder/playbook.yml +++ b/roles/mail_forwarder/playbook.yml @@ -99,6 +99,10 @@ name: swaks state: installed + - name: Set-up port forwarding + command: "iptables -t nat -A PREROUTING -p tcp -m tcp --dport 27 -j REDIRECT --to-ports 25" + changed_when: False + handlers: - name: Update CA certificate cache @@ -123,6 +127,7 @@ root: "root testuser" smtp_from_relay_allowed: True smtp_relay_host: mail-server + smtp_relay_host_port: 27 smtp_relay_truststore: "{{ lookup('file', 'tests/data/x509/ca.cert.pem') }}" # common diff --git a/roles/mail_forwarder/templates/main.cf.j2 b/roles/mail_forwarder/templates/main.cf.j2 index f13509eb940a4ecf1f0f4f187c92909c812a174f..3d8464d1455b98479df6ef75aee3f7708c8f61e5 100644 --- a/roles/mail_forwarder/templates/main.cf.j2 +++ b/roles/mail_forwarder/templates/main.cf.j2 @@ -36,7 +36,7 @@ alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases myorigin = /etc/mailname mydestination = {{ inventory_hostname }}, {{ inventory_hostname_short }}, localhost.localdomain, localhost -relayhost = {{ smtp_relay_host }} +relayhost = {{ smtp_relay_host }}{% if smtp_relay_host and smtp_relay_host_port %}:{{ smtp_relay_host_port }}{% endif %}{{ '' }} mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 mailbox_command = procmail -a "$EXTENSION" mailbox_size_limit = 0 diff --git a/roles/mail_forwarder/tests/test_mandatory.py b/roles/mail_forwarder/tests/test_mandatory.py index 271ef0f9b7aaa5f0e3c69802fc4178446508afc9..b30b10833ff91cf509e7cda9a98a13387787483a 100644 --- a/roles/mail_forwarder/tests/test_mandatory.py +++ b/roles/mail_forwarder/tests/test_mandatory.py @@ -61,6 +61,7 @@ def test_direct_mail_sending(Command, File, Sudo): with Sudo(): mail_log = File('/var/log/mail.log') - pattern = "%s: to=, relay=domain1.*status=sent" % message_id + # Pattern used to verify the mail was sent directly on default port. + pattern = "%s: to=, relay=domain1\[[^]]*\]:25.*status=sent" % message_id assert re.search(pattern, mail_log.content) is not None diff --git a/roles/mail_forwarder/tests/test_optional.py b/roles/mail_forwarder/tests/test_optional.py index 273aa6c57bd431395b517327bb3984ca193e208a..05f76b698f6a4717f39a5dd6288ccf09e6de38bb 100644 --- a/roles/mail_forwarder/tests/test_optional.py +++ b/roles/mail_forwarder/tests/test_optional.py @@ -39,7 +39,7 @@ def test_postfix_main_cf_file_content(File): assert "myhostname = parameters-optional" in config_lines assert "mydestination = parameters-optional, parameters-optional, localhost.localdomain, localhost" in config_lines - assert "relayhost = mail-server" in config_lines + assert "relayhost = mail-server:27" in config_lines assert "mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128" in config_lines assert "smtp_tls_security_level=verify" in config_lines assert "smtp_tls_CAfile=/etc/ssl/certs/smtp_relay_truststore.pem" in config_lines @@ -81,7 +81,9 @@ def test_relay_mail_sending(Command, File, Sudo): with Sudo(): mail_log = File('/var/log/mail.log') - pattern = "%s: to=, relay=mail-server.*status=sent" % message_id + # Pattern used to verify the mail was sent over relay on designated + # port. + pattern = r"%s: to=, relay=mail-server\[[^]]*\]:27.*status=sent" % message_id assert re.search(pattern, mail_log.content) is not None diff --git a/roles/mail_forwarder/tests/test_smtp_relay_host_port.py b/roles/mail_forwarder/tests/test_smtp_relay_host_port.py new file mode 100644 index 0000000000000000000000000000000000000000..915866932142f9c96b3da87e7d91d899d05e9563 --- /dev/null +++ b/roles/mail_forwarder/tests/test_smtp_relay_host_port.py @@ -0,0 +1,46 @@ +import re +import time + + +import testinfra.utils.ansible_runner + + +testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( + '.molecule/ansible_inventory').get_hosts('parameters-no-incoming') + + +def test_postfix_main_cf_file_content(File): + """ + Tests if the Postfix main configuration file content is correct. + """ + + config = File('/etc/postfix/main.cf') + config_lines = config.content.split("\n") + + assert "myhostname = parameters-no-incoming" in config_lines + assert "mydestination = parameters-no-incoming, parameters-no-incoming, localhost.localdomain, localhost" in config_lines + assert "relayhost = mail-server" in config_lines + assert "mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128" in config_lines + assert "smtp_tls_security_level=verify" in config_lines + assert "smtp_tls_CAfile=/etc/ssl/certs/smtp_relay_truststore.pem" in config_lines + assert "smtp_host_lookup = dns, native" in config_lines + + +def test_relay_mail_sending(Command, File, Sudo): + """ + Tests if mails are sent correctly via relay if relay has been configured. + """ + + send = Command('swaks --suppress-data --to root@domain1 --server localhost') + assert send.rc == 0 + message_id = re.search('Ok: queued as (.*)', send.stdout).group(1) + + # Wait for a little while for message to be processed. + time.sleep(5) + + with Sudo(): + mail_log = File('/var/log/mail.log') + # Pattern used to verify the mail was sent over relay on default port. + pattern = r"%s: to=, relay=mail-server\[[^]]*\]:25.*status=sent" % message_id + + assert re.search(pattern, mail_log.content) is not None