Email Output Renderer
back to 'in and out'

This renderer is used for generating email. The output is a message object very similar to that found in the python email package.

To use it, firstly, you create an email output renderer instance:

>>> from twiddler.output.emailer import Email,DummySMTP
>>> email = Email(smtp_host=DummySMTP)

smtp_host normally defaults to the localhost and would normally be passed as a string containing the domain name of the smtp server to use. However, here, we pass in the special Dummy singleton which is useful for debugging as it means any mail that would have been sent by SMTP will instead be printed to the console.

Now that we have an email output renderer, a Twiddler can be created in the normal way with the email render specified as the output:

>>> from twiddler import Twiddler
>>> from twiddler.input.plaintext import PlainText
>>> t = Twiddler('''Dear $name,
... Thank you for your order totalling $total
... ''',input=PlainText,output=email)

We can manipulate this Twiddler as normal:

>>> o = t.clone()
>>> o['name'].replace('Chris')
>>> o['total'].replace(u'£%0.2f' % 82.7)

When this is rendered, it sends the email to the specified recipients:

>>> o.render(mfrom='orders@simplistix.co.uk',
...          mto='chris@simplistix.co.uk',
...          subject='Your order')
Dummy SMTP send from 'orders@simplistix.co.uk' to 'chris@simplistix.co.uk'
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
Date:   ...
From: orders@simplistix.co.uk
Message-ID: ...
Subject: Your order
To: chris@simplistix.co.uk
<BLANKLINE>
Dear Chris,
Thank you for your order totalling =C2=A382.70
<BLANKLINE>

The parameters listened to by the email renderer include:

charset

This specifies the character set to use to encode the content of
the email. This can be either an email.Charset.Charset instance or
a string such as 'utf-8'. The default is a Charset that uses utf-8
encoding and quoted-printable representation. You may want to
specify a different representation if your content includes a lot
of non-western-european language or binary data such as files.

content_type

This is a string representing the content type of the body of the
email. The default is 'text/plain' but you will need to specify
'text/html' if you're generating html emails.

mfrom

The From address for the email

mto

The To address for the email. This can be a sequence of addresses.

mcc

The CC address for the email. This can be a sequence of addresses.

mbcc

The BCC address for the email. This can be a sequence of addresses.

subject

The subject for the email.

headers

The is optional and can be used to provide a dictionary of extra
headers to add to the message being generated. The keys of the
dictionary are the header names and the values are the header
values.

Now, some aspects of an email may be the same across a lot of emails that are being generated. For this reason, you can pass parameters to the constructor of the output renderer:

>>> email = Email(smtp_host=DummySMTP,
...               mfrom='orders@simplistix.co.uk',
...               mto='default@simplistix.co.uk',
...               subject='Your order',
...               headers={'X-Mailer':'Twiddler Emailer'})

The parameters will now be taken into account when the output is used with a Twiddler:

>>> t = Twiddler('''Dear $name,
... Thank you for your order totalling $total
... ''',input=PlainText,output=email)
>>> t['name'].replace('Chris')
>>> t['total'].replace(u'£%0.2f' % 82.7)
>>> t.render(mto='chris@simplistix.co.uk')
Dummy SMTP send from 'orders@simplistix.co.uk' to 'chris@simplistix.co.uk'
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
Date: ...
From: orders@simplistix.co.uk
Message-ID: ...
Subject: Your order
To: chris@simplistix.co.uk
X-Mailer: Twiddler Emailer
<BLANKLINE>
Dear Chris,
Thank you for your order totalling =C2=A382.70
<BLANKLINE>

NB: As you can see, the parameters passed to the render method still override those passed to the contructor of the output.

The full list of parameters you can pass to the constructor for the emailer output renderer is as follows:

smtp_host

This is the host that will be used to send any email. As described
and shown above, DummySMTP can also be passed for testing and
debugging. It defaults to 'localhost'

smtp_port

This is the port that will be used to send any email. It should be
a string containing the number of the port. '25' is used by default.

mfrom

The From address for any email generated with this output.

mto

The To address for any email generated with this output. This can
be a sequence of addresses. 

mcc

The CC address for any email generated with this output. This can
be a sequence of addresses. 

mbcc

The BCC address for any email generated with this output. This can
be a sequence of addresses. 

subject

The subject for any email generated with this output.

headers

The is optional and can be used to provide a dictionary of extra
headers to add to any email generated with this output. The keys
of the dictionary are the header names and the values are the
header values.

