Exemple #1
0
 def compose(self, to_addrs=[], from_addr='', subject='', message='', cc_addrs=[], 
             bcc_addrs=[], content_type='text/plain', attachments=[]):
     
     self.subject = subject
     self.to_addrs = to_addrs
     self.from_addr = from_addr
     
     if not attachments and content_type == 'text/plain':
         msg = MIMEText(message)
     else:
         msg = MIMEMultipart()
     
     # should be refactored
     msg['To'] = ','.join(to_addrs)
     msg['From'] = from_addr
     if cc_addrs:
         msg['Cc'] = ','.join(cc_addrs)
     msg['Subject'] = subject
     msg['Date'] = Utils.formatdate(localtime=1)
     msg['Message-ID'] = Utils.make_msgid()
     
     if content_type != 'text/plain':
         body = MIMEMultipart('alternative')
         body.attach(genpart(message, content_type))
         msg.attach(body)
     
     for a in attachments:
         msg.attach(attachment(a))
     
     self.msg = msg.as_string()
Exemple #2
0
def sendMail(subject, text, *attachmentFilePaths):
    gmailUser = '******'
    gmailPassword = '******'
    recipient = '*****@*****.**'

    #    msg = MIMEMultipart()
    msg = MIMEText(text)
    msg['From'] = gmailUser
    msg['To'] = recipient
    msg['Subject'] = subject
    msg['In-Reply-To'] = "<*****@*****.**>"
    #    msg.attach(MIMEText(text))

    for attachmentFilePath in attachmentFilePaths:
        msg.attach(getAttachment(attachmentFilePath))

    mailServer = smtplib.SMTP('smtp.gmail.com', 587)
    mailServer.ehlo()
    mailServer.starttls()
    mailServer.ehlo()
    mailServer.login(gmailUser, gmailPassword)
    mailServer.sendmail(gmailUser, recipient, msg.as_string())
    mailServer.close()

    print('Sent email to % s' % recipient)
Exemple #3
0
def send_mail(recipients, sender, subject, text, reply_to=None, files=[], server="localhost"):
	import smtplib
	from email.header import Header
	from email.MIMEMultipart import MIMEMultipart
	from email.MIMEBase import MIMEBase
	from email.MIMEText import MIMEText
	from email.Utils import COMMASPACE, formatdate
	from email import Encoders
	if type(recipients) != list:
		raise UsageError("recipients must be a list")
	if type(files) != list:
		raise UsageError("files must be a list")
	msg = MIMEText(text.encode('utf-8'), 'plain', 'utf-8')
	msg['From'] = sender
	msg['To'] = COMMASPACE.join(recipients)
	msg['Date'] = formatdate(localtime=True)
	msg['Subject'] = Header(subject, 'utf-8')
	if reply_to:
		msg.add_header('reply-to', reply_to)
	for f in files:
		part = MIMEBase('application', "octet-stream")
		part.set_payload(open(f,"rb").read())
		Encoders.encode_base64(part)
		part.add_header('Content-Disposition', 'attachment; filename="%s"' %(os.path.basename(f)))
		msg.attach(part)
	smtp = smtplib.SMTP(server)
	smtp.sendmail(sender, recipients, msg.as_string() )
	smtp.close()
Exemple #4
0
def sendMail(subject, text, *attachmentFilePaths):
    gmailUser = '******'
    gmailPassword = '******'
    recipient = '*****@*****.**'

#    msg = MIMEMultipart()
    msg = MIMEText(text)
    msg['From'] = gmailUser
    msg['To'] = recipient
    msg['Subject'] = subject
    msg['In-Reply-To'] = "<*****@*****.**>"
#    msg.attach(MIMEText(text))

    for attachmentFilePath in attachmentFilePaths:
        msg.attach(getAttachment(attachmentFilePath))

    mailServer = smtplib.SMTP('smtp.gmail.com', 587)
    mailServer.ehlo()
    mailServer.starttls()
    mailServer.ehlo()
    mailServer.login(gmailUser, gmailPassword)
    mailServer.sendmail(gmailUser, recipient, msg.as_string())
    mailServer.close()

    print('Sent email to % s' % recipient)
Exemple #5
0
 def send(self,host,subject,message,fromEmail,recipients,attPath=None,attName='attachment_1.txt'):
     """
     Email on a failed crawler. Sender should not be internal for outlook purposes.
     
     *Required Parameters*
     :param host: email host
     :param subject: email subject
     :param message: email 'message' or body
     :param fromEmail: email address to send from
     :param recipients: recipients of the email
     
     *Optional Parameters*
     :param attPath: the path of any attachment (either a string or list --to discourage excessive attachments)
     :param attName: the name of any attachment (either a string or list --to discourage excessive attachments)
     """
     print "Sending Alert Message"
     
     #prep
     body=MIMEMultipart('alternative')
     body.attach(MIMEText(subject))
     msg=MIMEText(message)
     
     msg=MIMEMultipart()
     msg.attach(body)
     msg['From']=fromEmail
     msg['To']=recipients
     msg['Subject']=subject
     
     if attPath is not None:
         attPaths=[]
         attNames=[]
         if type(attPath) is str:
             attPaths.append(attPath)
             attNames.append(attName)
         else:
             for i in range(len(attPath)):
                 attPaths.append(attPath[i])
                 attNames.append(attName[i])
             
         for i in range(len(attPaths)):
             with open(attPaths[i],'r') as fp:
                 part=MIMEBase('application',"octet-stream")
                 
                 part.set_payload(fp.read())
                 Encoders.encode_base64(part)
                 part.add_header('Content-Disposition','attachment',filename=attNames[i])
                 
                 #attach
                 msg.attach(part)
     
     #send
     mailobj=smtplib.SMTP(host)
     print "Recipients "+str(recipients.split(","))
     mailobj.sendmail(fromEmail,recipients.split(","),msg.as_string())
     mailobj.quit()
     print "Mail Sent"
Exemple #6
0
 def smtp(self, sender, recipients='', subject="", msg="",
          fmt="", attatchment=None):
     mail = MIMEText() if not fmt else MIMEMultipart('alternative')
     mail['From'] = sender
     mail['To'] = ', '.join(recipients)
     mail['Subject'] = subject
     if not fmt:
         mail.attach(MIMEText(msg, 'plain'))
     else:
         mail.attach(MIMEText(msg, 'html'))
     return self.server.sendmail(sender, recipients, mail.as_string())
