[2] | 1 | #!/usr/bin/env python
|
---|
| 2 | # Rick van der Zwet
|
---|
| 3 | # TODO: May need to implement some RFC checkers
|
---|
| 4 | #
|
---|
| 5 | #
|
---|
| 6 | import sys,smtplib,re,socket,random,string,os,getopt
|
---|
| 7 | import mimetypes
|
---|
| 8 | import time
|
---|
| 9 | from time import gmtime,strftime
|
---|
| 10 | from email.MIMEMultipart import MIMEMultipart
|
---|
| 11 | from email.MIMEBase import MIMEBase
|
---|
| 12 | from email.MIMEText import MIMEText
|
---|
| 13 | from email.Utils import COMMASPACE, formatdate
|
---|
| 14 | from email import Encoders
|
---|
| 15 |
|
---|
| 16 | __svnversion__ = "$Id: foomail.py 633 2008-06-12 19:29:56Z rick $"
|
---|
| 17 | __author__ = "Rick van der Zwet"
|
---|
| 18 |
|
---|
| 19 |
|
---|
| 20 | def usage():
|
---|
| 21 | print "usage %s -f <from> -r <recipient> -s <server> [--spam]" % sys.argv[0]
|
---|
| 22 | print "[--virus] [--file <size in kB>] [--message <file>]"
|
---|
| 23 | print "[--subject <string>] [--to <string>] [--cc <string>]"
|
---|
| 24 | print "[--force]"
|
---|
| 25 |
|
---|
| 26 | default_domain = 'example.com'
|
---|
| 27 | def emailparse(email):
|
---|
| 28 | if re.compile('.*@.*').match(email):
|
---|
| 29 | return(email)
|
---|
| 30 | else:
|
---|
| 31 | return(email + '@' + default_domain)
|
---|
| 32 |
|
---|
| 33 | try:
|
---|
[401] | 34 | opts, args = getopt.getopt(sys.argv[1:], "f:r:s:dp:t",
|
---|
| 35 | ["from=","force","recipient=","server=","spam","port=","virus","files=","dry-run","message=","subject=","to=","trace","cc="])
|
---|
[2] | 36 | except getopt.GetoptError:
|
---|
| 37 | usage()
|
---|
| 38 | sys.exit(128)
|
---|
| 39 |
|
---|
| 40 | spam = False
|
---|
| 41 | virus = False
|
---|
| 42 | server = False
|
---|
[401] | 43 | port = "25"
|
---|
| 44 | trace = False
|
---|
[2] | 45 | recipient = False
|
---|
| 46 | sender = False
|
---|
| 47 | files = False
|
---|
| 48 | force = False
|
---|
| 49 | dry = False
|
---|
| 50 | message = False
|
---|
| 51 | subject = False
|
---|
| 52 | to = False
|
---|
| 53 | cc = False
|
---|
| 54 |
|
---|
| 55 | tests = ""
|
---|
| 56 |
|
---|
| 57 | for o, a in opts:
|
---|
| 58 | if o in ("-f","--from"):
|
---|
| 59 | sender_raw = a
|
---|
| 60 | sender = emailparse(a)
|
---|
| 61 | elif o in ( "-r", "--recipient"):
|
---|
| 62 | recipient_raw = a
|
---|
| 63 | recipient = emailparse(a)
|
---|
| 64 | elif o in ("-s", "--server"):
|
---|
| 65 | server = a
|
---|
[401] | 66 | elif o in ("-p", "--port"):
|
---|
[400] | 67 | port = a
|
---|
[401] | 68 | elif o == "--trace":
|
---|
| 69 | trace = True
|
---|
[2] | 70 | elif o == "--spam":
|
---|
| 71 | spam = True
|
---|
| 72 | tests += " Spam"
|
---|
| 73 | elif o == "--virus":
|
---|
| 74 | virus = True
|
---|
| 75 | tests += " Virus"
|
---|
| 76 | elif o == "--files":
|
---|
| 77 | files = a
|
---|
| 78 | elif o in ("-d","--dry-run"):
|
---|
| 79 | dry = True
|
---|
| 80 | elif o in ("--message"):
|
---|
| 81 | message = a
|
---|
| 82 | elif o in ("--subject"):
|
---|
| 83 | subject = a
|
---|
| 84 | elif o in ("--to"):
|
---|
| 85 | to = a
|
---|
| 86 | elif o in ("--cc"):
|
---|
| 87 | cc = a
|
---|
| 88 | elif o in ("--force"):
|
---|
| 89 | force = True;
|
---|
| 90 |
|
---|
| 91 | error = False
|
---|
| 92 | if not sender:
|
---|
| 93 | print "No sender defined"
|
---|
| 94 | error = True
|
---|
| 95 | elif not recipient:
|
---|
| 96 | print "No recipient defined"
|
---|
| 97 | error = True
|
---|
| 98 | elif not server:
|
---|
| 99 | print "No server defined"
|
---|
| 100 | error = True
|
---|
| 101 |
|
---|
| 102 | if error:
|
---|
| 103 | usage()
|
---|
| 104 | sys.exit(128)
|
---|
| 105 |
|
---|
| 106 | if force:
|
---|
| 107 | sender = sender_raw
|
---|
| 108 | recipient = recipient_raw
|
---|
| 109 |
|
---|
| 110 |
|
---|
| 111 | #Subject here, just to keep the settings/layout a bit more constent
|
---|
| 112 | if not subject:
|
---|
| 113 | subject = 'Test email send at %a, %d %b %Y %T %z'
|
---|
| 114 | subject = strftime(subject,gmtime())
|
---|
| 115 |
|
---|
| 116 | if not to:
|
---|
| 117 | to = 'Testing received <' + recipient + '>'
|
---|
| 118 | to = recipient
|
---|
| 119 |
|
---|
| 120 | email = MIMEMultipart()
|
---|
[183] | 121 | hostname = socket.gethostname()
|
---|
[2] | 122 |
|
---|
| 123 | email['From'] = 'Testing sender <' + sender + '>'
|
---|
| 124 | email['To'] = to
|
---|
| 125 | if cc:
|
---|
| 126 | email['Cc'] = cc
|
---|
| 127 | email['X-Server'] = server
|
---|
[400] | 128 | email['X-Port'] = port
|
---|
[183] | 129 | email['X-Hostname'] = hostname
|
---|
[2] | 130 | email['Message-ID' ] = '<' +''.join(random.sample(string.letters +
|
---|
| 131 | string.digits,10)) + '@' + email['X-Hostname'] + '>'
|
---|
| 132 | email['Date'] = strftime('%a, %d %b %Y %T %z',gmtime())
|
---|
| 133 | email['Subject'] = subject
|
---|
| 134 | email['X-Version'] = __svnversion__
|
---|
| 135 | email['X-Author'] = __author__
|
---|
| 136 | email['X-Tests'] = tests
|
---|
| 137 | #email['Reply-To'] = "Rick vd Zwet <rick@joost.com>, Wouter Simons <wouter@joost.com>"
|
---|
| 138 | if spam:
|
---|
| 139 | email['X-Spam'] = 'XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X'
|
---|
| 140 |
|
---|
| 141 |
|
---|
| 142 | def defaultmessage():
|
---|
| 143 | msg = ''
|
---|
| 144 | msg += \
|
---|
| 145 | '''
|
---|
| 146 | Hi,
|
---|
| 147 |
|
---|
| 148 | Sorry to bother you...
|
---|
| 149 |
|
---|
| 150 | Please ignore this message as it is used to test
|
---|
| 151 | and verify systems to make sure everything works
|
---|
| 152 | flawless.
|
---|
| 153 |
|
---|
| 154 | %(virus)s
|
---|
| 155 |
|
---|
| 156 | Technical details:\n''' % email
|
---|
| 157 |
|
---|
| 158 | for k in email.keys():
|
---|
| 159 | v = email[k]
|
---|
| 160 | msg += "* %-15s : %s\n" % (k,v)
|
---|
| 161 |
|
---|
| 162 |
|
---|
| 163 | msg = msg + \
|
---|
| 164 | '''
|
---|
| 165 | Best regards,
|
---|
| 166 | Your system administrator
|
---|
[383] | 167 | --
|
---|
| 168 | BSD Licensed Source Code for this tool at:
|
---|
| 169 | https://rickvanderzwet.nl/svn/personal/foomailer
|
---|
[2] | 170 | '''
|
---|
| 171 | return(msg)
|
---|
| 172 |
|
---|
| 173 | if message:
|
---|
| 174 | f = open(message,'r')
|
---|
| 175 | msg = f.read()
|
---|
| 176 | f.close()
|
---|
| 177 | else:
|
---|
| 178 | msg = defaultmessage()
|
---|
| 179 |
|
---|
| 180 | email.attach(MIMEText(msg))
|
---|
| 181 |
|
---|
| 182 | if virus:
|
---|
| 183 | part = MIMEBase('application', "octet-stream")
|
---|
| 184 | part.set_payload('X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*')
|
---|
| 185 | Encoders.encode_base64(part)
|
---|
| 186 | part.add_header('Content-Disposition', 'attachment; filename="eicar.txt"')
|
---|
| 187 | email.attach(part)
|
---|
| 188 |
|
---|
| 189 | if files:
|
---|
| 190 | for file in files.split(':'):
|
---|
| 191 | mimetype = mimetypes.guess_type(file)[0].split('/')
|
---|
| 192 | part = MIMEBase(mimetype[0],mimetype[1])
|
---|
| 193 | f = open(file,'r')
|
---|
| 194 | part.set_payload(f.read())
|
---|
| 195 | f.close()
|
---|
| 196 | Encoders.encode_base64(part)
|
---|
| 197 | part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
|
---|
| 198 | email.attach(part)
|
---|
| 199 |
|
---|
| 200 | print email.as_string()
|
---|
| 201 |
|
---|
| 202 | if not dry:
|
---|
| 203 | mark = time.time()
|
---|
[400] | 204 | server = smtplib.SMTP(server, port)
|
---|
[401] | 205 | server.set_debuglevel(trace)
|
---|
[183] | 206 | server.helo(hostname)
|
---|
| 207 | server.ehlo(hostname)
|
---|
[2] | 208 | server.sendmail(sender, recipient, email.as_string())
|
---|
| 209 | server.quit()
|
---|
| 210 | print "Sending took sec: %.2f" % (time.time() - mark)
|
---|