------------------------------------------------------------ revno: 6521 committer: Barry Warsaw <[EMAIL PROTECTED]> branch nick: 3.0 timestamp: Tue 2007-07-03 01:09:53 -0400 message: Convert TestHold to a doctest and update code as necessary. No general modernization of Hold.py was performed. added: Mailman/docs/hold.txt modified: Mailman/Handlers/Hold.py Mailman/ListAdmin.py Mailman/MailList.py Mailman/database/model/mailinglist.py Mailman/testing/test_handlers.py
=== added file 'Mailman/docs/hold.txt' --- a/Mailman/docs/hold.txt 1970-01-01 00:00:00 +0000 +++ b/Mailman/docs/hold.txt 2007-07-03 05:09:53 +0000 @@ -0,0 +1,373 @@ +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.Switchboard import Switchboard + >>> from Mailman.configuration import config + >>> from Mailman.database import flush + >>> mlist = config.list_manager.create('[EMAIL PROTECTED]') + >>> mlist.preferred_language = 'en' + >>> mlist.real_name = '_XTest' + >>> # XXX This will almost certainly change once we've worked out the web + >>> # space layout for mailing lists now. + >>> mlist._data.web_page_url = 'http://lists.example.com/' + >>> flush() + +XXX The Hold handler requires that the mailing list be locked because it +touches the pending database. Eventually the pending database should be moved +into the real database so that the lock is no longer necessary. + + >>> mlist.Lock() + +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. + + >>> from email import message_from_string + >>> from Mailman.Message import Message + >>> msg = message_from_string("""\ + ... From: [EMAIL PROTECTED] + ... + ... An important message. + ... """, Message) + >>> msgdata = {'approved': True} + >>> process(mlist, msg, msgdata) + >>> print msg.as_string() + From: [EMAIL PROTECTED] + <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 + >>> flush() + >>> msg = message_from_string("""\ + ... From: [EMAIL PROTECTED] + ... Subject: unsubscribe + ... + ... """, Message) + >>> 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 + >>> flush() + >>> msg = message_from_string("""\ + ... From: [EMAIL PROTECTED] + ... To: [EMAIL PROTECTED], [EMAIL PROTECTED] + ... Cc: [EMAIL PROTECTED] + ... Cc: [EMAIL PROTECTED] (Dan Person) + ... To: Elly Q. Person <[EMAIL PROTECTED]> + ... + ... Hey folks! + ... """, Message) + >>> 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 = '' + >>> flush() + >>> msg = message_from_string("""\ + ... From: [EMAIL PROTECTED] + ... Subject: An implicit message + ... + ... """, 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: [EMAIL PROTECTED] + Subject: An implicit message + <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 = 'From: .*person@(blah.)?example.com' + >>> flush() + >>> msg = message_from_string("""\ + ... From: [EMAIL PROTECTED] + ... To: [EMAIL PROTECTED] + ... Subject: An implicit message + ... + ... """, 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: [EMAIL PROTECTED] + ... To: [EMAIL PROTECTED] + ... Subject: An implicit message + ... + ... """, Message) + >>> msgdata = {} + >>> process(mlist, msg, msgdata) + >>> print msgdata + {} + +Just a bit of clean up. + + >>> mlist.bounce_matching_headers = None + >>> flush() + + +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 + >>> flush() + >>> one_line = 'x' * 79 + >>> big_body = '\n'.join([one_line] * 15) + >>> msg = message_from_string("""\ + ... From: [EMAIL PROTECTED] + ... To: [EMAIL PROTECTED] + ... + ... """ + big_body, Message) + >>> 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 + >>> flush() + >>> msg = message_from_string("""\ + ... From: [EMAIL PROTECTED] + ... + ... """, Message) + >>> 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['[EMAIL PROTECTED]'] + >>> print qmsg.as_string() + Subject: _xtest post from [EMAIL PROTECTED] requires approval + From: [EMAIL PROTECTED] + To: [EMAIL PROTECTED] + 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: [EMAIL PROTECTED] + From: [EMAIL PROTECTED] + Subject: (no subject) + Reason: Message has implicit destination + <BLANKLINE> + At your convenience, visit: + <BLANKLINE> + http://lists.example.com/admindb/[EMAIL PROTECTED] + <BLANKLINE> + to approve or deny the request. + <BLANKLINE> + --... + Content-Type: message/rfc822 + MIME-Version: 1.0 + <BLANKLINE> + From: [EMAIL PROTECTED] + <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: [EMAIL PROTECTED] + From: [EMAIL PROTECTED] + 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', '[EMAIL PROTECTED]'), + ('nodecorate', True), ('received_time', ...), + ('recips', ['[EMAIL PROTECTED]']), + ('reduced_list_headers', True), + ('tomoderators', 1), ('version', 3)] + >>> qmsg, qdata = qfiles['[EMAIL PROTECTED]'] + >>> 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: [EMAIL PROTECTED] + To: [EMAIL PROTECTED] + 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/[EMAIL PROTECTED]/... + <BLANKLINE> + <BLANKLINE> + >>> sorted(qdata.items()) + [('_parsemsg', False), ('listname', '[EMAIL PROTECTED]'), + ('nodecorate', True), ('received_time', ...), + ('recips', ['[EMAIL PROTECTED]']), + ('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['[EMAIL PROTECTED]'] + >>> for line in qmsg.get_payload().splitlines(): + ... mo = re.search('confirm/[^/]+/(?P<cookie>.*)$', line) + ... if mo: + ... cookie = mo.group('cookie') + ... break + >>> data = mlist.pend_confirm(cookie) + >>> data + ('H', ...) + >>> filename = '[EMAIL PROTECTED]' % data[1] + >>> heldmsg = os.path.join(config.DATA_DIR, filename) + +Use helper function to read the held message. + + >>> from Mailman.ListAdmin import readMessage + >>> msg = readMessage(heldmsg) + >>> print msg.as_string() + From: [EMAIL PROTECTED] + <BLANKLINE> + <BLANKLINE> + +Clean up. + + >>> clear() + >>> mlist.Unlock() === modified file 'Mailman/Handlers/Hold.py' --- a/Mailman/Handlers/Hold.py 2007-03-21 14:11:53 +0000 +++ b/Mailman/Handlers/Hold.py 2007-07-03 05:09:53 +0000 @@ -84,7 +84,7 @@ def rejection_notice(self, mlist): listurl = mlist.GetScriptURL('listinfo', absolute=1) - request = mlist.GetRequestEmail() + request = mlist.request_address return _("""Please do *not* post administrative requests to the mailing list. If you wish to subscribe, visit $listurl or send a message with the word `help' in it to the request address, $request, for further @@ -133,7 +133,7 @@ if msgdata.get('approved'): return # Get the sender of the message - listname = mlist.internal_name() + listname = mlist.list_name adminaddr = listname + '-admin' sender = msg.get_sender() # Special case an ugly sendmail feature: If there exists an alias of the @@ -204,7 +204,7 @@ if isinstance(exc, ClassType) or isinstance(exc, type): # Go ahead and instantiate it now. exc = exc() - listname = mlist.real_name + listname = mlist.list_name sender = msgdata.get('sender', msg.get_sender()) usersubject = msg.get('subject') charset = Utils.GetCharSet(mlist.preferred_language) @@ -213,9 +213,9 @@ else: usersubject = _('(no subject)') message_id = msg.get('message-id', 'n/a') - owneraddr = mlist.GetOwnerEmail() - adminaddr = mlist.GetBouncesEmail() - requestaddr = mlist.GetRequestEmail() + owneraddr = mlist.owner_address + adminaddr = mlist.bounces_address + requestaddr = mlist.request_address # We need to send both the reason and the rejection notice through the # translator again, because of the games we play above reason = Utils.wrap(exc.reason_notice()) @@ -240,12 +240,17 @@ # This message should appear to come from <list>-admin so as to handle any # bounce processing that might be needed. cookie = mlist.pend_new(Pending.HELD_MESSAGE, id) + # Get the language to send the response in. If the sender is a member, + # then send it in the member's language, otherwise send it in the mailing + # list's preferred language. + member = mlist.members.get_member(sender) + lang = (member.preferred_language if member else mlist.preferred_language) if not fromusenet and ackp(msg) and mlist.respond_to_post_requests and \ - mlist.autorespondToSender(sender, mlist.getMemberLanguage(sender)): + mlist.autorespondToSender(sender, lang): # Get a confirmation cookie d['confirmurl'] = '%s/%s' % (mlist.GetScriptURL('confirm', absolute=1), cookie) - lang = msgdata.get('lang', mlist.getMemberLanguage(sender)) + lang = msgdata.get('lang', lang) subject = _('Your message to $listname awaits moderator approval') text = Utils.maketext('postheld.txt', d, lang=lang, mlist=mlist) nmsg = Message.UserNotification(sender, adminaddr, subject, text, lang) === modified file 'Mailman/ListAdmin.py' --- a/Mailman/ListAdmin.py 2007-05-28 20:21:41 +0000 +++ b/Mailman/ListAdmin.py 2007-07-03 05:09:53 +0000 @@ -68,10 +68,6 @@ class ListAdmin: - def InitVars(self): - # non-configurable data - self.next_request_id = 1 - def InitTempVars(self): self._db = None self._filename = os.path.join(self.full_path, 'request.pck') @@ -114,7 +110,7 @@ next = self.next_request_id self.next_request_id += 1 if self._db.setdefault(next, missing) is missing: - yield next + return next def SaveRequestsDb(self): self._closedb() @@ -183,7 +179,7 @@ ext = 'pck' else: ext = 'txt' - filename = 'heldmsg-%s-%d.%s' % (self.internal_name(), id, ext) + filename = 'heldmsg-%s-%d.%s' % (self.fqdn_listname, id, ext) with open(os.path.join(config.DATA_DIR, filename), 'w') as fp: if config.HOLD_MESSAGES_AS_PICKLES: cPickle.dump(msg, fp, 1) === modified file 'Mailman/MailList.py' --- a/Mailman/MailList.py 2007-07-02 22:45:13 +0000 +++ b/Mailman/MailList.py 2007-07-03 05:09:53 +0000 @@ -155,19 +155,17 @@ self._lock.lock() def Lock(self, timeout=0): - database.lock(self) self._lock.lock(timeout) self._memberadaptor.lock() # Must reload our database for consistency. Watch out for lists that # don't exist. try: - self.Load(self.fqdn_listname) + self.Load() except Exception: self.Unlock() raise def Unlock(self): - database.unlock(self) self._lock.unlock(unconditionally=True) self._memberadaptor.unlock() @@ -551,15 +549,12 @@ # the lock (which is a serious problem!). TBD: do we need to be more # defensive? self._lock.refresh() - # Commit the database transaction - database.save(self) # The member adaptor may have its own save operation self._memberadaptor.save() self.SaveRequestsDb() self.CheckHTMLArchiveDir() def Load(self): - database.load(self) self._memberadaptor.load() @@ -1235,7 +1230,7 @@ addr = addr.lower() localpart = addr.split('@')[0] if (# TBD: backwards compatibility: deprecated - localpart == self.internal_name() or + localpart == self.list_name or # exact match against the complete list address addr == self.fqdn_listname): return True === modified file 'Mailman/database/model/mailinglist.py' --- a/Mailman/database/model/mailinglist.py 2007-06-21 14:23:40 +0000 +++ b/Mailman/database/model/mailinglist.py 2007-07-03 05:09:53 +0000 @@ -40,6 +40,7 @@ # Attributes not directly modifiable via the web u/i has_field('web_page_url', Unicode), has_field('admin_member_chunksize', Integer), + has_field('hold_and_cmd_autoresponses', PickleType), # Attributes which are directly modifiable via the web u/i. The more # complicated attributes are currently stored as pickles, though that # will change as the schema and implementation is developed. @@ -167,6 +168,8 @@ listname, hostname = split_listname(fqdn_listname) self.list_name = listname self.host_name = hostname + # For the pending database + self.next_request_id = 1 # Create several rosters for filtering out or querying the membership # table. from Mailman.database.model import roster @@ -176,6 +179,10 @@ self.members = roster.MemberRoster(self) self.regular_members = roster.RegularMemberRoster(self) self.digest_members = roster.DigestMemberRoster(self) + # Max autoresponses per day. A mapping between addresses and a + # 2-tuple of the date of the last autoresponse and the number of + # autoresponses sent on that date. + self.hold_and_cmd_autoresponses = {} @property def fqdn_listname(self): === modified file 'Mailman/testing/test_handlers.py' --- a/Mailman/testing/test_handlers.py 2007-07-02 22:45:13 +0000 +++ b/Mailman/testing/test_handlers.py 2007-07-03 05:09:53 +0000 @@ -39,7 +39,6 @@ from Mailman.Handlers import Acknowledge from Mailman.Handlers import AfterDelivery from Mailman.Handlers import Approve -from Mailman.Handlers import Hold from Mailman.Handlers import MimeDel from Mailman.Handlers import Moderate from Mailman.Handlers import Scrubber @@ -134,164 +133,6 @@ -class TestHold(TestBase): - def setUp(self): - TestBase.setUp(self) - self._mlist.administrivia = 1 - self._mlist.respond_to_post_requests = 0 - self._mlist.admin_immed_notify = 0 - # We're going to want to inspect this queue directory - self._sb = Switchboard(config.VIRGINQUEUE_DIR) - - def tearDown(self): - for f in os.listdir(config.VIRGINQUEUE_DIR): - os.unlink(os.path.join(config.VIRGINQUEUE_DIR, f)) - TestBase.tearDown(self) - try: - os.unlink(os.path.join(config.DATA_DIR, 'pending.db')) - except OSError, e: - if e.errno <> errno.ENOENT: raise - for f in [holdfile for holdfile in os.listdir(config.DATA_DIR) - if holdfile.startswith('heldmsg-')]: - os.unlink(os.path.join(config.DATA_DIR, f)) - - def test_short_circuit(self): - msgdata = {'approved': 1} - rtn = Hold.process(self._mlist, None, msgdata) - # Not really a great test, but there's little else to assert - self.assertEqual(rtn, None) - - def test_administrivia(self): - msg = email.message_from_string("""\ -From: [EMAIL PROTECTED] -Subject: unsubscribe - -""", Message.Message) - self.assertRaises(Hold.Administrivia, Hold.process, - self._mlist, msg, {}) - - def test_max_recips(self): - self._mlist.max_num_recipients = 5 - msg = email.message_from_string("""\ -From: [EMAIL PROTECTED] -To: [EMAIL PROTECTED], [EMAIL PROTECTED] -Cc: [EMAIL PROTECTED] -Cc: [EMAIL PROTECTED] (Jimmy D. Person) -To: Billy E. Person <[EMAIL PROTECTED]> - -Hey folks! -""", Message.Message) - self.assertRaises(Hold.TooManyRecipients, Hold.process, - self._mlist, msg, {}) - - def test_implicit_destination(self): - self._mlist.require_explicit_destination = 1 - msg = email.message_from_string("""\ -From: [EMAIL PROTECTED] -Subject: An implicit message - -""", Message.Message) - self.assertRaises(Hold.ImplicitDestination, Hold.process, - self._mlist, msg, {}) - - def test_implicit_destination_fromusenet(self): - self._mlist.require_explicit_destination = 1 - msg = email.message_from_string("""\ -From: [EMAIL PROTECTED] -Subject: An implicit message - -""", Message.Message) - rtn = Hold.process(self._mlist, msg, {'fromusenet': 1}) - self.assertEqual(rtn, None) - - def test_suspicious_header(self): - self._mlist.bounce_matching_headers = 'From: .*person@(blah.)?example.org' - msg = email.message_from_string("""\ -From: [EMAIL PROTECTED] -To: [EMAIL PROTECTED] -Subject: An implicit message - -""", Message.Message) - self.assertRaises(Hold.SuspiciousHeaders, Hold.process, - self._mlist, msg, {}) - - def test_suspicious_header_ok(self): - self._mlist.bounce_matching_headers = 'From: [EMAIL PROTECTED]' - msg = email.message_from_string("""\ -From: [EMAIL PROTECTED] -To: [EMAIL PROTECTED] -Subject: An implicit message - -""", Message.Message) - rtn = Hold.process(self._mlist, msg, {}) - self.assertEqual(rtn, None) - - def test_max_message_size(self): - self._mlist.max_message_size = 1 - msg = email.message_from_string("""\ -From: [EMAIL PROTECTED] -To: [EMAIL PROTECTED] - -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -""", Message.Message) - self.assertRaises(Hold.MessageTooBig, Hold.process, - self._mlist, msg, {}) - - def test_hold_notifications(self): - eq = self.assertEqual - self._mlist.respond_to_post_requests = 1 - self._mlist.admin_immed_notify = 1 - # Now cause an implicit destination hold - msg = email.message_from_string("""\ -From: [EMAIL PROTECTED] - -""", Message.Message) - self.assertRaises(Hold.ImplicitDestination, Hold.process, - self._mlist, msg, {}) - # Now we have to make sure there are two messages in the virgin queue, - # one to the sender and one to the list owners. - qfiles = {} - files = self._sb.files() - eq(len(files), 2) - for filebase in files: - qmsg, qdata = self._sb.dequeue(filebase) - to = qmsg['to'] - qfiles[to] = qmsg, qdata - # BAW: We could be testing many other attributes of either the - # messages or the metadata files... - keys = qfiles.keys() - keys.sort() - eq(keys, ['[EMAIL PROTECTED]', '[EMAIL PROTECTED]']) - # Get the pending cookie from the message to the sender - pmsg, pdata = qfiles['[EMAIL PROTECTED]'] - confirmlines = pmsg.get_payload().split('\n') - cookie = confirmlines[-3].split('/')[-1] - # We also need to make sure there's an entry in the Pending database - # for the hold message. - data = self._mlist.pend_confirm(cookie) - eq(data, ('H', 1)) - heldmsg = os.path.join(config.DATA_DIR, 'heldmsg-_xtest-1.pck') - self.failUnless(os.path.exists(heldmsg)) - os.unlink(heldmsg) - holdfiles = [f for f in os.listdir(config.DATA_DIR) - if f.startswith('heldmsg-')] - eq(len(holdfiles), 0) - - - class TestMimeDel(TestBase): def setUp(self): TestBase.setUp(self) @@ -968,7 +809,6 @@ def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestApprove)) - suite.addTest(unittest.makeSuite(TestHold)) suite.addTest(unittest.makeSuite(TestMimeDel)) suite.addTest(unittest.makeSuite(TestModerate)) suite.addTest(unittest.makeSuite(TestScrubber)) -- (no title) https://code.launchpad.net/~mailman-coders/mailman/3.0 You are receiving this branch notification because you are subscribed to it. To unsubscribe from this branch go to https://code.launchpad.net/~mailman-coders/mailman/3.0/+subscription/mailman-checkins. _______________________________________________ Mailman-checkins mailing list Mailman-checkins@python.org Unsubscribe: http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org