def send_mail(recipient, subject, body, attachments="", encoding='utf-8'):
    session = None
    if attachments == "":
        msg = MIMEText(body, 'plain', encoding)
        msg['Subject'] = Header(subject, encoding)
        msg['From'] = Header(u'"{0}" <{1}>'.format(SENDER_NAME, SENDER_EMAIL), encoding)
        msg['To'] = recipient
        msg['Date'] = formatdate()
    else:
        msg = MIMEMultipart()
        msg['Subject'] = Header(subject, encoding)
        msg['From'] = Header(u'"{0}" <{1}>'.format(SENDER_NAME, SENDER_EMAIL), encoding)
        msg['To'] = recipient
        msg['Date'] = formatdate()

        # This is the textual part:
        part = MIMEText(body)
        msg.attach(part)

        # That is what u see if dont have an email reader:
        msg.preamble = 'Multipart massage.\n'

        attachment_list = attachments.split(",")
        # Loop and print each city name.
        for attachment in attachment_list:
            print "attach file: ", attachment
            # This is the binary part(The Attachment):
            part = MIMEApplication(open(attachment,"rb").read())
            part.add_header('Content-Disposition', 'attachment', filename=attachment+".txt")
            msg.attach(part)

    try:
        if SMTP_SSL_TYPE == 'SMTP_SSL':
            session = smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT)
        else:
            session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
            if SMTP_SSL_TYPE == 'SMTP_TLS':
                session.ehlo()
                session.starttls()
                session.ehlo()
        session.login(SMTP_USERNAME, SMTP_PASSWORD)
        session.sendmail(SENDER_EMAIL, recipient, msg.as_string())
    except Exception as e:
        raise e
    finally:
        # close session
        if session:
            session.quit()
    def makeMessage(self):
        # It's the caller's responsibility to either encode the address fields
        # to ASCII strings or pass in Unicode strings.

        # Using the maxlinelen for the Headers as we have paranoid checks to
        # make sure that we have no carriage returns in the to or from email
        # addresses.  We use nice email addresses like 'Launchpad Community
        # Help Rotation team <*****@*****.**>' that
        # get broken over two lines in the header.  RFC 5322 specified that
        # the lines MUST be no more than 998, so we use that as our maximum.
        from_addr = Header(self.from_addr, maxlinelen=998).encode()
        to_addrs = [
            Header(address, maxlinelen=998).encode()
            for address in list(self.to_addrs)
        ]

        for address in [from_addr] + to_addrs:
            if not isinstance(address, str) or not is_ascii_only(address):
                raise AssertionError('Expected an ASCII str object, got: %r' %
                                     address)

        do_paranoid_email_content_validation(from_addr=from_addr,
                                             to_addrs=to_addrs,
                                             subject=self.subject,
                                             body=self.body)
        if len(self.attachments) == 0:
            msg = MIMEText(self.body.encode('utf-8'), 'plain', 'utf-8')
        else:
            msg = MIMEMultipart()
            body_part = MIMEText(self.body.encode('utf-8'), 'plain', 'utf-8')
            msg.attach(body_part)
            for attachment in self.attachments:
                msg.attach(attachment)

        # The header_body_values may be a list or tuple of values, so we will
        # add a header once for each value provided for that header.
        # (X-Launchpad-Bug, for example, may often be set more than once for a
        # bugmail.)
        for header, header_body_values in self.headers.items():
            if not zisinstance(header_body_values, (list, tuple)):
                header_body_values = [header_body_values]
            for header_body_value in header_body_values:
                msg[header] = header_body_value
        msg['To'] = ','.join(to_addrs)
        msg['From'] = from_addr
        msg['Subject'] = self.subject
        return msg
    def makeMessage(self):
        # It's the caller's responsibility to either encode the address fields
        # to ASCII strings or pass in Unicode strings.

        # Using the maxlinelen for the Headers as we have paranoid checks to
        # make sure that we have no carriage returns in the to or from email
        # addresses.  We use nice email addresses like 'Launchpad Community
        # Help Rotation team <*****@*****.**>' that
        # get broken over two lines in the header.  RFC 5322 specified that
        # the lines MUST be no more than 998, so we use that as our maximum.
        from_addr = Header(self.from_addr, maxlinelen=998).encode()
        to_addrs = [Header(address, maxlinelen=998).encode()
            for address in list(self.to_addrs)]

        for address in [from_addr] + to_addrs:
            if not isinstance(address, str) or not is_ascii_only(address):
                raise AssertionError(
                    'Expected an ASCII str object, got: %r' % address)

        do_paranoid_email_content_validation(
            from_addr=from_addr, to_addrs=to_addrs,
            subject=self.subject, body=self.body)
        if len(self.attachments) == 0:
            msg = MIMEText(self.body.encode('utf-8'), 'plain', 'utf-8')
        else:
            msg = MIMEMultipart()
            body_part = MIMEText(self.body.encode('utf-8'), 'plain', 'utf-8')
            msg.attach(body_part)
            for attachment in self.attachments:
                msg.attach(attachment)

        # The header_body_values may be a list or tuple of values, so we will
        # add a header once for each value provided for that header.
        # (X-Launchpad-Bug, for example, may often be set more than once for a
        # bugmail.)
        for header, header_body_values in self.headers.items():
            if not zisinstance(header_body_values, (list, tuple)):
                header_body_values = [header_body_values]
            for header_body_value in header_body_values:
                msg[header] = header_body_value
        msg['To'] = ','.join(to_addrs)
        msg['From'] = from_addr
        msg['Subject'] = self.subject
        return msg
 def emailOnFail(self,logfp):
     """
     Email on a failed crawler. Sender should not be internal for outlook purposes.
     
     *Required Parameter*
     
     :param logfp: log file path
     """
     print "Sending Alert Message"
     
     cfp=Config(self.__fpath)
     
     #get log as attachment
     att=""
     with open(logfp,'r') as fp:
         att=fp.read()
     
     #prep
     body=MIMEMultipart('alternative')
     body.attach(MIMEText("PARSER - Premature Detonation!!! Failed or Terminated Parser: "+os.path.join(self.__logbase,self.__execute)))
     msg=MIMEText("The Parser "+os.path.join(self.__logbase,self.__execute)+" Failed")
     
     msg=MIMEMultipart()
     msg.attach(body)
     msg['From']=cfp.getVar("mail","sender","string")
     msg['To']=cfp.getVar("mail","recipients","string")
     msg['Subject']="Failed CACRIM Parser"
     part=MIMEBase('application',"octet-stream")
     part.set_payload(att)
     Encoders.encode_base64(part)
     part.add_header('Content-Disposition','attachment',filename="faillog.txt")
     
     #attach
     msg.attach(part)
     
     #send
     mailobj=smtplib.SMTP(cfp.getVar("mail","host","string"))
     mailobj.sendmail(cfp.getVar("mail", "sender","string"),[cfp.getVar("mail","recipients","string").split(",")],msg.as_string())
     mailobj.quit()
     print "Mail Sent"
Exemple #11
0
def advancedSendMail( send_from, send_to, subject, text, html, cc_to = [], files = [], server = "192.168.42.13" ):
    assert type( send_to ) == list
    assert type( files ) == list

    if not text and not html:
        raise "No content to send!"
    elif text and not html :
        msg = MIMEText( text, "plain" )
    elif not text and html:
        msg = MIMEText( html, "html", "utf-8" )
    else:
        msg = MIMEMultipart( "alternative" )
        msg.attach( MIMEText( text, "plain" ) )
        msg.attach( MIMEText( html, "html" ) )

    msg.set_charset( "utf-8" )
    if len( files ) > 0 :
        tmpmsg = msg
        msg = MIMEMultipart()
        msg.attach( tmpmsg )

    msg['From'] = send_from
    msg['To'] = COMMASPACE.join( send_to )

    if cc_to:
        assert type( cc_to ) == list
        msg['cc'] = COMMASPACE.join( cc_to )
        send_to.extend( cc_to )

    msg['Date'] = formatdate( localtime = True )
    msg['Subject'] = subject

    for f in files:
        part = MIMEBase( 'application', "octet-stream" )
        if isinstance( f, basestring ):
            part.set_payload( open( f, "rb" ).read() )
            Encoders.encode_base64( part )
            part.add_header( 'Content-Disposition', 'attachment; filename="%s"' % Header( os.path.basename( f ), 'utf-8' ) )
        elif hasattr( f, "file_path" ) and hasattr( f, "file_name" ):
            part.set_payload( open( f.file_path, "rb" ).read() )
            Encoders.encode_base64( part )
            part.add_header( 'Content-Disposition', 'attachment; filename="%s"' % Header( f.file_name, 'utf-8' ) )
        msg.attach( part )

    smtp = smtplib.SMTP( server )
    smtp.sendmail( send_from, send_to, msg.as_string() )
    smtp.close()
Exemple #12
0
def sendmail(fr, to, subject, body, server=None, htmlbody=None):
    '''
    sending an email, basically
    
    todo: use email class (import email) to handle non-english characters and punctuation...
    '''
    if server is None:
        server = smtplib.SMTP('smtp.webfaction.com')
        server.login('giv_updates', 'whatwouldschneierdo')
    subject.replace('\n', '')
    msg = None
    if htmlbody is None:
        msg = MIMEText(body)
    else:
        msg = MIMEMultipart('alternative')
        part1 = MIMEText(body, 'plain')
        part2 = MIMEText(htmlbody, 'html')
        msg.attach(part1)
        msg.attach(part2)
    msg['Subject'] = subject
    msg['From'] = fr
    msg['To'] = to
    server.sendmail(fr, to, msg.as_string())
    return server
