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()
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)
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()
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"
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"
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()
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
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()
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
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() ))
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
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()
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
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()))
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
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()
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
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
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
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
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()