summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBarry Warsaw2010-08-12 12:58:24 -0400
committerBarry Warsaw2010-08-12 12:58:24 -0400
commit81663e54791c4e0ccbf54c89b168d8b11f05eba8 (patch)
treec976878b745bb96fff834ae3959e38d6eef6b446 /src
parent255c63fd28671c6b0366ef745db0b08fdfec3267 (diff)
downloadmailman-81663e54791c4e0ccbf54c89b168d8b11f05eba8.tar.gz
mailman-81663e54791c4e0ccbf54c89b168d8b11f05eba8.tar.zst
mailman-81663e54791c4e0ccbf54c89b168d8b11f05eba8.zip
Diffstat (limited to 'src')
-rw-r--r--src/mailman/interfaces/mailinglist.py56
-rw-r--r--src/mailman/model/mailinglist.py6
-rw-r--r--src/mailman/rest/docs/configuration.txt81
-rw-r--r--src/mailman/rest/helpers.py14
-rw-r--r--src/mailman/rest/lists.py35
5 files changed, 184 insertions, 8 deletions
diff --git a/src/mailman/interfaces/mailinglist.py b/src/mailman/interfaces/mailinglist.py
index 6f88ef64c..26373eb11 100644
--- a/src/mailman/interfaces/mailinglist.py
+++ b/src/mailman/interfaces/mailinglist.py
@@ -324,6 +324,58 @@ class IMailingList(Interface):
notifications.
""")
+ # Autoresponses.
+
+ autoresponse_grace_period = Attribute(
+ """Time period (in days) between automatic responses.
+
+ When this mailing list is set to send an auto-response for messages
+ sent to mailing list posts, the mailing list owners, or the `-request`
+ address, such reponses will not be sent to the same user more than
+ once during the grace period. Set to zero (or a negative value) for
+ no grace period (i.e. auto-respond to every message).
+ """)
+
+ autorespond_owner = Attribute(
+ """How should the mailing list automatically respond to messages sent
+ to the -owner or -moderator address?
+
+ Options are:
+ * No response sent
+ * Send a response and discard the original messge
+ * Send a response and continue processing the original message
+ """)
+
+ autoresponse_owner_text = Attribute(
+ """The text sent in an autoresponse to the owner or moderator.""")
+
+ autorespond_postings = Attribute(
+ """How should the mailing list automatically respond to messages sent
+ to the list's posting address?
+
+ Options are:
+ * No response sent
+ * Send a response and discard the original messge
+ * Send a response and continue processing the original message
+ """)
+
+ autoresponse_postings_text = Attribute(
+ """The text sent in an autoresponse to the list's posting address.""")
+
+ autorespond_requests = Attribute(
+ """How should the mailing list automatically respond to messages sent
+ to the list's `-request` address?
+
+ Options are:
+ * No response sent
+ * Send a response and discard the original messge
+ * Send a response and continue processing the original message
+ """)
+
+ autoresponse_request_text = Attribute(
+ """The text sent in an autoresponse to the list's `-request`
+ address.""")
+
# Processing.
pipeline = Attribute(
@@ -386,7 +438,7 @@ class IMailingList(Interface):
to a sequence to change it, or to None to empty it. Pass types are
consulted after filter types, and only if `pass_types` is non-empty.
""")
-
+
filter_extensions = Attribute(
"""Sequence of file extensions that should be filtered out.
@@ -400,7 +452,7 @@ class IMailingList(Interface):
Pass extensions are consulted after filter extensions, and only if
`pass_extensions` is non-empty.
""")
-
+
diff --git a/src/mailman/model/mailinglist.py b/src/mailman/model/mailinglist.py
index f81b5099a..e7dec473e 100644
--- a/src/mailman/model/mailinglist.py
+++ b/src/mailman/model/mailinglist.py
@@ -93,9 +93,9 @@ class MailingList(Model):
admin_immed_notify = Bool()
admin_notify_mchanges = Bool()
administrivia = Bool()
- archive = Bool()
- archive_private = Bool()
- archive_volume_frequency = Int()
+ archive = Bool() # XXX
+ archive_private = Bool() # XXX
+ archive_volume_frequency = Int() # XXX
# Automatic responses.
autoresponse_grace_period = TimeDelta()
autorespond_owner = Enum()
diff --git a/src/mailman/rest/docs/configuration.txt b/src/mailman/rest/docs/configuration.txt
index 874372478..54d29fead 100644
--- a/src/mailman/rest/docs/configuration.txt
+++ b/src/mailman/rest/docs/configuration.txt
@@ -20,6 +20,13 @@ All readable attributes for a list are available on a sub-resource.
administrivia: True
advertised: True
anonymous_list: False
+ autorespond_owner: none
+ autorespond_postings: none
+ autorespond_requests: none
+ autoresponse_grace_period: 90d
+ autoresponse_owner_text:
+ autoresponse_postings_text:
+ autoresponse_request_text:
bounces_address: test-one-bounces@example.com
collapse_alternatives: True
convert_html_to_plaintext: False
@@ -65,6 +72,13 @@ writable attributes in one request.
... administrivia=False,
... advertised=False,
... anonymous_list=True,
+ ... autorespond_owner='respond_and_discard',
+ ... autorespond_postings='respond_and_continue',
+ ... autorespond_requests='respond_and_discard',
+ ... autoresponse_grace_period='45d',
+ ... autoresponse_owner_text='the owner',
+ ... autoresponse_postings_text='the mailing list',
+ ... autoresponse_request_text='the robot',
... real_name='Fnords',
... include_rfc2369_headers=False,
... include_list_post_header=False,
@@ -89,6 +103,13 @@ These values are changed permanently.
administrivia: False
advertised: False
anonymous_list: True
+ autorespond_owner: respond_and_discard
+ autorespond_postings: respond_and_continue
+ autorespond_requests: respond_and_discard
+ autoresponse_grace_period: 45d
+ autoresponse_owner_text: the owner
+ autoresponse_postings_text: the mailing list
+ autoresponse_request_text: the robot
...
collapse_alternatives: False
convert_html_to_plaintext: True
@@ -115,6 +136,13 @@ be included. It is an error to leave one out (e.g. `pipeline`)...
... administrivia=False,
... advertised=False,
... anonymous_list=True,
+ ... autorespond_owner='respond_and_discard',
+ ... autorespond_postings='respond_and_continue',
+ ... autorespond_requests='respond_and_discard',
+ ... autoresponse_grace_period='45d',
+ ... autoresponse_owner_text='the owner',
+ ... autoresponse_postings_text='the mailing list',
+ ... autoresponse_request_text='the robot',
... real_name='Fnords',
... include_rfc2369_headers=False,
... include_list_post_header=False,
@@ -140,6 +168,13 @@ be included. It is an error to leave one out (e.g. `pipeline`)...
... administrivia=False,
... advertised=False,
... anonymous_list=True,
+ ... autorespond_owner='respond_and_discard',
+ ... autorespond_postings='respond_and_continue',
+ ... autorespond_requests='respond_and_discard',
+ ... autoresponse_grace_period='45d',
+ ... autoresponse_owner_text='the owner',
+ ... autoresponse_postings_text='the mailing list',
+ ... autoresponse_request_text='the robot',
... real_name='Fnords',
... include_rfc2369_headers=False,
... include_list_post_header=False,
@@ -164,6 +199,13 @@ It is also an error to spell an attribute value incorrectly...
... administrivia=False,
... advertised=False,
... anonymous_list=True,
+ ... autorespond_owner='respond_and_discard',
+ ... autorespond_postings='respond_and_continue',
+ ... autorespond_requests='respond_and_discard',
+ ... autoresponse_grace_period='45d',
+ ... autoresponse_owner_text='the owner',
+ ... autoresponse_postings_text='the mailing list',
+ ... autoresponse_request_text='the robot',
... real_name='Fnords',
... include_rfc2369_headers=False,
... include_list_post_header=False,
@@ -178,7 +220,7 @@ It is also an error to spell an attribute value incorrectly...
...
HTTPError: HTTP Error 400: Bad Request
-...or to name a pipeline that doesn't exist.
+...or to name a pipeline that doesn't exist...
>>> dump_json('http://localhost:8001/3.0/lists/'
... 'test-one@example.com/config',
@@ -187,6 +229,43 @@ It is also an error to spell an attribute value incorrectly...
... admin_notify_mchanges=True,
... advertised=False,
... anonymous_list=True,
+ ... autorespond_owner='respond_and_discard',
+ ... autorespond_postings='respond_and_continue',
+ ... autorespond_requests='respond_and_discard',
+ ... autoresponse_grace_period='45d',
+ ... autoresponse_owner_text='the owner',
+ ... autoresponse_postings_text='the mailing list',
+ ... autoresponse_request_text='the robot',
+ ... real_name='Fnords',
+ ... include_rfc2369_headers=False,
+ ... include_list_post_header=False,
+ ... digest_size_threshold=10.5,
+ ... pipeline='dummy',
+ ... filter_content=True,
+ ... convert_html_to_plaintext=True,
+ ... collapse_alternatives=False,
+ ... ),
+ ... 'PUT')
+ Traceback (most recent call last):
+ ...
+ HTTPError: HTTP Error 400: Bad Request
+
+...or to name an invalid auto-response enumeration value.
+
+ >>> dump_json('http://localhost:8001/3.0/lists/'
+ ... 'test-one@example.com/config',
+ ... dict(
+ ... admin_immed_notify=False,
+ ... admin_notify_mchanges=True,
+ ... advertised=False,
+ ... anonymous_list=True,
+ ... autorespond_owner='do_not_respond',
+ ... autorespond_postings='respond_and_continue',
+ ... autorespond_requests='respond_and_discard',
+ ... autoresponse_grace_period='45d',
+ ... autoresponse_owner_text='the owner',
+ ... autoresponse_postings_text='the mailing list',
+ ... autoresponse_request_text='the robot',
... real_name='Fnords',
... include_rfc2369_headers=False,
... include_list_post_header=False,
diff --git a/src/mailman/rest/helpers.py b/src/mailman/rest/helpers.py
index 4bef720ef..c6a020f61 100644
--- a/src/mailman/rest/helpers.py
+++ b/src/mailman/rest/helpers.py
@@ -32,7 +32,8 @@ __all__ = [
import json
import hashlib
-from datetime import datetime
+from datetime import datetime, timedelta
+from flufl.enum import Enum
from lazr.config import as_boolean
from restish.http import Response
from restish.resource import MethodDecorator
@@ -69,6 +70,17 @@ class ExtendedEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
+ elif isinstance(obj, timedelta):
+ # as_timedelta() does not recognize microseconds, so convert these
+ # to floating seconds, but only if there are any seconds.
+ if obj.seconds > 0 or obj.microseconds > 0:
+ seconds = obj.seconds + obj.microseconds / 1000000.0
+ return '{0}d{1}s'.format(obj.days, seconds)
+ return '{0}d'.format(obj.days)
+ elif hasattr(obj, 'enumclass') and issubclass(obj.enumclass, Enum):
+ # It's up to the decoding validator to associate this name with
+ # the right Enum class.
+ return obj.enumname
return json.JSONEncoder.default(self, obj)
diff --git a/src/mailman/rest/lists.py b/src/mailman/rest/lists.py
index 464b3a717..26aabbf49 100644
--- a/src/mailman/rest/lists.py
+++ b/src/mailman/rest/lists.py
@@ -27,12 +27,17 @@ __all__ = [
]
-from lazr.config import as_boolean
+import os
+import sys
+
+from lazr.config import as_boolean, as_timedelta
+from pkg_resources import resource_listdir
from restish import http, resource
from zope.component import getUtility
from mailman.app.lifecycle import create_list, remove_list
from mailman.config import config
+from mailman.interfaces.autorespond import ResponseAction
from mailman.interfaces.domain import BadDomainSpecificationError
from mailman.interfaces.listmanager import (
IListManager, ListAlreadyExistsError)
@@ -247,6 +252,14 @@ READABLE = (
# Notifications.
'admin_immed_notify',
'admin_notify_mchanges',
+ # Automatic responses.
+ 'autoresponse_grace_period',
+ 'autorespond_owner',
+ 'autoresponse_owner_text',
+ 'autorespond_postings',
+ 'autoresponse_postings_text',
+ 'autorespond_requests',
+ 'autoresponse_request_text',
# Processing.
'pipeline',
'administrivia',
@@ -263,6 +276,18 @@ def pipeline_validator(pipeline_name):
raise ValueError('Unknown pipeline: {0}'.format(pipeline_name))
+class enum_validator:
+ """Convert an enum value name into an enum value."""
+
+ def __init__(self, enum_class):
+ self._enum_class = enum_class
+
+ def __call__(self, enum_value):
+ # This will raise a ValueError if the enum value is unknown. Let that
+ # percolate up.
+ return self._enum_class[enum_value]
+
+
VALIDATORS = {
# Identity.
'real_name': unicode,
@@ -275,6 +300,14 @@ VALIDATORS = {
# Notifications.
'admin_immed_notify': as_boolean,
'admin_notify_mchanges': as_boolean,
+ # Automatic responses.
+ 'autoresponse_grace_period': as_timedelta,
+ 'autorespond_owner': enum_validator(ResponseAction),
+ 'autoresponse_owner_text': unicode,
+ 'autorespond_postings': enum_validator(ResponseAction),
+ 'autoresponse_postings_text': unicode,
+ 'autorespond_requests': enum_validator(ResponseAction),
+ 'autoresponse_request_text': unicode,
# Processing.
'pipeline': pipeline_validator,
'administrivia': as_boolean,