Exemple #13
0
    def sendEmail(self, server):
        ''' sendEmail(host_server):
        This module is a simple interface to send emails (with attachments) using the gmail or cern SMTP servers. When calling the module the only thing that needs 
        to be specified is which server is to be used (cern or gmail). Just follow the prompt commands once launched. The "smtplib" is a low-level package interface 
        for the Simple Mail Transfer Protocol (SMTP) protocol. The "email" package assists with parsing (analyzing a sentence into its parts and describe their 
        syntactic roles) and  generating emails.
        '''

        # Import modules here
        import traceback
        import email
        from smtplib import SMTP
        from email.MIMEText import MIMEText
        from email.MIMEMultipart import MIMEMultipart
        from email.MIMEBase import MIMEBase
        from email import encoders
        import mimetypes
        import sys
        import datetime
        import getpass

        # Define SMTP port to use and decide which of the two servers to use
        smtpPort = 587  #or 25
        if server == "cern":
            smtpHost = "smtp.cern.ch"
            emailAddress = "@cern.ch"
            smtpUsername = "******"
        elif server == "gmail":
            smtpHost = "smtp.gmail.com"
            emailAddress = "@gmail.com"
            smtpUsername = "******"
        else:
            self.Cout(
                'ERROR! The server argument %s is invalid. Please select between "cern" and "gmail". Exiting python shell.'
            )
            print __doc__
            sys.exit(1)

        # Get SMTP authorisation details
        self.Cout("Please provide your login credentials for %s to continue:" %
                  (smtpUsername))
        sender = smtpUsername
        smtpPassword = getpass.getpass("\tPassword = "******"Attempting to connect to:\n\thost = %s\n\tport = %s" %
                  (smtpHost, smtpPort))
        connection = SMTP(host=smtpHost, port=smtpPort)
        connection.set_debuglevel(False)  #True
        if smtpUsername is not False:
            connection.ehlo()
            if smtpPort != 25:
                connection.starttls()
                connection.ehlo()
                if smtpUsername and smtpPassword:
                    connection.login(smtpUsername, smtpPassword)
                    self.Cout(
                        "Succesfully logged on to:\n\tusername = %s\n\tpassword = %s"
                        % (smtpUsername, self.obscureString(smtpPassword)))
                else:
                    self.Cout(
                        "Unsuccesfull login. False credentials provided:\n\tusername = %s\n\tpassword = %s"
                        % (smtpUsername, self.obscureString(smtpPassword)))
                    print __doc__
                    sys.exit(1)

        # Get user input regarding email details
        self.Cout("Please provide the email details:")
        recipients = raw_input("\tTo: ")
        Cc = raw_input("\tCc: ")
        Bcc = raw_input("\tBcc (self excluded): ")
        subject = raw_input("\tSubject: ")
        content = raw_input("\tContent: ")
        attachment = raw_input("\tAttachment: ")
        if attachment == "":
            self.Cout("Nothing to attach.")
            bAttach = False
        else:
            self.Cout("Attachment file:\n\t%s" % (attachment))
            bAttach = True

        # Define return value as success == 0,  failure == 1
        returnValue = 1
        # Take care of recipient lists
        if not (hasattr(recipients, "__iter__")):
            recipients = [recipients]
        if not (hasattr(Cc, "__iter__")):
            Cc = [Cc]
        if not (hasattr(Bcc, "__iter__")):
            Bcc = [Bcc]
            Bcc.append(smtpUsername)

        # Define message details, including attachments
        try:
            if bAttach == False:
                text_subtype = 'plain'
                mainMsg = MIMEText(content, text_subtype)
            else:
                mainMsg = MIMEMultipart()
                # Guess the type of a file based on its filename or URL, given by url.
                ctype, encoding = mimetypes.guess_type(attachment)
                print "ctype, encoding = %s, %s" % (ctype, encoding)
                maintype, subtype = ctype.split("/", 1)
                print "maintype, subtype = %s, %s" % (maintype, subtype)

            # The following do not depend on attachment
            mainMsg[
                'From'] = sender  # Some SMTP servers will do this automatically, but not all
            mainMsg['To'] = ", ".join(recipients)
            mainMsg['cc'] = ", ".join(Cc)
            mainMsg['Bcc'] = ", ".join(Bcc)
            mainMsg['Subject'] = subject

            # Send emails body and attachments
            self.Cout("Sending email to %s" % (recipients))
            try:
                if bAttach:
                    mainMsg.attach(subMsg)
                    fp = open(attachment,
                              "rb")  # open attachment in read/binary mode
                    subMsg = MIMEBase(maintype, subtype)
                    subMsg.set_payload(fp.read())
                    fp.close()
                    encoders.encode_base64(subMsg)
                    subMsg.add_header("Content-Disposition",
                                      "attachment",
                                      filename=attachment)
                    mainMsg.attach(MIMEText(content))
                # Connect to server and send complete email
                connection.sendmail(sender, recipients + Cc + Bcc,
                                    mainMsg.as_string())
                returnValue = 0  # (success)
            except Exception, e:
                self.Cout("Got %s %s.\n\tShowing traceback:\n%s" %
                          (type(e), e, traceback.format_exc()))
                returnValue = 1  # (failure)
                print __doc__
            finally:
                self.Cout("Closing connection.")
                connection.close()
Exemple #14
0
    def send(self):
        """
        de: Sendet die Email an den Empfaenger.
            Wird das Email nur an einen Empfaenger gesendet, dann wird bei
            Erfolg <True> zurueck gegeben. Wird das Email an mehrere Empfaenger
            gesendet und wurde an mindestens einen der Empfaenger erfolgreich
            ausgeliefert, dann wird ebenfalls <True> zurueck gegeben.
            
            Wird das Email nur an einen Empfaenger gesendet, dann wird bei
            Misserfolg <False> zurueck gegeben. Wird das Email an mehrere 
            Empfaenger gesendet und wurde an keinen der Empfaenger erfolgreich
            ausgeliefert, dann wird <False> zurueck gegeben.
        """

        #
        # pruefen ob alle notwendigen Informationen angegeben wurden
        #
        if len(self.from_address.strip()) == 0:
            raise NoFromAddress_Exception
        if self.recipients.count() == 0:
            if (
                (self.cc_recipients.count() == 0) and 
                (self.bcc_recipients.count() == 0)
            ):
                raise NoToAddress_Exception
        if len(self.subject.strip()) == 0:
            raise NoSubject_Exception

        #
        # Email zusammensetzen
        #
        if self.attachments.count() == 0:
            # Nur Text
            msg = MIMEText(
                _text = self.message,
                _subtype = self.content_subtype,
                _charset = self.content_charset
            )
        else:
            # Multipart
            msg = MIMEMultipart()
            if self.message:
                att = MIMEText(
                    _text = self.message,
                    _subtype = self.content_subtype,
                    _charset = self.content_charset
                )
                msg.attach(att)

        # Empfänger, CC, BCC, Absender, User-Agent, Antwort-an 
        # und Betreff hinzufügen
        from_str = formataddr((self.from_caption, self.from_address))
        msg["From"] = from_str
        if self.reply_to_address:
            reply_to_str = formataddr((self.reply_to_caption, self.reply_to_address))
            msg["Reply-To"] = reply_to_str
        if self.recipients.count() > 0:
            msg["To"] = ", ".join(self.recipients.get_list())
        if self.cc_recipients.count() > 0:
            msg["Cc"] = ", ".join(self.cc_recipients.get_list())
        msg["Date"] = formatdate(time.time())
        msg["User-Agent"] = self.user_agent
        try:
            msg["Subject"] = Header(
                self.subject, self.header_charset
            )
        except(UnicodeDecodeError):
            msg["Subject"] = Header(
                self.subject, self.content_charset
            )
        msg.preamble = "You will not see this in a MIME-aware mail reader.\n"
        msg.epilogue = ""

        # Falls MULTIPART --> zusammensetzen
        if self.attachments.count() > 0:
            for filename in self.attachments.get_list():
                # Pruefen ob Datei existiert
                if not os.path.isfile(filename):
                    raise AttachmentNotFound_Exception, filename
                # Datentyp herausfinden
                ctype, encoding = mimetypes.guess_type(filename)
                if ctype is None or encoding is not None:
                    ctype = 'application/octet-stream'
                maintype, subtype = ctype.split('/', 1)
                if maintype == 'text':
                    fp = file(filename)
                    # Note: we should handle calculating the charset
                    att = MIMEText(fp.read(), _subtype=subtype)
                    fp.close()
                elif maintype == 'image':
                    fp = file(filename, 'rb')
                    att = MIMEImage(fp.read(), _subtype=subtype)
                    fp.close()
                elif maintype == 'audio':
                    fp = file(filename, 'rb')
                    att = MIMEAudio(fp.read(), _subtype=subtype)
                    fp.close()
                else:
                    fp = file(filename, 'rb')
                    att = MIMEBase(maintype, subtype)
                    att.set_payload(fp.read())
                    fp.close()
                    # Encode the payload using Base64
                    Encoders.encode_base64(att)
                # Set the filename parameter
                att.add_header(
                    'Content-Disposition', 
                    'attachment', 
                    filename = os.path.split(filename)[1].strip()
                )
                msg.attach(att)

        #
        # Am SMTP-Server anmelden und evt. authentifizieren
        #
        smtp = smtplib.SMTP()
        if self.smtp_server:
            smtp.connect(self.smtp_server)
        else:
            smtp.connect()
        if self.smtp_user:
            smtp.login(user = self.smtp_user, password = self.smtp_password)

        #
        # Email versenden
        #
        self.statusdict = smtp.sendmail(
            from_str, 
            (
                self.recipients.get_list() + 
                self.cc_recipients.get_list() + 
                self.bcc_recipients.get_list()
            ), 
            msg.as_string()
        )
        smtp.close()

        # Rueckmeldung
        return True
