diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mailman/app/moderator.py | 2 | ||||
| -rw-r--r-- | src/mailman/app/notifications.py | 4 | ||||
| -rw-r--r-- | src/mailman/app/templates.py | 107 | ||||
| -rw-r--r-- | src/mailman/app/tests/test_templates.py | 146 | ||||
| -rw-r--r-- | src/mailman/config/configure.zcml | 31 | ||||
| -rw-r--r-- | src/mailman/database/schema/postgres.sql | 8 | ||||
| -rw-r--r-- | src/mailman/database/schema/sqlite.sql | 8 | ||||
| -rw-r--r-- | src/mailman/docs/NEWS.rst | 12 | ||||
| -rw-r--r-- | src/mailman/interfaces/mailinglist.py | 56 | ||||
| -rw-r--r-- | src/mailman/interfaces/templates.py | 46 | ||||
| -rw-r--r-- | src/mailman/model/docs/requests.rst | 2 | ||||
| -rw-r--r-- | src/mailman/model/mailinglist.py | 8 | ||||
| -rw-r--r-- | src/mailman/rest/configuration.py | 4 | ||||
| -rw-r--r-- | src/mailman/rest/docs/configuration.rst | 16 | ||||
| -rw-r--r-- | src/mailman/rest/templates.py | 70 | ||||
| -rw-r--r-- | src/mailman/styles/default.py | 8 |
16 files changed, 485 insertions, 43 deletions
diff --git a/src/mailman/app/moderator.py b/src/mailman/app/moderator.py index 3c3603619..01dc4a232 100644 --- a/src/mailman/app/moderator.py +++ b/src/mailman/app/moderator.py @@ -260,7 +260,7 @@ def handle_subscription(mlist, id, action, comment=None): # request was made and accepted. pass else: - if mlist.send_welcome_msg: + if mlist.send_welcome_message: send_welcome_message(mlist, address, language, delivery_mode) if mlist.admin_notify_mchanges: send_admin_subscription_notice( diff --git a/src/mailman/app/notifications.py b/src/mailman/app/notifications.py index c5d50d5e3..78801402b 100644 --- a/src/mailman/app/notifications.py +++ b/src/mailman/app/notifications.py @@ -54,8 +54,8 @@ def send_welcome_message(mlist, address, language, delivery_mode, text=''): :param delivery_mode: the type of delivery the subscriber is getting :type delivery_mode: DeliveryMode """ - if mlist.welcome_msg: - welcome = wrap(mlist.welcome_msg) + '\n' + if mlist.welcome_message_uri: + welcome = wrap(mlist.welcome_message_uri) + '\n' else: welcome = '' # Find the IMember object which is subscribed to the mailing list, because diff --git a/src/mailman/app/templates.py b/src/mailman/app/templates.py new file mode 100644 index 000000000..61880da12 --- /dev/null +++ b/src/mailman/app/templates.py @@ -0,0 +1,107 @@ +# Copyright (C) 2012 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/>. + +"""Template loader.""" + +from __future__ import absolute_import, print_function, unicode_literals + +__metaclass__ = type +__all__ = [ + 'TemplateLoader', + ] + + +import urllib2 + +from contextlib import closing +from urllib import addinfourl +from urlparse import urlparse +from zope.component import getUtility +from zope.interface import implements + +from mailman.utilities.i18n import TemplateNotFoundError, find +from mailman.interfaces.languages import ILanguageManager +from mailman.interfaces.listmanager import IListManager +from mailman.interfaces.templates import ITemplateLoader + + + +class MailmanHandler(urllib2.BaseHandler): + # Handle internal mailman: URLs. + def mailman_open(self, req): + # Parse urls of the form: + # + # mailman:///<fqdn_listname>/<language>/<template_name> + # + # where only the template name is required. + mlist = code = template = None + # Parse the full requested URL and be sure it's something we handle. + original_url = req.get_full_url() + parsed = urlparse(original_url) + assert(parsed.scheme == 'mailman') + # The path can contain one, two, or three components. Since no empty + # path components are legal, filter them out. + parts = filter(None, parsed.path.split('/')) + if len(parts) == 0: + raise urllib2.URLError('No template specified') + elif len(parts) == 1: + template = parts[0] + elif len(parts) == 2: + part0, template = parts + # Is part0 a language code or a mailing list? It better be one or + # the other, and there's no possibility of namespace collisions + # because language codes don't contain @ and mailing list names + # MUST contain @. + language = getUtility(ILanguageManager).get(part0) + mlist = getUtility(IListManager).get(part0) + if language is None and mlist is None: + raise urllib2.URLError('Bad language or list name') + elif mlist is None: + code = language.code + elif len(parts) == 3: + fqdn_listname, code, template = parts + mlist = getUtility(IListManager).get(fqdn_listname) + if mlist is None: + raise urllib2.URLError('Missing list') + language = getUtility(ILanguageManager).get(code) + if language is None: + raise urllib2.URLError('No such language') + code = language.code + else: + raise urllib2.URLError('No such file') + # Find the template, mutating any missing template exception. + try: + path, fp = find(template, mlist, code) + except TemplateNotFoundError: + raise urllib2.URLError('No such file') + return addinfourl(fp, {}, original_url) + + + +class TemplateLoader: + """Loader of templates, with caching and support for mailman:// URIs.""" + + implements(ITemplateLoader) + + def __init__(self): + opener = urllib2.build_opener(MailmanHandler()) + urllib2.install_opener(opener) + + def get(self, uri): + """See `ITemplateLoader`.""" + with closing(urllib2.urlopen(uri)) as fp: + return fp.read() diff --git a/src/mailman/app/tests/test_templates.py b/src/mailman/app/tests/test_templates.py new file mode 100644 index 000000000..6dfbd7109 --- /dev/null +++ b/src/mailman/app/tests/test_templates.py @@ -0,0 +1,146 @@ +# Copyright (C) 2012 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 template downloader API.""" + +from __future__ import absolute_import, print_function, unicode_literals + +__metaclass__ = type +__all__ = [ + 'TestTemplateLoader', + ] + + +import os +import shutil +import urllib2 +import tempfile +import unittest + +from zope.component import getUtility + +from mailman.app.lifecycle import create_list +from mailman.config import config +from mailman.interfaces.languages import ILanguageManager +from mailman.interfaces.templates import ITemplateLoader +from mailman.testing.layers import ConfigLayer + + + +class TestTemplateLoader(unittest.TestCase): + """Test the template downloader API.""" + + layer = ConfigLayer + + def setUp(self): + self.var_dir = tempfile.mkdtemp() + config.push('template config', """\ + [paths.testing] + var_dir: {0} + """.format(self.var_dir)) + # Put a demo template in the site directory. + path = os.path.join(self.var_dir, 'templates', 'site', 'en') + os.makedirs(path) + with open(os.path.join(path, 'demo.txt'), 'w') as fp: + print('Test content', end='', file=fp) + self._loader = getUtility(ITemplateLoader) + getUtility(ILanguageManager).add('it', 'utf-8', 'Italian') + self._mlist = create_list('test@example.com') + + def tearDown(self): + config.pop('template config') + shutil.rmtree(self.var_dir) + + def test_mailman_internal_uris(self): + # mailman://demo.txt + content = self._loader.get('mailman:///demo.txt') + self.assertEqual(content, 'Test content') + + def test_mailman_internal_uris_twice(self): + # mailman:///demo.txt + content = self._loader.get('mailman:///demo.txt') + self.assertEqual(content, 'Test content') + content = self._loader.get('mailman:///demo.txt') + self.assertEqual(content, 'Test content') + + def test_mailman_uri_with_language(self): + content = self._loader.get('mailman:///en/demo.txt') + self.assertEqual(content, 'Test content') + + def test_mailman_uri_with_english_fallback(self): + content = self._loader.get('mailman:///it/demo.txt') + self.assertEqual(content, 'Test content') + + def test_mailman_uri_with_list_name(self): + content = self._loader.get('mailman:///test@example.com/demo.txt') + self.assertEqual(content, 'Test content') + + def test_mailman_full_uri(self): + content = self._loader.get('mailman:///test@example.com/en/demo.txt') + self.assertEqual(content, 'Test content') + + def test_mailman_full_uri_with_english_fallback(self): + content = self._loader.get('mailman:///test@example.com/it/demo.txt') + self.assertEqual(content, 'Test content') + + def test_uri_not_found(self): + try: + self._loader.get('mailman:///missing.txt') + except urllib2.URLError as error: + self.assertEqual(error.reason, 'No such file') + else: + raise AssertionError('Exception expected') + + def test_shorter_url_error(self): + try: + self._loader.get('mailman:///') + except urllib2.URLError as error: + self.assertEqual(error.reason, 'No template specified') + else: + raise AssertionError('Exception expected') + + def test_short_url_error(self): + try: + self._loader.get('mailman://') + except urllib2.URLError as error: + self.assertEqual(error.reason, 'No template specified') + else: + raise AssertionError('Exception expected') + + def test_bad_language(self): + try: + self._loader.get('mailman:///xx/demo.txt') + except urllib2.URLError as error: + self.assertEqual(error.reason, 'Bad language or list name') + else: + raise AssertionError('Exception expected') + + def test_bad_mailing_list(self): + try: + self._loader.get('mailman:///missing@example.com/demo.txt') + except urllib2.URLError as error: + self.assertEqual(error.reason, 'Bad language or list name') + else: + raise AssertionError('Exception expected') + + def test_too_many_path_components(self): + try: + self._loader.get('mailman:///missing@example.com/en/foo/demo.txt') + except urllib2.URLError as error: + self.assertEqual(error.reason, 'No such file') + else: + raise AssertionError('Exception expected') diff --git a/src/mailman/config/configure.zcml b/src/mailman/config/configure.zcml index aad79adaf..8c362c31b 100644 --- a/src/mailman/config/configure.zcml +++ b/src/mailman/config/configure.zcml @@ -23,68 +23,73 @@ /> <utility - factory="mailman.model.bans.BanManager" provides="mailman.interfaces.bans.IBanManager" + factory="mailman.model.bans.BanManager" /> <utility - factory="mailman.model.bounce.BounceProcessor" provides="mailman.interfaces.bounce.IBounceProcessor" + factory="mailman.model.bounce.BounceProcessor" /> <utility - factory="mailman.model.domain.DomainManager" provides="mailman.interfaces.domain.IDomainManager" + factory="mailman.model.domain.DomainManager" /> <utility - factory="mailman.languages.manager.LanguageManager" provides="mailman.interfaces.languages.ILanguageManager" + factory="mailman.languages.manager.LanguageManager" /> <utility - factory="mailman.model.listmanager.ListManager" provides="mailman.interfaces.listmanager.IListManager" + factory="mailman.model.listmanager.ListManager" /> <utility - factory="mailman.mta.aliases.MailTransportAgentAliases" provides="mailman.interfaces.mta.IMailTransportAgentAliases" + factory="mailman.mta.aliases.MailTransportAgentAliases" /> <utility - factory="mailman.model.messagestore.MessageStore" provides="mailman.interfaces.messages.IMessageStore" + factory="mailman.model.messagestore.MessageStore" /> <utility - factory="mailman.model.pending.Pendings" provides="mailman.interfaces.pending.IPendings" + factory="mailman.model.pending.Pendings" /> <utility - factory="mailman.app.registrar.Registrar" provides="mailman.interfaces.registrar.IRegistrar" + factory="mailman.app.registrar.Registrar" /> <utility - factory="mailman.styles.manager.StyleManager" provides="mailman.interfaces.styles.IStyleManager" + factory="mailman.styles.manager.StyleManager" /> <utility - factory="mailman.app.subscriptions.SubscriptionService" provides="mailman.interfaces.subscriptions.ISubscriptionService" + factory="mailman.app.subscriptions.SubscriptionService" /> <utility - factory="mailman.model.usermanager.UserManager" provides="mailman.interfaces.usermanager.IUserManager" + factory="mailman.model.usermanager.UserManager" /> <utility - factory="mailman.email.validate.Validator" provides="mailman.interfaces.address.IEmailValidator" + factory="mailman.email.validate.Validator" /> + <utility + provides="mailman.interfaces.templates.ITemplateLoader" + factory="mailman.app.templates.TemplateLoader" + /> + </configure> diff --git a/src/mailman/database/schema/postgres.sql b/src/mailman/database/schema/postgres.sql index bb209c4aa..206f8f76f 100644 --- a/src/mailman/database/schema/postgres.sql +++ b/src/mailman/database/schema/postgres.sql @@ -63,7 +63,7 @@ CREATE TABLE mailinglist ( gateway_to_mail BOOLEAN, gateway_to_news BOOLEAN, generic_nonmember_action INTEGER, - goodbye_msg TEXT, + goodbye_message_uri TEXT, header_matches BYTEA, hold_these_nonmembers BYTEA, info TEXT, @@ -95,9 +95,9 @@ CREATE TABLE mailinglist ( require_explicit_destination BOOLEAN, respond_to_post_requests BOOLEAN, scrub_nondigest BOOLEAN, - send_goodbye_msg BOOLEAN, + send_goodbye_message BOOLEAN, send_reminders BOOLEAN, - send_welcome_msg BOOLEAN, + send_welcome_message BOOLEAN, start_chain TEXT, subject_prefix TEXT, subscribe_auto_approval BYTEA, @@ -106,7 +106,7 @@ CREATE TABLE mailinglist ( topics_bodylines_limit INTEGER, topics_enabled BOOLEAN, unsubscribe_policy INTEGER, - welcome_msg TEXT, + welcome_message_uri TEXT, moderation_callback TEXT, PRIMARY KEY (id) ); diff --git a/src/mailman/database/schema/sqlite.sql b/src/mailman/database/schema/sqlite.sql index 74d523cf2..d5ef06f0f 100644 --- a/src/mailman/database/schema/sqlite.sql +++ b/src/mailman/database/schema/sqlite.sql @@ -159,7 +159,7 @@ CREATE TABLE mailinglist ( gateway_to_mail BOOLEAN, gateway_to_news BOOLEAN, generic_nonmember_action INTEGER, - goodbye_msg TEXT, + goodbye_message_uri TEXT, header_matches BLOB, hold_these_nonmembers BLOB, info TEXT, @@ -191,9 +191,9 @@ CREATE TABLE mailinglist ( require_explicit_destination BOOLEAN, respond_to_post_requests BOOLEAN, scrub_nondigest BOOLEAN, - send_goodbye_msg BOOLEAN, + send_goodbye_message BOOLEAN, send_reminders BOOLEAN, - send_welcome_msg BOOLEAN, + send_welcome_message BOOLEAN, start_chain TEXT, subject_prefix TEXT, subscribe_auto_approval BLOB, @@ -202,7 +202,7 @@ CREATE TABLE mailinglist ( topics_bodylines_limit INTEGER, topics_enabled BOOLEAN, unsubscribe_policy INTEGER, - welcome_msg TEXT, + welcome_message_uri TEXT, PRIMARY KEY (id) ); diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst index 2b4deb9c2..243d99163 100644 --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -25,6 +25,17 @@ Architecture is now used when search for all template overrides, site, domain, or mailing list. The in-tree English templates are used only as a last fallback. + * Support downloading templates by URI, including mailman:// URIs. This is + used in welcome and goodbye messages, and supports both language and + mailing list specifications. E.g. mailman:///test@example.com/it/welc.txt + +Database +-------- + * Schema changes: + - welcome_msg -> welcome_message_uri + - goodbye_msg -> goodbye_message_uri + - send_welcome_msg -> send_welcome_message + - send_goodbye_msg -> send_goodbye_message REST ---- @@ -46,6 +57,7 @@ Interfaces `Action.defer` (since the message is already being held). * `IListRequests.get_request()` now takes an optional `request_type` argument to narrow the search for the given request. + * New `ITemplateLoader` utility. Commands -------- diff --git a/src/mailman/interfaces/mailinglist.py b/src/mailman/interfaces/mailinglist.py index 69f50cf42..a7a964a06 100644 --- a/src/mailman/interfaces/mailinglist.py +++ b/src/mailman/interfaces/mailinglist.py @@ -516,6 +516,62 @@ class IMailingList(Interface): process_bounces = Attribute( """Whether or not the mailing list processes bounces.""") + # Notifications. + + send_welcome_message = Attribute( + """Flag indicating whether a welcome message should be sent.""") + + welcome_message_uri = Attribute( + """URI for the list's welcome message. + + This can be any URI supported by `httplib2` with the addition of + `mailman:` URIs, which reference internal default resources. This is + a template which can include the following placeholders: + + $listname - the FQDN list name for this mailing list. + $language - the language code, usually the list's preferred language. + + The resource will be downloaded and cached whenever the welcome + message is sent. The resource at this URI can contain the following + placeholders, which are also filled in through values on the mailing + list: + + $fqdn_listname - the FQDN list name for this mailing list. + $list_name - the human readable name for the mailing list. + $listinfo_uri - the URI to the list's information page. + $list_requests - the address to the list's `-request` address. + $user_name - the name of the subscribing user. + $user_address - the email address of the subscribing user. + $user_options_uri - the URI to this member's options page. + """) + + send_goodbye_message = Attribute( + """Flag indicating whether a goodbye message should be sent.""") + + goodbye_message_uri = Attribute( + """URI for the list's goodbye message. + + This can be any URI supported by `httplib2` with the addition of + `mailman:` URIs, which reference internal default resources. This is + a template which can include the following placeholders: + + $listname - the FQDN list name for this mailing list. + $language - the language code, usually the list's preferred language. + + The resource will be downloaded and cached whenever the welcome + message is sent. The resource at this URI can contain the following + placeholders, which are also filled in through values on the mailing + list: + + $fqdn_listname - the FQDN list name for this mailing list. + $list_name - the human readable name for the mailing list. + $listinfo_uri - the URI to the list's information page. + $list_requests - the address to the list's `-request` address. + $user_name - the name of the subscribing user. + $user_address - the email address of the subscribing user. + $user_options_uri - the URI to this member's options page. + """) + class IAcceptableAlias(Interface): diff --git a/src/mailman/interfaces/templates.py b/src/mailman/interfaces/templates.py new file mode 100644 index 000000000..a42f9f98e --- /dev/null +++ b/src/mailman/interfaces/templates.py @@ -0,0 +1,46 @@ +# Copyright (C) 2012 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/>. + +"""Template downloader with cache.""" + +from __future__ import absolute_import, print_function, unicode_literals + +__metaclass__ = type +__all__ = [ + 'ITemplateLoader', + ] + + +from zope.interface import Interface + + + +class ITemplateLoader(Interface): + """The template downloader utility.""" + + def get(uri): + """Download the named URI, and return the response and content. + + This API uses `urllib2`_ so consult its documentation for details. + + .. _`urllib2`: http://docs.python.org/library/urllib2.html + + :param uri: The URI of the resource. These may be any URI supported + by `urllib2` and also `mailman:` URIs for internal resources. + :type uri: string + :return: An open file object as defined by urllib2. + """ diff --git a/src/mailman/model/docs/requests.rst b/src/mailman/model/docs/requests.rst index 01fbfdc91..cf4eb90ac 100644 --- a/src/mailman/model/docs/requests.rst +++ b/src/mailman/model/docs/requests.rst @@ -540,7 +540,7 @@ subscriber. The subscription can also be accepted. This subscribes the address to the mailing list. - >>> mlist.send_welcome_msg = True + >>> mlist.send_welcome_message = True >>> id_4 = moderator.hold_subscription(mlist, ... 'fperson@example.org', 'Frank Person', ... 'abcxyz', DeliveryMode.regular, 'en') diff --git a/src/mailman/model/mailinglist.py b/src/mailman/model/mailinglist.py index 57b1ad9e4..fd7410465 100644 --- a/src/mailman/model/mailinglist.py +++ b/src/mailman/model/mailinglist.py @@ -147,7 +147,7 @@ class MailingList(Model): gateway_to_mail = Bool() gateway_to_news = Bool() generic_nonmember_action = Int() - goodbye_msg = Unicode() + goodbye_message_uri = Unicode() header_matches = Pickle() hold_these_nonmembers = Pickle() info = Unicode() @@ -179,9 +179,9 @@ class MailingList(Model): require_explicit_destination = Bool() respond_to_post_requests = Bool() scrub_nondigest = Bool() - send_goodbye_msg = Bool() + send_goodbye_message = Bool() send_reminders = Bool() - send_welcome_msg = Bool() + send_welcome_message = Bool() start_chain = Unicode() subject_prefix = Unicode() subscribe_auto_approval = Pickle() @@ -190,7 +190,7 @@ class MailingList(Model): topics_bodylines_limit = Int() topics_enabled = Bool() unsubscribe_policy = Int() - welcome_msg = Unicode() + welcome_message_uri = Unicode() def __init__(self, fqdn_listname): super(MailingList, self).__init__() diff --git a/src/mailman/rest/configuration.py b/src/mailman/rest/configuration.py index 4bff37d83..028ee86fa 100644 --- a/src/mailman/rest/configuration.py +++ b/src/mailman/rest/configuration.py @@ -199,10 +199,10 @@ ATTRIBUTES = dict( reply_goes_to_list=GetterSetter(enum_validator(ReplyToMunging)), request_address=GetterSetter(None), scheme=GetterSetter(None), - send_welcome_msg=GetterSetter(as_boolean), + send_welcome_message=GetterSetter(as_boolean), volume=GetterSetter(None), web_host=GetterSetter(None), - welcome_msg=GetterSetter(unicode), + welcome_message_uri=GetterSetter(unicode), ) diff --git a/src/mailman/rest/docs/configuration.rst b/src/mailman/rest/docs/configuration.rst index 55b732172..5f59a1915 100644 --- a/src/mailman/rest/docs/configuration.rst +++ b/src/mailman/rest/docs/configuration.rst @@ -58,10 +58,10 @@ All readable attributes for a list are available on a sub-resource. reply_goes_to_list: no_munging request_address: test-one-request@example.com scheme: http - send_welcome_msg: True + send_welcome_message: True volume: 1 web_host: lists.example.com - welcome_msg: + welcome_message_uri: Changing the full configuration @@ -98,8 +98,8 @@ all the writable attributes in one request. ... convert_html_to_plaintext=True, ... collapse_alternatives=False, ... reply_goes_to_list='point_to_list', - ... send_welcome_msg=False, - ... welcome_msg='Welcome!', + ... send_welcome_message=False, + ... welcome_message_uri='Welcome!', ... default_member_action='hold', ... default_nonmember_action='discard', ... generic_nonmember_action=2, @@ -146,9 +146,9 @@ These values are changed permanently. real_name: Fnords reply_goes_to_list: point_to_list ... - send_welcome_msg: False + send_welcome_message: False ... - welcome_msg: Welcome! + welcome_message_uri: Welcome! If you use ``PUT`` to change a list's configuration, all writable attributes must be included. It is an error to leave one or more out... @@ -179,8 +179,8 @@ must be included. It is an error to leave one or more out... ... convert_html_to_plaintext=True, ... collapse_alternatives=False, ... reply_goes_to_list='point_to_list', - ... send_welcome_msg=True, - ... welcome_msg='welcome message', + ... send_welcome_message=True, + ... welcome_message_uri='welcome message', ... default_member_action='accept', ... default_nonmember_action='accept', ... generic_nonmember_action=2, diff --git a/src/mailman/rest/templates.py b/src/mailman/rest/templates.py new file mode 100644 index 000000000..35e331199 --- /dev/null +++ b/src/mailman/rest/templates.py @@ -0,0 +1,70 @@ +# Copyright (C) 2012 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/>. + +"""Template finder.""" + +from __future__ import absolute_import, print_function, unicode_literals + +__metaclass__ = type +__all__ = [ + 'TemplateFinder', + ] + + +import os + +from restish import http, resource + +from mailman.config import config +from mailman.utilities.i18n import TemplateNotFoundError, find + + +# Use mimetypes.guess_all_extensions()? +EXTENSIONS = { + 'text/plain': '.txt', + 'text/html': '.html', + } + + + +class TemplateFinder(resource.Resource): + """Template finder resource.""" + + def __init__(self, mlist, template, language, content_type): + self.mlist = mlist + self.template = template + self.language = language + self.content_type = content_type + + @resource.GET() + def find_template(self, request): + # XXX We currently only support .txt and .html files. + extension = EXTENSIONS.get(self.content_type) + if extension is None: + return http.not_found() + template = self.template + extension + fp = None + try: + try: + path, fp = find(template, self.mlist, self.language) + except TemplateNotFoundError: + return http.not_found() + else: + return fp.read() + finally: + if fp is not None: + fp.close() diff --git a/src/mailman/styles/default.py b/src/mailman/styles/default.py index be5f89000..674b0a91f 100644 --- a/src/mailman/styles/default.py +++ b/src/mailman/styles/default.py @@ -74,8 +74,8 @@ class DefaultStyle: mlist.admin_notify_mchanges = False mlist.require_explicit_destination = True mlist.send_reminders = True - mlist.send_welcome_msg = True - mlist.send_goodbye_msg = True + mlist.send_welcome_message = True + mlist.send_goodbye_message = True mlist.bounce_matching_headers = """ # Lines that *start* with a '#' are comments. to: friend@public.com @@ -87,8 +87,8 @@ from: .*@uplinkpro.com mlist.anonymous_list = False mlist.description = '' mlist.info = '' - mlist.welcome_msg = '' - mlist.goodbye_msg = '' + mlist.welcome_message_uri = '' + mlist.goodbye_message_uri = '' mlist.subscribe_policy = 1 mlist.subscribe_auto_approval = [] mlist.unsubscribe_policy = 0 |