charset

This specifies the character set to use to encode the content of
any email generated with this output. This can be either an
email.Charset.Charset instance or a string such as 'utf-8'. The
default is a Charset that uses utf-8 encoding and quoted-printable
representation. You may want to specify a different representation
if your content includes a lot of non-western-european language or
binary data such as files. 

content_type

This is a string representing the content type of the body of any
email that will be generated with this output. The default is
'text/plain' but you will need to specify 'text/html' if you're
generating html emails. 

Python's email package provides many tools to help build email messages with more complicated structures. To help take advantage of these, Twiddler's email renderer allows you to return an object that behaves a lot like an email.MIMEMultipart.MIMEMultipart object:

>>> msg = t.render(mto='chris@simplistix.co.uk',as_message=True)

The only significant difference is that these objects has a helper method for quickly adding file attachments to an email:

>>> msg.add_file(data='my data',filename='test.txt')

The object returned also has a send method which sends the message using the parameters provided during consruction of the email output:

>>> msg.send()
Dummy SMTP send from 'orders@simplistix.co.uk' to 'chris@simplistix.co.uk'
MIME-Version: 1.0
Content-Type: multipart/mixed; charset="utf-8";
...
Content-Transfer-Encoding: quoted-printable
Date: ...
From: orders@simplistix.co.uk
Message-ID: ...
Subject: Your order
To: chris@simplistix.co.uk
X-Mailer: Twiddler Emailer
<BLANKLINE>
...
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
<BLANKLINE>
Dear Chris,
Thank you for your order totalling =C2=A382.70
<BLANKLINE>
...
Content-Type: text/plain
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="test.txt"
<BLANKLINE>
bXkgZGF0YQ==
...

This method also accepts python file objects:

>>> import os.path
>>> f = open(os.path.abspath(os.path.join(__file__,'..','..','tests','testfile.bin')))
>>> msg = t.render(mto='chris@simplistix.co.uk',as_message=True)
>>> msg.add_file(f)
>>> msg.send()
Dummy SMTP send from 'orders@simplistix.co.uk' to 'chris@simplistix.co.uk'
MIME-Version: 1.0
Content-Type: multipart/mixed; charset="utf-8";
...
Content-Transfer-Encoding: quoted-printable
Date: ...
From: orders@simplistix.co.uk
Message-ID: ...
Subject: Your order
To: chris@simplistix.co.uk
X-Mailer: Twiddler Emailer
<BLANKLINE>
...
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
<BLANKLINE>
Dear Chris,
Thank you for your order totalling =C2=A382.70
<BLANKLINE>
...
Content-Type: application/octet-stream
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="testfile.bin"
<BLANKLINE>
WFhY
...

You will noticed that the content type in the above mails is 'multipart/mixed', which is typically used when there is a mixture of textual content and binary attachments. Another common pattern is to have a 'multipart/alternate' encoding, where a plain text version and an html version of the same mail are sent together. Here's a simple example:

>>> t = Twiddler('''&lt;html>
... <body>
... <p>Dear &lt;span id="name">Mr Smith&lt;/span>,&lt;/p>
... <p>Thankyou for your order!&lt;/p>
... </body>
... </html>''',output=email)  
>>> t['name'].replace('Mr Withers',tag=False)
>>> msg = t.render(mto='chris@simplistix.co.uk',
...                as_message=True,
...                subtype='alternate',
...                content_type='text/html')
>>> from email.MIMEText import MIMEText
>>> msg.attach(MIMEText('''Dear Mr Withers,
... Thankyou for your order!'''))
>>> msg.send()
Dummy SMTP send from 'orders@simplistix.co.uk' to 'chris@simplistix.co.uk'
MIME-Version: 1.0
Content-Type: multipart/alternate; charset="utf-8";
...
Content-Transfer-Encoding: quoted-printable
Date: ...
From: orders@simplistix.co.uk
Message-ID: ...
Subject: Your order
To: chris@simplistix.co.uk
X-Mailer: Twiddler Emailer
<BLANKLINE>
...
Content-Type: text/html; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
<BLANKLINE>
<html>
<body>
<p>Dear Mr Withers,&lt;/p>
<p>Thankyou for your order!&lt;/p>
</body>
</html>
...
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
<BLANKLINE>
Dear Mr Withers,
Thankyou for your order!
...
changed August 1