Exemple #15
0
class Email(DataType.DataType):
    """
    Basic email representation.
    Based on: http://aspn.activestate.com/ASPN/docs/ActivePython/2.4/python/lib/node597.html
    """
    _name_ = "email"
    def __init__(self, **kwargs):
        DataType.DataType.__init__(self)
        self.attachments = []

        self.email = MIMEText(kwargs.get("content", ""))
        self.email['Subject'] = kwargs.get("subject", "")
        self.email['To'] = kwargs.get("to", "")
        self.email['From'] = kwargs.get("from", "")
        self.email.preamble = ''
        self.email.epilogue = ''

    def has_attachments(self):
        if len(self.attachments) > 0:
            return True
        return False
        
    def add_attachment(self, path):
        #Create a multipart message and each attachment gets a part
        if not self.email.is_multipart():
            newemail = MIMEMultipart()
            newemail['Subject'] = self.email['Subject']
            newemail['To'] = self.email['To']
            newemail['From'] = self.email['From']
            newemail.preamble = 'There are attachments\n'
            newemail.epilogue = ''
            self.email = newemail

        f = File.File(path)
        filename = f.get_filename()
        mt = f.get_mimetype()
        maintype, subtype = mt.split('/', 1)
        if maintype == 'text':
            fp = open(path)
            #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:
            fp = open(path, 'rb')
            msg = MIMEBase('application', 'octet-stream')
            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.email.attach(msg)
        self.attachments.append(path)

    def set_from_email_string(self, text_source):
        self.email = email.message_from_string(text_source)

    def get_email_string(self):
        return self.email.as_string()
    
    def get_subject(self):        
        return self.email['Subject']

    def __getstate__(self):
        data = DataType.DataType.__getstate__(self)
        data['email'] = self.get_email_string()
        return data

    def __setstate__(self, data):
        self.set_from_email_string(data['email'])
        DataType.DataType.__setstate__(self, data)

    def get_hash(self):
        return str(hash( self.get_email_string() ))
Exemple #16
0
def msg_builder():

    #import re
    #from core.data import smtp,fpr,DEBUG
    #from core.func import dbginfo
    # # from email.MIMENonMultipart import MIMENonMultipart
    #from email.MIMEMultipart import MIMEMultipart
    #from email.MIMEText import MIMEText
    #from email.MIMEBase import MIMEBase
    #from email.MIMEImage import MIMEImage
    #from email.mime.application import MIMEApplication

    smtp['mime-type'] = 'multipart'
    #smtp['mime-type'] = 'text'

    # check if some content have been already defined
    #contentKeyLen = []
    #for t in smtp['content'].keys():
    #    print t,len(smtp['content'][t])
    #    contentKeyLen.append(len(smtp['content'][t]))
    contentKeyLen = [len(smtp['content'][t]) for t in smtp['content'].keys()]

    ###     dbginfo('debug', 'type: %s' % contentKeyLen)

    # * * M I M E * * #
    use_mime = 1

    # mime  is used by default evan for simple text message
    # you need to manually specify to not use it and it would be
    # possible only when content is plain text

    # check if more than one types of content were defined
    # 0 - other keys does not contain any value
    # 1 - other keys contain some values
    # 2 - the key does not contain any value

    def checkContValue(d={}, k=''):
        #print d
        #print k
        if len(d[k]):
            #print len(d[k])
            for t in d.keys():
                if t != k and len(d[t]):
                    #print t,k,len(d[t])
                    return 1
            return 0
        else:
            return 2

    def get_binpart(d={}, ctype=''):
        #print d
        if d.get('raw'):
            if ctype == 'image':
                att = MIMEImage(d['raw'])
            else:
                att = MIMEApplication(d['raw'])
            #del att['Content-Type']
            # check if headers are defined
            for kh in d.keys():
                if re.match('^h_(.*)$', kh):
                    #print kh
                    hn = re.match('^h_(.*)$', kh)
                    #att[h.group(1)] = d[kh]
                    # if headers were defined and has some value and
                    # this same header is defined as a default header with MIME
                    # object than remove the default header before adding your own
                    if att[hn.group(1)] and d[kh] != '':
                        #print 'exist=',att[hn.group(1)]
                        #del att[hn.group(1)]
                        att.replace_header(hn.group(1), d[kh])
                    elif d[kh] != '':
                        att.add_header(hn.group(1), d[kh])

        if d.get('b64'):
            att = MIMEBase('application', 'octet-stream')
            for kh in d.keys():
                if re.match('^h_(.*)$', kh):
                    #print kh
                    hn = re.match('^h_(.*)$', kh)
                    if att[hn.group(1)] and d[kh] != '':
                        att.replace_header(hn.group(1), d[kh])

                    elif d[kh] != '':
                        #print 'ddd=',d[kh]
                        att.add_header(hn.group(1), d[kh])
                    att.set_payload("\n".join(d['b64']))
                    #print d['b64']
            #print att
        return att

    if smtp['use_mime'] == 1:
        #######################
        msgdata = MIMEBase

        # smtp dictionary contains different parts of message which are stored under
        # different types like text, html, img, vof, and att which is for binary in
        # most cases attachments

        lsOfNonEmptyContKey = [
            k for k, v in smtp['content'].iteritems() if len(v) > 0
        ]

        if checkContValue(smtp['content'], 'text') == 0:
            msgdata = MIMEText('\n'.join(smtp['content']['text']), 'plain')

        elif checkContValue(smtp['content'], 'html') == 0:
            msgdata = MIMEText('\n'.join(smtp['content']['html']), 'html')

        elif checkContValue(smtp['content'], 'img') == 0:

            #print smtp['content']['img']
            if len(smtp['content']['img']) > 1:
                msgdata = MIMEMultipart()
                for a in smtp['content']['img'].keys():
                    msgdata.attach(get_binpart(smtp['content']['img'][a]))
            else:
                for a in smtp['content']['img'].keys():
                    msgdata = get_binpart(smtp['content']['img'][a], 'image')

#         elif checkContValue(smtp['content'], 'zip')  == 0:
#             if len(smtp['content']['att']) > 1:
#                 msgdata = MIMEMultipart
#             else:
#                 msgdata = MIMEApplication

