summaryrefslogtreecommitdiff
path: root/Mailman/docs
diff options
context:
space:
mode:
authorBarry Warsaw2007-06-18 10:50:23 -0400
committerBarry Warsaw2007-06-18 10:50:23 -0400
commit511a33778c4195c4abca7c58aa6917e6a77059b6 (patch)
tree5bffc7a5793a8247310294ac86931741e73b1fc5 /Mailman/docs
parentf0e3b3934d5d458cadd814eeae07277b58650180 (diff)
downloadmailman-511a33778c4195c4abca7c58aa6917e6a77059b6.tar.gz
mailman-511a33778c4195c4abca7c58aa6917e6a77059b6.tar.zst
mailman-511a33778c4195c4abca7c58aa6917e6a77059b6.zip
Remove both the model and interface for RosterSets. These are no longer used
or necessary in the current data model. Convert the test_handlers.py Python test to an acknowledge.txt doctest, and make the Acknowledge.py handler work with the new data model. There are a few XXX comments left in here due to the fact that the web stuff is a total hack in the current branch currently. Added IMailingListWeb methods and properties to the MailingList model class: web_host and script_url(). Work out how IMembers will expose the lookup-order based preferences. By getting the attribute IMember.preferences you can see exactly the preferences overridden by this member. To use the lookup order, use IMember.delivery_mode, IMember.acknowledge_posts, etc. IOW, the IMember interface now provides the properties directly and access through this mechanism supports lookup order with definitive preference values. Also added IMember.unsubscribe() which does the obvious, and IMember.options_url() which is a total hack for providing a url (but not the ultimately right one) for the user's option page. Refactor the model's roster classes. Also added IRoster.get_member() method with efficient queries to return the right results. Make AdministratorRoster.members more efficient due to a better query. Update the membership.txt doctest to eliminate a chance ordering effect, and also to test finding members with .get_member(). The clean up section uses the new .unsubscribe() method.
Diffstat (limited to 'Mailman/docs')
-rw-r--r--Mailman/docs/acknowledge.txt176
-rw-r--r--Mailman/docs/membership.txt67
2 files changed, 238 insertions, 5 deletions
diff --git a/Mailman/docs/acknowledge.txt b/Mailman/docs/acknowledge.txt
new file mode 100644
index 000000000..6c7e3c28f
--- /dev/null
+++ b/Mailman/docs/acknowledge.txt
@@ -0,0 +1,176 @@
+Message acknowledgment
+======================
+
+When a user posts a message to a mailing list, and that user has chosen to
+receive acknowledgments of their postings, Mailman will sent them such an
+acknowledgment.
+
+ >>> from email import message_from_string
+ >>> from Mailman.Message import Message
+ >>> from Mailman.Handlers.Acknowledge import process
+ >>> from Mailman.configuration import config
+ >>> from Mailman.database import flush
+ >>> mlist = config.list_manager.create('_xtest@example.com')
+ >>> mlist.real_name = 'XTest'
+ >>> # XXX This will almost certainly change once we've worked out the web
+ >>> # space layout for mailing lists now.
+ >>> mlist._data.web_page_url = 'http://lists.example.com/'
+ >>> flush()
+
+ >>> # Ensure that the virgin queue is empty, since we'll be checking this
+ >>> # for new auto-response messages.
+ >>> from Mailman.Queue.sbcache import get_switchboard
+ >>> virginq = get_switchboard(config.VIRGINQUEUE_DIR)
+ >>> virginq.files()
+ []
+
+Subscribe a user to the mailing list.
+
+ >>> from Mailman.constants import MemberRole
+ >>> user_1 = config.user_manager.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>
+ >>> flush()
+
+
+Non-member posts
+----------------
+
+Non-members can't get acknowledgments of their posts to the mailing list.
+
+ >>> msg = message_from_string("""\
+ ... From: bperson@example.com
+ ...
+ ... """, Message)
+ >>> process(mlist, msg, {})
+ >>> virginq.files()
+ []
+
+We can also specify the original sender in the message's metadata. If that
+person is also not a member, no acknowledgment will be sent either.
+
+ >>> msg = message_from_string("""\
+ ... From: bperson@example.com
+ ...
+ ... """, Message)
+ >>> process(mlist, msg, dict(original_sender='cperson@example.com'))
+ >>> virginq.files()
+ []
+
+
+No acknowledgment requested
+---------------------------
+
+Unless the user has requested acknowledgments, they will not get one.
+
+ >>> msg = message_from_string("""\
+ ... From: aperson@example.com
+ ...
+ ... """, Message)
+ >>> process(mlist, msg, {})
+ >>> virginq.files()
+ []
+
+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 = config.user_manager.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>
+ >>> flush()
+
+ >>> process(mlist, msg, 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.
+
+ >>> user_1.preferences.acknowledge_posts = True
+ >>> flush()
+
+The receipt will include the original message's subject in the response body,
+
+ >>> msg = message_from_string("""\
+ ... From: aperson@example.com
+ ... Subject: Something witty and insightful
+ ...
+ ... """, Message)
+ >>> process(mlist, msg, {})
+
+ >>> len(virginq.files())
+ 1
+ >>> qmsg, qdata = virginq.dequeue(virginq.files()[0])
+ >>> virginq.files()
+ []
+ >>> # Print only some of the meta data. The rest is uninteresting.
+ >>> qdata['listname']
+ '_xtest@example.com'
+ >>> qdata['recips']
+ ['aperson@example.com']
+ >>> print qmsg.as_string()
+ MIME-Version: 1.0
+ Content-Type: text/plain; charset="us-ascii"
+ Content-Transfer-Encoding: 7bit
+ Subject: XTest post acknowledgment
+ From: _xtest-bounces@example.com
+ To: aperson@example.com
+ Message-ID: ...
+ Date: ...
+ Precedence: bulk
+ <BLANKLINE>
+ Your message entitled
+ <BLANKLINE>
+ Something witty and insightful
+ <BLANKLINE>
+ was successfully received by the XTest mailing list.
+ <BLANKLINE>
+ List info page: http://lists.example.com/listinfo/_xtest@example.com
+ Your preferences: http://example.com/aperson@example.com
+ <BLANKLINE>
+
+If there is no subject, then the receipt will use a generic message.
+
+ >>> msg = message_from_string("""\
+ ... From: aperson@example.com
+ ...
+ ... """, Message)
+ >>> process(mlist, msg, {})
+
+ >>> len(virginq.files())
+ 1
+ >>> qmsg, qdata = virginq.dequeue(virginq.files()[0])
+ >>> virginq.files()
+ []
+ >>> # Print only some of the meta data. The rest is uninteresting.
+ >>> qdata['listname']
+ '_xtest@example.com'
+ >>> qdata['recips']
+ ['aperson@example.com']
+ >>> print qmsg.as_string()
+ MIME-Version: 1.0
+ Content-Type: text/plain; charset="us-ascii"
+ Content-Transfer-Encoding: 7bit
+ Subject: XTest post acknowledgment
+ From: _xtest-bounces@example.com
+ To: aperson@example.com
+ Message-ID: ...
+ Date: ...
+ Precedence: bulk
+ <BLANKLINE>
+ Your message entitled
+ <BLANKLINE>
+ (no subject)
+ <BLANKLINE>
+ was successfully received by the XTest mailing list.
+ <BLANKLINE>
+ List info page: http://lists.example.com/listinfo/_xtest@example.com
+ Your preferences: http://example.com/aperson@example.com
+ <BLANKLINE>
diff --git a/Mailman/docs/membership.txt b/Mailman/docs/membership.txt
index 36b1508a8..9b6465d4a 100644
--- a/Mailman/docs/membership.txt
+++ b/Mailman/docs/membership.txt
@@ -168,12 +168,15 @@ Claire will be a regular delivery member but not a digest member.
It's easy to make the list administrators members of the mailing list too.
+ >>> members = []
>>> for address in mlist.administrators.addresses:
- ... address.subscribe(mlist, MemberRole.member)
- <Member: Ben Person <bperson@example.com> on
- _xtest@example.com as MemberRole.member>
- <Member: Anne Person <aperson@example.com> on
- _xtest@example.com as MemberRole.member>
+ ... member = address.subscribe(mlist, MemberRole.member)
+ ... members.append(member)
+ >>> sorted(members, key=lambda m: m.address.address)
+ [<Member: Anne Person <aperson@example.com> on
+ _xtest@example.com as MemberRole.member>,
+ <Member: Ben Person <bperson@example.com> on
+ _xtest@example.com as MemberRole.member>]
>>> flush()
>>> sorted(address.address for address in mlist.members.addresses)
['aperson@example.com', 'bperson@example.com', 'cperson@example.com']
@@ -181,3 +184,57 @@ It's easy to make the list administrators members of the mailing list too.
['aperson@example.com', 'bperson@example.com', 'cperson@example.com']
>>> sorted(address.address for address in mlist.digest_members.addresses)
[]
+
+
+Finding members
+---------------
+
+You can find the IMember object that is a member of a roster for a given text
+email address by using an IRoster's .get_member() method.
+
+ >>> mlist.owners.get_member('aperson@example.com')
+ <Member: Anne Person <aperson@example.com> on
+ _xtest@example.com as MemberRole.owner>
+ >>> mlist.administrators.get_member('aperson@example.com')
+ <Member: Anne Person <aperson@example.com> on
+ _xtest@example.com as MemberRole.owner>
+ >>> mlist.members.get_member('aperson@example.com')
+ <Member: Anne Person <aperson@example.com> on
+ _xtest@example.com as MemberRole.member>
+
+However, if the address is not subscribed with the appropriate role, then None
+is returned.
+
+ >>> print mlist.administrators.get_member('zperson@example.com')
+ None
+ >>> print mlist.moderators.get_member('aperson@example.com')
+ None
+ >>> print mlist.members.get_member('zperson@example.com')
+ None
+
+
+Clean up
+--------
+
+ >>> for member in mlist.members.members:
+ ... member.unsubscribe()
+ >>> for admin in mlist.administrators.members:
+ ... admin.unsubscribe()
+ >>> flush()
+ >>> list(mlist.members.members)
+ []
+ >>> list(mlist.administrators.members)
+ []
+ >>> for user in config.user_manager.users:
+ ... config.user_manager.delete_user(user)
+ >>> for address in config.user_manager.addresses:
+ ... config.user_manager.delete_address(address)
+ >>> for mlist in config.list_manager.mailing_lists:
+ ... config.list_manager.delete(mlist)
+ >>> flush()
+ >>> list(config.user_manager.users)
+ []
+ >>> list(config.user_manager.addresses)
+ []
+ >>> list(config.list_manager.mailing_lists)
+ []