2. The option of directly sending an email or adding it to the queue in your maildir.
pyramid_mailer uses the repoze_sendmail package for general email sending, queuing and transaction management, and the Lamson library for low-level multipart message encoding and wrapping. You do not have to install or run a Lamson mail service.
Install using pip install pyramid_mailer or easy_install pyramid_mailer.
If installing from source, untar/unzip, cd into the directory and do python setup.py install.
The source repository is on Bitbucket. Please report any bugs, issues or queries there.
Some Windows users have reported issues installing Lamson due to some dependencies that do not work on Windows.
The best way to install on Windows is to install the individual packages using the no dependencies option:
easy_install -N lamson chardet repoze.sendmail pyramid_mailer
In your application’s configuration stanza (where you create a Pyramid “Configurator”), use the config.include method:
config.include('pyramid_mailer')
Thereafter in view code, use the pyramid_mailer.get_mailer API to obtain the configured mailer:
from pyramid_mailer import get_mailer
mailer = get_mailer(request)
To send a message, you must first create a pyramid_mailer.message.Message instance:
from pyramid_mailer.message import Message
message = Message(subject="hello world",
sender="admin@mysite.com",
recipients=["arthur.dent@gmail.com"],
body="hello, arthur")
The Message is then passed to the Mailer instance. You can either send the message right away:
mailer.send(message)
or add it to your mail queue (a maildir on disk):
mailer.send_to_queue(message)
Usually you provide the sender to your Message instance. Often however a site might just use a single from address. If that is the case you can provide the default_sender to your Mailer and this will be used in throughout your application as the default if the sender is not otherwise provided.
If you don’t want to use transactions, you can side-step them by using send_immediately:
mailer.send_immediately(message, fail_silently=False)
This will send the email immediately, outwith the transaction, so if it fails you have to deal with it manually. The fail_silently flag will swallow any connection errors silently - if it’s not important whether the email gets sent.
To get started the harder way (without using config.include), create an instance of pyramid_mailer.mailer.Mailer:
from pyramid_mailer.mailer import Mailer
mailer = Mailer()
The Mailer class can take a number of optional settings, detailed in Configuration. It’s a good idea to create a single Mailer instance for your application, and add it to your registry in your configuration setup:
config = Configurator(settings=settings)
config.registry['mailer'] = Mailer.from_settings(settings)
or alternatively:
from pyramid_mailer import mailer_factory_from_settings
config.registry['mailer'] = mailer_factory_from_settings(settings)
You can then access your mailer in a view:
def my_view(request):
mailer = request.registry['mailer']
Note that the pyramid_mailer.get_mailer() API will not work if you construct and set your own mailer in this way.
If you create your Mailer instance using pyramid_mailer.mailer.Mailer.from_settings() or config.include('pyramid_mailer'), you can pass the settings from your .ini file or other source. By default, the prefix is assumed to be mail.. If you use the config.include mechanism, to set another prefix, use the pyramid_mailer.prefix key in the config file, e.g. pyramid_mailer.prefix = foo.. If you use the pyramid_mailer.Mailer.Mailer.from_settings() or pyramid_mailer.mailer_factory_from_settings() API, these accept a prefix directly.
Setting | Default | Description |
---|---|---|
mail.host | localhost | SMTP host |
mail.port | 25 | SMTP port |
mail.username | None | SMTP username |
mail.password | None | SMTP password |
mail.tls | False | Use TLS |
mail.ssl | False | Use SSL |
mail.keyfile | None | SSL key file |
mail.certfile | None | SSL certificate file |
mail.queue_path | None | Location of maildir |
mail.default_sender | None | Default from address |
mail.debug | False | SMTP debug level |
If you are using transaction management with your Pyramid application then pyramid_mailer will only send the emails (or add them to the mail queue) when the transactions are committed.
For example:
import transaction
from pyramid_mailer.mailer import Mailer
from pyramid_mailer.message import Message
mailer = Mailer()
message = Message(subject="hello arthur",
sender="ford.prefect@gmail.com",
recipients=['arthur.dent@gmail.com'],
body="hello from ford")
mailer.send(message)
transaction.commit()
The email is not actually sent until the transaction is committed.
When the repoze.tm2 tm middleware is in your Pyramid WSGI pipeline, transactions are already managed for you, so you don’t need to explicitly commit or abort within code that sends mail. Instead, if an exception is raised, the transaction will implicitly be aborted and mail will not be sent; otherwise it will be committed, and mail will be sent.
Attachments are added using the pyramid_mailer.message.Attachment class:
from pyramid_mailer.message import Attachment
from pyramid_mailer.message import Message
message = Message()
photo_data = open("photo.jpg", "rb").read()
attachment = Attachment("photo.jpg", "image/jpg", photo_data)
message.attach(attachment)
You can pass the data either as a string or file object, so the above code could be rewritten:
from pyramid_mailer.message import Attachment
from pyramid_mailer.message import Message
message = Message()
attachment = Attachment("photo.jpg", "image/jpg",
open("photo.jpg", "rb"))
message.attach(attachment)
When running unit tests you probably don’t want to actually send any emails inadvertently. However it’s still useful to keep track of what emails would be sent in your tests.
Another case is if your site is in development and you want to avoid accidental sending of any emails to customers.
In either case, config.include('pyramid_mailer.testing') can be used to make the current mailer an instance of the pyramid_mailer.mailer.DummyMailer:
from pyramid import testing
class TestViews(unittest.TestCase):
def setUp(self):
self.config = testing.setUp()
self.config.include('pyramid_mailer.testing')
def tearDown(self):
testing.tearDown()
def test_some_view(self):
from pyramid.testing import DummyRequest
request = DummyRequest()
mailer = get_mailer(request)
response = some_view(request)
The DummyMailer instance keeps track of emails “sent” in two properties: queue for emails send via pyramid_mailer.mailer.Mailer.send_to_queue() and outbox for emails sent via pyramid_mailer.mailer.Mailer.send(). Each stores the individual Message instances:
self.assertEqual(len(mailer.outbox) == 1)
self.assertEqual(mailer.outbox[0].subject == "hello world")
self.assertEqual(len(mailer.queue) == 1)
self.assertEqual(mailer.queue[0].subject == "hello world")
When you send mail to a queue via pyramid_mailer.Mailer.send_to_queue(), the mail will be placed into a maildir directory specified by the queue_path parameter or setting to pyramid_mailer.mailer.Mailer. A separate process will need to be launched to monitor this maildir and take actions based on its state. Such a program comes as part of repoze_sendmail (a dependency of the pyramid_mailer package). It is known as qp. qp will be installed into your Python (or virtualenv) bin or Scripts directory when you install repoze_sendmail.
You’ll need to arrange for qp to be a long-running process that monitors the maildir state.:
$ bin/qp /path/to/mail/queue
This will attempt to use the localhost SMTP server to send any messages in the queue over time. qp has other options that allow you to choose different settings. Use it’s --help parameter to see more:
$ bin/qp --help
Factory function to create a Mailer instance from settings. Equivalent to Mailer.from_settings
Versionadded : | 0.2.2 |
---|
Obtain a mailer previously registered via config.include('pyramid_mailer') or config.include('pyramid_mailer.testing').
Versionadded : | 0.4 |
---|
Manages sending of email messages.
Parameters: |
|
---|
Creates a new instance of Message from settings dict.
Parameters: |
|
---|
Sends a message. The message is handled inside a transaction, so in case of failure (or the message fails) the message will not be sent.
Parameters: |
|
---|
Sends a message immediately, outside the transaction manager.
If there is a connection error to the mail server this will have to be handled manually. However if you pass fail_silently the error will be swallowed.
Versionadded : | 0.3 |
---|---|
Parameters: |
|
Adds a message to a maildir queue.
In order to handle this, the setting mail.queue_path must be provided and must point to a valid maildir.
Parameters: |
|
---|
Dummy mailing instance, used for example in unit tests.
Keeps all sent messages internally in list as outbox property. Queued messages are instead added to queue property.
Mocks sending a transactional message. The message is added to the outbox list.
Parameters: |
|
---|
Mocks sending an immediate (non-transactional) message. The message is added to the outbox list.
Versionadded : | 0.3 |
---|---|
Parameters: |
|
Mocks sending to a maildir queue. The message is added to the queue list.
Parameters: |
|
---|
Encapsulates an email message.
Parameters: |
|
---|
Adds an email address to the BCC list.
Parameters: |
|
---|
Adds an email address to the CC list.
Parameters: |
|
---|
Adds another recipient to the message.
Parameters: |
|
---|
Adds an attachment to the message.
Parameters: |
|
---|
Creates a Lamson MailResponse instance
Checks for bad headers i.e. newlines in subject, sender or recipients.
Returns raw email.Message instance.Validates message first.
Checks if message is valid and raises appropriate exception.
Encapsulates file attachment information.
Parameters: |
|
---|
Raised if message is missing vital headers, such as recipients or sender address.
Raised if message contains newlines in headers.