summaryrefslogtreecommitdiff
path: root/mailman/docs/registration.txt
diff options
context:
space:
mode:
Diffstat (limited to 'mailman/docs/registration.txt')
-rw-r--r--mailman/docs/registration.txt362
1 files changed, 0 insertions, 362 deletions
diff --git a/mailman/docs/registration.txt b/mailman/docs/registration.txt
deleted file mode 100644
index d243188bc..000000000
--- a/mailman/docs/registration.txt
+++ /dev/null
@@ -1,362 +0,0 @@
-Address registration
-====================
-
-When a user wants to join a mailing list -- any mailing list -- in the running
-instance, he or she must first register with Mailman. The only thing they
-must supply is an email address, although there is additional information they
-may supply. All registered email addresses must be verified before Mailman
-will send them any list traffic.
-
- >>> from mailman.app.registrar import Registrar
- >>> from mailman.interfaces.registrar import IRegistrar
-
-The IUserManager manages users, but it does so at a fairly low level.
-Specifically, it does not handle verifications, email address syntax validity
-checks, etc. The IRegistrar is the interface to the object handling all this
-stuff.
-
-Add a domain, which will provide the context for the verification email
-message.
-
- >>> config.push('mail', """
- ... [domain.mail_example_dot_com]
- ... email_host: mail.example.com
- ... base_url: http://mail.example.com
- ... contact_address: postmaster@mail.example.com
- ... """)
-
- >>> domain = config.domains['mail.example.com']
-
-Get a registrar by adapting a context to the interface.
-
- >>> from zope.interface.verify import verifyObject
- >>> registrar = IRegistrar(domain)
- >>> verifyObject(IRegistrar, registrar)
- True
-
-Here is a helper function to check the token strings.
-
- >>> def check_token(token):
- ... assert isinstance(token, basestring), 'Not a string'
- ... assert len(token) == 40, 'Unexpected length: %d' % len(token)
- ... assert token.isalnum(), 'Not alphanumeric'
- ... print 'ok'
-
-Here is a helper function to extract tokens from confirmation messages.
-
- >>> import re
- >>> cre = re.compile('http://mail.example.com/confirm/(.*)')
- >>> def extract_token(msg):
- ... mo = cre.search(qmsg.get_payload())
- ... return mo.group(1)
-
-
-Invalid email addresses
------------------------
-
-The only piece of information you need to register is the email address.
-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('')
- Traceback (most recent call last):
- ...
- InvalidEmailAddress: ''
- >>> registrar.register('some name@example.com')
- Traceback (most recent call last):
- ...
- InvalidEmailAddress: 'some name@example.com'
- >>> registrar.register('<script>@example.com')
- Traceback (most recent call last):
- ...
- InvalidEmailAddress: '<script>@example.com'
- >>> registrar.register('\xa0@example.com')
- Traceback (most recent call last):
- ...
- InvalidEmailAddress: '\xa0@example.com'
- >>> registrar.register('noatsign')
- Traceback (most recent call last):
- ...
- InvalidEmailAddress: 'noatsign'
- >>> registrar.register('nodom@ain')
- Traceback (most recent call last):
- ...
- InvalidEmailAddress: 'nodom@ain'
-
-
-Register an email address
--------------------------
-
-Registration of an unknown address creates nothing until the confirmation step
-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')
- >>> 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')
- None
- >>> print usermgr.get_address(u'aperson@example.com')
- None
-
-But this address is waiting for confirmation.
-
- >>> pendingdb = config.db.pendings
- >>> sorted(pendingdb.confirm(token, expunge=False).items())
- [(u'address', u'aperson@example.com'),
- (u'real_name', u'Anne Person'),
- (u'type', u'registration')]
-
-
-Verification by email
----------------------
-
-There is also a verification email sitting in the virgin queue now. This
-message is sent to the user in order to verify the registered address.
-
- >>> switchboard = config.switchboards['virgin']
- >>> len(switchboard.files)
- 1
- >>> filebase = switchboard.files[0]
- >>> qmsg, qdata = switchboard.dequeue(filebase)
- >>> switchboard.finish(filebase)
- >>> print qmsg.as_string()
- MIME-Version: 1.0
- Content-Type: text/plain; charset="us-ascii"
- Content-Transfer-Encoding: 7bit
- Subject: confirm ...
- From: confirm-...@mail.example.com
- To: aperson@example.com
- Message-ID: <...>
- Date: ...
- Precedence: bulk
- <BLANKLINE>
- Email Address Registration Confirmation
- <BLANKLINE>
- Hello, this is the GNU Mailman server at mail.example.com.
- <BLANKLINE>
- We have received a registration request for the email address
- <BLANKLINE>
- aperson@example.com
- <BLANKLINE>
- Before you can start using GNU Mailman at this site, you must first
- confirm that this is your email address. You can do this by replying to
- this message, keeping the Subject header intact. Or you can visit this
- web page
- <BLANKLINE>
- http://mail.example.com/confirm/...
- <BLANKLINE>
- If you do not wish to register this email address simply disregard this
- message. If you think you are being maliciously subscribed to the list,
- or have any other questions, you may contact
- <BLANKLINE>
- postmaster@mail.example.com
- <BLANKLINE>
- >>> dump_msgdata(qdata)
- _parsemsg : False
- nodecorate : True
- recips : [u'aperson@example.com']
- reduced_list_headers: True
- version : 3
-
-The confirmation token shows up in several places, each of which provides an
-easy way for the user to complete the confirmation. The token will always
-appear in a URL in the body of the message.
-
- >>> sent_token = extract_token(qmsg)
- >>> sent_token == token
- True
-
-The same token will appear in the From header.
-
- >>> qmsg['from'] == 'confirm-' + token + '@mail.example.com'
- True
-
-It will also appear in the Subject header.
-
- >>> qmsg['subject'] == 'confirm ' + token
- True
-
-The user would then validate their just registered address by clicking on a
-url or responding to the message. Either way, the confirmation process
-extracts the token and uses that to confirm the pending registration.
-
- >>> registrar.confirm(token)
- True
-
-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
- <Address: Anne Person <aperson@example.com> [verified] at ...>
- >>> found_user = usermgr.get_user(u'aperson@example.com')
- >>> found_user
- <User "Anne Person" at ...>
- >>> found_user.controls(found_address.address)
- True
- >>> from datetime import datetime
- >>> isinstance(found_address.verified_on, datetime)
- True
-
-
-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')
- >>> check_token(token)
- ok
- >>> filebase = switchboard.files[0]
- >>> qmsg, qdata = switchboard.dequeue(filebase)
- >>> switchboard.finish(filebase)
- >>> sent_token = extract_token(qmsg)
- >>> token == sent_token
- True
- >>> registrar.confirm(token)
- True
- >>> registrar.confirm(token)
- False
-
-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')
- <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')
- None
- >>> filebase = switchboard.files[0]
- >>> qmsg, qdata = switchboard.dequeue(filebase)
- >>> switchboard.finish(filebase)
- >>> registrar.confirm(token)
- True
- >>> usermgr.get_user(u'cperson@example.com')
- <User "Claire Person" at ...>
- >>> usermgr.get_address(u'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 is not None
- True
-
-
-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')
- >>> check_token(token)
- ok
- >>> registrar.discard(token)
- >>> print pendingdb.confirm(token)
- None
- >>> print usermgr.get_address(u'eperson@example.com')
- None
- >>> print usermgr.get_user(u'eperson@example.com')
- None
-
-
-Registering a new address for an existing user
-----------------------------------------------
-
-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
- <User "Dave Person" at ...>
- >>> address = usermgr.get_address(u'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')
- <Address: David Person <david.person@example.com> [not verified] at ...>
- >>> token = registrar.register(u'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 is dperson
- True
- >>> user
- <User "Dave Person" at ...>
- >>> sorted((addr for addr in user.addresses), key=attrgetter('address'))
- [<Address: David Person <david.person@example.com> [verified] at ...>,
- <Address: Dave Person <dperson@example.com> [verified] at ...>]
-
-
-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')
- False
-
-Likewise, if you try to confirm, through the IUserRegistrar interface, a token
-that doesn't match a registration even, you will get None. However, the
-pending even matched with that token will still be removed.
-
- >>> from mailman.interfaces.pending import IPendable
- >>> from zope.interface import implements
-
- >>> class SimplePendable(dict):
- ... implements(IPendable)
- >>> pendable = SimplePendable(type='foo', bar='baz')
- >>> token = pendingdb.add(pendable)
- >>> registrar.confirm(token)
- False
- >>> print pendingdb.confirm(token)
- None
-
-
-Registration and subscription
------------------------------
-
-Fred registers with Mailman at the same time that he subscribes to a mailing
-list.
-
- >>> from mailman.app.lifecycle import create_list
- >>> mlist = create_list(u'alpha@example.com')
- >>> token = registrar.register(
- ... u'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')
- None
-
-But after confirmation, he is.
-
- >>> registrar.confirm(token)
- True
- >>> print mlist.members.get_member(u'fred.person@example.com')
- <Member: Fred Person <fred.person@example.com>
- on alpha@example.com as MemberRole.member>
-
-
-Clean up
---------
-
- >>> config.pop('mail')