# if only att were defined as file(raw data) or base64

        elif checkContValue(smtp['content'], 'vof') == 0:
            if len(smtp['content']['vof']) > 1:
                #    msgdata = MIMEMultipart()
                #    for a in smtp['content']['vof'].keys():
                #        msgdata.attach(get_binpart(smtp['content']['vof'][a]))
                fpr('Wrr: It shouldn\'t happened')
            else:
                #msgdata = MIMEApplication
                for a in smtp['content']['vof'].keys():
                    msgdata = get_binpart(smtp['content']['vof'][a])

        elif checkContValue(smtp['content'], 'att') == 0:
            if len(smtp['content']['att']) > 1:
                msgdata = MIMEMultipart()
                for a in smtp['content']['att'].keys():
                    msgdata.attach(get_binpart(smtp['content']['att'][a]))
            else:
                #msgdata = MIMEApplication
                for a in smtp['content']['att'].keys():
                    msgdata = get_binpart(smtp['content']['att'][a])

        # if more then 1 content parts were defined use MIMEMultipart
        elif len(lsOfNonEmptyContKey) > 1:
            ###             dbginfo('debug','lsOfNonEmptyContKey=%s' % lsOfNonEmptyContKey)
            altrn = MIMEBase
            ###             dbginfo('debug','altrn=%s' % str(altrn))
            if 'text' in lsOfNonEmptyContKey and 'html' in lsOfNonEmptyContKey:
                # it can be a multipart/alternative
                fpr('Message has TEXT and HTML parts. ')
                if raw_input(
                        "  Would you like use MIME multipart/alternative [y/N]: > "
                ) in ['y', 'Y']:
                    print
                    fpr('Creating multipart/alternative ')
                    print
                    altrn = MIMEMultipart('alternative')
                    # RFC say use text before html part
                    altrn.attach(
                        MIMEText('\n'.join(smtp['content']['text']), 'plain'))
                    altrn.attach(
                        MIMEText('\n'.join(smtp['content']['html']), 'html'))
                    # this can be a inner part of mimemultipart
                    # - remove text and html key
                    # - include alternative key to mark this operataion
                    lsOfNonEmptyContKey.remove('text')
                    lsOfNonEmptyContKey.remove('html')
                    lsOfNonEmptyContKey.append('multipart/alternative')
            # if user decide to use text and html parts as multipart/alternative AND
            # there is no other parts set msgdata as alternative
            # else use multipart/mixed
            #print altrn
            #print type(altrn)
            #print lsOfNonEmptyContKey
            #print len(lsOfNonEmptyContKey)
            if altrn != MIMEBase and len(lsOfNonEmptyContKey) == 1:
                dbginfo('debug', 'msgdata is altrn which is %s' % str(altrn))
                #print 'msgdata=altrn'
                msgdata = altrn
            else:
                dbginfo('debug', 'msgdata is MIMEMultipart')
                msgdata = MIMEMultipart()
                for k in lsOfNonEmptyContKey:
                    #print k
                    if k == 'multipart/alternative':
                        #print k
                        msgdata.attach(altrn)
                    if k == 'text':
                        msgdata.attach(
                            MIMEText('\n'.join(smtp['content']['text']),
                                     'plain'))
                    if k == 'html':
                        msgdata.attach(
                            MIMEText('\n'.join(smtp['content']['html']),
                                     'html'))
                    if k == 'img':
                        for a in smtp['content']['img'].keys():
                            msgdata.attach(
                                get_binpart(smtp['content']['img'][a]))
                    if k == 'vof':
                        for a in smtp['content']['vof'].keys():
                            msgdata.attach(
                                get_binpart(smtp['content']['vof'][a]))
                    if k == 'att':
                        for a in smtp['content']['att'].keys():
                            #tmp = get_binpart(smtp['content']['att'][a])
                            #msgdata.attach(tmp)
                            msgdata.attach(
                                get_binpart(smtp['content']['att'][a]))

        # HEADERS
        # can not be added header when there is no data and no msgdata type was
        # set to something different than MIMEBase
        # fpr.warn(str(msgdata))
        if msgdata == MIMEBase:
            #if DEBUG:
            #    fpr.warn('No content data was defined !')
            return 0
        #msg['Subject'] = smtp['headers'].get('h_Subject')
        for k in smtp['headers'].keys():
            #dbglog(k) #DEBUG
            if re.match('^h\d*_', k):
                #fpr.warn(k) #DEBUG
                h = re.match('^h\d*_(.*)$', k)
                #fpr.cyan(str(h)) #DEBUG
                #print (k,h.group(1)) #DEBUG
                if smtp['headers'][k] != '':
                    if type(smtp['headers'].get(k)) is str:
                        #fpr.green(smtp[k])
                        msgdata[h.group(1)] = smtp['headers'].get(k)
                    # list is for custom headers
                    if type(smtp['headers'].get(k)) is list:
                        msgdata[h.group(1)] = "\n".join(smtp['headers'].get(k))
                #else:
                #    print ('%s has empty value', k) #DEBUG

    ### NO MIME ###
    else:
        """ No MIME message - ascii plain text message """
        dbginfo('info', 'No MIME message, building as it is ;)')

        #if False:
        #    import email
        #    msgdata = email.message_from_string(smtp['content']['string'])
        #    dbginfo('debug', str(msgdata))
        msgdata = CMessage(smtp['content']['string'])

        #dbginfo('debug', str(msgdata))

    #print msg2
    #return msgdata.as_string()
    return msgdata
Exemple #17
0
def main():
    ''' Email client - can send through specific mail server, add attachment, TLS etc. '''
    # All the options accepted by the script
    usage_line='%prog -f env_from -t env_to -s subject -H smtp-host -F from -T to -r reply -R return-address, -d debug_level -p port_number, -D date, -e helo, -S tls, -a attach, -b body -c certificate -k privatekey'
    p = optparse.OptionParser(description='email client', prog='emailer',
                              version='0.1a', usage=usage_line)
    p.add_option("-f", "--env_from", dest="env_from", action="store", help="envelop from address for MTA")
    p.add_option("-t", "--env_to", dest="env_to", action="store", help="envelop to address for MTA")
    p.add_option("-s", "--subject", dest="subject", action="store", type="string", help="subject")
    p.add_option("-D", "--date", dest="date", action="store", help="date for MUA")
    p.add_option("-H", "--host", dest="host", action="store", help="smtp server hostname")
    p.add_option("-e", "--ehlo", dest="ehlo", action="store", help="helo or helo")
    p.add_option("-p", "--port", dest="port", type="int", action="store", help="smtp port number")
    p.add_option("-F", "--From", dest="From", action="store", help="from address for MUA")
    p.add_option("-T", "--to", dest="to", action="store", help="to address for MUA")
    p.add_option("-r", "--reply", dest="reply", action="store", help="reply address")
    p.add_option("-R", "--Return", dest="Return", action="store", help="Return-to address")
    p.add_option("-S", "--tls", dest="tls", action="store", help="tls - enables TLS")
    p.add_option("-d", "--debug", dest="debug", type="int", action="store", help="debug level")
    p.add_option("-a", "--attach", dest="attach", action="store", help="path to attachment file")
    p.add_option("-b", "--body", dest="body", action="store", help="Text or body of message")
    p.add_option("-C", "--cc", dest="cc", action="store", help="cc")
    p.add_option("-B", "--bcc", dest="bcc", action="store", help="bcc")
    p.add_option("-c", "--cert", dest="cert", action="store", help="cert")
    p.add_option("-k", "--key", dest="key", action="store", help="key")
    p.set_defaults(host="localhost", subject="No subject", debug=0)
    options, arguments = p.parse_args()
    # To do: add validator for all options; feature - secure smtp : user authentication.
    # To do: use idioms - less if..else, make it readable; exception handling; class
    # multithreading (send single email through multiple smtp servers at the same time).
    # To do: bind IP address (source ip); use function generator
    if len(arguments) != 0:
        p.print_help()
        sys.exit(1)
    if not options.env_from and not options.From:
        p.error("From address not given")
        sys.exit(1)
    if not options.env_to and not options.to:
        p.error("To address not given")
        sys.exit(1)
    if not options.body:
        p.error("Email body not given")
        sys.exit(1)
    if options.attach:
        if os.path.isfile(options.attach):
            textfile = options.attach
            fp = open(textfile, 'rb')
            msg = MIMEText(fp.read())
            fp.close()
        else:
            print "Attachment file " + options.attach + " does not exist "
            sys.exit(1)
    if options.env_from:
        fromaddr = options.env_from
    else:
        if options.From:
            fromaddr = options.From
    if options.env_to:
        toaddrs = [options.env_to]
    else:
        if options.to:
            toaddrs = [options.to]
    if options.subject:
        subject = options.subject
    if options.host:
        smtpserver = options.host
    debuglevel = options.debug
    if options.body:
        body = options.body
    if options.date:
        mydate = options.date
    if options.port:
        port = options.port
    if options.From:
        From = options.From
    else:
        if options.env_from:
            From = options.env_from

    if options.to:
        to = [options.to]
    else:
        if options.env_to:
            to = [options.env_to]
    if options.reply:
        reply = options.reply
    if options.Return:
        Return = options.Return
    if options.tls:
        tls = options.tls
    if options.attach:
        attach = options.attach
    if options.ehlo:
        ehlo = options.ehlo
    if options.cc:
        cc = options.cc
    if options.bcc:
        bcc = options.bcc
    if options.cert:
        certfile = options.bcc
    if options.key:
        keyfile = options.bcc
    if not options.attach:
        msg = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s\r\n" % (fromaddr, ", ".join(toaddrs), subject, body))
        print "Message length is " + repr(len(msg))
        server = smtplib.SMTP(smtpserver)
        server.ehlo()
        if debuglevel:
            server.set_debuglevel(debuglevel)
        if options.tls and options.cert and options.key:
            server.starttls(keyfile, certfile)
        elif options.tls:
            server.starttls()
        server.sendmail(fromaddr, toaddrs, msg)
    else:
        msg = MIMEMultipart()
        msg['From'] = From
        msg['To'] = COMMASPACE.join(to)
        if options.cc:
            msg['Cc'] = options.cc
        if options.bcc:
            msg['BCc'] = options.bcc
        if options.reply:
            msg['Reply-to'] = options.reply
        if options.Return:
            msg['Return-path'] = options.Return
        if options.date:
            msg['Date'] = options.date
        else:
            msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject
        msg.attach(MIMEText(body))
        part = MIMEBase('application', "octet-stream")
        part.set_payload(open(attach, "rb").read())
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename = "%s"' % os.path.basename(attach))
        msg.attach(part)
        server = smtplib.SMTP(smtpserver)
        server.ehlo()
        if options.tls:
            server.starttls()
        if debuglevel:
            server.set_debuglevel(debuglevel)
        server.sendmail(fromaddr, toaddrs, msg.as_string())
    server.quit()
