fwarren

python email html/text with attaments and CC/BCC

Mar 15th, 2016
606
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.88 KB | None | 0 0
  1. #!/usr/bin/python2
  2. # Adapted from http://code.activestate.com/recipes/576858-send-html-or-text-email-with-or-without-attachment/
  3.  
  4. from email import encoders
  5. from email.mime.audio import MIMEAudio
  6. from email.mime.base import MIMEBase
  7. from email.mime.image import MIMEImage
  8. from email.mime.multipart import MIMEMultipart
  9. from email.mime.text import MIMEText
  10. import mimetypes
  11. import os
  12. import re
  13. import smtplib
  14.  
  15. class Email:
  16.     """
  17.    This class handles the creation and sending of email messages
  18.    via SMTP.  This class also handles attachments and can send
  19.    HTML messages.  The code comes from various places around
  20.    the net and from my own brain.
  21.    """
  22.     def __init__(self, smtpServer):
  23.         """
  24.        Create a new empty email message object.
  25.  
  26.        @param smtpServer: The address of the SMTP server
  27.        @type smtpServer: String
  28.        """
  29.         self._textBody = None
  30.         self._htmlBody = None
  31.         self._bcc = []
  32.         self._cc = []
  33.         self._subject = ""
  34.         self._smtpServer = smtpServer
  35.         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])?)$")
  36.         self.clearRecipients()
  37.         self.clearAttachments()
  38.    
  39.     def send(self):
  40.         """
  41.        Send the email message represented by this object.
  42.        """
  43.         # Validate message
  44.         if self._textBody is None and self._htmlBody is None:
  45.             raise Exception("Error! Must specify at least one body type (HTML or Text)")
  46.         if len(self._to) == 0:
  47.             raise Exception("Must specify at least one recipient")
  48.        
  49.         # Create the message part
  50.         if self._textBody is not None and self._htmlBody is None:
  51.             msg = MIMEText(self._textBody, "plain")
  52.         elif self._textBody is None and self._htmlBody is not None:
  53.             msg = MIMEText(self._htmlBody, "html")
  54.         else:
  55.             msg = MIMEMultipart("alternative")
  56.             msg.attach(MIMEText(self._textBody, "plain"))
  57.             msg.attach(MIMEText(self._htmlBody, "html"))
  58.         # Add attachments, if any
  59.         if len(self._attach) != 0:
  60.             tmpmsg = msg
  61.             msg = MIMEMultipart()
  62.             msg.attach(tmpmsg)
  63.         for fname,attachname in self._attach:
  64.             if not os.path.exists(fname):
  65.                 print "File '%s' does not exist.  Not attaching to email." % fname
  66.                 continue
  67.             if not os.path.isfile(fname):
  68.                 print "Attachment '%s' is not a file.  Not attaching to email." % fname
  69.                 continue
  70.             # Guess at encoding type
  71.             ctype, encoding = mimetypes.guess_type(fname)
  72.             if ctype is None or encoding is not None:
  73.                 # No guess could be made so use a binary type.
  74.                 ctype = 'application/octet-stream'
  75.             maintype, subtype = ctype.split('/', 1)
  76.             if maintype == 'text':
  77.                 fp = open(fname)
  78.                 attach = MIMEText(fp.read(), _subtype=subtype)
  79.                 fp.close()
  80.             elif maintype == 'image':
  81.                 fp = open(fname, 'rb')
  82.                 attach = MIMEImage(fp.read(), _subtype=subtype)
  83.                 fp.close()
  84.             elif maintype == 'audio':
  85.                 fp = open(fname, 'rb')
  86.                 attach = MIMEAudio(fp.read(), _subtype=subtype)
  87.                 fp.close()
  88.             else:
  89.                 fp = open(fname, 'rb')
  90.                 attach = MIMEBase(maintype, subtype)
  91.                 attach.set_payload(fp.read())
  92.                 fp.close()
  93.                 # Encode the payload using Base64
  94.                 encoders.encode_base64(attach)
  95.             # Set the filename parameter
  96.             if attachname is None:
  97.                 filename = os.path.basename(fname)
  98.             else:
  99.                 filename = attachname
  100.             attach.add_header('Content-Disposition', 'attachment', filename=filename)
  101.             msg.attach(attach)
  102.         # Some header stuff
  103.         msg['Subject'] = self._subject
  104.         msg['From'] = self._from
  105.         msg['To'] = ", ".join(self._to)
  106.         msg['Cc'] = ", ".join(self._cc)
  107.         msg.preamble = "You need a MIME enabled mail reader to see this message"
  108.         # Send message
  109.         msg = msg.as_string()
  110.         server = smtplib.SMTP(self._smtpServer)
  111.         server.sendmail(self._from, self._to + self._cc + self._bcc, msg)
  112.         server.quit()
  113.    
  114.     def setSubject(self, subject):
  115.         """
  116.        Set the subject of the email message.
  117.        """
  118.         self._subject = subject
  119.    
  120.     def setFrom(self, address):
  121.         """
  122.        Set the email sender.
  123.        """
  124.         if not self.validateEmailAddress(address):
  125.             raise Exception("Invalid email address '%s'" % address)
  126.         self._from = address
  127.    
  128.     def clearRecipients(self):
  129.         """
  130.        Remove all currently defined recipients for
  131.        the email message.
  132.        """
  133.         self._to = []
  134.         self._cc = []
  135.         self._bcc = []
  136.    
  137.     def addRecipient(self, address):
  138.         """
  139.        Add a new recipient to the email message.
  140.        """
  141.         if not self.validateEmailAddress(address):
  142.             raise Exception("Invalid email address '%s'" % address)
  143.         self._to.append(address)
  144.  
  145.     def addCC(self, address):
  146.         """
  147.        Add a new carbon copy recipient to the email message.
  148.        """
  149.         if not self.validateEmailAddress(address):
  150.             raise Exception("Invalid cc email address '%s'" % address)
  151.         self._cc.append(address)
  152.  
  153.     def addBCC(self, address):
  154.         """
  155.        Add a new blind carbon copy recipient to the email message.
  156.        """
  157.         if not self.validateEmailAddress(address):
  158.             raise Exception("Invalid bcc email address '%s'" % address)
  159.         self._bcc.append(address)
  160.  
  161.     def setTextBody(self, body):
  162.         """
  163.        Set the plain text body of the email message.
  164.        """
  165.         self._textBody = body
  166.    
  167.     def setHtmlBody(self, body):
  168.         """
  169.        Set the HTML portion of the email message.
  170.        """
  171.         self._htmlBody = body
  172.    
  173.     def clearAttachments(self):
  174.         """
  175.        Remove all file attachments.
  176.        """
  177.         self._attach = []
  178.    
  179.     def addAttachment(self, fname, attachname=None):
  180.         """
  181.        Add a file attachment to this email message.
  182.  
  183.        @param fname: The full path and file name of the file
  184.                      to attach.
  185.        @type fname: String
  186.        @param attachname: This will be the name of the file in
  187.                           the email message if set.  If not set
  188.                           then the filename will be taken from
  189.                           the fname parameter above.
  190.        @type attachname: String
  191.        """
  192.         if fname is None:
  193.             return
  194.         self._attach.append( (fname, attachname) )
  195.    
  196.     def validateEmailAddress(self, address):
  197.         """
  198.        Validate the specified email address.
  199.        
  200.        @return: True if valid, False otherwise
  201.        @rtype: Boolean
  202.        """
  203.         if self._reEmail.search(address) is None:
  204.             return False
  205.         return True
  206.    
  207. if __name__ == "__main__":
  208.     # Run some tests
  209.     m.setFrom('[email protected]')
  210.     m.addRecipient(employee2@test.com)
  211.     m.addRecipient(employee3@test.com)
  212.     m.addCC("[email protected]")
  213.     m.addBCC("[email protected]")
  214.    
  215.     m.setSubject("Text and HTML Message with CC and BCC")
  216.     m.setTextBody("You should not see this text in a MIME aware reader")
  217.     m.setHtmlBody("The following should be <b>bold</b>.")
  218.     m.addAttachment('/tmp/temp.png')
  219.     m.send()
Advertisement
Add Comment
Please, Sign In to add comment