diff options
| author | Barry Warsaw | 2017-05-23 18:23:32 +0000 |
|---|---|---|
| committer | Barry Warsaw | 2017-05-23 18:23:32 +0000 |
| commit | 3dc9e4c7f2cbed2bbfac9b76fdc74ffdf564b208 (patch) | |
| tree | d650c8dc5c24e8a2b13754d196beac891d543fd4 /src/mailman/mta | |
| parent | a7c563e9048d302c52558e6e2202fdfb49961843 (diff) | |
| parent | 30a21e0aacd4fcf755816e31b031aec81f83c98e (diff) | |
| download | mailman-3dc9e4c7f2cbed2bbfac9b76fdc74ffdf564b208.tar.gz mailman-3dc9e4c7f2cbed2bbfac9b76fdc74ffdf564b208.tar.zst mailman-3dc9e4c7f2cbed2bbfac9b76fdc74ffdf564b208.zip | |
Merge branch 'issue-318' into 'master'
Add support for regex based postfix transport maps and relay_domains.
Closes #318
See merge request !263
Diffstat (limited to 'src/mailman/mta')
| -rw-r--r-- | src/mailman/mta/postfix.py | 49 | ||||
| -rw-r--r-- | src/mailman/mta/tests/test_aliases.py | 168 |
2 files changed, 155 insertions, 62 deletions
diff --git a/src/mailman/mta/postfix.py b/src/mailman/mta/postfix.py index d819533a3..6e71d0651 100644 --- a/src/mailman/mta/postfix.py +++ b/src/mailman/mta/postfix.py @@ -56,6 +56,8 @@ class LMTP: # Locate and read the Postfix specific configuration file. mta_config = external_configuration(config.mta.configuration) self.postmap_command = mta_config.get('postfix', 'postmap_command') + self.transport_file_type = mta_config.get( + 'postfix', 'transport_file_type') def create(self, mlist): """See `IMailTransportAgentLifecycle`.""" @@ -84,19 +86,21 @@ class LMTP: self._generate_domains_file(fp) # Atomically rename to the intended path. os.rename(domains_path_new, domains_path) - # Now, run the postmap command on both newly generated files. If - # one files, still try the other one. - errors = [] - for path in (lmtp_path, domains_path): - command = self.postmap_command + ' ' + path - status = (os.system(command) >> 8) & 0xff - if status: - msg = 'command failure: %s, %s, %s' - errstr = os.strerror(status) - log.error(msg, command, status, errstr) - errors.append(msg % (command, status, errstr)) - if errors: - raise RuntimeError(NL.join(errors)) + # If the transport_file_type is 'hash' then run the postmap command + # on newly generated file to convert them in to hash table like + # Postfix wants. + if self.transport_file_type == 'hash': + errors = [] + for path in (lmtp_path, domains_path): + command = self.postmap_command + ' ' + path + status = (os.system(command) >> 8) & 0xff + if status: + msg = 'command failure: %s, %s, %s' + errstr = os.strerror(status) + log.error(msg, command, status, errstr) + errors.append(msg % (command, status, errstr)) + if errors: + raise RuntimeError(NL.join(errors)) def _generate_lmtp_file(self, fp): # The format for Postfix's LMTP transport map is defined here: @@ -125,12 +129,23 @@ class LMTP: file=fp) for mlist in sorted(by_domain[domain], key=sort_key): aliases = list(utility.aliases(mlist)) - width = max(len(alias) for alias in aliases) + 3 - print(ALIASTMPL.format(aliases.pop(0), config, width), file=fp) + width = max(len(alias) for alias in aliases) + \ + aliases[0].count('.') + 7 + print(ALIASTMPL.format(self._decorate(aliases.pop(0)), + config, width), file=fp) for alias in aliases: - print(ALIASTMPL.format(alias, config, width), file=fp) + print(ALIASTMPL.format(self._decorate(alias), + config, width), file=fp) print(file=fp) + def _decorate(self, name): + # Postfix regex tables need regex matching listname or domains. This + # method just decorates the name to be printed in the transport map + # file or relay domains file. + if self.transport_file_type == 'regex': + return '/^{}$/'.format(name).replace('.', '\.') + return name + def _generate_domains_file(self, fp): # Uniquify the domains, then sort them alphabetically. domains = set() @@ -145,5 +160,5 @@ class LMTP: # you're on your own. """.format(now().replace(microsecond=0)), file=fp) for domain in sorted(domains): - print('{0} {0}'.format(domain), file=fp) + print('{} {}'.format(self._decorate(domain), domain), file=fp) print(file=fp) diff --git a/src/mailman/mta/tests/test_aliases.py b/src/mailman/mta/tests/test_aliases.py index d5cea3ecb..b8090c86d 100644 --- a/src/mailman/mta/tests/test_aliases.py +++ b/src/mailman/mta/tests/test_aliases.py @@ -154,15 +154,15 @@ example.com example.com contents = _strip_header(fp.read()) self.assertMultiLineEqual(contents, """\ # Aliases which are visible only in the @example.com domain. -test@example.com lmtp:[127.0.0.1]:9024 -test-bounces@example.com lmtp:[127.0.0.1]:9024 -test-confirm@example.com lmtp:[127.0.0.1]:9024 -test-join@example.com lmtp:[127.0.0.1]:9024 -test-leave@example.com lmtp:[127.0.0.1]:9024 -test-owner@example.com lmtp:[127.0.0.1]:9024 -test-request@example.com lmtp:[127.0.0.1]:9024 -test-subscribe@example.com lmtp:[127.0.0.1]:9024 -test-unsubscribe@example.com lmtp:[127.0.0.1]:9024 +test@example.com lmtp:[127.0.0.1]:9024 +test-bounces@example.com lmtp:[127.0.0.1]:9024 +test-confirm@example.com lmtp:[127.0.0.1]:9024 +test-join@example.com lmtp:[127.0.0.1]:9024 +test-leave@example.com lmtp:[127.0.0.1]:9024 +test-owner@example.com lmtp:[127.0.0.1]:9024 +test-request@example.com lmtp:[127.0.0.1]:9024 +test-subscribe@example.com lmtp:[127.0.0.1]:9024 +test-unsubscribe@example.com lmtp:[127.0.0.1]:9024 """) def test_two_lists(self): @@ -185,25 +185,25 @@ example.com example.com contents = _strip_header(fp.read()) self.assertMultiLineEqual(contents, """\ # Aliases which are visible only in the @example.com domain. -other@example.com lmtp:[127.0.0.1]:9024 -other-bounces@example.com lmtp:[127.0.0.1]:9024 -other-confirm@example.com lmtp:[127.0.0.1]:9024 -other-join@example.com lmtp:[127.0.0.1]:9024 -other-leave@example.com lmtp:[127.0.0.1]:9024 -other-owner@example.com lmtp:[127.0.0.1]:9024 -other-request@example.com lmtp:[127.0.0.1]:9024 -other-subscribe@example.com lmtp:[127.0.0.1]:9024 -other-unsubscribe@example.com lmtp:[127.0.0.1]:9024 +other@example.com lmtp:[127.0.0.1]:9024 +other-bounces@example.com lmtp:[127.0.0.1]:9024 +other-confirm@example.com lmtp:[127.0.0.1]:9024 +other-join@example.com lmtp:[127.0.0.1]:9024 +other-leave@example.com lmtp:[127.0.0.1]:9024 +other-owner@example.com lmtp:[127.0.0.1]:9024 +other-request@example.com lmtp:[127.0.0.1]:9024 +other-subscribe@example.com lmtp:[127.0.0.1]:9024 +other-unsubscribe@example.com lmtp:[127.0.0.1]:9024 -test@example.com lmtp:[127.0.0.1]:9024 -test-bounces@example.com lmtp:[127.0.0.1]:9024 -test-confirm@example.com lmtp:[127.0.0.1]:9024 -test-join@example.com lmtp:[127.0.0.1]:9024 -test-leave@example.com lmtp:[127.0.0.1]:9024 -test-owner@example.com lmtp:[127.0.0.1]:9024 -test-request@example.com lmtp:[127.0.0.1]:9024 -test-subscribe@example.com lmtp:[127.0.0.1]:9024 -test-unsubscribe@example.com lmtp:[127.0.0.1]:9024 +test@example.com lmtp:[127.0.0.1]:9024 +test-bounces@example.com lmtp:[127.0.0.1]:9024 +test-confirm@example.com lmtp:[127.0.0.1]:9024 +test-join@example.com lmtp:[127.0.0.1]:9024 +test-leave@example.com lmtp:[127.0.0.1]:9024 +test-owner@example.com lmtp:[127.0.0.1]:9024 +test-request@example.com lmtp:[127.0.0.1]:9024 +test-subscribe@example.com lmtp:[127.0.0.1]:9024 +test-unsubscribe@example.com lmtp:[127.0.0.1]:9024 """) def test_two_lists_two_domains(self): @@ -229,24 +229,102 @@ example.net example.net contents = _strip_header(fp.read()) self.assertMultiLineEqual(contents, """\ # Aliases which are visible only in the @example.com domain. -test@example.com lmtp:[127.0.0.1]:9024 -test-bounces@example.com lmtp:[127.0.0.1]:9024 -test-confirm@example.com lmtp:[127.0.0.1]:9024 -test-join@example.com lmtp:[127.0.0.1]:9024 -test-leave@example.com lmtp:[127.0.0.1]:9024 -test-owner@example.com lmtp:[127.0.0.1]:9024 -test-request@example.com lmtp:[127.0.0.1]:9024 -test-subscribe@example.com lmtp:[127.0.0.1]:9024 -test-unsubscribe@example.com lmtp:[127.0.0.1]:9024 +test@example.com lmtp:[127.0.0.1]:9024 +test-bounces@example.com lmtp:[127.0.0.1]:9024 +test-confirm@example.com lmtp:[127.0.0.1]:9024 +test-join@example.com lmtp:[127.0.0.1]:9024 +test-leave@example.com lmtp:[127.0.0.1]:9024 +test-owner@example.com lmtp:[127.0.0.1]:9024 +test-request@example.com lmtp:[127.0.0.1]:9024 +test-subscribe@example.com lmtp:[127.0.0.1]:9024 +test-unsubscribe@example.com lmtp:[127.0.0.1]:9024 # Aliases which are visible only in the @example.net domain. -other@example.net lmtp:[127.0.0.1]:9024 -other-bounces@example.net lmtp:[127.0.0.1]:9024 -other-confirm@example.net lmtp:[127.0.0.1]:9024 -other-join@example.net lmtp:[127.0.0.1]:9024 -other-leave@example.net lmtp:[127.0.0.1]:9024 -other-owner@example.net lmtp:[127.0.0.1]:9024 -other-request@example.net lmtp:[127.0.0.1]:9024 -other-subscribe@example.net lmtp:[127.0.0.1]:9024 -other-unsubscribe@example.net lmtp:[127.0.0.1]:9024 +other@example.net lmtp:[127.0.0.1]:9024 +other-bounces@example.net lmtp:[127.0.0.1]:9024 +other-confirm@example.net lmtp:[127.0.0.1]:9024 +other-join@example.net lmtp:[127.0.0.1]:9024 +other-leave@example.net lmtp:[127.0.0.1]:9024 +other-owner@example.net lmtp:[127.0.0.1]:9024 +other-request@example.net lmtp:[127.0.0.1]:9024 +other-subscribe@example.net lmtp:[127.0.0.1]:9024 +other-unsubscribe@example.net lmtp:[127.0.0.1]:9024 +""") + + def test_missing_postmap_command_raises_runtime_errorr(self): + # Changing the postmap command to false will always + # return a non-zero exit code. + self.postfix.postmap_command = 'false' + # Generating postmap hash files will raise a runtimerror. + with self.assertRaises(RuntimeError): + self.postfix.regenerate(self.tempdir) + # Now change the command back to true will make the + # command run normally. + self.postfix.postmap_command = 'true' + self.postfix.regenerate(self.tempdir) + # There should be two files in the tempdir. + self.assertEqual(sorted(os.listdir(self.tempdir)), + ['postfix_domains', 'postfix_lmtp']) + + def test_aliases_regex(self): + # Test aliases generation for regex maps for postfix. + # Set the transport map type to regex. + self.postfix.transport_file_type = 'regex' + self.postfix.regenerate(self.tempdir) + # The domains file just contains the example.com domain. + with open(os.path.join(self.tempdir, 'postfix_domains')) as fp: + contents = _strip_header(fp.read()) + self.assertMultiLineEqual(contents, """\ +/^example\.com$/ example.com +""") + + # the lmtp file contains transport mapping to the lmtp server. + with open(os.path.join(self.tempdir, 'postfix_lmtp')) as fp: + contents = _strip_header(fp.read()) + self.assertMultiLineEqual(contents, """\ +# Aliases which are visible only in the @example.com domain. +/^test@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-bounces@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-confirm@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-join@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-leave@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-owner@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-request@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-subscribe@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-unsubscribe@example\.com$/ lmtp:[127.0.0.1]:9024 +""") + + def test_aliases_regex_with_dots(self): + # Test regex is generated for listnames with multiple dots. + self.postfix.transport_file_type = 'regex' + create_list('test.list.name.dots@example.com') + self.postfix.regenerate(self.tempdir) + with open(os.path.join(self.tempdir, 'postfix_domains')) as fp: + contents = _strip_header(fp.read()) + self.assertMultiLineEqual(contents, """\ +/^example\.com$/ example.com +""") + with open(os.path.join(self.tempdir, 'postfix_lmtp')) as fp: + contents = _strip_header(fp.read()) + self.assertMultiLineEqual(contents, """\ +# Aliases which are visible only in the @example.com domain. +/^test@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-bounces@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-confirm@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-join@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-leave@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-owner@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-request@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-subscribe@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test-unsubscribe@example\.com$/ lmtp:[127.0.0.1]:9024 + +/^test\.list\.name\.dots@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test\.list\.name\.dots-bounces@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test\.list\.name\.dots-confirm@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test\.list\.name\.dots-join@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test\.list\.name\.dots-leave@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test\.list\.name\.dots-owner@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test\.list\.name\.dots-request@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test\.list\.name\.dots-subscribe@example\.com$/ lmtp:[127.0.0.1]:9024 +/^test\.list\.name\.dots-unsubscribe@example\.com$/ lmtp:[127.0.0.1]:9024 """) |
