""" Provides nifty interface for email composing and sending via SMTP. """ import logging from email.MIMEMultipart import MIMEMultipart from email.MIMEText import MIMEText from email.Header import Header import smtplib import socket import settings # Storage for emails. In debug mode all emails sending with # EmailMessage will be stored in debug_cache variable debug_cache = [] def format_header(value, charset): """ Format value to make it safe for using in email headers. """ try: value.decode('ascii') except (UnicodeDecodeError, UnicodeEncodeError): return Header(value.encode(charset), charset) else: return value class EmailMessage(object): """ Provide nifty interface for email composing and sending via SMTP. """ def __init__(self, to_email, from_email, subject, body, text_body=None, charset='utf-8'): self.to_email = to_email self.from_email = from_email self.subject = subject self.body = body self.text_body = text_body self.from_email = from_email self.charset = charset def as_message(self): """ Return python email.MIMEMultipart.MIMEMultipart object. """ msg = MIMEMultipart() # Following headers are useful to show the email correctly # in your recipient's email box, and to avoid being marked # as spam. They are NOT essential to the sendmail call later msg['Subject'] = format_header(self.subject, self.charset) msg['From'] = format_header(self.from_email, self.charset) msg['Reply-to'] = format_header(self.from_email, self.charset) msg['To'] = format_header(self.to_email, self.charset) msg.preamble = 'Multipart message' msg.epilogue = '' # Encapsulate the plain text and html versions of the message body in an # 'alternative' part, so MUAs can decide which they want to display. msg_alternative = MIMEMultipart('alternative') msg.attach(msg_alternative) if not self.text_body is None: part = MIMEText(self.text_body.encode(self.charset), _charset=self.charset, _subtype='plain') msg_alternative.attach(part) if not self.body is None: part = MIMEText(self.body.encode(self.charset), _charset=self.charset, _subtype='html') msg_alternative.attach(part) return msg def as_string(self): """ Return textual representation of email message suitable for sending via SMTP. """ return self.as_message().as_string() def send(self, smtp_host=None, smtp_port=None, debug=False): """ Send message via SMTP. Return True or False indicating the success of message sending. """ if smtp_host is None: smtp_host = settings.DEFAULT_SMTP_HOST if smtp_port is None: smtp_port = settings.DEFAULT_SMTP_PORT logging.debug('\n\n') logging.debug(u'Sending email') logging.debug('from=[%s]' % self.from_email) logging.debug('to=[%s]' % self.to_email) logging.debug('subject=[%s]' % self.subject) logging.debug(u'body:\n%s' % self.body) logging.debug(u'text_body:\n%s' % self.text_body) logging.debug('\n\n') if debug: debug_cache.append(self.as_message()) logging.debug('Saving message in debug cache') return True else: logging.debug('Sending message via SMTP') try: s = smtplib.SMTP() s.connect(smtp_host, smtp_port) s.sendmail(self.from_email, self.to_email, self.as_string()) s.close() except (socket.error, smtplib.SMTPException), ex: logging.error(ex) return False else: return True