summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2012-03-03 23:29:26 -0500
committerBarry Warsaw2012-03-03 23:29:26 -0500
commit7e5470afdef0a60796cdb7974f30c46cfbfcbd4f (patch)
tree9e788a48c0aeb4553b3b1fa966fc7ecb24be22f9
parente09c13199c2a60724ee601902a51a816e627e024 (diff)
downloadmailman-7e5470afdef0a60796cdb7974f30c46cfbfcbd4f.tar.gz
mailman-7e5470afdef0a60796cdb7974f30c46cfbfcbd4f.tar.zst
mailman-7e5470afdef0a60796cdb7974f30c46cfbfcbd4f.zip
-rw-r--r--src/mailman/app/moderator.py2
-rw-r--r--src/mailman/app/notifications.py4
-rw-r--r--src/mailman/app/templates.py107
-rw-r--r--src/mailman/app/tests/test_templates.py146
-rw-r--r--src/mailman/config/configure.zcml31
-rw-r--r--src/mailman/database/schema/postgres.sql8
-rw-r--r--src/mailman/database/schema/sqlite.sql8
-rw-r--r--src/mailman/docs/NEWS.rst12
-rw-r--r--src/mailman/interfaces/mailinglist.py56
-rw-r--r--src/mailman/interfaces/templates.py46
-rw-r--r--src/mailman/model/docs/requests.rst2
-rw-r--r--src/mailman/model/mailinglist.py8
-rw-r--r--src/mailman/rest/configuration.py4
-rw-r--r--src/mailman/rest/docs/configuration.rst16
-rw-r--r--src/mailman/rest/templates.py70
-rw-r--r--src/mailman/styles/default.py8
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