Added module for emailing
This commit is contained in:
parent
6fff4bc3c8
commit
51fd560f92
223
emailer.py
Executable file
223
emailer.py
Executable file
@ -0,0 +1,223 @@
|
||||
#!/usr/bin/python2
|
||||
|
||||
from email import encoders
|
||||
from email.mime.audio import MIMEAudio
|
||||
from email.mime.base import MIMEBase
|
||||
from email.mime.image import MIMEImage
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
import mimetypes
|
||||
import os
|
||||
import re
|
||||
import smtplib
|
||||
|
||||
class Email:
|
||||
"""
|
||||
This class handles the creation and sending of email messages
|
||||
via SMTP. This class also handles attachments and can send
|
||||
HTML messages. The code comes from various places around
|
||||
the net and from my own brain.
|
||||
"""
|
||||
def __init__(self, smtpServer):
|
||||
"""
|
||||
Create a new empty email message object.
|
||||
|
||||
@param smtpServer: The address of the SMTP server
|
||||
@type smtpServer: String
|
||||
"""
|
||||
self._textBody = None
|
||||
self._htmlBody = None
|
||||
self._bcc = []
|
||||
self._cc = []
|
||||
self._subject = ""
|
||||
self._smtpServer = smtpServer
|
||||
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])?)$")
|
||||
self.clearRecipients()
|
||||
self.clearAttachments()
|
||||
|
||||
def send(self):
|
||||
"""
|
||||
Send the email message represented by this object.
|
||||
"""
|
||||
# Validate message
|
||||
if self._textBody is None and self._htmlBody is None:
|
||||
raise Exception("Error! Must specify at least one body type (HTML or Text)")
|
||||
if len(self._to) == 0:
|
||||
raise Exception("Must specify at least one recipient")
|
||||
|
||||
# Create the message part
|
||||
if self._textBody is not None and self._htmlBody is None:
|
||||
msg = MIMEText(self._textBody, "plain")
|
||||
elif self._textBody is None and self._htmlBody is not None:
|
||||
msg = MIMEText(self._htmlBody, "html")
|
||||
else:
|
||||
msg = MIMEMultipart("alternative")
|
||||
msg.attach(MIMEText(self._textBody, "plain"))
|
||||
msg.attach(MIMEText(self._htmlBody, "html"))
|
||||
# Add attachments, if any
|
||||
if len(self._attach) != 0:
|
||||
tmpmsg = msg
|
||||
msg = MIMEMultipart()
|
||||
msg.attach(tmpmsg)
|
||||
for fname,attachname in self._attach:
|
||||
if not os.path.exists(fname):
|
||||
print "File '%s' does not exist. Not attaching to email." % fname
|
||||
continue
|
||||
if not os.path.isfile(fname):
|
||||
print "Attachment '%s' is not a file. Not attaching to email." % fname
|
||||
continue
|
||||
# Guess at encoding type
|
||||
ctype, encoding = mimetypes.guess_type(fname)
|
||||
if ctype is None or encoding is not None:
|
||||
# No guess could be made so use a binary type.
|
||||
ctype = 'application/octet-stream'
|
||||
maintype, subtype = ctype.split('/', 1)
|
||||
if maintype == 'text':
|
||||
fp = open(fname)
|
||||
attach = MIMEText(fp.read(), _subtype=subtype)
|
||||
fp.close()
|
||||
elif maintype == 'image':
|
||||
fp = open(fname, 'rb')
|
||||
attach = MIMEImage(fp.read(), _subtype=subtype)
|
||||
fp.close()
|
||||
elif maintype == 'audio':
|
||||
fp = open(fname, 'rb')
|
||||
attach = MIMEAudio(fp.read(), _subtype=subtype)
|
||||
fp.close()
|
||||
else:
|
||||
fp = open(fname, 'rb')
|
||||
attach = MIMEBase(maintype, subtype)
|
||||
attach.set_payload(fp.read())
|
||||
fp.close()
|
||||
# Encode the payload using Base64
|
||||
encoders.encode_base64(attach)
|
||||
# Set the filename parameter
|
||||
if attachname is None:
|
||||
filename = os.path.basename(fname)
|
||||
else:
|
||||
filename = attachname
|
||||
attach.add_header('Content-Disposition', 'attachment', filename=filename)
|
||||
msg.attach(attach)
|
||||
# Some header stuff
|
||||
msg['Subject'] = self._subject
|
||||
msg['From'] = self._from
|
||||
msg['To'] = ", ".join(self._to)
|
||||
msg['Cc'] = ", ".join(self._cc)
|
||||
msg.preamble = "You need a MIME enabled mail reader to see this message"
|
||||
# Send message
|
||||
msg = msg.as_string()
|
||||
server = smtplib.SMTP(self._smtpServer)
|
||||
server.sendmail(self._from, self._to + self._cc + self._bcc, msg)
|
||||
server.quit()
|
||||
|
||||
def setSubject(self, subject):
|
||||
"""
|
||||
Set the subject of the email message.
|
||||
"""
|
||||
self._subject = subject
|
||||
|
||||
def setFrom(self, address):
|
||||
"""
|
||||
Set the email sender.
|
||||
"""
|
||||
if not self.validateEmailAddress(address):
|
||||
raise Exception("Invalid email address '%s'" % address)
|
||||
self._from = address
|
||||
|
||||
def clearRecipients(self):
|
||||
"""
|
||||
Remove all currently defined recipients for
|
||||
the email message.
|
||||
"""
|
||||
self._to = []
|
||||
self._cc = []
|
||||
self._bcc = []
|
||||
|
||||
def addRecipient(self, address):
|
||||
"""
|
||||
Add a new recipient to the email message.
|
||||
"""
|
||||
if not self.validateEmailAddress(address):
|
||||
raise Exception("Invalid email address '%s'" % address)
|
||||
self._to.append(address)
|
||||
|
||||
def addCC(self, address):
|
||||
"""
|
||||
Add a new carbon copy recipient to the email message.
|
||||
"""
|
||||
if not self.validateEmailAddress(address):
|
||||
raise Exception("Invalid cc email address '%s'" % address)
|
||||
self._cc.append(address)
|
||||
|
||||
def addBCC(self, address):
|
||||
"""
|
||||
Add a new blind carbon copy recipient to the email message.
|
||||
"""
|
||||
if not self.validateEmailAddress(address):
|
||||
raise Exception("Invalid bcc email address '%s'" % address)
|
||||
self._bcc.append(address)
|
||||
|
||||
def setTextBody(self, body):
|
||||
"""
|
||||
Set the plain text body of the email message.
|
||||
"""
|
||||
self._textBody = body
|
||||
|
||||
def setHtmlBody(self, body):
|
||||
"""
|
||||
Set the HTML portion of the email message.
|
||||
"""
|
||||
self._htmlBody = body
|
||||
|
||||
def clearAttachments(self):
|
||||
"""
|
||||
Remove all file attachments.
|
||||
"""
|
||||
self._attach = []
|
||||
|
||||
def addAttachment(self, fname, attachname=None):
|
||||
"""
|
||||
Add a file attachment to this email message.
|
||||
|
||||
@param fname: The full path and file name of the file
|
||||
to attach.
|
||||
@type fname: String
|
||||
@param attachname: This will be the name of the file in
|
||||
the email message if set. If not set
|
||||
then the filename will be taken from
|
||||
the fname parameter above.
|
||||
@type attachname: String
|
||||
"""
|
||||
if fname is None:
|
||||
return
|
||||
self._attach.append( (fname, attachname) )
|
||||
|
||||
def validateEmailAddress(self, address):
|
||||
"""
|
||||
Validate the specified email address.
|
||||
|
||||
@return: True if valid, False otherwise
|
||||
@rtype: Boolean
|
||||
"""
|
||||
if self._reEmail.search(address) is None:
|
||||
return False
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
print "Tests go here..."
|
||||
"""
|
||||
# Run some tests
|
||||
mFrom = 'fredw@northriverboats.com'
|
||||
mTo = "fred.warren@gmail.com"
|
||||
m = Email('northriverboats-com.mail.protection.outlook.com')
|
||||
m.setFrom(mFrom)
|
||||
m.addRecipient(mTo)
|
||||
m.addCC("fredw@northriverboats.com")
|
||||
m.addBCC("w.brokenbourgh@pismotek.com")
|
||||
|
||||
m.setSubject("Text and HTML Message with CC and BCC")
|
||||
m.setTextBody("You should not see this text in a MIME aware reader")
|
||||
m.setHtmlBody("The following should be <b>bold</b>. If this works Will, you will be BCC'd on this.")
|
||||
m.addAttachment('/tmp/shot.png')
|
||||
m.send()
|
||||
"""
|
Loading…
Reference in New Issue
Block a user