for Python 2.x
#!/usr/bin/env python # -*- coding: utf-8 -*- class ConfigFile: def __init__(self): from os.path import expanduser home = expanduser('~') self.rcfile = '%s/.mailfilerc' % home self.loadConfigFile() def initConfigFile(self): c = '''[mail] from=xxx@@xxx.com to=xxx@@xxx.com [smtp] host=smtp.xxx.com port=25 user=xxx passwd=xxx ''' f = open(self.rcfile, 'w') f.write(c) f.close() def loadConfigFile(self): import ConfigParser from os.path import exists if exists(self.rcfile): cf = ConfigParser.ConfigParser() cf.read(self.rcfile) self.host = cf.get('smtp', 'host') self.port = cf.getint('smtp', 'port') self.user = cf.get('smtp', 'user') self.passwd = cf.get('smtp', 'passwd') self.FROM = cf.get('mail','from') self.TO = cf.get('mail','to') else: self.initConfigFile() print ('** Please edit the config file %s !!!' % self.rcfile) def sendmail(host, port, user, passwd, FILE): import email, smtplib, base64, sys from os.path import getsize from os import remove from decimal import Decimal as dec fp1=open(FILE) msg = email.message_from_file(fp1) fp1.close() FROM = email.utils.parseaddr(msg.get('from'))[1] TO = email.utils.parseaddr(msg.get('to'))[1] h = email.Header.Header(msg.get('subject')) SUBJECT = email.Header.decode_header(h)[0][0] print (('Connecting SMTP server %s ...') % host) smtp=smtplib.SMTP(host, port) #smtp.set_debuglevel(1) smtp.docmd('EHLO server') smtp.docmd('AUTH LOGIN') smtp.send(base64.b64encode(user)+'\r\n') smtp.getreply() smtp.send(base64.b64encode(passwd)+'\r\n') smtp.getreply() print('Logined') smtp.docmd('MAIL FROM:<%s>' % FROM) smtp.docmd('RCPT TO:<%s>' % TO) smtp.docmd('DATA') print('begin send data...') BUFSIZE=2048 f=open(FILE,'rb') fileLen=getsize(FILE) curper=0 bytes=f.read(BUFSIZE) while(bytes!=b'' and bytes!=''): curper+=len(bytes) sys.stdout.flush() sys.stdout.write('\r%6.2f %%' % (dec(100*curper)/dec(fileLen))) smtp.send(bytes.decode('utf-8')) bytes=f.read(BUFSIZE) f.close() smtp.send('\r\n.\r\n') smtp.getreply() smtp.quit() remove(FILE) print (('\nmail sended. ^_^')) class Mail: def __init__(self, FROM, TO, SUBJECT = None, CHARSET = 'utf-8'): from email.mime.multipart import MIMEMultipart self.FROM = FROM self.TO = TO self.SUBJECT = SUBJECT self.CHARSET = CHARSET self.text = '' self.fileinfo = '\n----\n' self.files = [] self.msg = MIMEMultipart() self.msg['From'] = '<%s>' % self.FROM self.msg['To'] = '<%s>' % self.TO def addtext(self, text = ''): self.text += text def addfile(self, FILE): import mimetypes from email.mime.image import MIMEImage from email.mime.text import MIMEText from email.mime.audio import MIMEAudio from email.mime.application import MIMEApplication from os.path import basename fileName = r'%s' % FILE baseName = basename(fileName) 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': att = MIMEText((lambda f: (f.read(), f.close()))(open(fileName, 'rb'))[0], \ _subtype = subtype, _charset = self.CHARSET) att.add_header('Content-Disposition', 'attachment', \ filename = self.header(baseName)) att.set_charset(self.CHARSET) self.files.append(att) elif maintype == 'image': att = MIMEImage((lambda f: (f.read(), f.close()))(open(fileName, 'rb'))[0], \ _subtype = subtype) att.add_header('Content-Disposition', 'attachment', \ filename = self.header(baseName)) att.set_charset(self.CHARSET) self.files.append(att) elif maintype == 'audio': att = MIMEAudio((lambda f: (f.read(), f.close()))(open(fileName, 'rb'))[0], \ _subtype = subtype) att.add_header('Content-Disposition', 'attachment', \ filename = self.header(baseName)) att.set_charset(self.CHARSET) self.files.append(att) else: att = MIMEApplication((lambda f: (f.read(), f.close()))(open(fileName, 'rb'))[0], \ _subtype = subtype) att.add_header('Content-Disposition', 'attachment', \ filename = self.header(baseName)) att.set_charset(self.CHARSET) self.files.append(att) if not self.SUBJECT: self.SUBJECT = baseName self.fileinfo += '%s\t%s\n' % (self.md5sum(fileName), baseName) def makemail(self): from email.mime.text import MIMEText import uuid self.msg['Subject'] = self.header(self.SUBJECT) txt = MIMEText(self.utf8(self.text + self.fileinfo), \ 'plain', self.CHARSET) self.msg.attach(txt) for x in self.files: self.msg.attach(x) fName = 'MAIL_' + str(uuid.uuid4()) fp = open(fName,'w') fp.write(self.msg.as_string()) fp.close() return fName def utf8(self, data): try: return data.decode(self.CHARSET).encode(self.CHARSET) except: return data.decode('gb18030').encode(self.CHARSET) def header(self, data): '''encode into base64.''' from email.Header import Header return Header(data, self.CHARSET).encode() def md5sum(self, FILE): '''return a file's md5sum.''' from hashlib import md5 BUFSIZE = 1024 m = md5() file = open(FILE, 'r') bytes = file.read(BUFSIZE) while(bytes != b''): m.update(bytes) bytes = file.read(BUFSIZE) file.close() return m.hexdigest() def main(): import sys from optparse import OptionParser from os.path import exists parser = OptionParser(usage = 'Usage: %prog [options] ') parser.add_option('-a', dest = 'fileList', action = 'append', \ help = 'attach FILE', metavar = 'FILE') parser.add_option('-s', dest = 'subject', action = 'store', \ help = 'set SUBJECT', metavar = 'SUBJECT') parser.add_option('-v', dest = 'verbose', action = 'store_true', \ help = 'show only,not send') parser.add_option('-t', dest = 'isType', action = 'store_true', \ help = 'type text from stdin') parser.set_defaults(verbose = False) parser.set_defaults(isType = False) (opts, args) = parser.parse_args() if not opts.fileList and not opts.subject and not args: parser.print_help() sys.exit(1) cf = ConfigFile() From = cf.FROM if not args: mailTo = cf.TO else: mailTo = args[0] mymail = Mail(From, mailTo, opts.subject) if opts.isType: text = sys.stdin.read() mymail.addtext(text) if opts.fileList: for file in opts.fileList: if exists(file): mymail.addfile(file) fileName = mymail.makemail() if opts.verbose: print(mymail.msg.as_string()) else: sendmail(cf.host, cf.port, cf.user, cf.passwd, fileName) if __name__ == '__main__' : main()
for Python 3.x
#!/usr/bin/env python3 '''mailfile.py for python3''' class ConfigFile: def __init__(self): from os.path import expanduser home = expanduser('~') self.rcfile = '%s/.mailfilerc' % home self.loadConfigFile() def initConfigFile(self): c = '''[mail] from=xxx@@xxx.com to=xxx@@xxx.com [smtp] host=smtp.xxx.com port=25 user=xxx passwd=xxx ''' f = open(self.rcfile, 'w') f.write(c) f.close() def loadConfigFile(self): import configparser from os.path import exists if exists(self.rcfile): cf = configparser.ConfigParser() cf.read(self.rcfile) self.host = cf.get('smtp', 'host') self.port = cf.getint('smtp', 'port') self.user = cf.get('smtp', 'user') self.passwd = cf.get('smtp', 'passwd') self.FROM = cf.get('mail','from') self.TO = cf.get('mail','to') else: self.initConfigFile() print ('** Please edit the config file %s !!!' % self.rcfile) def sendmail(host, port, user, passwd, FILE): import email, smtplib, base64, sys from os.path import getsize from os import remove from decimal import Decimal as dec fp=open(FILE) msg = email.message_from_file(fp) fp.close() FROM = email.utils.parseaddr(msg.get('from'))[1] TO = email.utils.parseaddr(msg.get('to'))[1] h = msg.get('subject') SUBJECT = email.header.decode_header(h)[0][0] print(('Connecting SMTP server %s ...') % host) smtp = smtplib.SMTP(host, port) #smtp.set_debuglevel(1) smtp.docmd('EHLO server') smtp.docmd('AUTH LOGIN') smtp.send(base64.b64encode(user.encode('utf-8')).decode('utf-8')+'\r\n') smtp.getreply() smtp.send(base64.b64encode(passwd.encode('utf-8')).decode('utf-8')+'\r\n') smtp.getreply() print('Logined') smtp.docmd('MAIL FROM:<%s>' % FROM) smtp.docmd('RCPT TO:<%s>' % TO) smtp.docmd('DATA') print(('send mail %s to <%s> ...') % (SUBJECT.decode('utf-8'), TO)) print('begin send data...') BUFSIZE = 2048 f = open(FILE, 'rb') fileLen = getsize(FILE) curper = 0 bytes = f.read(BUFSIZE) while(bytes != b'' and bytes != ''): curper += len(bytes) sys.stdout.write('\r%6.2f %%' % (dec(100)*dec(curper)/dec(fileLen))) smtp.send(bytes.decode('utf-8')) bytes = f.read(BUFSIZE) f.close() smtp.send('\r\n.\r\n') smtp.getreply() smtp.quit() remove(FILE) print('\nmail sended. ^_^') class mail: def __init__(self, FROM, TO, SUBJECT = None, CHARSET = 'utf-8'): from email.mime.multipart import MIMEMultipart self.FROM = FROM self.TO = TO self.SUBJECT = SUBJECT self.CHARSET = CHARSET self.text = '' self.fileinfo = '\n----\n' self.files = [] self.msg = MIMEMultipart() self.msg['From'] = self.FROM self.msg['To'] = self.TO def addtext(self, text = ''): self.text += text def addfile(self, FILE): import mimetypes from email.mime.image import MIMEImage from os.path import basename fileName = r'%s' % FILE baseName = basename(fileName) ctype, encoding = mimetypes.guess_type(fileName) if ctype is None or encoding is not None: ctype = 'application/octet-stream' maintype, subtype = ctype.split('/', 1) att = MIMEImage((lambda f: (f.read(), f.close())) \ (open(fileName, 'rb'))[0], _subtype = subtype) att.add_header('Content-Disposition', 'attachment', \ filename = self.header(baseName)) att.set_charset(self.CHARSET) att.set_payload(att.get_payload().decode()) self.files.append(att) if not self.SUBJECT: self.SUBJECT = baseName self.fileinfo += '%s\t%s\n' % (self.md5sum(fileName), baseName) def makemail(self): from email.mime.text import MIMEText import uuid self.msg['Subject'] = self.header(self.SUBJECT) txt = MIMEText(self.utf8(self.text + self.fileinfo), \ 'plain', self.CHARSET) self.msg.attach(txt) for x in self.files: self.msg.attach(x) fName = 'MAIL_' + str(uuid.uuid4()) fp = open(fName,'w') fp.write(self.msg.as_string()) fp.close() return fName def utf8(self, data): return data.encode(self.CHARSET) def header(self, data): '''encode into base64.''' from email.header import Header return Header(data, self.CHARSET).encode() def md5sum(self, FILE): '''return a file's md5sum.''' from hashlib import md5 BUFSIZE = 1024 m = md5() file = open(FILE, 'rb') bytes = file.read(BUFSIZE) while(bytes != b''): m.update(bytes) bytes = file.read(BUFSIZE) file.close() return m.hexdigest() def main(): import sys from optparse import OptionParser from os.path import exists parser = OptionParser(usage = 'Usage: %prog [options] ') parser.add_option('-a', dest = 'fileList', action = 'append', \ help = 'attach FILE', metavar = 'FILE') parser.add_option('-s', dest = 'subject', action = 'store', \ help = 'set SUBJECT', metavar = 'SUBJECT') parser.add_option('-v', dest = 'verbose', action = 'store_true', \ help = 'show only,not send') parser.set_defaults(verbose = False) (opts, args) = parser.parse_args() if not opts.fileList and not opts.subject and not args: parser.print_help() sys.exit(1) cf = ConfigFile() From = cf.FROM if not args: mailTo = cf.TO else: mailTo = args[0] mymail = mail(From, mailTo, opts.subject) if opts.fileList: for file in opts.fileList: if exists(file): mymail.addfile(file) fileName = mymail.makemail() if opts.verbose: print(mymail.msg.as_string()) else: sendmail(cf.host, cf.port, cf.user, cf.passwd, fileName) if __name__ == '__main__' : main()