summaryrefslogtreecommitdiff
path: root/src/mailman/docs/addresses.txt
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/docs/addresses.txt')
-rw-r--r--src/mailman/docs/addresses.txt231
1 files changed, 231 insertions, 0 deletions
diff --git a/src/mailman/docs/addresses.txt b/src/mailman/docs/addresses.txt
new file mode 100644
index 000000000..9eccb2673
--- /dev/null
+++ b/src/mailman/docs/addresses.txt
@@ -0,0 +1,231 @@
+Email addresses
+===============
+
+Addresses represent a text email address, along with some meta data about
+those addresses, such as their registration date, and whether and when they've
+been validated. Addresses may be linked to the users that Mailman knows
+about. Addresses are subscribed to mailing lists though members.
+
+ >>> usermgr = config.db.user_manager
+
+
+Creating addresses
+------------------
+
+Addresses are created directly through the user manager, which starts out with
+no addresses.
+
+ >>> sorted(address.address for address in usermgr.addresses)
+ []
+
+Creating an unlinked email address is straightforward.
+
+ >>> address_1 = usermgr.create_address(u'aperson@example.com')
+ >>> sorted(address.address for address in usermgr.addresses)
+ [u'aperson@example.com']
+
+However, such addresses have no real name.
+
+ >>> address_1.real_name
+ u''
+
+You can also create an email address object with a real name.
+
+ >>> address_2 = usermgr.create_address(
+ ... u'bperson@example.com', u'Ben Person')
+ >>> sorted(address.address for address in usermgr.addresses)
+ [u'aperson@example.com', u'bperson@example.com']
+ >>> sorted(address.real_name for address in usermgr.addresses)
+ [u'', u'Ben Person']
+
+The str() of the address is the RFC 2822 preferred originator format, while
+the repr() carries more information.
+
+ >>> str(address_2)
+ 'Ben Person <bperson@example.com>'
+ >>> repr(address_2)
+ '<Address: Ben Person <bperson@example.com> [not verified] at 0x...>'
+
+You can assign real names to existing addresses.
+
+ >>> address_1.real_name = u'Anne Person'
+ >>> sorted(address.real_name for address in usermgr.addresses)
+ [u'Anne Person', u'Ben Person']
+
+These addresses are not linked to users, and can be seen by searching the user
+manager for an associated user.
+
+ >>> print usermgr.get_user(u'aperson@example.com')
+ None
+ >>> print usermgr.get_user(u'bperson@example.com')
+ None
+
+You can create email addresses that are linked to users by using a different
+interface.
+
+ >>> user_1 = usermgr.create_user(u'cperson@example.com', u'Claire Person')
+ >>> sorted(address.address for address in user_1.addresses)
+ [u'cperson@example.com']
+ >>> sorted(address.address for address in usermgr.addresses)
+ [u'aperson@example.com', u'bperson@example.com', u'cperson@example.com']
+ >>> sorted(address.real_name for address in usermgr.addresses)
+ [u'Anne Person', u'Ben Person', u'Claire Person']
+
+And now you can find the associated user.
+
+ >>> print usermgr.get_user(u'aperson@example.com')
+ None
+ >>> print usermgr.get_user(u'bperson@example.com')
+ None
+ >>> usermgr.get_user(u'cperson@example.com')
+ <User "Claire Person" at ...>
+
+
+Deleting addresses
+------------------
+
+You can remove an unlinked address from the user manager.
+
+ >>> usermgr.delete_address(address_1)
+ >>> sorted(address.address for address in usermgr.addresses)
+ [u'bperson@example.com', u'cperson@example.com']
+ >>> sorted(address.real_name for address in usermgr.addresses)
+ [u'Ben Person', u'Claire Person']
+
+Deleting a linked address does not delete the user, but it does unlink the
+address from the user.
+
+ >>> sorted(address.address for address in user_1.addresses)
+ [u'cperson@example.com']
+ >>> user_1.controls(u'cperson@example.com')
+ True
+ >>> address_3 = list(user_1.addresses)[0]
+ >>> usermgr.delete_address(address_3)
+ >>> sorted(address.address for address in user_1.addresses)
+ []
+ >>> user_1.controls(u'cperson@example.com')
+ False
+ >>> sorted(address.address for address in usermgr.addresses)
+ [u'bperson@example.com']
+
+
+Registration and validation
+---------------------------
+
+Addresses have two dates, the date the address was registered on and the date
+the address was validated on. Neither date is set by default.
+
+ >>> address_4 = usermgr.create_address(
+ ... u'dperson@example.com', u'Dan Person')
+ >>> print address_4.registered_on
+ None
+ >>> print address_4.verified_on
+ None
+
+The registered date takes a Python datetime object.
+
+ >>> from datetime import datetime
+ >>> address_4.registered_on = datetime(2007, 5, 8, 22, 54, 1)
+ >>> print address_4.registered_on
+ 2007-05-08 22:54:01
+ >>> print address_4.verified_on
+ None
+
+And of course, you can also set the validation date.
+
+ >>> address_4.verified_on = datetime(2007, 5, 13, 22, 54, 1)
+ >>> print address_4.registered_on
+ 2007-05-08 22:54:01
+ >>> print address_4.verified_on
+ 2007-05-13 22:54:01
+
+
+Subscriptions
+-------------
+
+Addresses get subscribed to mailing lists, not users. When the address is
+subscribed, a role is specified.
+
+ >>> address_5 = usermgr.create_address(
+ ... u'eperson@example.com', u'Elly Person')
+ >>> mlist = config.db.list_manager.create(u'_xtext@example.com')
+ >>> from mailman.interfaces.member import MemberRole
+ >>> address_5.subscribe(mlist, MemberRole.owner)
+ <Member: Elly Person <eperson@example.com> on
+ _xtext@example.com as MemberRole.owner>
+ >>> address_5.subscribe(mlist, MemberRole.member)
+ <Member: Elly Person <eperson@example.com> on
+ _xtext@example.com as MemberRole.member>
+
+Now Elly is both an owner and a member of the mailing list.
+
+ >>> sorted(mlist.owners.members)
+ [<Member: Elly Person <eperson@example.com> on
+ _xtext@example.com as MemberRole.owner>]
+ >>> sorted(mlist.moderators.members)
+ []
+ >>> sorted(mlist.administrators.members)
+ [<Member: Elly Person <eperson@example.com> on
+ _xtext@example.com as MemberRole.owner>]
+ >>> sorted(mlist.members.members)
+ [<Member: Elly Person <eperson@example.com> on
+ _xtext@example.com as MemberRole.member>]
+ >>> sorted(mlist.regular_members.members)
+ [<Member: Elly Person <eperson@example.com> on
+ _xtext@example.com as MemberRole.member>]
+ >>> sorted(mlist.digest_members.members)
+ []
+
+
+Case-preserved addresses
+------------------------
+
+Technically speaking, email addresses are case sensitive in the local part.
+Mailman preserves the case of addresses and uses the case preserved version
+when sending the user a message, but it treats addresses that are different in
+case equivalently in all other situations.
+
+ >>> address_6 = usermgr.create_address(
+ ... u'FPERSON@example.com', u'Frank Person')
+
+The str() of such an address prints the RFC 2822 preferred originator format
+with the original case-preserved address. The repr() contains all the gory
+details.
+
+ >>> str(address_6)
+ 'Frank Person <FPERSON@example.com>'
+ >>> repr(address_6)
+ '<Address: Frank Person <FPERSON@example.com> [not verified]
+ key: fperson@example.com at 0x...>'
+
+Both the case-insensitive version of the address and the original
+case-preserved version are available on attributes of the IAddress object.
+
+ >>> address_6.address
+ u'fperson@example.com'
+ >>> address_6.original_address
+ u'FPERSON@example.com'
+
+Because addresses are case-insensitive for all other purposes, you cannot
+create an address that differs only in case.
+
+ >>> usermgr.create_address(u'fperson@example.com')
+ Traceback (most recent call last):
+ ...
+ ExistingAddressError: FPERSON@example.com
+ >>> usermgr.create_address(u'fperson@EXAMPLE.COM')
+ Traceback (most recent call last):
+ ...
+ ExistingAddressError: FPERSON@example.com
+ >>> usermgr.create_address(u'FPERSON@example.com')
+ Traceback (most recent call last):
+ ...
+ ExistingAddressError: FPERSON@example.com
+
+You can get the address using either the lower cased version or case-preserved
+version. In fact, searching for an address is case insensitive.
+
+ >>> usermgr.get_address(u'fperson@example.com').address
+ u'fperson@example.com'
+ >>> usermgr.get_address(u'FPERSON@example.com').address
+ u'fperson@example.com'