Message   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 65
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 65
rs 10
wmc 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A send() 0 10 1
A add() 0 3 1
A mime() 0 8 1
A __init__() 0 9 3
A html() 0 8 2
1
# -*- coding: utf-8 -*-
2
3
"""Main module."""
4
from __future__ import absolute_import
5
from email.mime.multipart import MIMEMultipart
6
from email.mime.text import MIMEText
7
import smtplib
8
9
import markdown
0 ignored issues
show
introduced by
Unable to import 'markdown'
Loading history...
10
import premailer
0 ignored issues
show
introduced by
Unable to import 'premailer'
Loading history...
11
12
13
class Message(object):
14
    """ A simple email message made of Markdown strings
15
16
    A Message is a simplified version of a MIMEMultipart email message.
17
    Instead of having to seperately construct HTML and text version of
18
    an email, you can build a Message by adding lines of Markdown formatted
19
    strings.
20
21
    args:
22
        body (str, bytes, iterable of strings): The body of the email.
23
            It does not need to be complete, as you can add to it later.
24
        style (str): CSS formatting to be applied to HTML formatted verion
25
            of email.
26
        server (EmailServer): An EmailServer instance allowing a message
27
            to be sent directly from it's `send` method.
28
    """
29
    def __init__(self, body=None, style=None, server=None):
30
        if body is None:
31
            self.body = []
32
        else:
33
            if any((isinstance(body, str), isinstance(body, bytes))):
34
                body = [body]
35
            self.body = body
36
        self.style = style
37
        self.server = server
38
39
    def add(self, line):
40
        """ Adds a new Markdown formatted line to the current email body """
41
        self.body.append(line)
42
43
    @property
44
    def html(self):
45
        """ Returns HTML formatted and styled version of body """
46
        html = markdown.markdown('\n'.join(self.body))
47
        if self.style:
48
            return premailer.transform('<style>\n' + self.style +
49
                                       '\n</style>\n' + html)
50
        return html
51
52
    def __str__(self):
53
        return '\n'.join(self.body)
54
55
    def __repr__(self):
56
        return '<Message: {0} and {1} more lines>'.format(
57
            self.body[0], (len(self.body) - 1))
58
59
    def mime(self):
60
        """ Returns a MIMEMultipart message """
61
        msg = MIMEMultipart('alternative')
62
63
        msg.attach(MIMEText(str(self), 'plain'))
64
        msg.attach(MIMEText(self.html, 'html'))
65
66
        return msg
67
68
    def send(self, send_to, subject):
69
        """ Sends the formatted message to given recripient
70
71
        args:
72
            send_to (:obj:`str`, iterable of :obj:`str`): Email addresses to
73
                send to
74
            subject (str): Subject line of email to send
75
76
        """
77
        self.server.send_message(self, send_to, subject)
78
79
80
class EmailServer(object):
81
    """ Connection to a specific email server
82
83
    args:
84
        url (str): URL for the SMTP server
85
        port (int): SMTP port
86
        email_address (str): Email address to log into server and send from
87
        password (str): Password for email address on SMTP server
88
    """
89
    def __init__(self, url, port, email, password):
90
        self.url = url
91
        self.port = port
92
        self.email_address = email
93
        self.password = password
94
        self.server = None
95
96
    def _login(self):
97
        self.server = smtplib.SMTP(self.url, self.port)
98
        self.server.starttls()
99
        self.server.login(self.email_address, self.password)
100
101
    def _logout(self):
102
        self.server.quit()
103
104
    def quick_email(self, send_to, subject, body, style=None):
105
        """ Compose and send an email in a single call
106
107
        args:
108
            send_to (str):
109
            subject (str):
110
            body (:obj:`str`, iterable of :obj:`str`): Markdown formatted
111
                string or iterable of strings composing the message body
112
            style (str): CSS formatting for the message
113
        """
114
        message = Message(body, style=style)
115
116
        self.send_message(message, send_to, subject)
117
118
    def send_message(self, message, send_to, subject):
119
        """ Send a precomposed Message
120
121
        args:
122
            message (Message): Completed message to send
123
            send_to (str): Email address to send the message to
124
            subject (str): Subject of the email
125
        """
126
        message = message.mime()
127
128
        message['From'] = self.email_address
129
        message['To'] = send_to
130
131
        message['Subject'] = subject
132
133
        self._login()
134
        self.server.sendmail(self.email_address, send_to, message.as_string())
135
        self._logout()
136
137
    def message(self, body=None, style=None):
138
        """ Returns a Message object
139
140
        args:
141
            body (str, bytes, iterable of strings): The body of the email.
142
                It does not need to be complete, as you can add to it later.
143
            style (str): CSS formatting to be applied to HTML formatted verion
144
                of email.
145
        """
146
        return Message(body=body, style=style, server=self)
147