Add example about os.path.walk , which may used to implete --recursive option
[xmailer.git] / test / mimemail.py
blobc7a4dcdb7426d2c73cfdf14d1dd60ab73a10bebc
1 #!/usr/bin/python
2 # Justin Quick 02-2008 justquick@gmail.com
3 # Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
4 # Everyone is permitted to copy and distribute verbatim copies
5 # of this license document, but changing it is not allowed. see LICENSE
6 import sys,smtplib,MimeWriter,base64,StringIO,os,mimetypes,optparse,getpass,re,socket
7 # ip,domain and dns helpers
8 def getdomain(hostname): return '.'.join(hostname.split('.')[1:])
9 def likeip(astr):
10 return re.compile('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}').match(astr)
11 def getmx(domain):
12 # Returns highest priority server from mx search
13 capture,servers = 0,[]
14 for l in os.popen('dig %s mx'%domain):
15 l=l.strip()
16 if l==';; ANSWER SECTION:': capture = 1
17 elif l=='': capture = 0
18 elif capture:
19 a,b = l.split('\t')[-1].split(' ')
20 servers.append((int(a),b[:-1]))
21 servers.sort(lambda x,y: cmp(x[0],y[0]))
22 return servers[0][1]
23 # argument parser
24 desc = """MimeMail: Simple smtp client able to send mime messages which allows for: html body (from input or file), attachments, bcc/cc. It can also dig through a domain and retrieve the highest priority server from an mx search."""
25 parser = optparse.OptionParser(description=desc,
26 usage='%prog [<username>@<domain>|<username> <servername>]')
27 parser.add_option('-p',"--password", action='store_true',dest="passwd",
28 default=False,help="authenticate user, prompting for password")
29 parser.add_option("--key", dest="key",default='',help="the TLS keyfile")
30 parser.add_option("--cert", dest="cert",default='',help="the TLS certfile")
31 (options, args) = parser.parse_args()
32 # get username, smtp server hostname and domain for connection
33 if args and args[0].find('@')!=-1:
34 user,domain = args[0].split('@')
35 server = getmx(domain)
36 elif args and len(args)==2:
37 user,server = args
38 if likeip(server): server = socket.gethostbyaddr(server)[0]
39 domain = getdomain(server)
40 else:
41 print parser.format_help()
42 sys.exit()
43 # create connection
44 try: smtp = smtplib.SMTP(server)#; smtp.set_debuglevel(1)
45 except: raise 'Connection error with %s'%server
46 # login and check credentials
47 if options.passwd:
48 try: smtp.login(user,getpass.getpass('Password for %s@%s: '%(user,domain)))
49 except: raise 'Credentials error with %s on %s'%(user,server)
50 # start Transport Layer Security mode if keyfile and certfile
51 if options.key and options.cert:
52 smtp.starttls(options.key,options.cert)
53 smtp.helo()
54 # interface for writing MIME email messages
55 subject,body,to,bcc,cc,attchs = '','',[],[],[],[]
56 def prompt(prompt): return raw_input(prompt).strip()
57 def sub(c):
58 # subfunction handler
59 global server,port,subject,body,to,bcc,cc,attchs
60 try: c = int(c)
61 except: return
62 if c==1:
63 print 'New HTML body content:\n'
64 body = ''
65 while 1:
66 try: data = raw_input()
67 except EOFError: break
68 if not data: break
69 body += data
70 elif c==2:
71 body = open(prompt('Filename: ')).read()
72 elif c==3: subject = prompt('New subject: ')
73 elif c==4: to = prompt('Email addresses (comma sep): ').split(',')
74 elif c==5:
75 fi = prompt('Filename: ')
76 if not os.path.isfile(fi):
77 raise IOError, 'File %s not found!'%fi
78 attchs.append(fi)
79 elif c==6:
80 bcc = prompt('BCCs (comma sep): ').split(',')
81 cc = prompt('CCs (comma sep): ').split(',')
82 elif c==7: return c
83 # interface
84 print """Connected. Now compose message:
85 \t1. New message body
86 \t2. Load message body from file
87 \t3. Subject
88 \t4. To addresses
89 \t5. Add Attachment
90 \t6. Set BCC/CC
91 \t7. Send"""
92 while 1:
93 try: cmd = prompt("smtp> ")
94 except: print '\nExiting'; sys.exit()
95 if sub(cmd): break
96 # Init mime message with necessary headers
97 message = StringIO.StringIO()
98 writer = MimeWriter.MimeWriter(message)
99 writer.addheader('Subject', subject)
100 for addr in to: writer.addheader('To', addr)
101 for addr in cc: writer.addheader('Cc', addr)
102 for addr in bcc: writer.addheader('Bcc', addr)
103 writer.startmultipartbody('mixed')
104 # add body
105 part = writer.nextpart()
106 bod = part.startbody('text/html')
107 bod.write(body)
108 # add attachments
109 for attch in attchs:
110 part = writer.nextpart()
111 part.addheader('Content-Transfer-Encoding', 'base64')
112 part.addheader("Content-Disposition",
113 'attachment; filename="%s"'%os.path.basename(attch))
114 mime = mimetypes.guess_type(attch)[0]
115 if not mime: mime = 'text/plain'
116 base64.encode(open(attch,'rb'),part.startbody(mime))
117 # send the mail
118 writer.lastpart()
119 errors = smtp.sendmail('%s@%s'%(user,domain), to, message.getvalue())
120 # catch errrors
121 if not errors: print 'Email sent sucessfully'
122 else:
123 for k,v in errors.items(): print 'Error with address %s: %s'%(k,v)
124 # close connection before exiting
125 smtp.quit()