Exemple #18
0
    def send(self):
        """
        Send the mail. Returns True if successfully sent to at least one
        recipient.
        """

        # validation
        if len(self.from_address.strip()) == 0:
            raise NoFromAddress_Exception
        if self.recipients.count() == 0:
            if (
                (self.cc_recipients.count() == 0) and
                (self.bcc_recipients.count() == 0)
            ):
                raise NoToAddress_Exception
        if len(self.subject.strip()) == 0:
            raise NoSubject_Exception

        # assemble
        if self.attachments.count() == 0:
            msg = MIMEText(
                _text = self.message,
                _subtype = self.content_subtype,
                _charset = self.content_charset
            )
        else:
            msg = MIMEMultipart()
            if self.message:
                att = MIMEText(
                    _text = self.message,
                    _subtype = self.content_subtype,
                    _charset = self.content_charset
                )
                msg.attach(att)

        # add headers
        from_str = formataddr((self.from_caption, self.from_address))
        msg["From"] = from_str
        if self.reply_to_address:
            reply_to_str = formataddr((self.reply_to_caption, self.reply_to_address))
            msg["Reply-To"] = reply_to_str
        if self.recipients.count() > 0:
            msg["To"] = ", ".join(self.recipients.get_list())
        if self.cc_recipients.count() > 0:
            msg["Cc"] = ", ".join(self.cc_recipients.get_list())
        msg["Date"] = formatdate(time.time())
        msg["User-Agent"] = self.user_agent
        try:
            msg["Subject"] = Header(
                self.subject, self.header_charset
            )
        except(UnicodeDecodeError):
            msg["Subject"] = Header(
                self.subject, self.content_charset
            )
        msg.preamble = "You will not see this in a MIME-aware mail reader.\n"
        msg.epilogue = ""

        # assemble multipart
        if self.attachments.count() > 0:
            for typ, info in self.attachments.get_list():
                if typ == 'file':
                    filename = info
                    if not os.path.isfile(filename):
                        raise AttachmentNotFound_Exception, filename
                    mimetype, encoding = mimetypes.guess_type(filename)
                    if mimetype is None or encoding is not None:
                        mimetype = 'application/octet-stream'
                    if mimetype.startswith('text/'):
                        fp = file(filename)
                    else:
                        fp = file(filename, 'rb')
                    text = fp.read()
                    fp.close()
                else:
                    filename, text, mimetype = info
                maintype, subtype = mimetype.split('/', 1)
                if maintype == 'text':
                    # Note: we should handle calculating the charset
                    att = MIMEText(text, _subtype=subtype)
                elif maintype == 'image':
                    att = MIMEImage(text, _subtype=subtype)
                elif maintype == 'audio':
                    att = MIMEAudio(text, _subtype=subtype)
                else:
                    att = MIMEBase(maintype, subtype)
                    att.set_payload(text)
                    # Encode the payload using Base64
                    Encoders.encode_base64(att)
                # Set the filename parameter
                att.add_header(
                    'Content-Disposition',
                    'attachment',
                    filename = os.path.basename(filename).strip()
                )
                msg.attach(att)

        # connect to server
        smtp = smtplib.SMTP()
        if self.smtp_server:
            smtp.connect(self.smtp_server)
        else:
            smtp.connect()

        # TLS?
        if self.use_tls:
            smtp.ehlo()
            smtp.starttls()
            smtp.ehlo()

        # authenticate
        if self.smtp_user:
            smtp.login(user = self.smtp_user, password = self.smtp_password)

        # send
        self.statusdict = smtp.sendmail(
            from_str,
            (
                self.recipients.get_list() +
                self.cc_recipients.get_list() +
                self.bcc_recipients.get_list()
            ),
            msg.as_string()
        )
        smtp.close()

        return True
Exemple #19
0
class Email(DataType.DataType):
    """
    Basic email representation.
    Based on: http://aspn.activestate.com/ASPN/docs/ActivePython/2.4/python/lib/node597.html
    """
    _name_ = "email"

    def __init__(self, **kwargs):
        DataType.DataType.__init__(self)
        self.attachments = []

        self.email = MIMEText(kwargs.get("content", ""))
        self.email['Subject'] = kwargs.get("subject", "")
        self.email['To'] = kwargs.get("to", "")
        self.email['From'] = kwargs.get("from", "")
        self.email.preamble = ''
        self.email.epilogue = ''

    def has_attachments(self):
        if len(self.attachments) > 0:
            return True
        return False

    def add_attachment(self, path):
        #Create a multipart message and each attachment gets a part
        if not self.email.is_multipart():
            newemail = MIMEMultipart()
            newemail['Subject'] = self.email['Subject']
            newemail['To'] = self.email['To']
            newemail['From'] = self.email['From']
            newemail.preamble = 'There are attachments\n'
            newemail.epilogue = ''
            self.email = newemail

        f = File.File(path)
        filename = f.get_filename()
        mt = f.get_mimetype()
        maintype, subtype = mt.split('/', 1)
        if maintype == 'text':
            fp = open(path)
            #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:
            fp = open(path, 'rb')
            msg = MIMEBase('application', 'octet-stream')
            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.email.attach(msg)
        self.attachments.append(path)

    def set_from_email_string(self, text_source):
        self.email = email.message_from_string(text_source)

    def get_email_string(self):
        return self.email.as_string()

    def get_subject(self):
        return self.email['Subject']

    def __getstate__(self):
        data = DataType.DataType.__getstate__(self)
        data['email'] = self.get_email_string()
        return data

    def __setstate__(self, data):
        self.set_from_email_string(data['email'])
        DataType.DataType.__setstate__(self, data)

    def get_hash(self):
        return str(hash(self.get_email_string()))
