| 16699 |
manish.sha |
1 |
from email import encoders
|
|
|
2 |
from email.mime.audio import MIMEAudio
|
|
|
3 |
from email.mime.base import MIMEBase
|
|
|
4 |
from email.mime.image import MIMEImage
|
|
|
5 |
from email.mime.multipart import MIMEMultipart
|
|
|
6 |
from email.mime.text import MIMEText
|
|
|
7 |
import mimetypes
|
|
|
8 |
import os
|
|
|
9 |
import re
|
|
|
10 |
import smtplib
|
|
|
11 |
|
|
|
12 |
class Email:
|
|
|
13 |
"""
|
|
|
14 |
This class handles the creation and sending of email messages
|
|
|
15 |
via SMTP. This class also handles attachments and can send
|
|
|
16 |
HTML messages. The code comes from various places around
|
|
|
17 |
the net and from my own brain.
|
|
|
18 |
"""
|
|
|
19 |
def __init__(self, smtpServer):
|
|
|
20 |
"""
|
|
|
21 |
Create a new empty email message object.
|
|
|
22 |
|
|
|
23 |
@param smtpServer: The address of the SMTP server
|
|
|
24 |
@type smtpServer: String
|
|
|
25 |
"""
|
|
|
26 |
self._textBody = None
|
|
|
27 |
self._htmlBody = None
|
|
|
28 |
self._subject = ""
|
|
|
29 |
self._smtpServer = smtpServer
|
|
|
30 |
self._reEmail = re.compile("^([\\w \\._]+\\<[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\>|[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)$")
|
|
|
31 |
self.clearRecipients()
|
|
|
32 |
self.clearAttachments()
|
|
|
33 |
|
|
|
34 |
def send(self):
|
|
|
35 |
"""
|
|
|
36 |
Send the email message represented by this object.
|
|
|
37 |
"""
|
|
|
38 |
# Validate message
|
|
|
39 |
if self._textBody is None and self._htmlBody is None:
|
|
|
40 |
raise Exception("Error! Must specify at least one body type (HTML or Text)")
|
|
|
41 |
if len(self._to) == 0:
|
|
|
42 |
raise Exception("Must specify at least one recipient")
|
|
|
43 |
|
|
|
44 |
# Create the message part
|
|
|
45 |
if self._textBody is not None and self._htmlBody is None:
|
|
|
46 |
msg = MIMEText(self._textBody, "plain")
|
|
|
47 |
elif self._textBody is None and self._htmlBody is not None:
|
|
|
48 |
msg = MIMEText(self._htmlBody, "html")
|
|
|
49 |
else:
|
|
|
50 |
msg = MIMEMultipart("alternative")
|
|
|
51 |
msg.attach(MIMEText(self._textBody, "plain"))
|
|
|
52 |
msg.attach(MIMEText(self._htmlBody, "html"))
|
|
|
53 |
# Add attachments, if any
|
|
|
54 |
if len(self._attach) != 0:
|
|
|
55 |
tmpmsg = msg
|
|
|
56 |
msg = MIMEMultipart()
|
|
|
57 |
msg.attach(tmpmsg)
|
|
|
58 |
for fname,attachname in self._attach:
|
|
|
59 |
if not os.path.exists(fname):
|
|
|
60 |
print "File '%s' does not exist. Not attaching to email." % fname
|
|
|
61 |
continue
|
|
|
62 |
if not os.path.isfile(fname):
|
|
|
63 |
print "Attachment '%s' is not a file. Not attaching to email." % fname
|
|
|
64 |
continue
|
|
|
65 |
# Guess at encoding type
|
|
|
66 |
ctype, encoding = mimetypes.guess_type(fname)
|
|
|
67 |
if ctype is None or encoding is not None:
|
|
|
68 |
# No guess could be made so use a binary type.
|
|
|
69 |
ctype = 'application/octet-stream'
|
|
|
70 |
maintype, subtype = ctype.split('/', 1)
|
|
|
71 |
if maintype == 'text':
|
|
|
72 |
fp = open(fname)
|
|
|
73 |
attach = MIMEText(fp.read(), _subtype=subtype)
|
|
|
74 |
fp.close()
|
|
|
75 |
elif maintype == 'image':
|
|
|
76 |
fp = open(fname, 'rb')
|
|
|
77 |
attach = MIMEImage(fp.read(), _subtype=subtype)
|
|
|
78 |
fp.close()
|
|
|
79 |
elif maintype == 'audio':
|
|
|
80 |
fp = open(fname, 'rb')
|
|
|
81 |
attach = MIMEAudio(fp.read(), _subtype=subtype)
|
|
|
82 |
fp.close()
|
|
|
83 |
else:
|
|
|
84 |
fp = open(fname, 'rb')
|
|
|
85 |
attach = MIMEBase(maintype, subtype)
|
|
|
86 |
attach.set_payload(fp.read())
|
|
|
87 |
fp.close()
|
|
|
88 |
# Encode the payload using Base64
|
|
|
89 |
encoders.encode_base64(attach)
|
|
|
90 |
# Set the filename parameter
|
|
|
91 |
if attachname is None:
|
|
|
92 |
filename = os.path.basename(fname)
|
|
|
93 |
else:
|
|
|
94 |
filename = attachname
|
|
|
95 |
attach.add_header('Content-Disposition', 'attachment', filename=filename)
|
|
|
96 |
msg.attach(attach)
|
|
|
97 |
# Some header stuff
|
|
|
98 |
msg['Subject'] = self._subject
|
|
|
99 |
msg['From'] = self._from
|
|
|
100 |
msg['To'] = ", ".join(self._to)
|
|
|
101 |
msg.preamble = "You need a MIME enabled mail reader to see this message"
|
|
|
102 |
# Send message
|
|
|
103 |
msg = msg.as_string()
|
|
|
104 |
server = smtplib.SMTP(self._smtpServer)
|
|
|
105 |
server.sendmail(self._from, self._to, msg)
|
|
|
106 |
server.quit()
|
|
|
107 |
|
|
|
108 |
def setSubject(self, subject):
|
|
|
109 |
"""
|
|
|
110 |
Set the subject of the email message.
|
|
|
111 |
"""
|
|
|
112 |
self._subject = subject
|
|
|
113 |
|
|
|
114 |
def setFrom(self, address):
|
|
|
115 |
"""
|
|
|
116 |
Set the email sender.
|
|
|
117 |
"""
|
|
|
118 |
if not self.validateEmailAddress(address):
|
|
|
119 |
raise Exception("Invalid email address '%s'" % address)
|
|
|
120 |
self._from = address
|
|
|
121 |
|
|
|
122 |
def clearRecipients(self):
|
|
|
123 |
"""
|
|
|
124 |
Remove all currently defined recipients for
|
|
|
125 |
the email message.
|
|
|
126 |
"""
|
|
|
127 |
self._to = []
|
|
|
128 |
|
|
|
129 |
def addRecipient(self, address):
|
|
|
130 |
"""
|
|
|
131 |
Add a new recipient to the email message.
|
|
|
132 |
"""
|
|
|
133 |
if not self.validateEmailAddress(address):
|
|
|
134 |
raise Exception("Invalid email address '%s'" % address)
|
|
|
135 |
self._to.append(address)
|
|
|
136 |
|
|
|
137 |
def setTextBody(self, body):
|
|
|
138 |
"""
|
|
|
139 |
Set the plain text body of the email message.
|
|
|
140 |
"""
|
|
|
141 |
self._textBody = body
|
|
|
142 |
|
|
|
143 |
def setHtmlBody(self, body):
|
|
|
144 |
"""
|
|
|
145 |
Set the HTML portion of the email message.
|
|
|
146 |
"""
|
|
|
147 |
self._htmlBody = body
|
|
|
148 |
|
|
|
149 |
def clearAttachments(self):
|
|
|
150 |
"""
|
|
|
151 |
Remove all file attachments.
|
|
|
152 |
"""
|
|
|
153 |
self._attach = []
|
|
|
154 |
|
|
|
155 |
def addAttachment(self, fname, attachname=None):
|
|
|
156 |
"""
|
|
|
157 |
Add a file attachment to this email message.
|
|
|
158 |
|
|
|
159 |
@param fname: The full path and file name of the file
|
|
|
160 |
to attach.
|
|
|
161 |
@type fname: String
|
|
|
162 |
@param attachname: This will be the name of the file in
|
|
|
163 |
the email message if set. If not set
|
|
|
164 |
then the filename will be taken from
|
|
|
165 |
the fname parameter above.
|
|
|
166 |
@type attachname: String
|
|
|
167 |
"""
|
|
|
168 |
if fname is None:
|
|
|
169 |
return
|
|
|
170 |
self._attach.append( (fname, attachname) )
|
|
|
171 |
|
|
|
172 |
def validateEmailAddress(self, address):
|
|
|
173 |
"""
|
|
|
174 |
Validate the specified email address.
|
|
|
175 |
|
|
|
176 |
@return: True if valid, False otherwise
|
|
|
177 |
@rtype: Boolean
|
|
|
178 |
"""
|
|
|
179 |
if self._reEmail.search(address) is None:
|
|
|
180 |
return False
|
|
|
181 |
return True
|