Changeset 405 for foomailer/foomail.py


Ignore:
Timestamp:
Jun 3, 2020, 11:53:43 AM (4 years ago)
Author:
Rick van der Zwet
Message:

foomailer: Revamp argument style to reduce code-size.

While here re-do argument formatting to better fit my requirements

File:
1 edited

Legend:

Unmodified
Added
Removed
  • foomailer/foomail.py

    • Property svn:keywords set to Id
    r404 r405  
    11#!/usr/bin/env python
    2 # Rick van der Zwet
    3 # TODO: May need to implement some RFC checkers
     2#
     3# Rick van der Zwet <rick@vanderzwet.net>
    44#
    55#
    6 import sys,smtplib,re,socket,random,string,os,getopt
     6import argparse
    77import mimetypes
     8import os
     9import random
     10import re
     11import smtplib
     12import socket
     13import string
     14import sys
     15import textwrap
    816import time
     17
    918from time import gmtime,strftime
    1019from email.mime.multipart import MIMEMultipart
     
    1423from email import encoders
    1524
    16 __svnversion__ = "$Id: foomail.py 633 2008-06-12 19:29:56Z rick $"
     25__svnversion__ = "$Id$"
    1726__author__ = "Rick van der Zwet"
    1827
    1928
    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]")
     29default_subject = strftime('Test email send at  %a, %d %b %Y %T %z', gmtime())
    2530
    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)
     31parser = argparse.ArgumentParser(
     32            description=textwrap.dedent('''
     33            Sent test emails for mailserver verification and debugging
    3234
    33 try:
    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="])
    36 except getopt.GetoptError:
    37     usage()
    38     sys.exit(128)
    39 
    40 spam = False
    41 virus = False
    42 server = False
    43 port = "25"
    44 trace = False
    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
    66     elif o in ("-p", "--port"):
    67         port = a
    68     elif o == "--trace":
    69         trace = True
    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
     35            Author : %s
     36            Version: %s
     37            ''' % (__author__, __svnversion__)),
     38            formatter_class=argparse.RawDescriptionHelpFormatter)
     39parser.add_argument('--from', '-f', dest='sender', required=True)
     40parser.add_argument('--recipient', '-r', required=True)
     41parser.add_argument('--server', '-s', required=True)
     42parser.add_argument('--cc', help='Carbon Copy header')
     43parser.add_argument('--file', action='append', help='Attachments to sent')
     44parser.add_argument('--hostname', default=socket.gethostname(), help='EHLO/HELO hostname to present')
     45parser.add_argument('--message', help='Alternative message text of body')
     46parser.add_argument('--subject', default=default_subject, help='Alternative Subject header')
     47parser.add_argument('--spam', action='store_true', help='Include X-Spam testing headers')
     48parser.add_argument('--port', type=int, default=25, help='SMTP port used for connection')
     49parser.add_argument('--reply-to', help='Set Reply-To: header')
     50parser.add_argument('--to', help='Alternative To: header')
     51parser.add_argument('--silent', action='store_true', help='Do not-follow SMTP flow verbosely')
     52parser.add_argument('--virus', action='store_true', help='Include eicar.txt sample virus')
     53parser.add_argument('--dry-run', '-d', action='store_true', help='Do not actually sent out the message')
     54args = parser.parse_args()
    10955
    11056
    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 
    12057email = MIMEMultipart()
    121 hostname = socket.gethostname()
    122 
    123 email['From'] = 'Testing sender <' + sender + '>'
    124 email['To'] = to
    125 if cc:
    126     email['Cc'] = cc
    127 email['X-Server'] = server
    128 email['X-Port'] = port
    129 email['X-Hostname'] = hostname
     58email['From'] = 'Testing sender <' + args.sender + '>'
     59email['To'] = args.to or args.recipient
     60if args.cc:
     61    email['Cc'] = args.cc
     62email['X-Server'] = args.server
     63email['X-Port'] = str(args.port)
     64email['X-Hostname'] = args.hostname
    13065email['Message-ID' ] = '<' +''.join(random.sample(string.ascii_letters +
    13166                       string.digits,10)) + '@' + email['X-Hostname'] + '>'
    13267email['Date'] = strftime('%a, %d %b %Y %T %z',gmtime())
    133 email['Subject'] = subject
     68email['Subject'] = args.subject
    13469email['X-Version'] = __svnversion__
    13570email['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:
     71
     72tests = []
     73if args.spam:
     74    tests.append('spam')
     75if args.virus:
     76    test.append('virus')
     77email['X-Tests'] = ' '.join(tests)
     78
     79if args.reply_to:
     80    email['Reply-To'] = args.reply_to
     81
     82if args.spam:
    13983    email['X-Spam'] = 'XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X'
    14084
    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
     85if args.message:
     86    f = open(args.message,'r')
     87    msg = f.read()
     88    f.close()
     89else:
     90    msg = textwrap.dedent('''
     91        Hi,
     92       
     93            Sorry to bother you...
     94       
     95        Please ignore this message as it is used to test
     96        and verify systems to make sure everything works
     97        flawless.
     98       
     99        %(virus)s
     100       
     101        Technical details:\n''' % email)
    157102   
    158103    for k in list(email.keys()):
     
    160105        msg += "* %-15s : %s\n" % (k,v)
    161106   
    162    
    163     msg = msg + \
    164     '''
    165 Best regards,
    166 Your system administrator
    167 --
    168 BSD Licensed Source Code for this tool at:
    169 https://rickvanderzwet.nl/svn/personal/foomailer
    170     '''
    171     return(msg)
     107    msg += textwrap.dedent('''
     108        Best regards,
     109        Your system administrator
     110        --
     111        BSD Licensed Source Code for this tool at:
     112        https://rickvanderzwet.nl/svn/personal/foomailer
     113        ''')
    172114
    173 if message:
    174     f = open(message,'r')
    175     msg = f.read()
    176     f.close()
    177 else:
    178     msg = defaultmessage()
    179115
    180116email.attach(MIMEText(msg))
    181117
    182 if virus:
     118if args.virus:
    183119    part = MIMEBase('application', "octet-stream")
    184120    part.set_payload('X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*')
     
    187123    email.attach(part)
    188124
    189 if files:
    190     for file in files.split(':'):
    191         mimetype = mimetypes.guess_type(file)[0].split('/')
     125if args.file:
     126    for filename in args.file:
     127        mimetype = mimetypes.guess_type(filename)[0].split('/')
    192128        part = MIMEBase(mimetype[0],mimetype[1])
    193         f = open(file,'r')
     129        f = open(filename,'r')
    194130        part.set_payload(f.read())
    195131        f.close()
    196132        encoders.encode_base64(part)
    197         part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
     133        part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(filename))
    198134        email.attach(part)
    199135
    200136print(email.as_string())
    201137
    202 if not dry:
     138if not args.dry_run:
    203139    mark = time.time()
    204     server = smtplib.SMTP(server, port, timeout=600)
    205     server.set_debuglevel(trace)
    206     server.helo(hostname)
    207     server.ehlo(hostname)
    208     server.sendmail(sender, recipient, email.as_string())
     140    server = smtplib.SMTP(args.server, args.port, timeout=600)
     141    server.set_debuglevel(not args.silent)
     142    server.helo(args.hostname)
     143    server.ehlo(args.hostname)
     144    server.sendmail(args.sender, args.recipient, email.as_string())
    209145    server.quit()
    210146    print("Sending took sec: %.2f" % (time.time() - mark))
Note: See TracChangeset for help on using the changeset viewer.