Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Python send email with html and plain versions and attachments
- import os.path
- import types
- import smtplib
- import email.Message
- from email import Encoders
- from email.MIMEAudio import MIMEAudio
- from email.MIMEBase import MIMEBase
- from email.MIMEMultipart import MIMEMultipart
- from email.MIMEImage import MIMEImage
- from email.MIMEText import MIMEText
- import mimetypes
- class SendMail(object):
- '''The swiss army knife of email programs. Here are some of the features:
- 1) you can build parts of the message in pieces. This is useful for when
- you need to send out lots of emails with similar content. For example,
- I needed to added a unique unsubcribe token to each email. The email had
- a large attachment. This made it so I did not have to reprocess the
- attachment for each email.
- 2) allows you to include both html and plain text versions of the message
- in the email.
- 3) handles the encoding of a wide range of attachment file types.
- 4) sends the email with the TLS protocol if the server uses TLS
- gmail uses TLS.
- This code was pieced together from snippets of code found using google.
- How to use? Just look down the list of methods. Use the ones you need.
- It should be pretty obvious. You will need to set the attributes:
- "from_email_addr" and "subject" directly before calling send.
- This code has NOT been throughly tested because there are too many combinations.
- I just test the combinations I need.
- '''
- def __init__(self,smtpserver,smtpuser = '',smtppass = '',port=None, debug=False):
- self.smtpserver=smtpserver
- self.smtpuser=smtpuser
- self.smtppass=smtppass
- self.port=port
- self.debug=debug
- self.encoded_attachments=[]
- self.cc_list=[]
- def add_attachments(self,attachment_list):
- '''attachment_list: a list of full file paths'''
- self.encoded_attachments=[]
- for path in attachment_list:
- dirname,filename=os.path.split(path)
- # Guess the content type based on the file's extension. Encoding
- # will be ignored, although we should check for simple things like
- # gzip'd or compressed files.
- ctype, encoding = mimetypes.guess_type(path)
- if ctype is None or encoding is not None:
- # No guess could be made, or the file is encoded (compressed), so
- # use a generic bag-of-bits type.
- ctype = 'application/octet-stream'
- maintype, subtype = ctype.split('/', 1)
- if maintype == 'text':
- fp = open(path)
- # Note: we should handle calculating the charset
- msg = MIMEText(fp.read(), _subtype=subtype)
- fp.close()
- elif maintype == 'image':
- fp = open(path, 'rb')
- msg = MIMEImage(fp.read(), _subtype=subtype)
- fp.close()
- elif maintype == 'audio':
- fp = open(path, 'rb')
- msg = MIMEAudio(fp.read(), _subtype=subtype)
- fp.close()
- else: # includes MS Word docs
- fp = open(path, 'rb')
- msg = MIMEBase(maintype, subtype)
- msg.set_payload(fp.read())
- fp.close()
- # Encode the payload using Base64
- Encoders.encode_base64(msg)
- # Set the filename parameter
- msg.add_header('Content-Disposition', 'attachment', filename=filename)
- self.encoded_attachments.append(msg)
- def add_to(self,to_list):
- self.to_list=to_list
- self.to_str=','.join(to_list)
- def add_cc(self,cc_list):
- self.cc_list=cc_list
- self.cc_str=','.join(cc_list)
- def add_body(self,body):
- if type(body) is types.StringType:
- self.body=MIMEText(body,'plain')
- else:
- self.body=MIMEMultipart('alternative')
- for k in body:
- self.body.attach(MIMEText(body[k],k))
- def send(self):
- '''No error checking. It should just crash if some stuff is not setup. '''
- message=MIMEMultipart()
- message.preamble = 'You will not see this in a MIME-aware mail reader.\n'
- message.epilogue = '' # To guarantee the message ends with a newline
- message.attach(self.body)
- message['To']=self.to_str
- if self.cc_list:
- message['CC']=self.cc_str
- # Set these attributes up directly before calling this method
- message['Subject'] = self.subject
- message['From']=self.from_email_addr
- print self.encoded_attachments
- for a in self.encoded_attachments:
- message.attach(a)
- # Send it
- server = smtplib.SMTP(self.smtpserver,self.port)
- try:
- server.set_debuglevel(self.debug)
- server.ehlo()
- # If we can encrypt this session, do it
- if server.has_extn('STARTTLS'):
- server.starttls()
- server.ehlo() # re-identify ourselves over TLS connection
- server.login(self.smtpuser, self.smtppass)
- smtpresult =server.sendmail(self.from_email_addr, self.to_list+self.cc_list, message.as_string())
- finally:
- server.quit()
- if smtpresult:
- for recip in smtpresult.keys():
- print """Could not delivery mail to: %s Server said: %s %s""" \
- % (recip, smtpresult[recip][0], smtpresult[recip][1])
- return False
- else:
- return True
- def send_simple_email(self,to_list,from_email_addr,subject,body,attachment_list=[],
- cc_list=[]):
- '''A wrapper for if you do not need to do things in pieces. You can also use this
- as a guide for how to build up an email in pieces.
- '''
- self.add_to(to_list)
- self.add_cc(cc_list)
- self.from_email_addr=from_email_addr
- self.subject=subject
- self.add_body(body)
- self.add_attachments(attachment_list)
- return self.send()
- if __name__=="__main__":
- smtpuser = 'my_email@gmail.com'
- smtppass=raw_input('Enter gmail password->')
- body={}
- body['html']='<h1>hi</h1>'
- body['plain']='hello'
- sm=SendMail('smtp.gmail.com', smtpuser = smtpuser, smtppass = smtppass, port=587)
- r=sm.send_simple_email(['to_someone@yahoo.com'],'my_email@gmail.com','Test - from Fred',
- body,attachment_list=[r'C:\Documents and Settings\my_media\uploads\Case-of-the-Week invite 02-24-10.doc'])
- print r
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement