repoze.sendmail

repoze.sendmail allows coupling the sending of email messages with a transaction, using the Zope transaction manager. This allows messages to only be sent out when and if a transaction is committed, preventing users from receiving notifications about events which may not have completed successfully. Messages may be sent directly or stored in a queue for later sending. The queued mail approach is the more common and recommended path. For convenience, the package includes a console application which can flush the queue, sending the messages that it finds.

repoze.sendmail is a fork of zope.sendmail. Functionality that was specific to running in a Zope context has been removed, making this version more generally useful to users of other frameworks.

Note that repoze.sendmail works only under Python 2.6+ and Python 3.2+.

Delivering Mail Messages from Application Code

Messages are sent by means of a Delivery object. repoze.sendmail include Two delivery implementations:

  • repoze.sendmail.delivery.QueuedMailDelivery
  • repoze.sendmail.delivery.DirectMailDelivery

A delivery implements the interface defined by repoze.sendmail.interfaces.IDelivery. That interface defines a single send method:

def send(fromaddr, toaddrs, message):
    """ Sends message on transaction commit. """
  • fromaddr is the address of the sender of the message.
  • toaddrs is a list of email addresses for recipients of the message.
  • message must be an instance of email.message.Message and is the actual message which will be sent.

Delivery via a Mail Queue

To create a queued delivery:

from email.message import Message
from repoze.sendmail.delivery import QueuedMailDelivery

message = Message()
message['From'] = 'Chris <chris@example.com>'
message['To'] = 'Paul <paul@example.com>, Tres <tres@example.com>'
message['Subject'] = "repoze.sendmail is a useful package"
message.set_payload("The subject line says it all.")

delivery = QueuedMailDelivery('path/to/queue')
delivery.send('chris@example.com', ['paul@example.com', 'tres@example.com'],
              message)

The message will be added to the maildir queue in ‘path/to/queue’ when and if the current transaction is committed successsfully.

repoze.sendmail includes a console app utility for sending queued messages:

$ bin/qp path/to/queue

This will attempt to use an SMTP server at localhost to send any messages found in the queue. To see all options available:

$ bin/qp --help

Direct SMTP Delivery

Direct delivery (using the SMTP protocol) can also be used:

from repoze.sendmail.delivery import DirectMailDelivery
from repoze.sendmail.mailer import SMTPMailer

mailer = SMTPMailer()  # Uses localhost, port 25 be default.
delivery = DirectMailDelivery(mailer)
delivery.send('chris@example.com', ['paul@example.com', 'tres@example.com'],
              message)

Delivery via the sendmail Command

If you are on a Unix/BSD machine and prefer to use the standard unix sendmail interface ( which is likely provided by exim, postfix or qmail ) via a binary at ‘/usr/sbin/sendmail’ you can simply opt to use the following classes :

mailer = SendmailMailer() delivery = DirectMailDelivery(mailer)

you may also customize this delivery with the location of another binary:

mailer = SendmailMailer( sendmail_app=’/usr/local/bin/sendmail’ )

Transaction Integration

repoze.sendmail hooks into the Zope transaction manager and only sends messages on transaction commit. If you are using a framework which does not use transactions by default, you will need to begin and commit a transaction of your own in order for mail to be sent:

import transaction
transaction.manager.begin()
try:
    my_code_here()
    transaction.manager.commit()
except e:
    transaction.manager.abort()
    raise e