======================== The command queue runner ======================== This queue runner's purpose is to process and respond to email commands. Commands are extensible using the Mailman plug-in system, but Mailman comes with a number of email commands out of the box. These are processed when a message is sent to the list's ``-request`` address. >>> mlist = create_list('test@example.com') A command in the Subject ======================== For example, the ``echo`` command simply echoes the original command back to the sender. The command can be in the ``Subject`` header. :: >>> msg = message_from_string("""\ ... From: aperson@example.com ... To: test-request@example.com ... Subject: echo hello ... Message-ID: ... ... """) >>> from mailman.inject import inject_message >>> inject_message(mlist, msg, switchboard='command') >>> from mailman.queue.command import CommandRunner >>> from mailman.testing.helpers import make_testable_runner >>> command = make_testable_runner(CommandRunner) >>> command.run() And now the response is in the ``virgin`` queue. >>> from mailman.queue import Switchboard >>> virgin_queue = config.switchboards['virgin'] >>> len(virgin_queue.files) 1 >>> from mailman.testing.helpers import get_queue_messages >>> item = get_queue_messages('virgin')[0] >>> print item.msg.as_string() Subject: The results of your email commands From: test-bounces@example.com To: aperson@example.com ... The results of your email command are provided below. - Original message details: From: aperson@example.com Subject: echo hello Date: ... Message-ID: - Results: echo hello - Done. >>> dump_msgdata(item.msgdata) _parsemsg : False listname : test@example.com nodecorate : True recipients : [u'aperson@example.com'] reduced_list_headers: True version : ... A command in the body ===================== The command can also be found in the body of the message, as long as the message is plain text. :: >>> msg = message_from_string("""\ ... From: bperson@example.com ... To: test-request@example.com ... Message-ID: ... ... echo foo bar ... """) >>> inject_message(mlist, msg, switchboard='command') >>> command.run() >>> len(virgin_queue.files) 1 >>> item = get_queue_messages('virgin')[0] >>> print item.msg.as_string() Subject: The results of your email commands From: test-bounces@example.com To: bperson@example.com ... Precedence: bulk The results of your email command are provided below. - Original message details: From: bperson@example.com Subject: n/a Date: ... Message-ID: - Results: echo foo bar - Done. Implicit commands ================= For some commands, specifically for joining and leaving a mailing list, there are email aliases that act like commands, even when there's nothing else in the ``Subject`` or body. For example, to join a mailing list, a user need only email the ``-join`` address or ``-subscribe`` address (the latter is deprecated). Because Dirk has never registered with Mailman before, he gets two responses. The first is a confirmation message so that Dirk can validate his email address, and the other is the results of his email command. :: >>> msg = message_from_string("""\ ... From: Dirk Person ... To: test-join@example.com ... ... """) >>> inject_message(mlist, msg, switchboard='command', subaddress='join') >>> command.run() >>> len(virgin_queue.files) 2 >>> def sortkey(item): ... return str(item.msg['subject']) >>> messages = sorted(get_queue_messages('virgin'), key=sortkey) >>> from mailman.interfaces.registrar import IRegistrar >>> from zope.component import getUtility >>> registrar = getUtility(IRegistrar) >>> for item in messages: ... subject = item.msg['subject'] ... print 'Subject:', subject ... if 'confirm' in str(subject): ... token = str(subject).split()[1].strip() ... status = registrar.confirm(token) ... assert status, 'Confirmation failed' Subject: The results of your email commands Subject: confirm ... Similarly, to leave a mailing list, the user need only email the ``-leave`` or ``-unsubscribe`` address (the latter is deprecated). :: >>> msg = message_from_string("""\ ... From: dperson@example.com ... To: test-leave@example.com ... ... """) >>> inject_message(mlist, msg, switchboard='command', subaddress='leave') >>> command.run() >>> len(virgin_queue.files) 1 >>> item = get_queue_messages('virgin')[0] >>> print item.msg.as_string() Subject: The results of your email commands From: test-bounces@example.com To: dperson@example.com ... The results of your email command are provided below. - Original message details: From: dperson@example.com Subject: n/a Date: ... Message-ID: ... - Results: Dirk Person left test@example.com - Done. The ``-confirm`` address is also available as an implicit command. :: >>> msg = message_from_string("""\ ... From: dperson@example.com ... To: test-confirm+123@example.com ... ... """) >>> inject_message(mlist, msg, switchboard='command', subaddress='confirm') >>> command.run() >>> len(virgin_queue.files) 1 >>> item = get_queue_messages('virgin')[0] >>> print item.msg.as_string() Subject: The results of your email commands From: test-bounces@example.com To: dperson@example.com ... The results of your email command are provided below. - Original message details: From: dperson@example.com Subject: n/a Date: ... Message-ID: ... - Results: Confirmation token did not match - Done. Stopping command processing =========================== The ``end`` command stops email processing, so that nothing following is looked at by the command queue. :: >>> msg = message_from_string("""\ ... From: cperson@example.com ... To: test-request@example.com ... Message-ID: ... ... echo foo bar ... end ignored ... echo baz qux ... """) >>> inject_message(mlist, msg, switchboard='command') >>> command.run() >>> len(virgin_queue.files) 1 >>> item = get_queue_messages('virgin')[0] >>> print item.msg.as_string() Subject: The results of your email commands ... - Results: echo foo bar - Unprocessed: echo baz qux - Done. The ``stop`` command is an alias for ``end``. :: >>> msg = message_from_string("""\ ... From: cperson@example.com ... To: test-request@example.com ... Message-ID: ... ... echo foo bar ... stop ignored ... echo baz qux ... """) >>> inject_message(mlist, msg, switchboard='command') >>> command.run() >>> len(virgin_queue.files) 1 >>> item = get_queue_messages('virgin')[0] >>> print item.msg.as_string() Subject: The results of your email commands ... - Results: echo foo bar - Unprocessed: echo baz qux - Done.