diff options
| -rw-r--r-- | src/mailman/docs/NEWS.rst | 7 | ||||
| -rw-r--r-- | src/mailman/handlers/decorate.py | 14 | ||||
| -rw-r--r-- | src/mailman/handlers/docs/decorate.rst | 10 | ||||
| -rw-r--r-- | src/mailman/handlers/tests/test_decorate.py | 89 |
4 files changed, 119 insertions, 1 deletions
diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst index 341f22f0a..0f778c494 100644 --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -52,6 +52,13 @@ Internal API * A handful of unused legacy exceptions have been removed. The redundant `MailmanException` has been removed; use `MailmanError` everywhere. +Message handling +---------------- + * New placeholders have been added for message headers and footers. You can + use a placeholder of the format `$<archiver-name>_url` to insert the + permalink to the message in the named archiver, for any archiver enabled + for the mailing list. Given by Abhilash Raj. + REST ---- * REST API version 3.1 introduced. Mostly backward compatible with version diff --git a/src/mailman/handlers/decorate.py b/src/mailman/handlers/decorate.py index 7f09c74e4..1d752cee5 100644 --- a/src/mailman/handlers/decorate.py +++ b/src/mailman/handlers/decorate.py @@ -31,6 +31,7 @@ from email.mime.text import MIMEText from mailman.core.i18n import _ from mailman.email.message import Message from mailman.interfaces.handler import IHandler +from mailman.interfaces.mailinglist import IListArchiverSet from mailman.interfaces.templates import ITemplateLoader from mailman.utilities.string import expand from urllib.error import URLError @@ -59,19 +60,30 @@ def process(mlist, msg, msgdata): if member.user.display_name else member.address.original_email) d['user_optionsurl'] = member.options_url + # Calculate the archiver permalink substitution variables. This provides + # the $<archive-name>_url placeholder for every enabled archiver. + for archiver in IListArchiverSet(mlist).archivers: + if archiver.is_enabled: + # Get the permalink of the message from the archiver. + archive_url = archiver.system_archiver.permalink(mlist, msg) + if archive_url is not None: + placeholder = '{}_url'.format(archiver.system_archiver.name) + d[placeholder] = archive_url # These strings are descriptive for the log file and shouldn't be i18n'd d.update(msgdata.get('decoration-data', {})) try: header = decorate(mlist, mlist.header_uri, d) except URLError: + header = None log.exception('Header decorator URI not found ({0}): {1}'.format( mlist.fqdn_listname, mlist.header_uri)) try: footer = decorate(mlist, mlist.footer_uri, d) except URLError: + footer = None log.exception('Footer decorator URI not found ({0}): {1}'.format( mlist.fqdn_listname, mlist.footer_uri)) - # Escape hatch if both the footer and header are empty + # Escape hatch if both the footer and header are empty or None. if not header and not footer: return # Be MIME smart here. We only attach the header and footer by diff --git a/src/mailman/handlers/docs/decorate.rst b/src/mailman/handlers/docs/decorate.rst index bc98d3d28..e6199f8e0 100644 --- a/src/mailman/handlers/docs/decorate.rst +++ b/src/mailman/handlers/docs/decorate.rst @@ -122,6 +122,16 @@ will remain in the header or footer unchanged. $dummy footer +Adding archiver permalink URLs in the message footer +==================================================== + +You can add links to archived messages in the footer using special placeholder +variables. For all available and enabled archiver for the mailing list, use a +placeholder of the format ``$<archiver_name>_url``. For example, if you have +HyperKitty enabled you can add ``${hyperkitty_url}`` to point to the message +in HyperKitty. + + Handling RFC 3676 'format=flowed' parameters ============================================ diff --git a/src/mailman/handlers/tests/test_decorate.py b/src/mailman/handlers/tests/test_decorate.py new file mode 100644 index 000000000..c8aba63db --- /dev/null +++ b/src/mailman/handlers/tests/test_decorate.py @@ -0,0 +1,89 @@ +# Copyright (C) 2014-2015 by the Free Software Foundation, Inc. +# +# This file is part of GNU Mailman. +# +# GNU Mailman is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# GNU Mailman. If not, see <http://www.gnu.org/licenses/>. + +"""Test the decorate handler.""" + +__all__ = [ + 'TestDecorate', + ] + + +import os +import shutil +import tempfile +import unittest + +from mailman.app.lifecycle import create_list +from mailman.config import config +from mailman.handlers import decorate +from mailman.interfaces.archiver import IArchiver +from mailman.testing.helpers import specialized_message_from_string as mfs +from mailman.testing.layers import ConfigLayer +from zope.interface import implementer + + + +@implementer(IArchiver) +class TestArchiver: + """A test archiver""" + + name = 'testarchiver' + is_enabled = False + + @staticmethod + def permalink(mlist, msg): + return 'http://example.com/link_to_message' + + + +class TestDecorate(unittest.TestCase): + """Test the cook_headers handler.""" + + layer = ConfigLayer + + def setUp(self): + self._mlist = create_list('test@example.com') + self._msg = mfs("""\ +To: test@example.com +From: aperson@example.com +Message-ID: <somerandomid.example.com> +Content-Type: text/plain; + +This is a test message. +""") + template_dir = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, template_dir) + site_dir = os.path.join(template_dir, 'site', 'en') + os.makedirs(site_dir) + config.push('archiver', """\ + [paths.testing] + template_dir: {} + [archiver.testarchiver] + class: mailman.handlers.tests.test_decorate.TestArchiver + enable: yes + """.format(template_dir)) + self.addCleanup(config.pop, 'archiver') + self.footer_path = os.path.join(site_dir, 'myfooter.txt') + + def test_decorate_footer_with_archive_url(self): + with open(self.footer_path, 'w', encoding='utf-8') as fp: + print('${testarchiver_url}', file=fp) + self._mlist.footer_uri = 'mailman:///myfooter.txt' + self._mlist.preferred_language = 'en' + decorate.process(self._mlist, self._msg, {}) + self.assertIn('http://example.com/link_to_message', + self._msg.as_string()) |
