summaryrefslogtreecommitdiff
path: root/Mailman/docs/hold.txt
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman/docs/hold.txt')
-rw-r--r--Mailman/docs/hold.txt362
1 files changed, 0 insertions, 362 deletions
diff --git a/Mailman/docs/hold.txt b/Mailman/docs/hold.txt
deleted file mode 100644
index a93953435..000000000
--- a/Mailman/docs/hold.txt
+++ /dev/null
@@ -1,362 +0,0 @@
-Holding messages
-================
-
-One of the most important functions of Mailman is to moderate messages by
-holding some for approval before they will post to the mailing list. Messages
-are held when they meet any of a number of criteria.
-
- >>> import os
- >>> import errno
- >>> from Mailman.Handlers.Hold import process
- >>> from Mailman.queue import Switchboard
- >>> from Mailman.configuration import config
- >>> mlist = config.db.list_manager.create(u'_xtest@example.com')
- >>> mlist.preferred_language = u'en'
- >>> mlist.real_name = u'_XTest'
- >>> # XXX This will almost certainly change once we've worked out the web
- >>> # space layout for mailing lists now.
- >>> mlist.web_page_url = u'http://lists.example.com/'
-
-Here's a helper function used when we don't care about what's in the virgin
-queue or in the pending database.
-
- >>> switchboard = Switchboard(config.VIRGINQUEUE_DIR)
- >>> def clear():
- ... for filebase in switchboard.files:
- ... msg, msgdata = switchboard.dequeue(filebase)
- ... switchboard.finish(filebase)
- ... for holdfile in os.listdir(config.DATA_DIR):
- ... if holdfile.startswith('heldmsg-'):
- ... os.unlink(os.path.join(config.DATA_DIR, holdfile))
- ... try:
- ... os.unlink(os.path.join(config.DATA_DIR, 'pending.db'))
- ... except OSError, e:
- ... if e.errno <> errno.ENOENT:
- ... raise
-
-
-Short circuiting
-----------------
-
-If the message metadata indicates that the message is pre-approved, then the
-handler returns immediately.
-
- >>> msg = message_from_string("""\
- ... From: aperson@example.com
- ...
- ... An important message.
- ... """)
- >>> msgdata = {'approved': True}
- >>> process(mlist, msg, msgdata)
- >>> print msg.as_string()
- From: aperson@example.com
- <BLANKLINE>
- An important message.
- <BLANKLINE>
- >>> msgdata
- {'approved': True}
-
-
-Administrivia
--------------
-
-Mailman scans parts of the message for administrivia, meaning text that looks
-like an email command. This is to prevent people sending 'help' or
-'subscribe' message, etc. to the list members. First, we enable the scanning
-of administrivia for the list.
-
- >>> mlist.administrivia = True
- >>> msg = message_from_string("""\
- ... From: aperson@example.com
- ... Subject: unsubscribe
- ...
- ... """)
- >>> process(mlist, msg, {})
- Traceback (most recent call last):
- ...
- Administrivia
- >>> clear()
-
-
-Maximum number of recipients
-----------------------------
-
-Mailman will hold messages that have more than a specified number of explicit
-recipients.
-
- >>> mlist.max_num_recipients = 5
- >>> msg = message_from_string("""\
- ... From: aperson@example.com
- ... To: _xtest@example.com, bperson@example.com
- ... Cc: cperson@example.com
- ... Cc: dperson@example.com (Dan Person)
- ... To: Elly Q. Person <eperson@example.com>
- ...
- ... Hey folks!
- ... """)
- >>> process(mlist, msg, {})
- Traceback (most recent call last):
- ...
- TooManyRecipients
- >>> clear()
-
-
-Implicit destination
---------------------
-
-Mailman will hold messages that have implicit destination, meaning that the
-mailing list's posting address isn't included in the explicit recipients.
-
- >>> mlist.require_explicit_destination = True
- >>> mlist.acceptable_aliases = u''
- >>> msg = message_from_string("""\
- ... From: aperson@example.org
- ... Subject: An implicit message
- ...
- ... """)
- >>> process(mlist, msg, {})
- Traceback (most recent call last):
- ...
- ImplicitDestination
- >>> clear()
-
-A message gated from NNTP will obviously have an implicit destination. Such
-gated messages will not be held for implicit destination because it's assumed
-that Mailman pulled it from the appropriate news group.
-
- >>> msgdata = {'fromusenet': True}
- >>> process(mlist, msg, msgdata)
- >>> print msg.as_string()
- From: aperson@example.org
- Subject: An implicit message
- Message-ID: ...
- X-Message-ID-Hash: ...
- <BLANKLINE>
- <BLANKLINE>
- >>> print msgdata
- {'fromusenet': True}
-
-
-Suspicious headers
-------------------
-
-Suspicious headers are a way for Mailman to hold messages that match a
-particular regular expression. This mostly historical feature is fairly
-confusing to users, and the list attribute that controls this is misnamed.
-
- >>> mlist.bounce_matching_headers = u'From: .*person@(blah.)?example.com'
- >>> msg = message_from_string("""\
- ... From: aperson@example.com
- ... To: _xtest@example.com
- ... Subject: An implicit message
- ...
- ... """)
- >>> process(mlist, msg, {})
- Traceback (most recent call last):
- ...
- SuspiciousHeaders
- >>> clear()
-
-But if the header doesn't match the regular expression, it'll get posted just
-fine. This one comes from a .org address.
-
- >>> msg = message_from_string("""\
- ... From: aperson@example.org
- ... To: _xtest@example.com
- ... Subject: An implicit message
- ...
- ... """)
- >>> msgdata = {}
- >>> process(mlist, msg, msgdata)
- >>> print msgdata
- {}
-
-Just a bit of clean up.
-
- >>> mlist.bounce_matching_headers = None
-
-
-Message size
-------------
-
-Mailman can hold messages that are bigger than a given size. Generally this
-is used to prevent huge attachments from getting posted to the list. This
-value is calculated in terms of KB (1024 bytes).
-
- >>> mlist.max_message_size = 1
- >>> one_line = 'x' * 79
- >>> big_body = '\n'.join([one_line] * 15)
- >>> msg = message_from_string("""\
- ... From: aperson@example.com
- ... To: _xtest@example.com
- ...
- ... """ + big_body)
- >>> process(mlist, msg, {})
- Traceback (most recent call last):
- ...
- MessageTooBig
- >>> clear()
-
-
-Hold Notifications
-------------------
-
-Whenever Mailman holds a message, it sends notifications both to the list
-owner and to the original sender, as long as it is configured to do so. We
-can show this by first holding a message.
-
- >>> mlist.respond_to_post_requests = True
- >>> mlist.admin_immed_notify = True
- >>> msg = message_from_string("""\
- ... From: aperson@example.com
- ...
- ... """)
- >>> process(mlist, msg, {})
- Traceback (most recent call last):
- ...
- ImplicitDestination
-
-There should be two messages in the virgin queue, one to the list owner and
-one to the original author.
-
- >>> len(switchboard.files)
- 2
- >>> qfiles = {}
- >>> for filebase in switchboard.files:
- ... qmsg, qdata = switchboard.dequeue(filebase)
- ... switchboard.finish(filebase)
- ... qfiles[qmsg['to']] = qmsg, qdata
- >>> qmsg, qdata = qfiles['_xtest-owner@example.com']
- >>> print qmsg.as_string()
- Subject: _xtest post from aperson@example.com requires approval
- From: _xtest-owner@example.com
- To: _xtest-owner@example.com
- MIME-Version: 1.0
- Content-Type: multipart/mixed; boundary="..."
- Message-ID: ...
- Date: ...
- Precedence: bulk
- <BLANKLINE>
- --...
- Content-Type: text/plain; charset="us-ascii"
- MIME-Version: 1.0
- Content-Transfer-Encoding: 7bit
- <BLANKLINE>
- As list administrator, your authorization is requested for the
- following mailing list posting:
- <BLANKLINE>
- List: _xtest@example.com
- From: aperson@example.com
- Subject: (no subject)
- Reason: Message has implicit destination
- <BLANKLINE>
- At your convenience, visit:
- <BLANKLINE>
- http://lists.example.com/admindb/_xtest@example.com
- <BLANKLINE>
- to approve or deny the request.
- <BLANKLINE>
- --...
- Content-Type: message/rfc822
- MIME-Version: 1.0
- <BLANKLINE>
- From: aperson@example.com
- Message-ID: ...
- X-Message-ID-Hash: ...
- <BLANKLINE>
- <BLANKLINE>
- --...
- Content-Type: message/rfc822
- MIME-Version: 1.0
- <BLANKLINE>
- Content-Type: text/plain; charset="us-ascii"
- MIME-Version: 1.0
- Content-Transfer-Encoding: 7bit
- Subject: confirm ...
- Sender: _xtest-request@example.com
- From: _xtest-request@example.com
- Date: ...
- Message-ID: ...
- <BLANKLINE>
- If you reply to this message, keeping the Subject: header intact,
- Mailman will discard the held message. Do this if the message is
- spam. If you reply to this message and include an Approved: header
- with the list password in it, the message will be approved for posting
- to the list. The Approved: header can also appear in the first line
- of the body of the reply.
- --...
- >>> sorted(qdata.items())
- [('_parsemsg', False), ('listname', u'_xtest@example.com'),
- ('nodecorate', True), ('received_time', ...),
- ('recips', [u'_xtest-owner@example.com']),
- ('reduced_list_headers', True),
- ('tomoderators', 1), ('version', 3)]
- >>> qmsg, qdata = qfiles['aperson@example.com']
- >>> print qmsg.as_string()
- MIME-Version: 1.0
- Content-Type: text/plain; charset="us-ascii"
- Content-Transfer-Encoding: 7bit
- Subject: Your message to _xtest awaits moderator approval
- From: _xtest-bounces@example.com
- To: aperson@example.com
- Message-ID: ...
- Date: ...
- Precedence: bulk
- <BLANKLINE>
- Your mail to '_xtest' with the subject
- <BLANKLINE>
- (no subject)
- <BLANKLINE>
- Is being held until the list moderator can review it for approval.
- <BLANKLINE>
- The reason it is being held:
- <BLANKLINE>
- Message has implicit destination
- <BLANKLINE>
- Either the message will get posted to the list, or you will receive
- notification of the moderator's decision. If you would like to cancel
- this posting, please visit the following URL:
- <BLANKLINE>
- http://lists.example.com/confirm/_xtest@example.com/...
- <BLANKLINE>
- <BLANKLINE>
- >>> sorted(qdata.items())
- [('_parsemsg', False), ('listname', u'_xtest@example.com'),
- ('nodecorate', True), ('received_time', ...),
- ('recips', [u'aperson@example.com']),
- ('reduced_list_headers', True), ('version', 3)]
-
-In addition, the pending database is holding the original messages, waiting
-for them to be disposed of by the original author or the list moderators. The
-database is essentially a dictionary, with the keys being the randomly
-selected tokens included in the urls and the values being a 2-tuple where the
-first item is a type code and the second item is a message id.
-
- >>> import re
- >>> cookie = None
- >>> qmsg, qdata = qfiles['aperson@example.com']
- >>> for line in qmsg.get_payload().splitlines():
- ... mo = re.search('confirm/[^/]+/(?P<cookie>.*)$', line)
- ... if mo:
- ... cookie = mo.group('cookie')
- ... break
- >>> data = config.db.pendings.confirm(cookie)
- >>> sorted(data.items())
- [(u'id', ...), (u'type', u'held message')]
-
-The message itself is held in the message store.
-
- >>> rkey, rdata = config.db.requests.get_list_requests(mlist).get_request(
- ... data['id'])
- >>> msg = config.db.message_store.get_message_by_id(
- ... rdata['_mod_message_id'])
- >>> print msg.as_string()
- From: aperson@example.com
- Message-ID: ...
- X-Message-ID-Hash: ...
- <BLANKLINE>
- <BLANKLINE>
-
-Clean up.
-
- >>> clear()