Exemple #20
0
    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):
                raise Exception("File '{0}' does not exist.  Not attaching to email.".format(fname))
                continue
            if not os.path.isfile(fname):
                raise Exception("Attachment '{0}' is not a file.  Not attaching to email.".format(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)

        # Complete header
        # This is where To, CC, BCC are differentiated
        msg['Subject'] = self._subject
        msg['From'] = self._from
        msg['To'] = ", ".join(self._to)
        msg['CC'] = ", ".join(self._cc)
        msg['BCC'] = ", ".join(self._bcc)
        if self._replyTo is not None:
            msg['reply-to'] = self._replyTo
        msg.preamble = "You need a MIME enabled mail reader to see this message"
        msg = msg.as_string()
        allRecipients = self._to + self._cc + self._bcc

        # Send message
        try:
            server = smtplib.SMTP(self._smtpServer, self._smtpPort, self._hostname, 5)
            server.set_debuglevel(self._debugLevel)
            server.ehlo()
            if self._username:
                if server.has_extn('STARTTLS'):
                    server.starttls()
                else:
                    server.quit()
                    server = smtplib.SMTP_SSL(self._smtpServer, self._smtpPort, self._hostname)
                    server.set_debuglevel(self._debugLevel)
                server.ehlo()  # re-identify ourselves over secure connection
                server.login(self._username, self._password)

            result = server.sendmail(self._from, allRecipients, msg)
        except Exception, err:
            raise err
Exemple #21
0
def main():
    ''' Email client - can send through specific mail server, add attachment, TLS etc. '''
    # All the options accepted by the script
    usage_line = '%prog -f env_from -t env_to -s subject -H smtp-host -F from -T to -r reply -R return-address, -d debug_level -p port_number, -D date, -e helo, -S tls, -a attach, -b body -c certificate -k privatekey'
    p = optparse.OptionParser(description='email client',
                              prog='emailer',
                              version='0.1a',
                              usage=usage_line)
    p.add_option("-f",
                 "--env_from",
                 dest="env_from",
                 action="store",
                 help="envelop from address for MTA")
    p.add_option("-t",
                 "--env_to",
                 dest="env_to",
                 action="store",
                 help="envelop to address for MTA")
    p.add_option("-s",
                 "--subject",
                 dest="subject",
                 action="store",
                 type="string",
                 help="subject")
    p.add_option("-D",
                 "--date",
                 dest="date",
                 action="store",
                 help="date for MUA")
    p.add_option("-H",
                 "--host",
                 dest="host",
                 action="store",
                 help="smtp server hostname")
    p.add_option("-e",
                 "--ehlo",
                 dest="ehlo",
                 action="store",
                 help="helo or helo")
    p.add_option("-p",
                 "--port",
                 dest="port",
                 type="int",
                 action="store",
                 help="smtp port number")
    p.add_option("-F",
                 "--From",
                 dest="From",
                 action="store",
                 help="from address for MUA")
    p.add_option("-T",
                 "--to",
                 dest="to",
                 action="store",
                 help="to address for MUA")
    p.add_option("-r",
                 "--reply",
                 dest="reply",
                 action="store",
                 help="reply address")
    p.add_option("-R",
                 "--Return",
                 dest="Return",
                 action="store",
                 help="Return-to address")
    p.add_option("-S",
                 "--tls",
                 dest="tls",
                 action="store",
                 help="tls - enables TLS")
    p.add_option("-d",
                 "--debug",
                 dest="debug",
                 type="int",
                 action="store",
                 help="debug level")
    p.add_option("-a",
                 "--attach",
                 dest="attach",
                 action="store",
                 help="path to attachment file")
    p.add_option("-b",
                 "--body",
                 dest="body",
                 action="store",
                 help="Text or body of message")
    p.add_option("-C", "--cc", dest="cc", action="store", help="cc")
    p.add_option("-B", "--bcc", dest="bcc", action="store", help="bcc")
    p.add_option("-c", "--cert", dest="cert", action="store", help="cert")
    p.add_option("-k", "--key", dest="key", action="store", help="key")
    p.set_defaults(host="localhost", subject="No subject", debug=0)
    options, arguments = p.parse_args()
    # To do: add validator for all options; feature - secure smtp : user authentication.
    # To do: use idioms - less if..else, make it readable; exception handling; class
    # multithreading (send single email through multiple smtp servers at the same time).
    # To do: bind IP address (source ip); use function generator
    if len(arguments) != 0:
        p.print_help()
        sys.exit(1)
    if not options.env_from and not options.From:
        p.error("From address not given")
        sys.exit(1)
    if not options.env_to and not options.to:
        p.error("To address not given")
        sys.exit(1)
    if not options.body:
        p.error("Email body not given")
        sys.exit(1)
    if options.attach:
        if os.path.isfile(options.attach):
            textfile = options.attach
            fp = open(textfile, 'rb')
            msg = MIMEText(fp.read())
            fp.close()
        else:
            print "Attachment file " + options.attach + " does not exist "
            sys.exit(1)
    if options.env_from:
        fromaddr = options.env_from
    else:
        if options.From:
            fromaddr = options.From
    if options.env_to:
        toaddrs = [options.env_to]
    else:
        if options.to:
            toaddrs = [options.to]
    if options.subject:
        subject = options.subject
    if options.host:
        smtpserver = options.host
    debuglevel = options.debug
    if options.body:
        body = options.body
    if options.date:
        mydate = options.date
    if options.port:
        port = options.port
    if options.From:
        From = options.From
    else:
        if options.env_from:
            From = options.env_from

    if options.to:
        to = [options.to]
    else:
        if options.env_to:
            to = [options.env_to]
    if options.reply:
        reply = options.reply
    if options.Return:
        Return = options.Return
    if options.tls:
        tls = options.tls
    if options.attach:
        attach = options.attach
    if options.ehlo:
        ehlo = options.ehlo
    if options.cc:
        cc = options.cc
    if options.bcc:
        bcc = options.bcc
    if options.cert:
        certfile = options.bcc
    if options.key:
        keyfile = options.bcc
    if not options.attach:
        msg = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s\r\n" %
               (fromaddr, ", ".join(toaddrs), subject, body))
        print "Message length is " + repr(len(msg))
        server = smtplib.SMTP(smtpserver)
        server.ehlo()
        if debuglevel:
            server.set_debuglevel(debuglevel)
        if options.tls and options.cert and options.key:
            server.starttls(keyfile, certfile)
        elif options.tls:
            server.starttls()
        server.sendmail(fromaddr, toaddrs, msg)
    else:
        msg = MIMEMultipart()
        msg['From'] = From
        msg['To'] = COMMASPACE.join(to)
        if options.cc:
            msg['Cc'] = options.cc
        if options.bcc:
            msg['BCc'] = options.bcc
        if options.reply:
            msg['Reply-to'] = options.reply
        if options.Return:
            msg['Return-path'] = options.Return
        if options.date:
            msg['Date'] = options.date
        else:
            msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject
        msg.attach(MIMEText(body))
        part = MIMEBase('application', "octet-stream")
        part.set_payload(open(attach, "rb").read())
        Encoders.encode_base64(part)
        part.add_header(
            'Content-Disposition',
            'attachment; filename = "%s"' % os.path.basename(attach))
        msg.attach(part)
        server = smtplib.SMTP(smtpserver)
        server.ehlo()
        if options.tls:
            server.starttls()
        if debuglevel:
            server.set_debuglevel(debuglevel)
        server.sendmail(fromaddr, toaddrs, msg.as_string())
    server.quit()
Exemple #22
0
def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=None, reply_to=False,
               attach=None, debug=False, subtype='plain', x_headers=None):

    """Send an email."""
    import smtplib
    from email.MIMEText import MIMEText
    from email.MIMEBase import MIMEBase
    from email.MIMEMultipart import MIMEMultipart
    from email.Header import Header
    from email.Utils import formatdate, COMMASPACE
    from email.Utils import formatdate, COMMASPACE
    from email import Encoders

    if x_headers is None:
        x_headers = {}

    if not ssl:
        ssl = config.get('smtp_ssl', False)

    if not email_from and not config['email_from']:
        raise Exception("No Email sender by default, see config file")

    if not email_cc:
        email_cc = []
    if not email_bcc:
        email_bcc = []

    if not attach:
        try:
            msg = MIMEText(body.encode('utf8') or '',_subtype=subtype,_charset='utf-8')
        except:
            msg = MIMEText(body or '',_subtype=subtype,_charset='utf-8')
    else:
        msg = MIMEMultipart()

    msg['Subject'] = Header(ustr(subject), 'utf-8')
    msg['From'] = email_from
    del msg['Reply-To']
    if reply_to:
        msg['Reply-To'] = reply_to
    else:
        msg['Reply-To'] = msg['From']
    msg['To'] = COMMASPACE.join(email_to)
    if email_cc:
        msg['Cc'] = COMMASPACE.join(email_cc)
    if email_bcc:
        msg['Bcc'] = COMMASPACE.join(email_bcc)
    msg['Date'] = formatdate(localtime=True)

    # Add EKD Tryton Server information
    msg['X-Generated-By'] = 'EKD-Tryton (http://www.tryton.org)'
    msg['X-EKD-Tryton-Server-Host'] = socket.gethostname()
    msg['X-EKD-Tryton-Server-Version'] = release.version

    # Add dynamic X Header
    for key, value in x_headers.items():
        msg['X-EKD-Tryton-%s' % key] = str(value)

    if attach:
        try:
            msg.attach(MIMEText(body.encode('utf8') or '',_subtype=subtype,_charset='utf-8'))
        except:
            msg.attach(MIMEText(body or '', _charset='utf-8', _subtype=subtype) )
        for (fname,fcontent) in attach:
            part = MIMEBase('application', "octet-stream")
            part.set_payload( fcontent )
            Encoders.encode_base64(part)
            part.add_header('Content-Disposition', 'attachment; filename="%s"' % (fname,))
            msg.attach(part)

    class WriteToLogger(object):
        def __init__(self):
            self.logger = netsvc.Logger()

        def write(self, s):
            self.logger.notifyChannel('email_send', netsvc.LOG_DEBUG, s)

    try:
        oldstderr = smtplib.stderr
        s = smtplib.SMTP()

        try:
            # in case of debug, the messages are printed to stderr.
            if debug:
                smtplib.stderr = WriteToLogger()

            s.set_debuglevel(int(bool(debug)))  # 0 or 1

            s.connect(config['smtp_server'], config['smtp_port'])
            if ssl:
                s.ehlo()
                s.starttls()
                s.ehlo()

            if config['smtp_user'] or config['smtp_password']:
                s.login(config['smtp_user'], config['smtp_password'])

            s.sendmail(email_from, 
                       flatten([email_to, email_cc, email_bcc]), 
                       msg.as_string()
                      )

        finally:
            s.quit()
            if debug:
                smtplib.stderr = oldstderr

    except Exception, e:
        netsvc.Logger().notifyChannel('email_send', netsvc.LOG_ERROR, e)
        return False
