[Zope3-checkins] CVS: Zope3/src/zope/app/interfaces - mail.py:1.1

Stephan Richter srichter@cbu.edu
Wed, 16 Apr 2003 09:45:43 -0400


Update of /cvs-repository/Zope3/src/zope/app/interfaces
In directory cvs.zope.org:/tmp/cvs-serv29814/interfaces

Added Files:
	mail.py 
Log Message:
This is a first stab at a flexible facility to send out mail. I discussed
the API with Barry a bit, before writing this code. 

Goals:

  - Keep the actual IMailService interface as simple as possible.

  - Allow flexible mechanisms to send mail.

  - Be able to implement and register you own mail sending policies. 

Implementation:

  - The global mail service is an asynchronous mail sender, which means 
    it does not block the request. Once it is done, it will send an event
    to which interested parties can subscribe.

  - The AsyncMailService registers and works with Mailer objects, which 
    encode the policy of the mailing. I supplied a SimpleMailer, which has
    no specific policies and a BatchMailer, which allows to send the 
    messages in batches, so that the SMTP server will not overload. I 
    currently do not have any of the mailers in action, but I am going to
    add MailService support to the zwiki product for testing purposes soon.

  - MailService will make heavy use of the EventService for publishing 
    status updates, which is necessary due to its async nature. Currently 
    I have only one event, but I plan to add more soon.

To Do:

  - I lied about the AsyncMailService to be async! :-) I actually have not 
    implemented the async behavior yet; I need help from other people for
    this feature. Should I use thread or asyncore, and how do I use either 
    one. I am not really knowledgable in this area.

  - As mentioned above, add more events.

  - Come up with advanced unit tests for the BatchMailer.

  - Put the MailService-specific ZCML directive into a higher up ZCML file,
    since it contains server-specific information, similar to the ones for 
    HTTP and FTP.


=== Added File Zope3/src/zope/app/interfaces/mail.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""MailService Interfaces

Interfaces relevant for the MailService

$Id: mail.py,v 1.1 2003/04/16 13:45:43 srichter Exp $
"""
from zope.interface import Interface, Attribute
import zope.schema 

from zope.app.interfaces.event import IEvent
from zope.app.i18n import ZopeMessageIDFactory as _


class IMailService(Interface):
    """A mail service allows someone to send an email to a group of people.

    Note: This interface is purposfully held very simple, so that it is easy
    to provide a basic mail service implementation.
    """

    hostname = zope.schema.TextLine(
        title=_(u"Hostname"),
        description=_(u"Name of server to be used as SMTP server."))

    port = zope.schema.Int(
        title=_(u"Port"),
        description=_(u"Port of SMTP service"),
        default=25)

    username = zope.schema.TextLine(
        title=_(u"Username"),
        description=_(u"Username used for optional SMTP authentication."))
    
    password = zope.schema.Password(
        title=_(u"Password"),
        description=_(u"Password used for optional SMTP authentication."))

    def send(fromaddr, toaddrs, message):
        """Send a message to the tos (list of email unicode strings) with a
        sender specified in from (unicode string).
        """


# XXX: Needs better name: AsyncMailService, MailerMailService, ... 
class IAsyncMailService(IMailService):
    """This mail service handles mail delivery using so called Mailer objects.

    The policies for sending the mail are encoded in the Mailer object. Also,
    it is recommended that the mailer is called in a different thread, so that
    the request is not blocked."""

    def createMailer(name):
        """Create a Mailer object which class was registered under the passed
        name."""

    def getMailerNames():
        """Return a list of the names of all registered mailers."""

    def getDefaultMailerName():
        """Return the name of the default Mailer. None, means there is no
        defaulter mailer class defined."""

    def send(fromaddr, toaddrs, message, mailer=None):
        """This interface extends the send method by an optional mailer
        attribute. If the mailer is None, an object from the default mailer
        class is created and used.
        """


class IMailer(Interface):
    """This is a generic Mailer interface.

    Mailers implement mailing policies, such as batching, scheduling and so
    on."""

    def send(fromaddr, toaddrs, message, hostname, port, username, password):
        """Send a set of messages. How and when the mailer is going to send
        out the mail is purely up to the mailer's policy."""


class IBatchMailer(IMailer):
    """The Batch Mailer allows to send E-mails in batches, so that the server
    loaad will not be too high."""

    batchSize = zope.schema.Int(
        title=_(u"Batch Size"),
        description=_(u"Amount of E-mails sent in one batch."),
        min=1)

    batchDelay = zope.schema.Int(
        title=_(u"Batch Delay"),
        description=_(u"Delay time in milliseconds between batches."),
        min=100)


class IScheduleMailer(IMailer):
    """This mailer allows you to specify a specific date/time to send the
    mails."""
    
    sendAt = zope.schema.Datetime(
        title=_(u"Send at"),
        description=_(u"Date/time the message should be send."))


class IMailEvent(IEvent):
    """Generic Mailer event that can be snet from the mailer or the mail
    service."""

    mailer = Attribute("Mailer object that is used to send the mail.")


class IMailSentEvent(IMailEvent):
    """Event that is fired when all the mail in the mailer was sent.

    Note: Subscribing to this event eliminates the need for implementing
    callback functions for the async delivery."""