Python
10 Aug 2008 HTML Text
 
 
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"""
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