Exemple #23
0
    def send(self):
        """
        Send the mail. Returns True if successfully sent to at least one
        recipient.
        """

        # validation
        if len(self.from_address.strip()) == 0:
            raise NoFromAddress_Exception
        if self.recipients.count() == 0:
            if ((self.cc_recipients.count() == 0)
                    and (self.bcc_recipients.count() == 0)):
                raise NoToAddress_Exception
        if len(self.subject.strip()) == 0:
            raise NoSubject_Exception

        # assemble
        if self.attachments.count() == 0:
            msg = MIMEText(_text=self.message,
                           _subtype=self.content_subtype,
                           _charset=self.content_charset)
        else:
            msg = MIMEMultipart()
            if self.message:
                att = MIMEText(_text=self.message,
                               _subtype=self.content_subtype,
                               _charset=self.content_charset)
                msg.attach(att)

        # add headers
        from_str = formataddr((self.from_caption, self.from_address))
        msg["From"] = from_str
        if self.reply_to_address:
            reply_to_str = formataddr(
                (self.reply_to_caption, self.reply_to_address))
            msg["Reply-To"] = reply_to_str
        if self.recipients.count() > 0:
            msg["To"] = ", ".join(self.recipients.get_list())
        if self.cc_recipients.count() > 0:
            msg["Cc"] = ", ".join(self.cc_recipients.get_list())
        msg["Date"] = formatdate(time.time())
        msg["User-Agent"] = self.user_agent
        try:
            msg["Subject"] = Header(self.subject, self.header_charset)
        except (UnicodeDecodeError):
            msg["Subject"] = Header(self.subject, self.content_charset)
        msg.preamble = "You will not see this in a MIME-aware mail reader.\n"
        msg.epilogue = ""

        # assemble multipart
        if self.attachments.count() > 0:
            for typ, info in self.attachments.get_list():
                if typ == 'file':
                    filename = info
                    if not os.path.isfile(filename):
                        raise AttachmentNotFound_Exception, filename
                    mimetype, encoding = mimetypes.guess_type(filename)
                    if mimetype is None or encoding is not None:
                        mimetype = 'application/octet-stream'
                    if mimetype.startswith('text/'):
                        fp = file(filename)
                    else:
                        fp = file(filename, 'rb')
                    text = fp.read()
                    fp.close()
                else:
                    filename, text, mimetype = info
                maintype, subtype = mimetype.split('/', 1)
                if maintype == 'text':
                    # Note: we should handle calculating the charset
                    att = MIMEText(text, _subtype=subtype)
                elif maintype == 'image':
                    att = MIMEImage(text, _subtype=subtype)
                elif maintype == 'audio':
                    att = MIMEAudio(text, _subtype=subtype)
                else:
                    att = MIMEBase(maintype, subtype)
                    att.set_payload(text)
                    # Encode the payload using Base64
                    Encoders.encode_base64(att)
                # Set the filename parameter
                att.add_header('Content-Disposition',
                               'attachment',
                               filename=os.path.basename(filename).strip())
                msg.attach(att)

        # connect to server
        smtp = smtplib.SMTP()
        if self.smtp_server:
            smtp.connect(self.smtp_server)
        else:
            smtp.connect()

        # TLS?
        if self.use_tls:
            smtp.ehlo()
            smtp.starttls()
            smtp.ehlo()

        # authenticate
        if self.smtp_user:
            smtp.login(user=self.smtp_user, password=self.smtp_password)

        # send
        self.statusdict = smtp.sendmail(
            from_str,
            (self.recipients.get_list() + self.cc_recipients.get_list() +
             self.bcc_recipients.get_list()), msg.as_string())
        smtp.close()

        return True
Exemple #24
0
def buildEmailMessage(from_url, to_url, msg=None,
                      subject=None, attachment_list=None,
                      extra_headers=None,
                      additional_headers=None,
                      cc_url=None, bcc_url=None):
  """
    Builds a mail message which is ready to be
    sent by Zope MailHost.

    * attachment_list is a list of dictionaries with those keys:
     - name : name of the attachment,
     - content: data of the attachment
     - mime_type: mime-type corresponding to the attachment
    * extra_headers is a dictionary of custom headers to add to the email.
      "X-" prefix is automatically added to those headers.
    * additional_headers is similar to extra_headers, but no prefix is added.
  """

  if attachment_list == None:
    # Create non multi-part MIME message.
    message = MIMEText(msg, _charset='utf-8')
    attachment_list = []
  else:
    # Create multi-part MIME message.
    message = MIMEMultipart()
    message.preamble = "If you can read this, your mailreader\n" \
                        "can not handle multi-part messages!\n"
    message.attach(MIMEText(msg, _charset='utf-8'))

  if extra_headers:
    for key, value in extra_headers.items():
      message.add_header('X-%s' % key, value)

  if additional_headers:
    for key, value in additional_headers.items():
      message.add_header(key, value)

  if subject:
    message.add_header('Subject',
                        make_header([(subject, 'utf-8')]).encode())
  if from_url:
    message.add_header('From', from_url)
  if to_url:
    message.add_header('To', to_url)
  if cc_url: 
    message.add_header('Cc', cc_url)
  if bcc_url: 
    message.add_header('Bcc', bcc_url)

  for attachment in attachment_list:
    attachment_name = attachment.get('name', '')
    attachment_name = attachment_name or '' # Prevent None params

    # try to guess the mime type
    if not attachment.has_key('mime_type'):
      mime_type, encoding = guess_type( attachment_name )
      if mime_type is not None:
        attachment['mime_type'] = mime_type
      else:
        attachment['mime_type'] = 'application/octet-stream'

    # attach it
    if attachment['mime_type'] == 'text/plain':
      part = MIMEText(attachment['content'], _charset='utf-8')
    else:
      major, minor = attachment['mime_type'].split('/', 1)
      if major == 'text':
        part = MIMEText(attachment['content'], _subtype=minor)
      elif major == 'image':
        part = MIMEImage(attachment['content'], _subtype=minor)
      elif major == 'audio':
        part = MIMEAudio(attachment['content'], _subtype=minor)
      else:
        #  encode non-plaintext attachment in base64      
        part = MIMEBase(major, minor)
        part.set_payload(attachment['content'])
        Encoders.encode_base64(part)

    part.add_header('Content-Disposition', 'attachment',
                    filename=attachment_name)
    part.add_header('Content-ID', '<%s>' % \
                    ''.join(['%s' % ord(i) for i in attachment_name]))
    message.attach(part)

  return message
Exemple #25
0
    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):
                raise Exception(
                    "File '{0}' does not exist.  Not attaching to email.".
                    format(fname))
                continue
            if not os.path.isfile(fname):
                raise Exception(
                    "Attachment '{0}' is not a file.  Not attaching to email.".
                    format(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)

        # Complete header
        # This is where To, CC, BCC are differentiated
        msg['Subject'] = self._subject
        msg['From'] = self._from
        msg['To'] = ", ".join(self._to)
        msg['CC'] = ", ".join(self._cc)
        msg['BCC'] = ", ".join(self._bcc)
        if self._replyTo is not None:
            msg['reply-to'] = self._replyTo
        msg.preamble = "You need a MIME enabled mail reader to see this message"
        msg = msg.as_string()
        allRecipients = self._to + self._cc + self._bcc

        # Send message
        try:
            server = smtplib.SMTP(self._smtpServer, self._smtpPort,
                                  self._hostname, 5)
            server.set_debuglevel(self._debugLevel)
            server.ehlo()
            if self._username:
                if server.has_extn('STARTTLS'):
                    server.starttls()
                else:
                    server.quit()
                    server = smtplib.SMTP_SSL(self._smtpServer, self._smtpPort,
                                              self._hostname)
                    server.set_debuglevel(self._debugLevel)
                server.ehlo()  # re-identify ourselves over secure connection
                server.login(self._username, self._password)

            result = server.sendmail(self._from, allRecipients, msg)
        except Exception, err:
            raise err
Exemple #26
0
    def send(self):
        """
        Send the email message represented by this object.
        """
        # Validate message
        if self._text_body is None and self._html_body 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._text_body is not None and self._html_body is None:
            msg = MIMEText(self._text_body, "plain")
        elif self._text_body is None and self._html_body is not None:
            msg = MIMEText(self._html_body, "html")
        else:
            msg = MIMEMultipart("alternative")
            msg.attach(MIMEText(self._text_body, "plain"))
            msg.attach(MIMEText(self._html_body, "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)
        if self._reply_to:
            msg['Reply-To'] = self._reply_to
        if len(self._cc) > 0:
            msg['Cc'] = ", ".join(self._cc)
        if len(self._bcc) > 0:
            msg['Bcc'] = ", ".join(self._bcc)
        msg.preamble = "You need a MIME enabled mail reader to see this message"
        # Send message
        msg = msg.as_string()
        server = None
        if self._smtp_ssl:
            server = smtplib.SMTP_SSL(host=self._smtp_server,
                port=self._smtp_port)
        else:
            server = smtplib.SMTP(host=self._smtp_server, port=self._smtp_port)
        if self._smtp_user:
            server.login(self._smtp_user, self._smtp_password)
        server.sendmail(self._from, self._to, msg)
        server.quit()