Email Output Renderer

  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('''<html>
  ... <body>
  ... <p>Dear <span id="name">Mr Smith</span>,</p>
  ... <p>Thankyou for your order!</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,</p>
  <p>Thankyou for your order!</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!
  ...

