Skip to content

Instantly share code, notes, and snippets.

@reedobrien
Created March 14, 2012 00:48
Show Gist options
  • Save reedobrien/2033059 to your computer and use it in GitHub Desktop.
Save reedobrien/2033059 to your computer and use it in GitHub Desktop.
import smtplib
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from html2text import html2text
def get_encoding(unicode_text):
"""
Guess the charset and return it
"""
for charset in 'US-ASCII', 'ISO-8859-1', 'UTF-8':
try:
unicode_text.encode(charset)
return charset
except UnicodeError:
pass
else:
break
class Emailer(object):
"""
:param html: the html for the body of the message with {} string formatting
:param text: the text for the body of the message with {} string formatting
:param from_addr: the MUA visible from address i.e. the default
u"MYORG <[email protected]>"
:param listid: the list-id. Default: u'MYORG Notifications <notifications.MYORG.net>'
:param recipients: a list of recipients. Default: []
:param sender: the smtp sender for MAIL FROM command Default:
u"[email protected]"
:param server: the server to connect to for sending mail Default:
u'localhost'
:param smtplib: the smtplib library to use. Here to pass in a dummy for testing.
:param subject: the subject line. Default: u"MYORG Email Update"
"""
def __init__(self,
html,
coll,
text=None,
from_addr=u"MYORG <[email protected]>",
listid=u'<notifications.MYORG.net>',
recipients=[],
sender=u"[email protected]",
server=u'abadina.MYORG.org',
smtplib=smtplib,
subject=u"MYORG Email Update",
):
self.html = unicode(html)
self.text = unicode(text) if text else None
self.from_addr = from_addr
self.listid = listid
self.recipients = recipients
self.receivers = [] # like ["[email protected]", ]
self.server = smtplib.SMTP(server)
self.sender = sender
self.subject = subject
self.coll = coll
def add_recipient(self, userdata):
"""
:param userdata: a dict structure with the necessary data for
the format substitution in the current mailer. It should also
have the "_id" and "email".
"""
self.recipients.append(userdata)
def add_bcc(self, bcc_address):
"""
:param bcc_address: an email address to add to bcc.
"""
self.receivers.append(bcc_address)
def send(self):
try:
for userdata in self.recipients:
html_message = self.html.format(userdata)
if self.text is None:
text_message = html2text(html_message)
else:
text_message = self.text.format(userdata)
msg_receivers = self.receivers + [userdata['email'], ]
print msg_receivers
# get engoding since we don't know who has
# funny characters
body_text_encoding = get_encoding(text_message)
body_html_encoding = get_encoding(html_message)
# Set up the message instance
msg = MIMEMultipart('alternative')
## Headers
msg['From'] = self.from_addr
msg['Subject'] = self.subject
# check for international names and encode accordingly
todata = u'{0[first_name]} {0[last_name]} <{0[email]}>'.format(
userdata).strip()
todata_encoding = get_encoding(todata)
to = Header(todata.encode(todata_encoding), todata_encoding)
msg['To'] = to
## Add headers for easy back-reference
msg['X-MYORG-Recipient'] = userdata['email']
msg['X-MYORG-User'] = self.sender
msg['List-ID'] = self.listid
# Record the MIME types of both parts - text/plain and text/html.
text_part = MIMEText(text_message.encode(body_text_encoding), 'plain',
body_text_encoding)
html_part = MIMEText(html_message.encode(body_html_encoding), 'html',
body_html_encoding)
# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(text_part)
msg.attach(html_part)
# sendmail function takes 3 arguments: sender's address, recipient's address
# and message to send - here it is sent as one string.
try:
self.server.sendmail(self.sender,
msg_receivers,
msg.as_string())
userdata['sent'] = True
userdata['subject'] = self.subject
self.coll.save(userdata)
except Exception, e:
pass # handle exception
except Exception, e:
print e
def quit(self):
self.server.quit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment