Full-featured e-mailing system: flexible, slim and sexy
Project description
|Build Status|
Mail'Em
=======
Full-featured e-mailing system: flexible, slim and sexy.
- Unicode
- Easy attachments
- Inline images
- E-Mail templates
- Tools for unit-tests
- Made perfect once and for all. Simple and cute :)
Here'a a full example:
.. code:: python
from mailem import Message, Postman, Attachment, ImageAttachment
from mailem.connection import SMTPConnection
# Create the message
messages = [
# Message with attachments
Message(
['kolypto@gmail.com'],
u"Mail'em test",
u"<b>yeah baby, it works!</b>",
attachments = [
Attachment(u'test.txt', open('test.txt').read())
]
),
# Message with inline images (!)
Message(
['kolypto@gmail.com'],
u"Mail'em test with inline images",
u"Cute: <img src='cid:cute.jpg' />", # cid:<filename>
attachments = [
ImageAttachment('cute.jpg', open('cute.jpg').read(), 'inline')
]
),
]
# Initialize a postman with SMTP connection to GMail
postman = Postman('user@gmail.com',
SMTPConnection(
'smtp.gmail.com', 587,
'user@gmail.com', 'pass',
tls=True
))
# Send everything we have
with postman.connect() as c:
map(c.sendmail, messages)
Also see `Template <#template>`__.
Table of Contents
=================
Message
=======
.. code:: python
Message(recipients, subject, html=None,
text=None, sender=None, cc=None,
bcc=None, attachments=None,
reply_to=None, date=None, headers=None)
Construct a Message object.
Notes:
- Full unicode support, and Unicode is the default
- You can provide ``html`` or ``text`` contents. If both are specified
-- the message will have an 'alternative' container, so the user will
receive both HTML and plaintext. The client will choose which one to
display.
- E-Mail addresses, such as ``recipients`` and ``sender``, can be
specified in one of the following formats:
- ``'user@example.com'``: Just an e-mail address
- ``('user@example.com', u'Honored User')``: email address with name
Arguments:
- ``recipients``: List of recipients
- ``subject``: Message subject
- ``html``: Message body, HTML
- ``text``: Message body, Text
- ``sender``: Sender e-mail address. If not set explicitly, the default
will be used on send
- ``cc``: CC list
- ``bcc``: BCC list
- ``attachments``: List of attachments
- ``reply_to``: Reply-to address
- ``date``: Send date
- ``headers``: Additional headers
Attachment
----------
.. code:: python
Attachment(filename, data,
content_type='application/octet-stream',
disposition='attachment', headers=None)
File attachment information.
This can be provided to the ```Message`` <#message>`__ object on
construction.
- ``filename``: Filename of attachment
- ``data``: Taw file data
- ``content_type``: File mimetype
- ``disposition``: Content-Disposition: 'attachment', 'inline', ...
- ``headers``: Additional headers for the attachment
ImageAttachment
---------------
.. code:: python
ImageAttachment(filename, data,
disposition='attachment', headers=None)
Image attachment.
- It guesses the Content-Type from the data stream
- Supports 'inline' images: images embedded in the email. Useful for
templates.
Once an 'inline' image is created, its filename is used for
'Content-ID', which allows to reference it in the HTML body:
.. code:: python
from mailem import Message, Attachment, ImageAttachment
msg = Message(
['test@example.com'],
'Hello',
'<img src="cid:flowers.jpg" />', # Referenced with "cid:<filename>"
attachments=[
ImageAttachment('flowers.jpg', open('flowers.jpg').read(), 'inline')
]
)
Arguments:
- ``filename``: Image attachment filename. Will also become
'Content-ID' when inlined.
- ``data``: The raw file data
Postman
=======
.. code:: python
Postman(sender, connection)
Postman is the object you use to send messages through a configured
Connection object.
Example:
.. code:: python
from mailem import Message, Postman
from mailem.connection import SMTPConnection
# Construct the message
msg = Message(
['kolypto@gmail.com'],
u"Mail'em test",
u"<b>yeah baby, it works!</b>"
)
# Create the postman (see SMTPConnection)
postman = Postman('user@gmail.com',
SMTPConnection(...))
# Connect, and send the message
with postman.connect() as c:
c.sendmail(msg)
- ``sender``: Default sender: e-mail or (name, email). Is used for
messages which do not specify the sender address explicitly.
- ``connection``: Connection object to use. See below.
``Postman.connect()``
~~~~~~~~~~~~~~~~~~~~~
Get connected Postman context manager.
``Postman.loopback()``
~~~~~~~~~~~~~~~~~~~~~~
Get a context manager which installs a LoopbackConnection on this
postman.
This allows you to record outgoing messages by mocking a Postman. See
```LoopbackConnection`` <#loopbackconnection>`__.
Connection
==========
Connection object represents a connection to a service which can send
e-mail messages for us.
SMTPConnection
--------------
.. code:: python
SMTPConnection(host, port, username,
password, local_hostname=None,
ssl=False, tls=False)
SMTP connection.
See `smtplib <https://docs.python.org/2/library/smtplib.html>`__ for the
list of exceptions that may occur.
Example:
.. code:: python
from mailem import Postman
from mailem.connection import SMTPConnection
postman = Postman('user@gmail.com',
SMTPConnection(
'smtp.gmail.com', 587,
'user@gmail.com', 'pass',
tls=True
))
with postman.connect() as c:
c.sendmail(msg)
Arguments:
- ``host``: SMTP server hostname
- ``port``: SMTP server port number.
- ``username``: User name to authenticate with
- ``password``: Password
- ``local_hostname``: FQDN of the local host for the HELO/EHLO command.
When ``None``, is detected automatically.
- ``ssl``: Use SSL protocol?
- ``tls``: Use TLS handshake?
LoopbackConnection
------------------
.. code:: python
LoopbackConnection()
Loopback connection allows to record all outgoing messages instead of
sending them.
You can install it manually:
.. code:: python
from mailem import Postman
from mailem.connection import LoopbackConnection
lo = LoopbackConnection()
postman = Postman('user@example.com', lo)
#... send
messages = lo.get_messages()
or you can mock an existing Postman with ``loopback()`` helper:
.. code:: python
from mailem import Postman
from mailem.connection import SMTPConnection
postman = Postman('user@example.com',
SMTPConnection(...))
with postman.loopback() as lo:
# Send
with postman.connect() as c: # mocked!
c.sendmail(msg)
# Get
sent_messages = lo.get_messages()
Loopback can be installed multiple times, and only top-level loopback
will catch the messages:
.. code:: python
with postman.loopback() as lo1:
with postman.loopback() as lo2:
with postman.connect() as c:
c.sendmail(msg)
len(lo1) #-> 0
len(lo2) #-> 1
Also note that ``LoopbackConnection`` subclasses ``list``, so all list
methods, including iteration, is available.
Template
========
.. code:: python
Template(subject=None, html=None,
text=None, attachments=None,
defaults=None)
A templated e-mail.
By default, the Template uses Python's ``Template`` renderer, which
allows simple PHP-style substitution, but this can be overridden using
set\_renderer().
First, a template is defined:
.. code:: python
from mailem import Attachment
from mailem.template import Template
signup = Template('Congrats $user, you've signed up!',
'Welcome to our website!<br><img src="cid:logo.jpg" /> -- $domain',
attachments=[
Attachment('logo.jpg', open('logo.jpg').read(), 'inline'))
],
defaults={'domain': 'localhost'} # default template values
)
Now, having the template, you render it to a ```Message`` <#message>`__
by calling it:
.. code:: python
message = signup(['user@gmail.com'], dict(user='Honored User',))
Ready for sending! :)
- ``subject``: Message subject template
- ``html``: HTML message template, if any
- ``text``: Text message template, if any
- ``attachments``: Attachments for the template. Most probably, inline
elements.
- ``defaults``: Default template values, if required. The user can
override these later.
``Template.set_renderer(Renderer)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Set renderer to be used with this template.
A Renderer is any class that can be constructed with a template string
argument, and called with template values dict to render it.
When no renderer was explicitly set, it defaults to
PythonTemplateRenderer.
- ``Renderer``: Renderer class.
``Template.__call__(recipients, values, **kwargs)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create a ``Message`` object using the template values.
- ``recipients``: Message recipients list
- ``values``: Dictionary with template values
- ``**kwargs``: keyword arguments for the ```Message`` <#message>`__
constructor
``Template.from_directory(path, subject_name='subject.txt', html_name='index.htm', text_name='index.txt', inline_rex='^i-(.*)')``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Convenience class method to import a directory as a template:
- ``subject.txt`` is the subject string template
- ``index.htm`` is the HTML template
- ``index.txt`` is the plaintext template
- All files matching the 'i-(\*)' format are attached as 'inline', and
hence can be referenced in the template:
E.g. file 'i-flower.jpg' can be inlined as
``<img src="cid:flower.jpg" />``.
- All other files are just attachments.
Example:
.. code:: python
signup = Template.from_directory('templates/signup/')
- ``path``: Path to the directory
- ``subject_name``: Subject template filename
- ``html_name``: Html template filename
- ``text_name``: Plaintext template filename
- ``inline_rex``: Regular expression to match files that should be
inlined.
If the RegExp defines capture groups, group $1 will be used as the
fact filename.
.. |Build Status| image:: https://api.travis-ci.org/kolypto/py-mailem.png?branch=master
:target: https://travis-ci.org/kolypto/py-mailem
Mail'Em
=======
Full-featured e-mailing system: flexible, slim and sexy.
- Unicode
- Easy attachments
- Inline images
- E-Mail templates
- Tools for unit-tests
- Made perfect once and for all. Simple and cute :)
Here'a a full example:
.. code:: python
from mailem import Message, Postman, Attachment, ImageAttachment
from mailem.connection import SMTPConnection
# Create the message
messages = [
# Message with attachments
Message(
['kolypto@gmail.com'],
u"Mail'em test",
u"<b>yeah baby, it works!</b>",
attachments = [
Attachment(u'test.txt', open('test.txt').read())
]
),
# Message with inline images (!)
Message(
['kolypto@gmail.com'],
u"Mail'em test with inline images",
u"Cute: <img src='cid:cute.jpg' />", # cid:<filename>
attachments = [
ImageAttachment('cute.jpg', open('cute.jpg').read(), 'inline')
]
),
]
# Initialize a postman with SMTP connection to GMail
postman = Postman('user@gmail.com',
SMTPConnection(
'smtp.gmail.com', 587,
'user@gmail.com', 'pass',
tls=True
))
# Send everything we have
with postman.connect() as c:
map(c.sendmail, messages)
Also see `Template <#template>`__.
Table of Contents
=================
Message
=======
.. code:: python
Message(recipients, subject, html=None,
text=None, sender=None, cc=None,
bcc=None, attachments=None,
reply_to=None, date=None, headers=None)
Construct a Message object.
Notes:
- Full unicode support, and Unicode is the default
- You can provide ``html`` or ``text`` contents. If both are specified
-- the message will have an 'alternative' container, so the user will
receive both HTML and plaintext. The client will choose which one to
display.
- E-Mail addresses, such as ``recipients`` and ``sender``, can be
specified in one of the following formats:
- ``'user@example.com'``: Just an e-mail address
- ``('user@example.com', u'Honored User')``: email address with name
Arguments:
- ``recipients``: List of recipients
- ``subject``: Message subject
- ``html``: Message body, HTML
- ``text``: Message body, Text
- ``sender``: Sender e-mail address. If not set explicitly, the default
will be used on send
- ``cc``: CC list
- ``bcc``: BCC list
- ``attachments``: List of attachments
- ``reply_to``: Reply-to address
- ``date``: Send date
- ``headers``: Additional headers
Attachment
----------
.. code:: python
Attachment(filename, data,
content_type='application/octet-stream',
disposition='attachment', headers=None)
File attachment information.
This can be provided to the ```Message`` <#message>`__ object on
construction.
- ``filename``: Filename of attachment
- ``data``: Taw file data
- ``content_type``: File mimetype
- ``disposition``: Content-Disposition: 'attachment', 'inline', ...
- ``headers``: Additional headers for the attachment
ImageAttachment
---------------
.. code:: python
ImageAttachment(filename, data,
disposition='attachment', headers=None)
Image attachment.
- It guesses the Content-Type from the data stream
- Supports 'inline' images: images embedded in the email. Useful for
templates.
Once an 'inline' image is created, its filename is used for
'Content-ID', which allows to reference it in the HTML body:
.. code:: python
from mailem import Message, Attachment, ImageAttachment
msg = Message(
['test@example.com'],
'Hello',
'<img src="cid:flowers.jpg" />', # Referenced with "cid:<filename>"
attachments=[
ImageAttachment('flowers.jpg', open('flowers.jpg').read(), 'inline')
]
)
Arguments:
- ``filename``: Image attachment filename. Will also become
'Content-ID' when inlined.
- ``data``: The raw file data
Postman
=======
.. code:: python
Postman(sender, connection)
Postman is the object you use to send messages through a configured
Connection object.
Example:
.. code:: python
from mailem import Message, Postman
from mailem.connection import SMTPConnection
# Construct the message
msg = Message(
['kolypto@gmail.com'],
u"Mail'em test",
u"<b>yeah baby, it works!</b>"
)
# Create the postman (see SMTPConnection)
postman = Postman('user@gmail.com',
SMTPConnection(...))
# Connect, and send the message
with postman.connect() as c:
c.sendmail(msg)
- ``sender``: Default sender: e-mail or (name, email). Is used for
messages which do not specify the sender address explicitly.
- ``connection``: Connection object to use. See below.
``Postman.connect()``
~~~~~~~~~~~~~~~~~~~~~
Get connected Postman context manager.
``Postman.loopback()``
~~~~~~~~~~~~~~~~~~~~~~
Get a context manager which installs a LoopbackConnection on this
postman.
This allows you to record outgoing messages by mocking a Postman. See
```LoopbackConnection`` <#loopbackconnection>`__.
Connection
==========
Connection object represents a connection to a service which can send
e-mail messages for us.
SMTPConnection
--------------
.. code:: python
SMTPConnection(host, port, username,
password, local_hostname=None,
ssl=False, tls=False)
SMTP connection.
See `smtplib <https://docs.python.org/2/library/smtplib.html>`__ for the
list of exceptions that may occur.
Example:
.. code:: python
from mailem import Postman
from mailem.connection import SMTPConnection
postman = Postman('user@gmail.com',
SMTPConnection(
'smtp.gmail.com', 587,
'user@gmail.com', 'pass',
tls=True
))
with postman.connect() as c:
c.sendmail(msg)
Arguments:
- ``host``: SMTP server hostname
- ``port``: SMTP server port number.
- ``username``: User name to authenticate with
- ``password``: Password
- ``local_hostname``: FQDN of the local host for the HELO/EHLO command.
When ``None``, is detected automatically.
- ``ssl``: Use SSL protocol?
- ``tls``: Use TLS handshake?
LoopbackConnection
------------------
.. code:: python
LoopbackConnection()
Loopback connection allows to record all outgoing messages instead of
sending them.
You can install it manually:
.. code:: python
from mailem import Postman
from mailem.connection import LoopbackConnection
lo = LoopbackConnection()
postman = Postman('user@example.com', lo)
#... send
messages = lo.get_messages()
or you can mock an existing Postman with ``loopback()`` helper:
.. code:: python
from mailem import Postman
from mailem.connection import SMTPConnection
postman = Postman('user@example.com',
SMTPConnection(...))
with postman.loopback() as lo:
# Send
with postman.connect() as c: # mocked!
c.sendmail(msg)
# Get
sent_messages = lo.get_messages()
Loopback can be installed multiple times, and only top-level loopback
will catch the messages:
.. code:: python
with postman.loopback() as lo1:
with postman.loopback() as lo2:
with postman.connect() as c:
c.sendmail(msg)
len(lo1) #-> 0
len(lo2) #-> 1
Also note that ``LoopbackConnection`` subclasses ``list``, so all list
methods, including iteration, is available.
Template
========
.. code:: python
Template(subject=None, html=None,
text=None, attachments=None,
defaults=None)
A templated e-mail.
By default, the Template uses Python's ``Template`` renderer, which
allows simple PHP-style substitution, but this can be overridden using
set\_renderer().
First, a template is defined:
.. code:: python
from mailem import Attachment
from mailem.template import Template
signup = Template('Congrats $user, you've signed up!',
'Welcome to our website!<br><img src="cid:logo.jpg" /> -- $domain',
attachments=[
Attachment('logo.jpg', open('logo.jpg').read(), 'inline'))
],
defaults={'domain': 'localhost'} # default template values
)
Now, having the template, you render it to a ```Message`` <#message>`__
by calling it:
.. code:: python
message = signup(['user@gmail.com'], dict(user='Honored User',))
Ready for sending! :)
- ``subject``: Message subject template
- ``html``: HTML message template, if any
- ``text``: Text message template, if any
- ``attachments``: Attachments for the template. Most probably, inline
elements.
- ``defaults``: Default template values, if required. The user can
override these later.
``Template.set_renderer(Renderer)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Set renderer to be used with this template.
A Renderer is any class that can be constructed with a template string
argument, and called with template values dict to render it.
When no renderer was explicitly set, it defaults to
PythonTemplateRenderer.
- ``Renderer``: Renderer class.
``Template.__call__(recipients, values, **kwargs)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create a ``Message`` object using the template values.
- ``recipients``: Message recipients list
- ``values``: Dictionary with template values
- ``**kwargs``: keyword arguments for the ```Message`` <#message>`__
constructor
``Template.from_directory(path, subject_name='subject.txt', html_name='index.htm', text_name='index.txt', inline_rex='^i-(.*)')``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Convenience class method to import a directory as a template:
- ``subject.txt`` is the subject string template
- ``index.htm`` is the HTML template
- ``index.txt`` is the plaintext template
- All files matching the 'i-(\*)' format are attached as 'inline', and
hence can be referenced in the template:
E.g. file 'i-flower.jpg' can be inlined as
``<img src="cid:flower.jpg" />``.
- All other files are just attachments.
Example:
.. code:: python
signup = Template.from_directory('templates/signup/')
- ``path``: Path to the directory
- ``subject_name``: Subject template filename
- ``html_name``: Html template filename
- ``text_name``: Plaintext template filename
- ``inline_rex``: Regular expression to match files that should be
inlined.
If the RegExp defines capture groups, group $1 will be used as the
fact filename.
.. |Build Status| image:: https://api.travis-ci.org/kolypto/py-mailem.png?branch=master
:target: https://travis-ci.org/kolypto/py-mailem
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
mailem-0.0.1-0.tar.gz
(15.8 kB
view hashes)
Built Distribution
mailem-0.0.1_0-py2-none-any.whl
(20.4 kB
view hashes)