diff options
| author | Barry Warsaw | 2009-07-18 22:31:45 -0400 |
|---|---|---|
| committer | Barry Warsaw | 2009-07-18 22:31:45 -0400 |
| commit | d9ad19e86ff658a74870fb488cd74e5002b63bc3 (patch) | |
| tree | 29a7e53c290a95d6280772d6aa52a8b160649596 /src | |
| parent | 422a6757e6aafbd12c220aa8dfdc33f8c377718c (diff) | |
| download | mailman-d9ad19e86ff658a74870fb488cd74e5002b63bc3.tar.gz mailman-d9ad19e86ff658a74870fb488cd74e5002b63bc3.tar.zst mailman-d9ad19e86ff658a74870fb488cd74e5002b63bc3.zip | |
Diffstat (limited to 'src')
52 files changed, 461 insertions, 415 deletions
diff --git a/src/mailman/docs/chains.txt b/src/mailman/docs/chains.txt index 186590a93..3fee28e7d 100644 --- a/src/mailman/docs/chains.txt +++ b/src/mailman/docs/chains.txt @@ -1,3 +1,4 @@ +====== Chains ====== @@ -10,7 +11,7 @@ processing of messages. The Discard chain ------------------ +================= The Discard chain simply throws the message away. @@ -50,7 +51,7 @@ The Discard chain simply throws the message away. The Reject chain ----------------- +================ The Reject chain bounces the message back to the original sender, and logs this action. @@ -95,7 +96,7 @@ The bounce message is now sitting in the Virgin queue. The Hold Chain --------------- +============== The Hold chain places the message into the admin request database and depending on the list's settings, sends a notification to both the original @@ -248,7 +249,7 @@ The message itself is held in the message store. The Accept chain ----------------- +================ The Accept chain sends the message on the 'prep' queue, where it will be processed and sent on to the list membership. @@ -282,7 +283,7 @@ processed and sent on to the list membership. Run-time chains ---------------- +=============== We can also define chains at run time, and these chains can be mutated. Run-time chains are made up of links where each link associates both a rule diff --git a/src/mailman/docs/languages.txt b/src/mailman/docs/languages.txt index 87c68f034..77b51cbeb 100644 --- a/src/mailman/docs/languages.txt +++ b/src/mailman/docs/languages.txt @@ -49,7 +49,7 @@ You can iterate over all the known language codes. >>> mgr.add('pl', 'iso-8859-2', 'Polish') >>> sorted(mgr.codes) - ['en', 'it', 'pl'] + [u'en', u'it', u'pl'] You can iterate over all the known languages. @@ -76,7 +76,7 @@ You can get a particular language by its code. >>> print mgr['xx'].code Traceback (most recent call last): ... - KeyError: 'xx' + KeyError: u'xx' >>> print mgr.get('it').description Italian >>> print mgr.get('xx') diff --git a/src/mailman/docs/lifecycle.txt b/src/mailman/docs/lifecycle.txt index 8f45dc880..e6dcc7c33 100644 --- a/src/mailman/docs/lifecycle.txt +++ b/src/mailman/docs/lifecycle.txt @@ -28,7 +28,7 @@ bogus posting address, you get an exception. >>> create_list('not a valid address') Traceback (most recent call last): ... - InvalidEmailAddress: 'not a valid address' + InvalidEmailAddress: u'not a valid address' If the posting address is valid, but the domain has not been registered with Mailman yet, you get an exception. diff --git a/src/mailman/docs/pending.txt b/src/mailman/docs/pending.txt index abfba4885..5d7706bf6 100644 --- a/src/mailman/docs/pending.txt +++ b/src/mailman/docs/pending.txt @@ -38,7 +38,7 @@ basically means returning the IPendable structure (as a dict) from the database that matches the token. If the token isn't in the database, None is returned. - >>> pendable = pendingdb.confirm('missing') + >>> pendable = pendingdb.confirm(bytes('missing')) >>> print pendable None >>> pendable = pendingdb.confirm(token) diff --git a/src/mailman/docs/pipelines.txt b/src/mailman/docs/pipelines.txt index 36bf2dd23..5ad6ba243 100644 --- a/src/mailman/docs/pipelines.txt +++ b/src/mailman/docs/pipelines.txt @@ -10,7 +10,7 @@ rules and chains, there is no way to stop a pipeline from processing the message once it's started. >>> from mailman.app.lifecycle import create_list - >>> mlist = create_list(u'xtest@example.com') + >>> mlist = create_list('xtest@example.com') >>> print mlist.pipeline built-in >>> from mailman.core.pipelines import process diff --git a/src/mailman/docs/registration.txt b/src/mailman/docs/registration.txt index 519b81ba8..ff6466f82 100644 --- a/src/mailman/docs/registration.txt +++ b/src/mailman/docs/registration.txt @@ -17,7 +17,7 @@ stuff. >>> from mailman.interfaces.domain import IDomainManager >>> manager = IDomainManager(config) - >>> domain = manager[u'example.com'] + >>> domain = manager['example.com'] Get a registrar by adapting a domain. @@ -51,27 +51,27 @@ Some amount of sanity checks are performed on the email address, although honestly, not as much as probably should be done. Still, some patently bad addresses are rejected outright. - >>> registrar.register(u'') + >>> registrar.register('') Traceback (most recent call last): ... InvalidEmailAddress: u'' - >>> registrar.register(u'some name@example.com') + >>> registrar.register('some name@example.com') Traceback (most recent call last): ... InvalidEmailAddress: u'some name@example.com' - >>> registrar.register(u'<script>@example.com') + >>> registrar.register('<script>@example.com') Traceback (most recent call last): ... InvalidEmailAddress: u'<script>@example.com' - >>> registrar.register(u'\xa0@example.com') + >>> registrar.register('\xa0@example.com') Traceback (most recent call last): ... InvalidEmailAddress: u'\xa0@example.com' - >>> registrar.register(u'noatsign') + >>> registrar.register('noatsign') Traceback (most recent call last): ... InvalidEmailAddress: u'noatsign' - >>> registrar.register(u'nodom@ain') + >>> registrar.register('nodom@ain') Traceback (most recent call last): ... InvalidEmailAddress: u'nodom@ain' @@ -85,16 +85,16 @@ is complete. No IUser or IAddress is created at registration time, but a record is added to the pending database, and the token for that record is returned. - >>> token = registrar.register(u'aperson@example.com', u'Anne Person') + >>> token = registrar.register('aperson@example.com', 'Anne Person') >>> check_token(token) ok There should be no records in the user manager for this address yet. >>> usermgr = config.db.user_manager - >>> print usermgr.get_user(u'aperson@example.com') + >>> print usermgr.get_user('aperson@example.com') None - >>> print usermgr.get_address(u'aperson@example.com') + >>> print usermgr.get_address('aperson@example.com') None But this address is waiting for confirmation. @@ -185,10 +185,10 @@ extracts the token and uses that to confirm the pending registration. Now, there is an IAddress in the database matching the address, as well as an IUser linked to this address. The IAddress is verified. - >>> found_address = usermgr.get_address(u'aperson@example.com') + >>> found_address = usermgr.get_address('aperson@example.com') >>> found_address <Address: Anne Person <aperson@example.com> [verified] at ...> - >>> found_user = usermgr.get_user(u'aperson@example.com') + >>> found_user = usermgr.get_user('aperson@example.com') >>> found_user <User "Anne Person" at ...> >>> found_user.controls(found_address.address) @@ -204,7 +204,7 @@ Non-standard registrations If you try to confirm a registration token twice, of course only the first one will work. The second one is ignored. - >>> token = registrar.register(u'bperson@example.com') + >>> token = registrar.register('bperson@example.com') >>> check_token(token) ok >>> filebase = switchboard.files[0] @@ -222,25 +222,25 @@ If an address is in the system, but that address is not linked to a user yet and the address is not yet validated, then no user is created until the confirmation step is completed. - >>> usermgr.create_address(u'cperson@example.com') + >>> usermgr.create_address('cperson@example.com') <Address: cperson@example.com [not verified] at ...> - >>> token = registrar.register(u'cperson@example.com', u'Claire Person') - >>> print usermgr.get_user(u'cperson@example.com') + >>> token = registrar.register('cperson@example.com', 'Claire Person') + >>> print usermgr.get_user('cperson@example.com') None >>> filebase = switchboard.files[0] >>> qmsg, qdata = switchboard.dequeue(filebase) >>> switchboard.finish(filebase) >>> registrar.confirm(token) True - >>> usermgr.get_user(u'cperson@example.com') + >>> usermgr.get_user('cperson@example.com') <User "Claire Person" at ...> - >>> usermgr.get_address(u'cperson@example.com') + >>> usermgr.get_address('cperson@example.com') <Address: cperson@example.com [verified] at ...> Even if the address being registered has already been verified, the registration sends a confirmation. - >>> token = registrar.register(u'cperson@example.com') + >>> token = registrar.register('cperson@example.com') >>> token is not None True @@ -251,15 +251,15 @@ Discarding A confirmation token can also be discarded, say if the user changes his or her mind about registering. When discarded, no IAddress or IUser is created. - >>> token = registrar.register(u'eperson@example.com', u'Elly Person') + >>> token = registrar.register('eperson@example.com', 'Elly Person') >>> check_token(token) ok >>> registrar.discard(token) >>> print pendingdb.confirm(token) None - >>> print usermgr.get_address(u'eperson@example.com') + >>> print usermgr.get_address('eperson@example.com') None - >>> print usermgr.get_user(u'eperson@example.com') + >>> print usermgr.get_user('eperson@example.com') None @@ -270,24 +270,24 @@ When a new address for an existing user is registered, there isn't too much different except that the new address will still need to be verified before it can be used. - >>> dperson = usermgr.create_user(u'dperson@example.com', u'Dave Person') + >>> dperson = usermgr.create_user('dperson@example.com', 'Dave Person') >>> dperson <User "Dave Person" at ...> - >>> address = usermgr.get_address(u'dperson@example.com') + >>> address = usermgr.get_address('dperson@example.com') >>> address.verified_on = datetime.now() >>> from operator import attrgetter >>> sorted((addr for addr in dperson.addresses), key=attrgetter('address')) [<Address: Dave Person <dperson@example.com> [verified] at ...>] - >>> dperson.register(u'david.person@example.com', u'David Person') + >>> dperson.register('david.person@example.com', 'David Person') <Address: David Person <david.person@example.com> [not verified] at ...> - >>> token = registrar.register(u'david.person@example.com') + >>> token = registrar.register('david.person@example.com') >>> filebase = switchboard.files[0] >>> qmsg, qdata = switchboard.dequeue(filebase) >>> switchboard.finish(filebase) >>> registrar.confirm(token) True - >>> user = usermgr.get_user(u'david.person@example.com') + >>> user = usermgr.get_user('david.person@example.com') >>> user is dperson True >>> user @@ -303,7 +303,7 @@ Corner cases If you try to confirm a token that doesn't exist in the pending database, the confirm method will just return None. - >>> registrar.confirm('no token') + >>> registrar.confirm(bytes('no token')) False Likewise, if you try to confirm, through the IUserRegistrar interface, a token @@ -329,19 +329,19 @@ Registration and subscription Fred registers with Mailman at the same time that he subscribes to a mailing list. - >>> mlist = create_list(u'alpha@example.com') + >>> mlist = create_list('alpha@example.com') >>> token = registrar.register( - ... u'fred.person@example.com', 'Fred Person', mlist) + ... 'fred.person@example.com', 'Fred Person', mlist) Before confirmation, Fred is not a member of the mailing list. - >>> print mlist.members.get_member(u'fred.person@example.com') + >>> print mlist.members.get_member('fred.person@example.com') None But after confirmation, he is. >>> registrar.confirm(token) True - >>> print mlist.members.get_member(u'fred.person@example.com') + >>> print mlist.members.get_member('fred.person@example.com') <Member: Fred Person <fred.person@example.com> on alpha@example.com as MemberRole.member> diff --git a/src/mailman/docs/requests.txt b/src/mailman/docs/requests.txt index c49f09895..4a04017aa 100644 --- a/src/mailman/docs/requests.txt +++ b/src/mailman/docs/requests.txt @@ -39,7 +39,7 @@ mailing list you need to get its requests object. >>> from zope.interface.verify import verifyObject >>> verifyObject(IRequests, config.db.requests) True - >>> mlist = create_list(u'test@example.com') + >>> mlist = create_list('test@example.com') >>> requests = config.db.requests.get_list_requests(mlist) >>> verifyObject(IListRequests, requests) True @@ -63,10 +63,10 @@ of associated data. The request database assigns no semantics to the held data, except for the request type. Here we hold some simple bits of data. >>> from mailman.interfaces.requests import RequestType - >>> id_1 = requests.hold_request(RequestType.held_message, u'hold_1') - >>> id_2 = requests.hold_request(RequestType.subscription, u'hold_2') - >>> id_3 = requests.hold_request(RequestType.unsubscription, u'hold_3') - >>> id_4 = requests.hold_request(RequestType.held_message, u'hold_4') + >>> id_1 = requests.hold_request(RequestType.held_message, 'hold_1') + >>> id_2 = requests.hold_request(RequestType.subscription, 'hold_2') + >>> id_3 = requests.hold_request(RequestType.unsubscription, 'hold_3') + >>> id_4 = requests.hold_request(RequestType.held_message, 'hold_4') >>> id_1, id_2, id_3, id_4 (1, 2, 3, 4) @@ -96,7 +96,7 @@ If we try to hold a request with a bogus type, we get an exception. We can hold requests with additional data. >>> data = dict(foo='yes', bar='no') - >>> id_5 = requests.hold_request(RequestType.held_message, u'hold_5', data) + >>> id_5 = requests.hold_request(RequestType.held_message, 'hold_5', data) >>> id_5 5 >>> requests.count @@ -215,9 +215,9 @@ Holding messages For this section, we need a mailing list and at least one message. - >>> mlist = create_list(u'alist@example.com') - >>> mlist.preferred_language = u'en' - >>> mlist.real_name = u'A Test List' + >>> mlist = create_list('alist@example.com') + >>> mlist.preferred_language = 'en' + >>> mlist.real_name = 'A Test List' >>> msg = message_from_string("""\ ... From: aperson@example.org ... To: alist@example.com @@ -243,7 +243,7 @@ We can also hold a message with some additional metadata. >>> msgdata = dict(sender='aperson@example.com', ... approved=True, ... received_time=123.45) - >>> id_2 = moderator.hold_message(mlist, msg, msgdata, u'Feeling ornery') + >>> id_2 = moderator.hold_message(mlist, msg, msgdata, 'Feeling ornery') >>> requests.get_request(id_2) is not None True @@ -346,7 +346,7 @@ is deleted. ... """) >>> id_4 = moderator.hold_message(mlist, msg, {}, 'Needs approval') >>> moderator.handle_message(mlist, id_4, Action.discard) - >>> print config.db.message_store.get_message_by_id(u'<12345>') + >>> print config.db.message_store.get_message_by_id('<12345>') None But if we ask to preserve the message when we discard it, it will be held in @@ -354,7 +354,7 @@ the message store after disposition. >>> id_4 = moderator.hold_message(mlist, msg, {}, 'Needs approval') >>> moderator.handle_message(mlist, id_4, Action.discard, preserve=True) - >>> stored_msg = config.db.message_store.get_message_by_id(u'<12345>') + >>> stored_msg = config.db.message_store.get_message_by_id('<12345>') >>> print stored_msg.as_string() From: aperson@example.org To: alist@example.com @@ -372,10 +372,10 @@ moderators. # Set a new Message-ID from the previous hold so we don't try to store # collisions in the message storage. >>> del msg['message-id'] - >>> msg['Message-ID'] = u'<abcde>' + >>> msg['Message-ID'] = '<abcde>' >>> id_4 = moderator.hold_message(mlist, msg, {}, 'Needs approval') >>> moderator.handle_message(mlist, id_4, Action.discard, - ... forward=[u'zperson@example.com']) + ... forward=['zperson@example.com']) >>> qmsg, qdata = dequeue() >>> print qmsg.as_string() Subject: Forward of moderated message @@ -416,8 +416,8 @@ choosing and their preferred language. >>> from mailman.interfaces.member import DeliveryMode >>> mlist.admin_immed_notify = False >>> id_3 = moderator.hold_subscription(mlist, - ... u'bperson@example.org', u'Ben Person', - ... u'{NONE}abcxyz', DeliveryMode.regular, u'en') + ... 'bperson@example.org', 'Ben Person', + ... '{NONE}abcxyz', DeliveryMode.regular, 'en') >>> requests.get_request(id_3) is not None True @@ -436,8 +436,8 @@ queue when the message is held. >>> # XXX This will almost certainly change once we've worked out the web >>> # space layout for mailing lists now. >>> id_4 = moderator.hold_subscription(mlist, - ... u'cperson@example.org', u'Claire Person', - ... u'{NONE}zyxcba', DeliveryMode.regular, u'en') + ... 'cperson@example.org', 'Claire Person', + ... '{NONE}zyxcba', DeliveryMode.regular, 'en') >>> requests.get_request(id_4) is not None True >>> qmsg, qdata = dequeue() @@ -533,8 +533,8 @@ mailing list. >>> mlist.send_welcome_msg = True >>> id_4 = moderator.hold_subscription(mlist, - ... u'fperson@example.org', u'Frank Person', - ... u'{NONE}abcxyz', DeliveryMode.regular, u'en') + ... 'fperson@example.org', 'Frank Person', + ... '{NONE}abcxyz', DeliveryMode.regular, 'en') A message will be sent to the moderators telling them about the held subscription and the fact that they may need to approve it. @@ -673,7 +673,7 @@ The admin message is sent to the moderators. Frank Person is now a member of the mailing list. - >>> member = mlist.members.get_member(u'fperson@example.org') + >>> member = mlist.members.get_member('fperson@example.org') >>> member <Member: Frank Person <fperson@example.org> on alist@example.com as MemberRole.member> @@ -682,10 +682,10 @@ Frank Person is now a member of the mailing list. >>> print member.delivery_mode DeliveryMode.regular >>> user = config.db.user_manager.get_user(member.address.address) - >>> user.real_name - u'Frank Person' - >>> user.password - u'{NONE}abcxyz' + >>> print user.real_name + Frank Person + >>> print user.password + {NONE}abcxyz Holding unsubscription requests @@ -697,21 +697,21 @@ unsubscription holds can send the list's moderators an immediate notification. >>> mlist.admin_immed_notify = False >>> from mailman.interfaces.member import MemberRole - >>> user_1 = config.db.user_manager.create_user(u'gperson@example.com') + >>> user_1 = config.db.user_manager.create_user('gperson@example.com') >>> address_1 = list(user_1.addresses)[0] >>> address_1.subscribe(mlist, MemberRole.member) <Member: gperson@example.com on alist@example.com as MemberRole.member> - >>> user_2 = config.db.user_manager.create_user(u'hperson@example.com') + >>> user_2 = config.db.user_manager.create_user('hperson@example.com') >>> address_2 = list(user_2.addresses)[0] >>> address_2.subscribe(mlist, MemberRole.member) <Member: hperson@example.com on alist@example.com as MemberRole.member> - >>> id_5 = moderator.hold_unsubscription(mlist, u'gperson@example.com') + >>> id_5 = moderator.hold_unsubscription(mlist, 'gperson@example.com') >>> requests.get_request(id_5) is not None True >>> virginq.files [] >>> mlist.admin_immed_notify = True - >>> id_6 = moderator.hold_unsubscription(mlist, u'hperson@example.com') + >>> id_6 = moderator.hold_unsubscription(mlist, 'hperson@example.com') >>> qmsg, qdata = dequeue() >>> print qmsg.as_string() MIME-Version: 1.0 @@ -758,7 +758,7 @@ subscribed. >>> moderator.handle_unsubscription(mlist, id_5, Action.discard) >>> print requests.get_request(id_5) None - >>> mlist.members.get_member(u'gperson@example.com') + >>> mlist.members.get_member('gperson@example.com') <Member: gperson@example.com on alist@example.com as MemberRole.member> The request can be rejected, in which case a message is sent to the member, @@ -802,18 +802,18 @@ and the person remains a member of the mailing list. reduced_list_headers: True version : 3 - >>> mlist.members.get_member(u'hperson@example.com') + >>> mlist.members.get_member('hperson@example.com') <Member: hperson@example.com on alist@example.com as MemberRole.member> The unsubscription request can also be accepted. This removes the member from the mailing list. >>> mlist.send_goodbye_msg = True - >>> mlist.goodbye_msg = u'So long!' + >>> mlist.goodbye_msg = 'So long!' >>> mlist.admin_immed_notify = False - >>> id_7 = moderator.hold_unsubscription(mlist, u'gperson@example.com') + >>> id_7 = moderator.hold_unsubscription(mlist, 'gperson@example.com') >>> moderator.handle_unsubscription(mlist, id_7, Action.accept) - >>> print mlist.members.get_member(u'gperson@example.com') + >>> print mlist.members.get_member('gperson@example.com') None There are now two messages in the virgin queue, one to the member who was just diff --git a/src/mailman/docs/styles.txt b/src/mailman/docs/styles.txt index d12e57b08..7524ecf64 100644 --- a/src/mailman/docs/styles.txt +++ b/src/mailman/docs/styles.txt @@ -1,3 +1,4 @@ +=========== List styles =========== @@ -13,7 +14,7 @@ modify the mailing list any way it wants. Let's start with a vanilla mailing list and a default style manager. - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> from mailman.styles.manager import StyleManager >>> style_manager = StyleManager() >>> style_manager.populate() @@ -22,7 +23,7 @@ Let's start with a vanilla mailing list and a default style manager. The default style ------------------ +================= There is a default style which implements the legacy application of list defaults from previous versions of Mailman. This style only matching a @@ -49,7 +50,7 @@ manager's `lookup()` method. Registering styles ------------------- +================== New styles must implement the IStyle interface. @@ -61,7 +62,7 @@ New styles must implement the IStyle interface. ... priority = 10 ... def apply(self, mailing_list): ... # Just does something very simple. - ... mailing_list.msg_footer = u'test footer' + ... mailing_list.msg_footer = 'test footer' ... def match(self, mailing_list, styles): ... # Applies to any test list ... if 'test' in mailing_list.fqdn_listname: @@ -76,15 +77,15 @@ style. This is because the default style only gets applied when no other styles match the mailing list. >>> sorted(style.name for style in style_manager.lookup(mlist)) - ['test'] + [u'test'] >>> for style in style_manager.lookup(mlist): ... style.apply(mlist) - >>> mlist.msg_footer - u'test footer' + >>> print mlist.msg_footer + test footer Style priority --------------- +============== When multiple styles match a particular mailing list, they are applied in descending order of priority. In other words, a priority zero style would be @@ -95,16 +96,16 @@ applied last. ... priority = 5 ... # Use the base class's match() method. ... def apply(self, mailing_list): - ... mailing_list.msg_footer = u'another footer' + ... mailing_list.msg_footer = 'another footer' - >>> mlist.msg_footer = u'' + >>> mlist.msg_footer = '' >>> mlist.msg_footer u'' >>> style_manager.register(AnotherTestStyle()) >>> for style in style_manager.lookup(mlist): ... style.apply(mlist) - >>> mlist.msg_footer - u'another footer' + >>> print mlist.msg_footer + another footer You can change the priority of a style, and if you reapply the styles, they will take effect in the new priority order. @@ -115,22 +116,22 @@ will take effect in the new priority order. >>> style_2.priority = 10 >>> for style in style_manager.lookup(mlist): ... style.apply(mlist) - >>> mlist.msg_footer - u'test footer' + >>> print mlist.msg_footer + test footer Unregistering styles --------------------- +==================== You can unregister a style, making it unavailable in the future. >>> style_manager.unregister(style_2) >>> sorted(style.name for style in style_manager.lookup(mlist)) - ['test'] + [u'test'] Corner cases ------------- +============ If you register a style with the same name as an already registered style, you get an exception. @@ -153,4 +154,4 @@ If you try to unregister a style that isn't registered, you get an exception. >>> style_manager.unregister(style_2) Traceback (most recent call last): ... - KeyError: 'another' + KeyError: u'another' diff --git a/src/mailman/docs/usermanager.txt b/src/mailman/docs/usermanager.txt index f8cbfeef2..3c5369b84 100644 --- a/src/mailman/docs/usermanager.txt +++ b/src/mailman/docs/usermanager.txt @@ -1,3 +1,4 @@ +================ The user manager ================ @@ -14,7 +15,7 @@ config object. Creating users --------------- +============== There are several ways you can create a user object. The simplest is to create a 'blank' user by not providing an address or real name at creation @@ -39,19 +40,19 @@ The user has preferences, but none of them will be specified. A user can be assigned a real name. - >>> user.real_name = u'Anne Person' + >>> user.real_name = 'Anne Person' >>> sorted(user.real_name for user in usermgr.users) [u'Anne Person'] A user can be assigned a password. - >>> user.password = u'secret' + >>> user.password = 'secret' >>> sorted(user.password for user in usermgr.users) [u'secret'] You can also create a user with an address to start out with. - >>> user_2 = usermgr.create_user(u'bperson@example.com') + >>> user_2 = usermgr.create_user('bperson@example.com') >>> verifyObject(IUser, user_2) True >>> sorted(address.address for address in user_2.addresses) @@ -61,13 +62,13 @@ You can also create a user with an address to start out with. As above, you can assign a real name to such users. - >>> user_2.real_name = u'Ben Person' + >>> user_2.real_name = 'Ben Person' >>> sorted(user.real_name for user in usermgr.users) [u'Anne Person', u'Ben Person'] You can also create a user with just a real name. - >>> user_3 = usermgr.create_user(real_name=u'Claire Person') + >>> user_3 = usermgr.create_user(real_name='Claire Person') >>> verifyObject(IUser, user_3) True >>> sorted(address.address for address in user.addresses) @@ -77,7 +78,7 @@ You can also create a user with just a real name. Finally, you can create a user with both an address and a real name. - >>> user_4 = usermgr.create_user(u'dperson@example.com', u'Dan Person') + >>> user_4 = usermgr.create_user('dperson@example.com', 'Dan Person') >>> verifyObject(IUser, user_3) True >>> sorted(address.address for address in user_4.addresses) @@ -89,7 +90,7 @@ Finally, you can create a user with both an address and a real name. Deleting users --------------- +============== You delete users by going through the user manager. The deleted user is no longer available through the user manager iterator. @@ -100,7 +101,7 @@ longer available through the user manager iterator. Finding users -------------- +============= You can ask the user manager to find the IUser that controls a particular email address. You'll get back the original user object if it's found. Note @@ -117,7 +118,7 @@ object. If the address is not in the user database or does not have a user associated with it, you will get None back. - >>> print usermgr.get_user(u'zperson@example.com') + >>> print usermgr.get_user('zperson@example.com') None >>> user_4.unlink(address) >>> print usermgr.get_user(address.address) diff --git a/src/mailman/docs/users.txt b/src/mailman/docs/users.txt index b557a280d..ef4f3062b 100644 --- a/src/mailman/docs/users.txt +++ b/src/mailman/docs/users.txt @@ -1,3 +1,4 @@ +===== Users ===== @@ -11,13 +12,13 @@ See usermanager.txt for examples of how to create, delete, and find users. User data ---------- +========= Users may have a real name and a password. >>> user_1 = usermgr.create_user() - >>> user_1.password = u'my password' - >>> user_1.real_name = u'Zoe Person' + >>> user_1.password = 'my password' + >>> user_1.real_name = 'Zoe Person' >>> sorted(user.real_name for user in usermgr.users) [u'Zoe Person'] >>> sorted(user.password for user in usermgr.users) @@ -25,8 +26,8 @@ Users may have a real name and a password. The password and real name can be changed at any time. - >>> user_1.real_name = u'Zoe X. Person' - >>> user_1.password = u'another password' + >>> user_1.real_name = 'Zoe X. Person' + >>> user_1.password = 'another password' >>> sorted(user.real_name for user in usermgr.users) [u'Zoe X. Person'] >>> sorted(user.password for user in usermgr.users) @@ -34,7 +35,7 @@ The password and real name can be changed at any time. Users addresses ---------------- +=============== One of the pieces of information that a user links to is a set of email addresses they control, in the form of IAddress objects. A user can control @@ -43,9 +44,9 @@ many addresses, but addresses may be controlled by only one user. The easiest way to link a user to an address is to just register the new address on a user object. - >>> user_1.register(u'zperson@example.com', u'Zoe Person') + >>> user_1.register('zperson@example.com', 'Zoe Person') <Address: Zoe Person <zperson@example.com> [not verified] at 0x...> - >>> user_1.register(u'zperson@example.org') + >>> user_1.register('zperson@example.org') <Address: zperson@example.org [not verified] at 0x...> >>> sorted(address.address for address in user_1.addresses) [u'zperson@example.com', u'zperson@example.org'] @@ -54,7 +55,7 @@ address on a user object. You can also create the address separately and then link it to the user. - >>> address_1 = usermgr.create_address(u'zperson@example.net') + >>> address_1 = usermgr.create_address('zperson@example.net') >>> user_1.link(address_1) >>> sorted(address.address for address in user_1.addresses) [u'zperson@example.com', u'zperson@example.net', u'zperson@example.org'] @@ -73,27 +74,27 @@ You can also ask whether a given user controls a given address. >>> user_1.controls(address_1.address) True - >>> user_1.controls(u'bperson@example.com') + >>> user_1.controls('bperson@example.com') False Given a text email address, the user manager can find the user that controls that address. - >>> usermgr.get_user(u'zperson@example.com') is user_1 + >>> usermgr.get_user('zperson@example.com') is user_1 True - >>> usermgr.get_user(u'zperson@example.net') is user_1 + >>> usermgr.get_user('zperson@example.net') is user_1 True - >>> usermgr.get_user(u'zperson@example.org') is user_1 + >>> usermgr.get_user('zperson@example.org') is user_1 True - >>> print usermgr.get_user(u'bperson@example.com') + >>> print usermgr.get_user('bperson@example.com') None Addresses can also be unlinked from a user. >>> user_1.unlink(address_1) - >>> user_1.controls(u'zperson@example.net') + >>> user_1.controls('zperson@example.net') False - >>> print usermgr.get_user(u'aperson@example.net') + >>> print usermgr.get_user('aperson@example.net') None But don't try to unlink the address from a user it's not linked to. @@ -109,7 +110,7 @@ But don't try to unlink the address from a user it's not linked to. Users and preferences ---------------------- +===================== This is a helper function for the following section. @@ -132,12 +133,12 @@ Users have preferences, but these preferences have no default settings. Some of these preferences are booleans and they can be set to True or False. - >>> config.languages.add(u'it', u'iso-8859-1', u'Italian') + >>> config.languages.add('it', 'iso-8859-1', 'Italian') >>> from mailman.constants import DeliveryMode >>> prefs = user_1.preferences >>> prefs.acknowledge_posts = True - >>> prefs.preferred_language = u'it' + >>> prefs.preferred_language = 'it' >>> prefs.receive_list_copy = False >>> prefs.receive_own_postings = False >>> prefs.delivery_mode = DeliveryMode.regular @@ -150,7 +151,7 @@ Some of these preferences are booleans and they can be set to True or False. Subscriptions -------------- +============= Users know which mailing lists they are subscribed to, regardless of membership role. @@ -158,14 +159,14 @@ membership role. >>> user_1.link(address_1) >>> sorted(address.address for address in user_1.addresses) [u'zperson@example.com', u'zperson@example.net', u'zperson@example.org'] - >>> com = usermgr.get_address(u'zperson@example.com') - >>> org = usermgr.get_address(u'zperson@example.org') - >>> net = usermgr.get_address(u'zperson@example.net') + >>> com = usermgr.get_address('zperson@example.com') + >>> org = usermgr.get_address('zperson@example.org') + >>> net = usermgr.get_address('zperson@example.net') >>> from mailman.app.lifecycle import create_list - >>> mlist_1 = create_list(u'xtest_1@example.com') - >>> mlist_2 = create_list(u'xtest_2@example.com') - >>> mlist_3 = create_list(u'xtest_3@example.com') + >>> mlist_1 = create_list('xtest_1@example.com') + >>> mlist_2 = create_list('xtest_2@example.com') + >>> mlist_3 = create_list('xtest_3@example.com') >>> from mailman.interfaces.member import MemberRole >>> com.subscribe(mlist_1, MemberRole.member) @@ -188,7 +189,8 @@ membership role. >>> len(members) 4 >>> def sortkey(member): - ... return member.address.address, member.mailing_list, int(member.role) + ... return (member.address.address, member.mailing_list, + ... int(member.role)) >>> for member in sorted(members, key=sortkey): ... print member.address.address, member.mailing_list, member.role zperson@example.com xtest_1@example.com MemberRole.member diff --git a/src/mailman/pipeline/docs/ack-headers.txt b/src/mailman/pipeline/docs/ack-headers.txt index ca41df03e..49b203cad 100644 --- a/src/mailman/pipeline/docs/ack-headers.txt +++ b/src/mailman/pipeline/docs/ack-headers.txt @@ -1,3 +1,4 @@ +====================== Acknowledgment headers ====================== @@ -8,8 +9,8 @@ changes depend on mailing list settings and others depend on how the message is getting sent through the system. We'll take things one-by-one. >>> from mailman.pipeline.cook_headers import process - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') - >>> mlist.subject_prefix = u'' + >>> mlist = config.db.list_manager.create('_xtest@example.com') + >>> mlist.subject_prefix = '' When the message's metadata has a 'noack' key set, an 'X-Ack: no' header is added. diff --git a/src/mailman/pipeline/docs/acknowledge.txt b/src/mailman/pipeline/docs/acknowledge.txt index a4c68f900..72292cd80 100644 --- a/src/mailman/pipeline/docs/acknowledge.txt +++ b/src/mailman/pipeline/docs/acknowledge.txt @@ -1,3 +1,4 @@ +====================== Message acknowledgment ====================== @@ -6,9 +7,9 @@ receive acknowledgments of their postings, Mailman will sent them such an acknowledgment. >>> handler = config.handlers['acknowledge'] - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') - >>> mlist.real_name = u'XTest' - >>> mlist.preferred_language = u'en' + >>> mlist = config.db.list_manager.create('_xtest@example.com') + >>> mlist.real_name = 'XTest' + >>> mlist.preferred_language = 'en' >>> # XXX This will almost certainly change once we've worked out the web >>> # space layout for mailing lists now. @@ -22,14 +23,14 @@ Subscribe a user to the mailing list. >>> usermgr = config.db.user_manager >>> from mailman.interfaces.member import MemberRole - >>> user_1 = usermgr.create_user(u'aperson@example.com') + >>> user_1 = usermgr.create_user('aperson@example.com') >>> address_1 = list(user_1.addresses)[0] >>> address_1.subscribe(mlist, MemberRole.member) <Member: aperson@example.com on _xtest@example.com as MemberRole.member> Non-member posts ----------------- +================ Non-members can't get acknowledgments of their posts to the mailing list. @@ -49,13 +50,13 @@ person is also not a member, no acknowledgment will be sent either. ... ... """) >>> handler.process(mlist, msg, - ... dict(original_sender=u'cperson@example.com')) + ... dict(original_sender='cperson@example.com')) >>> virginq.files [] No acknowledgment requested ---------------------------- +=========================== Unless the user has requested acknowledgments, they will not get one. @@ -71,19 +72,19 @@ Similarly if the original sender is specified in the message metadata, and that sender is a member but not one who has requested acknowledgments, none will be sent. - >>> user_2 = usermgr.create_user(u'dperson@example.com') + >>> user_2 = usermgr.create_user('dperson@example.com') >>> address_2 = list(user_2.addresses)[0] >>> address_2.subscribe(mlist, MemberRole.member) <Member: dperson@example.com on _xtest@example.com as MemberRole.member> >>> handler.process(mlist, msg, - ... dict(original_sender=u'dperson@example.com')) + ... dict(original_sender='dperson@example.com')) >>> virginq.files [] Requested acknowledgments -------------------------- +========================= If the member requests acknowledgments, Mailman will send them one when they post to the mailing list. diff --git a/src/mailman/pipeline/docs/after-delivery.txt b/src/mailman/pipeline/docs/after-delivery.txt index b910e89a6..da1a3af08 100644 --- a/src/mailman/pipeline/docs/after-delivery.txt +++ b/src/mailman/pipeline/docs/after-delivery.txt @@ -1,3 +1,4 @@ +============== After delivery ============== @@ -7,7 +8,7 @@ bookkeeping pieces of information are updated. >>> import datetime >>> handler = config.handlers['after-delivery'] - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> post_time = datetime.datetime.now() - datetime.timedelta(minutes=10) >>> mlist.last_post_time = post_time >>> mlist.post_id = 10 diff --git a/src/mailman/pipeline/docs/archives.txt b/src/mailman/pipeline/docs/archives.txt index d90228525..c6351a659 100644 --- a/src/mailman/pipeline/docs/archives.txt +++ b/src/mailman/pipeline/docs/archives.txt @@ -1,3 +1,4 @@ +======== Archives ======== @@ -9,7 +10,7 @@ processes. >>> from mailman.app.lifecycle import create_list >>> handler = config.handlers['to-archive'] - >>> mlist = create_list(u'_xtest@example.com') + >>> mlist = create_list('_xtest@example.com') >>> switchboard = config.switchboards['archive'] A helper function. diff --git a/src/mailman/pipeline/docs/avoid-duplicates.txt b/src/mailman/pipeline/docs/avoid-duplicates.txt index fe91a9a71..adca9cbe5 100644 --- a/src/mailman/pipeline/docs/avoid-duplicates.txt +++ b/src/mailman/pipeline/docs/avoid-duplicates.txt @@ -1,3 +1,4 @@ +================ Avoid duplicates ================ @@ -7,24 +8,24 @@ recipients from the list of recipients that earlier handler modules (e.g. CalcRecips) calculates. >>> handler = config.handlers['avoid-duplicates'] - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') Create some members we're going to use. >>> from mailman.interfaces.member import MemberRole >>> address_a = config.db.user_manager.create_address( - ... u'aperson@example.com') + ... 'aperson@example.com') >>> address_b = config.db.user_manager.create_address( - ... u'bperson@example.com') + ... 'bperson@example.com') >>> member_a = address_a.subscribe(mlist, MemberRole.member) >>> member_b = address_b.subscribe(mlist, MemberRole.member) >>> # This is the message metadata dictionary as it would be produced by >>> # the CalcRecips handler. - >>> recips = dict(recips=[u'aperson@example.com', u'bperson@example.com']) + >>> recips = dict(recips=['aperson@example.com', 'bperson@example.com']) Short circuiting ----------------- +================ The module short-circuits if there are no recipients. @@ -47,7 +48,7 @@ The module short-circuits if there are no recipients. Suppressing the list copy -------------------------- +========================= Members can elect not to receive a list copy of any message on which they are explicitly named as a recipient. This is done by setting their diff --git a/src/mailman/pipeline/docs/calc-recips.txt b/src/mailman/pipeline/docs/calc-recips.txt index adfbeabbf..03a22e5dc 100644 --- a/src/mailman/pipeline/docs/calc-recips.txt +++ b/src/mailman/pipeline/docs/calc-recips.txt @@ -1,3 +1,4 @@ +====================== Calculating recipients ====================== @@ -6,18 +7,18 @@ of recipient addresses. These addresses are calculated by one of the handler modules and depends on a host of factors. >>> handler = config.handlers['calculate-recipients'] - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') Recipients are calculate from the list members, so add a bunch of members to start out with. First, create a bunch of addresses... >>> usermgr = config.db.user_manager - >>> address_a = usermgr.create_address(u'aperson@example.com') - >>> address_b = usermgr.create_address(u'bperson@example.com') - >>> address_c = usermgr.create_address(u'cperson@example.com') - >>> address_d = usermgr.create_address(u'dperson@example.com') - >>> address_e = usermgr.create_address(u'eperson@example.com') - >>> address_f = usermgr.create_address(u'fperson@example.com') + >>> address_a = usermgr.create_address('aperson@example.com') + >>> address_b = usermgr.create_address('bperson@example.com') + >>> address_c = usermgr.create_address('cperson@example.com') + >>> address_d = usermgr.create_address('dperson@example.com') + >>> address_e = usermgr.create_address('eperson@example.com') + >>> address_f = usermgr.create_address('fperson@example.com') ...then subscribe these addresses to the mailing list as members... @@ -38,7 +39,7 @@ start out with. First, create a bunch of addresses... Short-circuiting ----------------- +================ Sometimes, the list of recipients already exists in the message metadata. This can happen for example, when a message was previously delivered to some @@ -49,7 +50,7 @@ but not all of the recipients. ... ... Something of great import. ... """) - >>> recips = set((u'qperson@example.com', u'zperson@example.com')) + >>> recips = set(('qperson@example.com', 'zperson@example.com')) >>> msgdata = dict(recips=recips) >>> handler.process(mlist, msg, msgdata) >>> sorted(msgdata['recips']) @@ -57,7 +58,7 @@ but not all of the recipients. Regular delivery recipients ---------------------------- +=========================== Regular delivery recipients are those people who get messages from the list as soon as they are posted. In other words, these folks are not digest members. @@ -86,13 +87,13 @@ for details. Digest recipients ------------------ +================= XXX Test various digest deliveries. Urgent messages ---------------- +=============== XXX Test various urgent deliveries: * test_urgent_moderator() diff --git a/src/mailman/pipeline/docs/cleanse.txt b/src/mailman/pipeline/docs/cleanse.txt index 0940cdb4b..778ecb19d 100644 --- a/src/mailman/pipeline/docs/cleanse.txt +++ b/src/mailman/pipeline/docs/cleanse.txt @@ -1,3 +1,4 @@ +================= Cleansing headers ================= @@ -6,7 +7,7 @@ related to additional permissions that can be granted to the message and other headers can be used to fish for membership. >>> handler = config.handlers['cleanse'] - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') Headers such as Approved, Approve, and Urgent are used to grant special pemissions to individual messages. All may contain a password; the first two @@ -62,7 +63,7 @@ Pegasus mail. I don't remember what program uses X-Confirm-Reading-To though Anonymous lists ---------------- +=============== Anonymous mailing lists also try to cleanse certain identifying headers from the original posting, so that it is at least a bit more difficult to determine @@ -73,8 +74,8 @@ and Reply-To headers in the posted message are taken from list attributes. Hotmail apparently sets X-Originating-Email. >>> mlist.anonymous_list = True - >>> mlist.description = u'A Test Mailing List' - >>> mlist.preferred_language = u'en' + >>> mlist.description = 'A Test Mailing List' + >>> mlist.preferred_language = 'en' >>> msg = message_from_string("""\ ... From: bperson@example.com ... Reply-To: bperson@example.org diff --git a/src/mailman/pipeline/docs/cook-headers.txt b/src/mailman/pipeline/docs/cook-headers.txt index 2c6381c8f..127cd8aeb 100644 --- a/src/mailman/pipeline/docs/cook-headers.txt +++ b/src/mailman/pipeline/docs/cook-headers.txt @@ -1,3 +1,4 @@ +=============== Cooking headers =============== @@ -7,14 +8,14 @@ transformations. Some headers get added, others get changed. Some of these changes depend on mailing list settings and others depend on how the message is getting sent through the system. We'll take things one-by-one. - >>> mlist = create_list(u'_xtest@example.com') - >>> mlist.subject_prefix = u'' + >>> mlist = create_list('_xtest@example.com') + >>> mlist.subject_prefix = '' >>> mlist.include_list_post_header = False >>> mlist.archive = True Saving the original sender --------------------------- +========================== Because the original sender headers may get deleted or changed, CookHeaders will place the sender in the message metadata for safe keeping. @@ -28,8 +29,8 @@ will place the sender in the message metadata for safe keeping. >>> from mailman.pipeline.cook_headers import process >>> process(mlist, msg, msgdata) - >>> msgdata['original_sender'] - u'aperson@example.com' + >>> print msgdata['original_sender'] + aperson@example.com But if there was no original sender, then the empty string will be saved. @@ -45,7 +46,7 @@ But if there was no original sender, then the empty string will be saved. X-BeenThere header ------------------- +================== The X-BeenThere header is what Mailman uses to recognize messages that have already been processed by this mailing list. It's one small measure against @@ -57,8 +58,8 @@ mail loops. ... A message of great import. ... """) >>> process(mlist, msg, {}) - >>> msg['x-beenthere'] - u'_xtest@example.com' + >>> print msg['x-beenthere'] + _xtest@example.com Mailman appends X-BeenThere headers, so if there already is one in the original message, the posted message will contain two such headers. @@ -75,7 +76,7 @@ original message, the posted message will contain two such headers. Mailman version header ----------------------- +====================== Mailman will also insert an X-Mailman-Version header... @@ -98,12 +99,12 @@ Mailman will also insert an X-Mailman-Version header... ... A message of great import. ... """) >>> process(mlist, msg, {}) - >>> msg['x-mailman-version'] - u'3000' + >>> print msg['x-mailman-version'] + 3000 Precedence header ------------------ +================= Mailman will insert a Precedence header, which is a de-facto standard for telling automatic reply software (e.g. vacation(1)) not to respond to this @@ -115,8 +116,8 @@ message. ... A message of great import. ... """) >>> process(mlist, msg, {}) - >>> msg['precedence'] - u'list' + >>> print msg['precedence'] + list But Mailman will only add that header if the original message doesn't already have one of them. @@ -128,12 +129,12 @@ have one of them. ... A message of great import. ... """) >>> process(mlist, msg, {}) - >>> msg['precedence'] - u'junk' + >>> print msg['precedence'] + junk RFC 2919 and 2369 headers -------------------------- +========================= This is a helper function for the following section. @@ -180,7 +181,7 @@ But normally, a list will include these headers. >>> mlist.include_rfc2369_headers = True >>> mlist.include_list_post_header = True - >>> mlist.preferred_language = u'en' + >>> mlist.preferred_language = 'en' >>> msg = message_from_string("""\ ... From: aperson@example.com ... Message-ID: <12345> @@ -202,7 +203,7 @@ But normally, a list will include these headers. If the mailing list has a description, then it is included in the List-Id header. - >>> mlist.description = u'My test mailing list' + >>> mlist.description = 'My test mailing list' >>> msg = message_from_string("""\ ... From: aperson@example.com ... @@ -225,20 +226,20 @@ set the List-ID header. Start by creating a new domain. >>> from mailman.interfaces.domain import IDomainManager >>> manager = IDomainManager(config) - >>> domain = manager.add(u'mail.example.net') - >>> mlist.host_name = u'mail.example.net' + >>> domain = manager.add('mail.example.net') + >>> mlist.host_name = 'mail.example.net' >>> process(mlist, msg, {}) >>> print msg['list-id'] My test mailing list <_xtest.example.com> - >>> mlist.list_id = u'_xtest.mail.example.net' + >>> mlist.list_id = '_xtest.mail.example.net' >>> process(mlist, msg, {}) >>> print msg['list-id'] My test mailing list <_xtest.mail.example.net> - >>> mlist.host_name = u'example.com' - >>> mlist.list_id = u'_xtest.example.com' + >>> mlist.host_name = 'example.com' + >>> mlist.list_id = '_xtest.example.com' Any existing List-ID headers are removed from the original message. @@ -313,7 +314,7 @@ List-Archive header either. Archived-At ------------ +=========== RFC 5064 (draft) defines a new Archived-At header which contains the url to the individual message in the archives. The stock Pipermail archiver doesn't @@ -326,7 +327,7 @@ available to us now. Personalization ---------------- +=============== The To field normally contains the list posting address. However when messages are fully personalized, that header will get overwritten with the diff --git a/src/mailman/pipeline/docs/decorate.txt b/src/mailman/pipeline/docs/decorate.txt index b805e23cf..ee2f4d10e 100644 --- a/src/mailman/pipeline/docs/decorate.txt +++ b/src/mailman/pipeline/docs/decorate.txt @@ -1,3 +1,4 @@ +================== Message decoration ================== @@ -6,7 +7,7 @@ original message. A handler module takes care of this based on the settings of the mailing list and the type of message being processed. >>> from mailman.pipeline.decorate import process - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> msg_text = """\ ... From: aperson@example.org ... @@ -16,7 +17,7 @@ of the mailing list and the type of message being processed. Short circuiting ----------------- +================ Digest messages get decorated during the digest creation phase so no extra decorations are added for digest messages. @@ -35,7 +36,7 @@ decorations are added for digest messages. Decorating simple text messages -------------------------------- +=============================== Text messages that have no declared content type character set are by default, encoded in us-ascii. When the mailing list's preferred language is 'en' @@ -45,9 +46,9 @@ placeholder variables, the message's payload will be prepended by the verbatim header, and appended with the verbatim footer. >>> msg = message_from_string(msg_text) - >>> mlist.msg_header = u'header\n' - >>> mlist.msg_footer = u'footer' - >>> mlist.preferred_language = u'en' + >>> mlist.msg_header = 'header\n' + >>> mlist.msg_footer = 'footer' + >>> mlist.preferred_language = 'en' >>> process(mlist, msg, {}) >>> print msg.as_string() From: aperson@example.org @@ -63,9 +64,9 @@ data. An example of such information is the mailing list's "real name" (a short descriptive name for the mailing list). >>> msg = message_from_string(msg_text) - >>> mlist.msg_header = u'$real_name header\n' - >>> mlist.msg_footer = u'$real_name footer' - >>> mlist.real_name = u'XTest' + >>> mlist.msg_header = '$real_name header\n' + >>> mlist.msg_footer = '$real_name footer' + >>> mlist.real_name = 'XTest' >>> process(mlist, msg, {}) >>> print msg.as_string() From: aperson@example.org @@ -78,8 +79,8 @@ You can't just pick any interpolation variable though; if you do, the variable will remain in the header or footer unchanged. >>> msg = message_from_string(msg_text) - >>> mlist.msg_header = u'$dummy header\n' - >>> mlist.msg_footer = u'$dummy footer' + >>> mlist.msg_header = '$dummy header\n' + >>> mlist.msg_footer = '$dummy footer' >>> process(mlist, msg, {}) >>> print msg.as_string() From: aperson@example.org @@ -90,7 +91,7 @@ will remain in the header or footer unchanged. Handling RFC 3676 'format=flowed' parameters --------------------------------------------- +============================================ RFC 3676 describes a standard by which text/plain messages can marked by generating MUAs for better readability in compatible receiving MUAs. The @@ -102,9 +103,9 @@ When Mailman sees text/plain messages with such RFC 3676 parameters, it preserves these parameters when it concatenates headers and footers to the message payload. - >>> mlist.msg_header = u'header' - >>> mlist.msg_footer = u'footer' - >>> mlist.preferred_language = u'en' + >>> mlist.msg_header = 'header' + >>> mlist.msg_footer = 'footer' + >>> mlist.preferred_language = 'en' >>> msg = message_from_string("""\ ... From: aperson@example.org ... Content-Type: text/plain; format=flowed; delsp=no @@ -116,14 +117,14 @@ message payload. >>> # Don't use 'print' here as above because it won't be obvious from the >>> # output that the soft-line break space at the end of the 'Here is a >>> # message' line will be retained in the output. - >>> msg['content-type'] - u'text/plain; format="flowed"; delsp="no"; charset="us-ascii"' + >>> print msg['content-type'] + text/plain; format="flowed"; delsp="no"; charset="us-ascii" >>> [line for line in msg.get_payload().splitlines()] ['header', 'Here is a message ', 'with soft line breaks.', 'footer'] Decorating mixed-charset messages ---------------------------------- +================================= When a message has no explicit character set, it is assumed to be us-ascii. However, if the mailing list's preferred language has a different character @@ -131,10 +132,10 @@ set, Mailman will still try to concatenate the header and footer, but it will convert the text to utf-8 and base-64 encode the message payload. # 'ja' = Japanese; charset = 'euc-jp' - >>> mlist.preferred_language = u'ja' - >>> mlist.msg_header = u'$description header' - >>> mlist.msg_footer = u'$description footer' - >>> mlist.description = u'\u65e5\u672c\u8a9e' + >>> mlist.preferred_language = 'ja' + >>> mlist.msg_header = '$description header' + >>> mlist.msg_footer = '$description footer' + >>> mlist.description = '\u65e5\u672c\u8a9e' >>> from email.message import Message >>> msg = Message() @@ -153,14 +154,13 @@ convert the text to utf-8 and base-64 encode the message payload. <BLANKLINE> 5pel5pys6KqeIGhlYWRlcgpGcmFuw6dhaXNlCuaXpeacrOiqniBmb290ZXI= - Sometimes the message even has an unknown character set. In this case, Mailman has no choice but to decorate the original message with MIME attachments. - >>> mlist.preferred_language = u'en' - >>> mlist.msg_header = u'header' - >>> mlist.msg_footer = u'footer' + >>> mlist.preferred_language = 'en' + >>> mlist.msg_header = 'header' + >>> mlist.msg_footer = 'footer' >>> msg = message_from_string("""\ ... From: aperson@example.org ... Content-Type: text/plain; charset=unknown @@ -198,7 +198,7 @@ attachments. Decorating multipart messages ------------------------------ +============================= Multipart messages have to be decorated differently. The header and footer cannot be simply concatenated into the payload because that will break the @@ -209,9 +209,9 @@ When the outerpart is multipart/mixed, the header and footer can have a Content-Disposition of 'inline' so that MUAs can display these headers as if they were simply concatenated. - >>> mlist.preferred_language = u'en' - >>> mlist.msg_header = u'header' - >>> mlist.msg_footer = u'footer' + >>> mlist.preferred_language = 'en' + >>> mlist.msg_header = 'header' + >>> mlist.msg_footer = 'footer' >>> part_1 = message_from_string("""\ ... From: aperson@example.org ... @@ -258,7 +258,7 @@ they were simply concatenated. Decorating other content types ------------------------------- +============================== Non-multipart non-text content types will get wrapped in a multipart/mixed so that the header and footer can be added as attachments. @@ -297,7 +297,7 @@ that the header and footer can be added as attachments. Personalization ---------------- +=============== A mailing list can be 'personalized', meaning that each message is unique for each recipient. When the list is personalized, additional interpolation diff --git a/src/mailman/pipeline/docs/file-recips.txt b/src/mailman/pipeline/docs/file-recips.txt index 81510b6e7..479ae9975 100644 --- a/src/mailman/pipeline/docs/file-recips.txt +++ b/src/mailman/pipeline/docs/file-recips.txt @@ -1,3 +1,4 @@ +=============== File recipients =============== @@ -6,11 +7,11 @@ include file. This file must be called members.txt and it must live in the list's data directory. >>> handler = config.handlers['file-recipients'] - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') Short circuiting ----------------- +================ If the message's metadata already has recipients, this handler immediately returns. @@ -28,11 +29,11 @@ returns. A message. <BLANKLINE> >>> msgdata - {'recips': 7} + {u'recips': 7} Missing file ------------- +============ The include file must live inside the list's data directory, under the name members.txt. If the file doesn't exist, the list of recipients will be @@ -52,7 +53,7 @@ empty. Existing file -------------- +============= If the file exists, it contains a list of addresses, one per line. These addresses are returned as the set of recipients. @@ -80,7 +81,7 @@ in the recipients list. >>> from mailman.interfaces.member import MemberRole >>> address_1 = config.db.user_manager.create_address( - ... u'cperson@example.com') + ... 'cperson@example.com') >>> address_1.subscribe(mlist, MemberRole.member) <Member: cperson@example.com on _xtest@example.com as MemberRole.member> diff --git a/src/mailman/pipeline/docs/filtering.txt b/src/mailman/pipeline/docs/filtering.txt index f895220f0..241f282d9 100644 --- a/src/mailman/pipeline/docs/filtering.txt +++ b/src/mailman/pipeline/docs/filtering.txt @@ -1,3 +1,4 @@ +================= Content filtering ================= @@ -5,7 +6,7 @@ Mailman can filter the content of messages posted to a mailing list by stripping MIME subparts, and possibly reorganizing the MIME structure of a message. - >>> mlist = create_list(u'test@example.com') + >>> mlist = create_list('test@example.com') Several mailing list options control content filtering. First, the feature must be enabled, then there are two options that control which MIME types get @@ -20,7 +21,7 @@ for these variables, then we'll explain them in more detail below. Filtering the outer content type --------------------------------- +================================ A simple filtering setting will just search the content types of the messages parts, discarding all parts with a matching MIME type. If the message's outer @@ -28,7 +29,7 @@ content type matches the filter, the entire message will be discarded. >>> from mailman.interfaces.mime import FilterAction - >>> mlist.filter_types = [u'image/jpeg'] + >>> mlist.filter_types = ['image/jpeg'] >>> mlist.filter_action = FilterAction.discard >>> msg = message_from_string("""\ @@ -73,11 +74,11 @@ crafted internally by Mailman. <BLANKLINE> xxxxx >>> msgdata - {'isdigest': True} + {u'isdigest': True} Simple multipart filtering --------------------------- +========================== If one of the subparts in a multipart message matches the filter type, then just that subpart will be stripped. @@ -118,7 +119,7 @@ just that subpart will be stripped. Collapsing multipart/alternative messages ------------------------------------------ +========================================= When content filtering encounters a multipart/alternative part, and the results of filtering leave only one of the subparts, then the @@ -178,7 +179,7 @@ part with just one subpart, the entire message is converted to the left over part's content type. In other words, the left over inner part is promoted to being the outer part. - >>> mlist.filter_types = [u'image/jpeg', u'text/html'] + >>> mlist.filter_types = ['image/jpeg', 'text/html'] >>> msg = message_from_string("""\ ... From: aperson@example.com ... Content-Type: multipart/alternative; boundary=AAA @@ -204,11 +205,11 @@ being the outer part. Clean up. - >>> mlist.filter_types = [u'image/jpeg'] + >>> mlist.filter_types = ['image/jpeg'] Conversion to plain text ------------------------- +======================== Many mailing lists prohibit HTML email, and in fact, such email can be a phishing or spam vector. However, many mail readers will send HTML email by @@ -265,7 +266,7 @@ name of the file containing the message payload to filter. Discarding empty parts ----------------------- +====================== Similarly, if after filtering a multipart section ends up empty, then the entire multipart is discarded. For example, here's a message where an inner @@ -337,7 +338,7 @@ the entire inner multipart/mixed is discarded. Passing MIME types ------------------- +================== XXX Describe the pass_mime_types setting and how it interacts with filter_mime_types. diff --git a/src/mailman/pipeline/docs/nntp.txt b/src/mailman/pipeline/docs/nntp.txt index 3f48be1da..dda104309 100644 --- a/src/mailman/pipeline/docs/nntp.txt +++ b/src/mailman/pipeline/docs/nntp.txt @@ -1,13 +1,14 @@ -NNTP (i.e. Usenet) Gateway -========================== +============ +NNTP Gateway +============ Mailman has an NNTP gateway, whereby messages posted to the mailing list can be forwarded onto an NNTP newsgroup. Typically this means Usenet, but since NNTP is to Usenet as IP is to the web, it's more general than that. >>> handler = config.handlers['to-usenet'] - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') - >>> mlist.preferred_language = u'en' + >>> mlist = config.db.list_manager.create('_xtest@example.com') + >>> mlist.preferred_language = 'en' >>> switchboard = config.switchboards['news'] Gatewaying from the mailing list to the newsgroup happens through a separate @@ -46,8 +47,8 @@ However, other posted messages get gated to the newsgroup via the nntp queue. The list owner can set the linked newsgroup and the nntp host that its messages are gated to. - >>> mlist.linked_newsgroup = u'comp.lang.thing' - >>> mlist.nntp_host = u'news.example.com' + >>> mlist.linked_newsgroup = 'comp.lang.thing' + >>> mlist.nntp_host = 'news.example.com' >>> handler.process(mlist, msg, {}) >>> len(switchboard.files) 1 diff --git a/src/mailman/pipeline/docs/reply-to.txt b/src/mailman/pipeline/docs/reply-to.txt index e57b97e5d..2652753d6 100644 --- a/src/mailman/pipeline/docs/reply-to.txt +++ b/src/mailman/pipeline/docs/reply-to.txt @@ -1,3 +1,4 @@ +================ Reply-to munging ================ @@ -8,8 +9,8 @@ changes depend on mailing list settings and others depend on how the message is getting sent through the system. We'll take things one-by-one. >>> from mailman.pipeline.cook_headers import process - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') - >>> mlist.subject_prefix = u'' + >>> mlist = config.db.list_manager.create('_xtest@example.com') + >>> mlist.subject_prefix = '' Reply-to munging refers to the behavior where a mailing list can be configured to change or augment an existing Reply-To header in a message posted to the @@ -30,7 +31,7 @@ this mis-feature. Reply to list -------------- +============= A list can be configured to add a Reply-To header pointing back to the mailing list's posting address. If there's no Reply-To header in the original @@ -38,8 +39,8 @@ message, the list's posting address simply gets inserted. >>> from mailman.interfaces.mailinglist import ReplyToMunging >>> mlist.reply_goes_to_list = ReplyToMunging.point_to_list - >>> mlist.preferred_language = u'en' - >>> mlist.description = u'' + >>> mlist.preferred_language = 'en' + >>> mlist.description = '' >>> msg = message_from_string("""\ ... From: aperson@example.com ... @@ -47,8 +48,8 @@ message, the list's posting address simply gets inserted. >>> process(mlist, msg, {}) >>> len(msg.get_all('reply-to')) 1 - >>> msg['reply-to'] - u'_xtest@example.com' + >>> print msg['reply-to'] + _xtest@example.com It's also possible to strip any existing Reply-To header first, before adding the list's posting address. @@ -62,8 +63,8 @@ the list's posting address. >>> process(mlist, msg, {}) >>> len(msg.get_all('reply-to')) 1 - >>> msg['reply-to'] - u'_xtest@example.com' + >>> print msg['reply-to'] + _xtest@example.com If you don't first strip the header, then the list's posting address will just get appended to whatever the original version was. @@ -77,17 +78,17 @@ get appended to whatever the original version was. >>> process(mlist, msg, {}) >>> len(msg.get_all('reply-to')) 1 - >>> msg['reply-to'] - u'bperson@example.com, _xtest@example.com' + >>> print msg['reply-to'] + bperson@example.com, _xtest@example.com Explicit Reply-To ------------------ +================= The list can also be configured to have an explicit Reply-To header. >>> mlist.reply_goes_to_list = ReplyToMunging.explicit_header - >>> mlist.reply_to_address = u'my-list@example.com' + >>> mlist.reply_to_address = 'my-list@example.com' >>> msg = message_from_string("""\ ... From: aperson@example.com ... @@ -95,8 +96,8 @@ The list can also be configured to have an explicit Reply-To header. >>> process(mlist, msg, {}) >>> len(msg.get_all('reply-to')) 1 - >>> msg['reply-to'] - u'my-list@example.com' + >>> print msg['reply-to'] + my-list@example.com And as before, it's possible to either strip any existing Reply-To header... @@ -109,8 +110,8 @@ And as before, it's possible to either strip any existing Reply-To header... >>> process(mlist, msg, {}) >>> len(msg.get_all('reply-to')) 1 - >>> msg['reply-to'] - u'my-list@example.com' + >>> print msg['reply-to'] + my-list@example.com ...or not. @@ -123,5 +124,5 @@ And as before, it's possible to either strip any existing Reply-To header... >>> process(mlist, msg, {}) >>> len(msg.get_all('reply-to')) 1 - >>> msg['reply-to'] - u'my-list@example.com, bperson@example.com' + >>> print msg['reply-to'] + my-list@example.com, bperson@example.com diff --git a/src/mailman/pipeline/docs/replybot.txt b/src/mailman/pipeline/docs/replybot.txt index 6c4d896a4..36bc6198f 100644 --- a/src/mailman/pipeline/docs/replybot.txt +++ b/src/mailman/pipeline/docs/replybot.txt @@ -1,3 +1,4 @@ +========================== Automatic response handler ========================== @@ -6,12 +7,12 @@ receives on its posting address, owner address, or robot address. Automatic responses are subject to various conditions, such as headers in the original message or the amount of time since the last auto-response. - >>> mlist = create_list(u'_xtest@example.com') - >>> mlist.real_name = u'XTest' + >>> mlist = create_list('_xtest@example.com') + >>> mlist.real_name = 'XTest' Basic automatic responding --------------------------- +========================== Basic automatic responding occurs when the list is set up to respond to either its -owner address, its -request address, or to the posting address, and a @@ -24,7 +25,7 @@ a second response will be sent, with 0 meaning "there is no grace period". >>> mlist.autorespond_owner = ResponseAction.respond_and_continue >>> mlist.autoresponse_grace_period = datetime.timedelta() - >>> mlist.autoresponse_owner_text = u'owner autoresponse text' + >>> mlist.autoresponse_owner_text = 'owner autoresponse text' >>> msg = message_from_string("""\ ... From: aperson@example.com @@ -69,7 +70,7 @@ response. Short circuiting ----------------- +================ Several headers in the original message determine whether an automatic response should even be sent. For example, if the message has an "X-Ack: No" @@ -157,14 +158,14 @@ header is ignored. Available auto-responses ------------------------- +======================== As shown above, a message sent to the -owner address will get an auto-response with the text set for owner responses. Two other types of email will get auto-responses: those sent to the -request address... >>> mlist.autorespond_requests = ResponseAction.respond_and_continue - >>> mlist.autoresponse_request_text = u'robot autoresponse text' + >>> mlist.autoresponse_request_text = 'robot autoresponse text' >>> msg = message_from_string("""\ ... From: aperson@example.com @@ -196,7 +197,7 @@ auto-responses: those sent to the -request address... ...and those sent to the posting address. >>> mlist.autorespond_postings = ResponseAction.respond_and_continue - >>> mlist.autoresponse_postings_text = u'postings autoresponse text' + >>> mlist.autoresponse_postings_text = 'postings autoresponse text' >>> msg = message_from_string("""\ ... From: aperson@example.com @@ -227,7 +228,7 @@ auto-responses: those sent to the -request address... Grace periods -------------- +============= Automatic responses have a grace period, during which no additional responses will be sent. This is so as not to bombard the sender with responses. The diff --git a/src/mailman/pipeline/docs/scrubber.txt b/src/mailman/pipeline/docs/scrubber.txt index dec1c1f64..8bc33aa13 100644 --- a/src/mailman/pipeline/docs/scrubber.txt +++ b/src/mailman/pipeline/docs/scrubber.txt @@ -1,3 +1,4 @@ +============ The scrubber ============ @@ -7,8 +8,8 @@ scrub attachments from messages so that binary goop doesn't end up in an archive message. >>> from mailman.pipeline.scrubber import process, save_attachment - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') - >>> mlist.preferred_language = u'en' + >>> mlist = config.db.list_manager.create('_xtest@example.com') + >>> mlist.preferred_language = 'en' Helper functions for getting the attachment data. @@ -38,7 +39,7 @@ Helper functions for getting the attachment data. Saving attachments ------------------- +================== The Scrubber handler exposes a function called save_attachments() which can be used to strip various types of attachments and store them in the archive @@ -61,11 +62,11 @@ this is an unfortunate double negative). ... ... R0lGODdhAQABAIAAAAAAAAAAACwAAAAAAQABAAACAQUAOw== ... """) - >>> save_attachment(mlist, msg, 'dir') - u'<http://www.example.com/pipermail/_xtest@example.com/dir/xtest.gif>' + >>> print save_attachment(mlist, msg, 'dir') + <http://www.example.com/pipermail/_xtest@example.com/dir/xtest.gif> >>> data = read_attachment('dir/xtest.gif') - >>> data[:6] - 'GIF87a' + >>> print data[:6] + GIF87a >>> len(data) 34 @@ -93,21 +94,21 @@ Content-Disposition: filename. This is the default. ... ... R0lGODdhAQABAIAAAAAAAAAAACwAAAAAAQABAAACAQUAOw== ... """) - >>> save_attachment(mlist, msg, 'dir') - u'<http://www.example.com/pipermail/_xtest@example.com/dir/attachment.gif>' + >>> print save_attachment(mlist, msg, 'dir') + <http://www.example.com/pipermail/_xtest@example.com/dir/attachment.gif> >>> data = read_attachment('dir/xtest.gif') Traceback (most recent call last): IOError: [Errno ...] No such file or directory: u'.../archives/private/_xtest@example.com/dir/xtest.gif' >>> data = read_attachment('dir/attachment.gif') - >>> data[:6] - 'GIF87a' + >>> print data[:6] + GIF87a >>> len(data) 34 Scrubbing image attachments ---------------------------- +=========================== When scrubbing image attachments, the original message is modified to include a reference to the attachment file as available through the on-line archive. @@ -182,7 +183,7 @@ The URL will point to the attachment sitting in the archive. Scrubbing text attachments --------------------------- +========================== Similar to image attachments, text attachments will also be scrubbed, but the placeholder will be slightly different. @@ -220,6 +221,6 @@ placeholder will be slightly different. Clean up --------- +======== >>> config.pop('test config') diff --git a/src/mailman/pipeline/docs/subject-munging.txt b/src/mailman/pipeline/docs/subject-munging.txt index b2972683b..68ad940e8 100644 --- a/src/mailman/pipeline/docs/subject-munging.txt +++ b/src/mailman/pipeline/docs/subject-munging.txt @@ -1,3 +1,4 @@ +=============== Subject munging =============== @@ -8,20 +9,20 @@ changes depend on mailing list settings and others depend on how the message is getting sent through the system. We'll take things one-by-one. >>> from mailman.pipeline.cook_headers import process - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') - >>> mlist.subject_prefix = u'' + >>> mlist = config.db.list_manager.create('_xtest@example.com') + >>> mlist.subject_prefix = '' Inserting a prefix ------------------- +================== Another thing CookHeaders does is 'munge' the Subject header by inserting the subject prefix for the list at the front. If there's no subject header in the original message, Mailman uses a canned default. In order to do subject munging, a mailing list must have a preferred language. - >>> mlist.subject_prefix = u'[XTest] ' - >>> mlist.preferred_language = u'en' + >>> mlist.subject_prefix = '[XTest] ' + >>> mlist.preferred_language = 'en' >>> msg = message_from_string("""\ ... From: aperson@example.com ... @@ -50,8 +51,8 @@ the beginning of the header's value. ... """) >>> msgdata = {} >>> process(mlist, msg, msgdata) - >>> msgdata['origsubj'] - u'Something important' + >>> print msgdata['origsubj'] + Something important >>> print msg['subject'] [XTest] Something important @@ -64,8 +65,8 @@ Subject headers are not munged for digest messages. ... A message of great import. ... """) >>> process(mlist, msg, dict(isdigest=True)) - >>> msg['subject'] - u'Something important' + >>> print msg['subject'] + Something important Nor are they munged for 'fast tracked' messages, which are generally defined as messages that Mailman crafts internally. @@ -77,8 +78,8 @@ as messages that Mailman crafts internally. ... A message of great import. ... """) >>> process(mlist, msg, dict(_fasttrack=True)) - >>> msg['subject'] - u'Something important' + >>> print msg['subject'] + Something important If a Subject header already has a prefix, usually following a Re: marker, another one will not be added but the prefix will be moved to the front of the @@ -110,7 +111,7 @@ option available in Mailman 3. Internationalized headers -------------------------- +========================= Internationalization adds some interesting twists to the handling of subject prefixes. Part of what makes this interesting is the encoding of i18n headers @@ -129,14 +130,14 @@ set than the encoded header. Prefix numbers --------------- +============== Subject prefixes support a placeholder for the numeric post id. Every time a message is posted to the mailing list, a 'post id' gets incremented. This is a purely sequential integer that increases monotonically. By added a '%d' placeholder to the subject prefix, this post id can be included in the prefix. - >>> mlist.subject_prefix = u'[XTest %d] ' + >>> mlist.subject_prefix = '[XTest %d] ' >>> mlist.post_id = 456 >>> msg = message_from_string("""\ ... Subject: Something important @@ -218,7 +219,7 @@ In this test case, we get an extra space between the prefix and the original subject. It's because the original is 'crooked'. Note that a Subject starting with '\n ' is generated by some version of Eudora Japanese edition. - >>> mlist.subject_prefix = u'[XTest] ' + >>> mlist.subject_prefix = '[XTest] ' >>> msg = message_from_string("""\ ... Subject: ... Important message diff --git a/src/mailman/pipeline/docs/tagger.txt b/src/mailman/pipeline/docs/tagger.txt index 9f0bcd4b2..a552401f7 100644 --- a/src/mailman/pipeline/docs/tagger.txt +++ b/src/mailman/pipeline/docs/tagger.txt @@ -1,3 +1,4 @@ +============== Message tagger ============== @@ -9,7 +10,7 @@ its Subject: and Keywords: headers compared against these regular expressions. The message then gets tagged with the topic names of each hit. >>> from mailman.pipeline.tagger import process - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') Topics must be enabled for Mailman to do any topic matching, even if topics are defined. @@ -52,11 +53,11 @@ the message metadata gets a key with a list of matching topic names. <BLANKLINE> <BLANKLINE> >>> msgdata['topichits'] - ['bar fight'] + [u'bar fight'] Scanning body lines -------------------- +=================== The tagger can also look at a certain number of body lines, but only for Subject: and Keyword: header-like lines. When set to zero, no body lines are @@ -111,7 +112,7 @@ found. Keywords: barbaz <BLANKLINE> >>> msgdata['topichits'] - ['bar fight'] + [u'bar fight'] However, scanning stops at the first body line that doesn't look like a header. @@ -155,14 +156,14 @@ When set to a negative number, all body lines will be scanned. >>> process(mlist, msg, msgdata) >>> # Rather than print out 100 X-Ignore: headers, let's just prove that >>> # the X-Topics: header exists, meaning that the tagger did its job. - >>> msg['x-topics'] - u'bar fight' + >>> print msg['x-topics'] + bar fight >>> msgdata['topichits'] - ['bar fight'] + [u'bar fight'] Scanning sub-parts ------------------- +================== The tagger will also scan the body lines of text subparts in a multipart message, using the same rules as if all those body lines lived in a single @@ -200,7 +201,7 @@ text payload. --BOUNDARY-- <BLANKLINE> >>> msgdata['topichits'] - ['bar fight'] + [u'bar fight'] But the tagger will not descend into non-text parts. diff --git a/src/mailman/pipeline/docs/to-outgoing.txt b/src/mailman/pipeline/docs/to-outgoing.txt index 5305db19f..9d467bb5e 100644 --- a/src/mailman/pipeline/docs/to-outgoing.txt +++ b/src/mailman/pipeline/docs/to-outgoing.txt @@ -1,3 +1,4 @@ +==================== The outgoing handler ==================== @@ -10,7 +11,7 @@ basically describes how to encode the recipient's address in the originator headers for unambigous bounce processing. >>> handler = config.handlers['to-outgoing'] - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> switchboard = config.switchboards['out'] >>> def queue_size(): diff --git a/src/mailman/queue/docs/archiver.txt b/src/mailman/queue/docs/archiver.txt index 601857cd9..7d404cf56 100644 --- a/src/mailman/queue/docs/archiver.txt +++ b/src/mailman/queue/docs/archiver.txt @@ -1,3 +1,4 @@ +========= Archiving ========= @@ -5,7 +6,7 @@ Mailman can archive to any number of archivers that adhere to the IArchiver interface. By default, there's a Pipermail archiver. >>> from mailman.app.lifecycle import create_list - >>> mlist = create_list(u'test@example.com') + >>> mlist = create_list('test@example.com') >>> commit() >>> msg = message_from_string("""\ diff --git a/src/mailman/queue/docs/command.txt b/src/mailman/queue/docs/command.txt index c9a55d2a9..73be64de0 100644 --- a/src/mailman/queue/docs/command.txt +++ b/src/mailman/queue/docs/command.txt @@ -1,3 +1,4 @@ +======================== The command queue runner ======================== @@ -6,11 +7,11 @@ Commands are extensible using the Mailman plugin 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(u'test@example.com') + >>> 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. @@ -64,7 +65,7 @@ And now the response is in the virgin queue. 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. @@ -105,7 +106,7 @@ message is plain text. Stopping command processing ---------------------------- +=========================== The 'end' command stops email processing, so that nothing following is looked at by the command queue. diff --git a/src/mailman/queue/docs/digester.txt b/src/mailman/queue/docs/digester.txt index 2c9c813b2..bb2c05819 100644 --- a/src/mailman/queue/docs/digester.txt +++ b/src/mailman/queue/docs/digester.txt @@ -1,3 +1,4 @@ +========= Digesting ========= @@ -272,7 +273,7 @@ The RFC 1153 contains the digest in a single plain text message. Internationalized digests -------------------------- +========================= When messages come in with a content-type character set different than that of the list's preferred language, recipients will get an internationalized @@ -286,7 +287,7 @@ digest. French is not enabled by default site-wide, so enable that now. ... default_language: fr ... """) - >>> mlist.preferred_language = u'fr' + >>> mlist.preferred_language = 'fr' >>> msg = message_from_string("""\ ... From: aperson@example.org ... To: test@example.com @@ -467,7 +468,7 @@ The content can be decoded to see the actual digest text. Digest delivery ---------------- +=============== A mailing list's members can choose to receive normal delivery, plain text digests, or MIME digests. @@ -484,24 +485,24 @@ digests, or MIME digests. Two regular delivery members subscribe to the mailing list. - >>> member_1 = subscribe(u'uperson@example.com', DeliveryMode.regular) - >>> member_2 = subscribe(u'vperson@example.com', DeliveryMode.regular) + >>> member_1 = subscribe('uperson@example.com', DeliveryMode.regular) + >>> member_2 = subscribe('vperson@example.com', DeliveryMode.regular) Two MIME digest members subscribe to the mailing list. - >>> member_3 = subscribe(u'wperson@example.com', DeliveryMode.mime_digests) - >>> member_4 = subscribe(u'xperson@example.com', DeliveryMode.mime_digests) + >>> member_3 = subscribe('wperson@example.com', DeliveryMode.mime_digests) + >>> member_4 = subscribe('xperson@example.com', DeliveryMode.mime_digests) One RFC 1153 digest member subscribes to the mailing list. >>> member_5 = subscribe( - ... u'yperson@example.com', DeliveryMode.plaintext_digests) + ... 'yperson@example.com', DeliveryMode.plaintext_digests) >>> member_6 = subscribe( - ... u'zperson@example.com', DeliveryMode.plaintext_digests) + ... 'zperson@example.com', DeliveryMode.plaintext_digests) When a digest gets sent, the appropriate recipient list is chosen. - >>> mlist.preferred_language = u'en' + >>> mlist.preferred_language = 'en' >>> mlist.digest_size_threshold = 0.5 >>> fill_digest() >>> runner.run() diff --git a/src/mailman/queue/docs/incoming.txt b/src/mailman/queue/docs/incoming.txt index 7e1a98f6b..926b60965 100644 --- a/src/mailman/queue/docs/incoming.txt +++ b/src/mailman/queue/docs/incoming.txt @@ -1,3 +1,4 @@ +========================= The incoming queue runner ========================= @@ -12,13 +13,13 @@ message eventually ending up in one of the four disposition states described above. >>> from mailman.app.lifecycle import create_list - >>> mlist = create_list(u'_xtest@example.com') - >>> mlist.start_chain - u'built-in' + >>> mlist = create_list('_xtest@example.com') + >>> print mlist.start_chain + built-in Accepted messages ------------------ +================= We have a message that is going to be sent to the mailing list. This message is so perfectly fine for posting that it will be accepted and forward to the @@ -76,7 +77,7 @@ And now the message is in the pipeline queue. Held messages -------------- +============= The list moderator sets the emergency flag on the mailing list. The built-in chain will now hold all posted messages, so nothing will show up in the @@ -106,7 +107,7 @@ pipeline queue. Discarded messages ------------------- +================== Another possibility is that the message would get immediately discarded. The built-in chain does not have such a disposition by default, so let's craft a @@ -116,10 +117,10 @@ new chain and set it as the mailing list's start chain. >>> from mailman.interfaces.chain import LinkAction >>> truth_rule = config.rules['truth'] >>> discard_chain = config.chains['discard'] - >>> test_chain = Chain('always-discard', u'Testing discards') + >>> test_chain = Chain('always-discard', 'Testing discards') >>> link = Link(truth_rule, LinkAction.jump, discard_chain) >>> test_chain.append_link(link) - >>> mlist.start_chain = u'always-discard' + >>> mlist.start_chain = 'always-discard' >>> inject_message(mlist, msg) >>> file_pos = fp.tell() @@ -137,17 +138,17 @@ new chain and set it as the mailing list's start chain. Rejected messages ------------------ +================= Similar to discarded messages, a message can be rejected, or bounced back to the original sender. Again, the built-in chain doesn't support this so we'll just create a new chain that does. >>> reject_chain = config.chains['reject'] - >>> test_chain = Chain('always-reject', u'Testing rejections') + >>> test_chain = Chain('always-reject', 'Testing rejections') >>> link = Link(truth_rule, LinkAction.jump, reject_chain) >>> test_chain.append_link(link) - >>> mlist.start_chain = u'always-reject' + >>> mlist.start_chain = 'always-reject' The virgin queue needs to be cleared out due to artifacts from the previous tests above. diff --git a/src/mailman/queue/docs/lmtp.txt b/src/mailman/queue/docs/lmtp.txt index 75e91fd4e..b8b6335fb 100644 --- a/src/mailman/queue/docs/lmtp.txt +++ b/src/mailman/queue/docs/lmtp.txt @@ -1,3 +1,4 @@ +=========== LTMP server =========== @@ -23,7 +24,7 @@ It also helps to have a nice LMTP client. Posting address ---------------- +=============== If the mail server tries to send a message to a nonexistent mailing list, it will get a 550 error. @@ -45,7 +46,7 @@ will get a 550 error. Once the mailing list is created, the posting address is valid. >>> from mailman.app.lifecycle import create_list - >>> create_list(u'mylist@example.com') + >>> create_list('mylist@example.com') <mailing list "mylist@example.com" at ...> >>> commit() >>> lmtp.sendmail( @@ -62,7 +63,7 @@ Once the mailing list is created, the posting address is valid. Sub-addresses -------------- +============= The LMTP server understands each of the list's sub-addreses, such as -join, -leave, -request and so on. If the message is posted to an invalid @@ -98,6 +99,6 @@ But the message is accepted if posted to a valid sub-address. Clean up --------- +======== >>> master.stop() diff --git a/src/mailman/queue/docs/news.txt b/src/mailman/queue/docs/news.txt index f149ef93a..c9f2417a0 100644 --- a/src/mailman/queue/docs/news.txt +++ b/src/mailman/queue/docs/news.txt @@ -1,3 +1,4 @@ +=============== The news runner =============== @@ -7,8 +8,8 @@ the message for Usenet (yes, I know that NNTP is not Usenet, but this runner was originally written to gate to Usenet, which has its own rules). >>> from mailman.queue.news import prepare_message - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') - >>> mlist.linked_newsgroup = u'comp.lang.python' + >>> mlist = config.db.list_manager.create('_xtest@example.com') + >>> mlist.linked_newsgroup = 'comp.lang.python' Some NNTP servers such as INN reject messages containing a set of prohibited headers, so one of the things that the news runner does is remove these @@ -112,7 +113,7 @@ the message. Newsgroup moderation --------------------- +==================== When the newsgroup is moderated, an Approved: header with the list's posting address is added for the benefit of the Usenet system. @@ -126,8 +127,8 @@ address is added for the benefit of the Usenet system. ... ... """) >>> prepare_message(mlist, msg, {}) - >>> msg['approved'] - u'_xtest@example.com' + >>> print msg['approved'] + _xtest@example.com >>> mlist.news_moderation = NewsModeration.moderated >>> msg = message_from_string("""\ @@ -137,8 +138,8 @@ address is added for the benefit of the Usenet system. ... ... """) >>> prepare_message(mlist, msg, {}) - >>> msg['approved'] - u'_xtest@example.com' + >>> print msg['approved'] + _xtest@example.com But if the newsgroup is not moderated, the Approved: header is not changed. diff --git a/src/mailman/queue/docs/outgoing.txt b/src/mailman/queue/docs/outgoing.txt index 1c9d89041..b8cf25033 100644 --- a/src/mailman/queue/docs/outgoing.txt +++ b/src/mailman/queue/docs/outgoing.txt @@ -1,3 +1,4 @@ +===================== Outgoing queue runner ===================== @@ -11,16 +12,16 @@ recipient set will be batched, whether messages will be personalized and VERP'd, etc. The outgoing runner doesn't itself support retrying but it can move messages to the 'retry queue' for handling delivery failures. - >>> mlist = create_list(u'test@example.com') + >>> mlist = create_list('test@example.com') >>> from mailman.app.membership import add_member >>> from mailman.interfaces.member import DeliveryMode - >>> add_member(mlist, u'aperson@example.com', u'Anne Person', - ... u'password', DeliveryMode.regular, u'en') - >>> add_member(mlist, u'bperson@example.com', u'Bart Person', - ... u'password', DeliveryMode.regular, u'en') - >>> add_member(mlist, u'cperson@example.com', u'Cris Person', - ... u'password', DeliveryMode.regular, u'en') + >>> add_member(mlist, 'aperson@example.com', 'Anne Person', + ... 'password', DeliveryMode.regular, 'en') + >>> add_member(mlist, 'bperson@example.com', 'Bart Person', + ... 'password', DeliveryMode.regular, 'en') + >>> add_member(mlist, 'cperson@example.com', 'Cris Person', + ... 'password', DeliveryMode.regular, 'en') By setting the mailing list to personalize messages, each recipient will get a unique copy of the message, with certain headers tailored for that recipient. diff --git a/src/mailman/queue/docs/runner.txt b/src/mailman/queue/docs/runner.txt index d24a8334c..032ea4c50 100644 --- a/src/mailman/queue/docs/runner.txt +++ b/src/mailman/queue/docs/runner.txt @@ -1,3 +1,4 @@ +============= Queue runners ============= @@ -8,14 +9,14 @@ while, then wakes up and runs through its queue files again. Basic architecture ------------------- +================== The basic architecture of qrunner is implemented in the base class that all runners inherit from. This base class implements a .run() method that runs continuously in a loop until the .stop() method is called. - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') - >>> mlist.preferred_language = u'en' + >>> mlist = config.db.list_manager.create('_xtest@example.com') + >>> mlist.preferred_language = 'en' Here is a very simple derived qrunner class. Queue runners use a configuration section in the configuration files to determine run diff --git a/src/mailman/rest/docs/domains.txt b/src/mailman/rest/docs/domains.txt index 2afdce49d..db1fe7258 100644 --- a/src/mailman/rest/docs/domains.txt +++ b/src/mailman/rest/docs/domains.txt @@ -6,7 +6,7 @@ Domains # that first. >>> from mailman.interfaces.domain import IDomainManager >>> manager = IDomainManager(config) - >>> manager.remove(u'example.com') + >>> manager.remove('example.com') <Domain example.com...> >>> commit() @@ -20,8 +20,8 @@ initially none. Once a domain is added though, it is accessible through the API. - >>> manager.add(u'example.com', u'An example domain', - ... u'http://lists.example.com') + >>> manager.add('example.com', 'An example domain', + ... 'http://lists.example.com') <Domain example.com, An example domain, base_url: http://lists.example.com, contact_address: postmaster@example.com> @@ -43,15 +43,15 @@ Once a domain is added though, it is accessible through the API. At the top level, all domains are returned as separate entries. - >>> manager.add(u'example.org', - ... base_url=u'http://mail.example.org', - ... contact_address=u'listmaster@example.org') + >>> manager.add('example.org', + ... base_url='http://mail.example.org', + ... contact_address='listmaster@example.org') <Domain example.org, base_url: http://mail.example.org, contact_address: listmaster@example.org> - >>> manager.add(u'lists.example.net', - ... u'Porkmasters', - ... u'http://example.net', - ... u'porkmaster@example.net') + >>> manager.add('lists.example.net', + ... 'Porkmasters', + ... 'http://example.net', + ... 'porkmaster@example.net') <Domain lists.example.net, Porkmasters, base_url: http://example.net, contact_address: porkmaster@example.net> diff --git a/src/mailman/rules/docs/administrivia.txt b/src/mailman/rules/docs/administrivia.txt index dba882775..f43a31834 100644 --- a/src/mailman/rules/docs/administrivia.txt +++ b/src/mailman/rules/docs/administrivia.txt @@ -1,3 +1,4 @@ +============= Administrivia ============= @@ -6,7 +7,7 @@ commands in the Subject header or first few lines of the payload. This is used to catch messages posted to the list which should have been sent to the -request robot address. - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> mlist.administrivia = True >>> rule = config.rules['administrivia'] >>> print rule.name @@ -72,7 +73,7 @@ We don't show all the other possible email commands, but you get the idea. Non-administrivia ------------------ +================= Of course, messages that don't contain administrivia, don't match the rule. diff --git a/src/mailman/rules/docs/approve.txt b/src/mailman/rules/docs/approve.txt index dda531a4c..8ae23b8f3 100644 --- a/src/mailman/rules/docs/approve.txt +++ b/src/mailman/rules/docs/approve.txt @@ -1,3 +1,4 @@ +===================== Pre-approved postings ===================== @@ -13,8 +14,8 @@ approval queue. This has several use cases: In order to support this, a mailing list can be given a 'moderator password' which is shared among all the administrators. - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') - >>> mlist.moderator_password = u'abcxyz' + >>> mlist = config.db.list_manager.create('_xtest@example.com') + >>> mlist.moderator_password = 'abcxyz' The 'approved' rule determines whether the message contains the proper approval or not. @@ -25,7 +26,7 @@ approval or not. No approval ------------ +=========== If the message has no Approve or Approved header, then the rule does not match. @@ -42,14 +43,14 @@ If the message has an Approve or Approved header with a value that does not match the moderator password, then the rule does not match. However, the header is still removed. - >>> msg['Approve'] = u'12345' + >>> msg['Approve'] = '12345' >>> rule.check(mlist, msg, {}) False >>> print msg['approve'] None >>> del msg['approve'] - >>> msg['Approved'] = u'12345' + >>> msg['Approved'] = '12345' >>> rule.check(mlist, msg, {}) False >>> print msg['approved'] @@ -59,12 +60,12 @@ header is still removed. Using an approval header ------------------------- +======================== If the moderator password is given in an Approve header, then the rule matches, and the Approve header is stripped. - >>> msg['Approve'] = u'abcxyz' + >>> msg['Approve'] = 'abcxyz' >>> rule.check(mlist, msg, {}) True >>> print msg['approve'] @@ -72,7 +73,7 @@ matches, and the Approve header is stripped. Similarly, for the Approved header. - >>> msg['Approved'] = u'abcxyz' + >>> msg['Approved'] = 'abcxyz' >>> rule.check(mlist, msg, {}) True >>> print msg['approved'] @@ -80,7 +81,7 @@ Similarly, for the Approved header. Using a pseudo-header ---------------------- +===================== Different mail user agents have varying degrees to which they support custom headers like Approve and Approved. For this reason, Mailman also supports @@ -171,7 +172,7 @@ Similarly for the Approved header. MIME multipart support ----------------------- +====================== Mailman searches for the pseudo-header as the first non-whitespace line in the first text/plain message part of the message. This allows the feature to be @@ -355,7 +356,7 @@ And the pseudo-header is removed. Stripping text/html parts -------------------------- +========================= Because some mail readers will include both a text/plain part and a text/html alternative, the 'approved' rule has to search the alternatives and strip diff --git a/src/mailman/rules/docs/emergency.txt b/src/mailman/rules/docs/emergency.txt index 9d80fdb40..2c56d967b 100644 --- a/src/mailman/rules/docs/emergency.txt +++ b/src/mailman/rules/docs/emergency.txt @@ -1,3 +1,4 @@ +========= Emergency ========= @@ -5,7 +6,7 @@ When the mailing list has its emergency flag set, all messages posted to the list are held for moderator approval. >>> from mailman.app.lifecycle import create_list - >>> mlist = create_list(u'_xtest@example.com') + >>> mlist = create_list('_xtest@example.com') >>> msg = message_from_string("""\ ... From: aperson@example.com ... To: _xtest@example.com diff --git a/src/mailman/rules/docs/header-matching.txt b/src/mailman/rules/docs/header-matching.txt index 417000d67..9956832ea 100644 --- a/src/mailman/rules/docs/header-matching.txt +++ b/src/mailman/rules/docs/header-matching.txt @@ -1,3 +1,4 @@ +=============== Header matching =============== @@ -6,7 +7,7 @@ processing. There is a set of site-wide default header matches specified in the configuration file under the [spam.headers] section. >>> from mailman.app.lifecycle import create_list - >>> mlist = create_list(u'_xtest@example.com') + >>> mlist = create_list('_xtest@example.com') Because the default [spam.headers] section is empty, we'll just extend the current header matching chain with a pattern that matches 4 or more stars, @@ -94,7 +95,7 @@ Flush out the extended header matching rules. List-specific header matching ------------------------------ +============================= Each mailing list can also be configured with a set of header matching regular expression rules. These are used to impose list-specific header filtering diff --git a/src/mailman/rules/docs/implicit-dest.txt b/src/mailman/rules/docs/implicit-dest.txt index 8666c1f5c..04e93615e 100644 --- a/src/mailman/rules/docs/implicit-dest.txt +++ b/src/mailman/rules/docs/implicit-dest.txt @@ -1,10 +1,11 @@ +==================== Implicit destination ==================== The 'implicit-dest' rule matches when the mailing list's posting address is not explicitly mentioned in the set of message recipients. - >>> mlist = create_list(u'_xtest@example.com') + >>> mlist = create_list('_xtest@example.com') >>> rule = config.rules['implicit-dest'] >>> print rule.name implicit-dest @@ -56,7 +57,7 @@ then the rule will not match. >>> rule.check(mlist, msg, {}) True - >>> alias_set.add(u'myfriend@example.com') + >>> alias_set.add('myfriend@example.com') >>> rule.check(mlist, msg, {}) False @@ -69,7 +70,7 @@ that Mailman pulled it from the appropriate news group. Additional aliases can be added. - >>> alias_set.add(u'other@example.com') + >>> alias_set.add('other@example.com') >>> del msg['to'] >>> rule.check(mlist, msg, {}) True @@ -80,13 +81,13 @@ Additional aliases can be added. Aliases can be removed. - >>> alias_set.remove(u'other@example.com') + >>> alias_set.remove('other@example.com') >>> rule.check(mlist, msg, {}) True Aliases can also be cleared. - >>> msg['Cc'] = u'myfriend@example.com' + >>> msg['Cc'] = 'myfriend@example.com' >>> rule.check(mlist, msg, {}) False @@ -96,13 +97,13 @@ Aliases can also be cleared. Alias patterns --------------- +============== It's also possible to specify an alias pattern, i.e. a regular expression to match against the recipients. For example, we can say that if there is a recipient in the example.net domain, then the rule does not match. - >>> alias_set.add(u'^.*@example.net') + >>> alias_set.add('^.*@example.net') >>> rule.check(mlist, msg, {}) True @@ -112,7 +113,7 @@ recipient in the example.net domain, then the rule does not match. Bad aliases ------------ +=========== You cannot add an alias that looks like neither a pattern nor an email address. diff --git a/src/mailman/rules/docs/loop.txt b/src/mailman/rules/docs/loop.txt index 61612cd75..5015d3d95 100644 --- a/src/mailman/rules/docs/loop.txt +++ b/src/mailman/rules/docs/loop.txt @@ -1,10 +1,11 @@ +============= Posting loops ============= To avoid a posting loop, Mailman has a rule to check for the existence of an X-BeenThere header with the value of the list's posting address. - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> rule = config.rules['loop'] >>> print rule.name loop @@ -21,7 +22,7 @@ The header could be missing, in which case the rule does not match. The header could be present, but not match the list's posting address. - >>> msg['X-BeenThere'] = u'not-this-list@example.com' + >>> msg['X-BeenThere'] = 'not-this-list@example.com' >>> rule.check(mlist, msg, {}) False diff --git a/src/mailman/rules/docs/max-size.txt b/src/mailman/rules/docs/max-size.txt index 117691e59..a34c98627 100644 --- a/src/mailman/rules/docs/max-size.txt +++ b/src/mailman/rules/docs/max-size.txt @@ -1,3 +1,4 @@ +============ Message size ============ @@ -6,7 +7,7 @@ specified maximum. 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 = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> rule = config.rules['max-size'] >>> print rule.name max-size @@ -15,8 +16,8 @@ For example, setting the maximum message size to 1 means that any message bigger than that will match the rule. >>> mlist.max_message_size = 1 # 1024 bytes - >>> one_line = u'x' * 79 - >>> big_body = u'\n'.join([one_line] * 15) + >>> one_line = 'x' * 79 + >>> big_body = '\n'.join([one_line] * 15) >>> msg = message_from_string("""\ ... From: aperson@example.com ... To: _xtest@example.com diff --git a/src/mailman/rules/docs/moderation.txt b/src/mailman/rules/docs/moderation.txt index 65be0d7da..c4adcdf53 100644 --- a/src/mailman/rules/docs/moderation.txt +++ b/src/mailman/rules/docs/moderation.txt @@ -1,3 +1,4 @@ +================= Member moderation ================= @@ -6,7 +7,7 @@ postings, then only members with a cleared moderation flag will be able to email the list without having those messages be held for approval. The 'moderation' rule determines whether the message should be moderated or not. - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> rule = config.rules['moderation'] >>> print rule.name moderation @@ -26,7 +27,7 @@ moderation rule can't match. Let's add the message author as a non-moderated member. >>> user = config.db.user_manager.create_user( - ... u'aperson@example.org', u'Anne Person') + ... 'aperson@example.org', 'Anne Person') >>> address = list(user.addresses)[0] >>> from mailman.interfaces.member import MemberRole >>> member = address.subscribe(mlist, MemberRole.member) @@ -43,7 +44,7 @@ Once the member's moderation flag is set though, the rule matches. Non-members ------------ +=========== There is another, related rule for matching non-members, which simply matches if the sender is /not/ a member of the mailing list. diff --git a/src/mailman/rules/docs/news-moderation.txt b/src/mailman/rules/docs/news-moderation.txt index 2ba6aa065..5658ccfef 100644 --- a/src/mailman/rules/docs/news-moderation.txt +++ b/src/mailman/rules/docs/news-moderation.txt @@ -1,3 +1,4 @@ +==================== Newsgroup moderation ==================== @@ -8,7 +9,7 @@ posted to the newsgroup, and from there, gated to the mailing list. It's a circuitous route, but it works nonetheless by holding all messages posted directly to the mailing list. - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> rule = config.rules['news-moderation'] >>> print rule.name news-moderation diff --git a/src/mailman/rules/docs/no-subject.txt b/src/mailman/rules/docs/no-subject.txt index 576111cd7..f9b3ece03 100644 --- a/src/mailman/rules/docs/no-subject.txt +++ b/src/mailman/rules/docs/no-subject.txt @@ -1,10 +1,11 @@ +================= No Subject header ================= This rule matches if the message has no Subject header, or if the header is the empty string when stripped. - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> rule = config.rules['no-subject'] >>> print rule.name no-subject @@ -28,6 +29,6 @@ Delete the Subject header and the rule matches. Even a Subject header with only whitespace still matches the rule. - >>> msg['Subject'] = u' ' + >>> msg['Subject'] = ' ' >>> rule.check(mlist, msg, {}) True diff --git a/src/mailman/rules/docs/recipients.txt b/src/mailman/rules/docs/recipients.txt index 3cd49d501..e8c63b59a 100644 --- a/src/mailman/rules/docs/recipients.txt +++ b/src/mailman/rules/docs/recipients.txt @@ -1,10 +1,11 @@ +============================ Maximum number of recipients ============================ The 'max-recipients' rule matches when there are more than the maximum allowed number of explicit recipients addressed by the message. - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> rule = config.rules['max-recipients'] >>> print rule.name max-recipients diff --git a/src/mailman/rules/docs/rules.txt b/src/mailman/rules/docs/rules.txt index 095d11466..2836d10a1 100644 --- a/src/mailman/rules/docs/rules.txt +++ b/src/mailman/rules/docs/rules.txt @@ -1,3 +1,4 @@ +===== Rules ===== @@ -7,7 +8,7 @@ links determine what happens when a rule matches. All rules ---------- +========= Rules are maintained in the configuration object as a dictionary mapping rule names to rule objects. @@ -40,13 +41,13 @@ You can get a rule by name. Rule checks ------------ +=========== Individual rules can be checked to see if they match, by running the rule's `check()` method. This returns a boolean indicating whether the rule was matched or not. - >>> mlist = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> msg = message_from_string("""\ ... From: aperson@example.com ... diff --git a/src/mailman/rules/docs/suspicious.txt b/src/mailman/rules/docs/suspicious.txt index 190a34aca..79d3eeea5 100644 --- a/src/mailman/rules/docs/suspicious.txt +++ b/src/mailman/rules/docs/suspicious.txt @@ -1,3 +1,4 @@ +================== Suspicious headers ================== @@ -5,14 +6,14 @@ 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 = config.db.list_manager.create(u'_xtest@example.com') + >>> mlist = config.db.list_manager.create('_xtest@example.com') >>> rule = config.rules['suspicious-header'] >>> print rule.name suspicious-header Set the so-called suspicious header configuration variable. - >>> mlist.bounce_matching_headers = u'From: .*person@(blah.)?example.com' + >>> mlist.bounce_matching_headers = 'From: .*person@(blah.)?example.com' >>> msg = message_from_string("""\ ... From: aperson@example.com ... To: _xtest@example.com diff --git a/src/mailman/styles/default.py b/src/mailman/styles/default.py index 2b07b6f49..d1904a150 100644 --- a/src/mailman/styles/default.py +++ b/src/mailman/styles/default.py @@ -55,7 +55,7 @@ class DefaultStyle: mlist = mailing_list # List identity. mlist.real_name = mlist.list_name.capitalize() - mlist.list_id = u'{0.list_name}.{0.host_name}'.format(mlist) + mlist.list_id = '{0.list_name}.{0.host_name}'.format(mlist) mlist.include_rfc2369_headers = True mlist.include_list_post_header = True # Most of these were ripped from the old MailList.InitVars() method. diff --git a/src/mailman/tests/test_documentation.py b/src/mailman/tests/test_documentation.py index 48b71d72c..0409e737c 100644 --- a/src/mailman/tests/test_documentation.py +++ b/src/mailman/tests/test_documentation.py @@ -69,16 +69,19 @@ class chdir: -def specialized_message_from_string(text): +def specialized_message_from_string(unicode_text): """Parse text into a message object. This is specialized in the sense that an instance of Mailman's own Message object is returned, and this message object has an attribute `original_size` which is the pre-calculated size in bytes of the message's text representation. + + Also, the text must be ASCII-only unicode. """ # This mimic what Switchboard.dequeue() does when parsing a message from # text into a Message instance. + text = unicode_text.encode('ascii') original_size = len(text) message = message_from_string(text, Message) message.original_size = original_size |
