def main(): try: signal.signal(signal.SIGINT, sig_handler) iworkspace() ishell() # except Ctrl+C, Ctrl+D # except (KeyboardInterrupt, EOFError): except EOFError: print print fpr.err('Interrupted by user! Session lost!') try: sys.exit(0) except SystemExit: os._exit(0) except Exception, error: print fpr.warn('> Unpredictable Exception has been catched') fpr.err('>>> %s' % str(error)) fpr('> Need help regarding the error, please send me a copy. Thank you.' ) fpr.warn( '> Restarting main() to keep the session.\n> Please save the session and restart me..' ) waitin() main()
def dbginfo(itype,msg,log=None): if itype.lower() == 'error': fpr.err( ('-'*(tc-4-len('-- Error --')) + '-- Error --' )) fpr.info(msg) if log: fpr.err('_'*(tc-4)) print fpr(log) fpr.err('_'*(tc-4)) fpr.err('-'*(tc-4)) if itype.lower() == 'warrning': fpr.warn( ('-'*(tc-4-len('-- Warrning --')) + '-- Warrning --' )) fpr.info(msg) if log: fpr.warn('_'*(tc-4)) print fpr(log) fpr.warn('_'*(tc-4)) fpr.warn('-'*(tc-4)) if itype.lower() == 'debug': #from core.data import DEBUG if not DEBUG: return 0 fpr.purple( ('-'*(tc-4-len('-- Debug --')) + '-- Debug --' )) fpr.info(msg) if log: fpr.purple('_'*(tc-4)) print fpr(log) fpr.purple('_'*(tc-4)) fpr.purple('-'*(tc-4))
def info(itype,msg,log=None,adj='c',frame='warn'): #TODO: add color option for frame # if itype.lower() == 'info': fpr.warn( ('_'*(tc-4-len('__')) + '__' )) print fpr(msg,adj=adj) if log: fpr.info('_'*(tc-4)) print fpr.info(log) fpr.info('_'*(tc-4)) fpr.warn('_'*(tc-4))
def parse_spfHeaders(h): if h: print h try: q = spf.query('0.0.0.0', '', '') q.mechanism = 'unknown' p = q.parse_header(h) ph = q.get_header(q.result, **p) print print p['identity'] fpr.blue(str(p)) fpr.warn(str(ph)) except Exception, e: fpr.err("Error: %s" % e)
def viewDKIMSignTag(_all=0): #TODO: # add Less funct with condition # d = smtp['sign']['dkim'] if not d.get(0): fpr('No DKIM Signature') return for k in range(d['dstat'] + 1): #print d #print k # if not _all then show current only if not _all and k != d['dstat']: k += 1 else: if k in d: dn = d[k] if smtp.get('h' + str(k) + '_DKIM-Signature'): fpr('Signature attached (#%s)' % k, adj='r') else: fpr('Signature not attached (current #%s)' % k, adj='r') fpr.info('_' * (tc - 4)) print fpr('DKIM signature set tags:') print fpr(' version : v=%s' % dn.get('version', '1')) fpr(' alghoritm : a=%s' % dn.get('alghoritm', 'rsa-sha256')) fpr(' canonicalization : c=%s' % dn.get('canonicalize', '')) fpr(' selector : s=%s' % dn.get('selector', '')) fpr(' domain : d=%s' % dn.get('domain', '')) fpr(' header : h=%s' % dn.get('header', "from : to : subject")) fpr(' identity : i=%s' % dn.get('identity', '')) fpr(' length : l=%s' % dn.get('length', '')) print if dn.get('privkey'): fpr('Private Key status : -- Loaded -- ') else: fpr.warn('Private Key status : -- Not loaded -- ') print if dn.get('sig'): fpr('DKIM-Signature: %s' % dn.get('sig', ''), adj='l') else: fpr.warn('DKIM-Signature: -- Not generated --') print if smtp['headers'].get('h' + str(k) + '_DKIM-Signature'): fpr('DKIM-Signature was attached') else: fpr.warn('DKIM-Signature was not attached') print fpr.info('_' * (tc - 4))
def viewTheMsg(s=0): # from core.ui.cless import Less # from core.msg.builder import msg_builder # try: # from cStringIO import StringIO # except: # from StringIO import StringIO # fs = StringIO() # # from email.MIMEBase import MIMEBase # from email.iterators import _structure # from email.message import Message msgdata = msg_builder() if DEBUG > 1: from pprint import pprint print '----' pprint(msgdata) print 'type:', type(msgdata) print 'repr:', repr(msgdata) print 'dir :', dir(msgdata) print '__len__():', msgdata.__len__() # no. of headers print '__str__():', msgdata.__str__() print 'len():', len(msgdata) print msgdata.get_payload() print '----' if hasattr(msgdata, 'as_string'): fpr.blue('_' * (tc - 4)) print #if msgdata != MIMEBase: if True: # view the message mime structure if s: #email.iterators._structure(msgdata, fs) if hasattr(msgdata, 'get_content_typ'): _structure(msgdata, fs) #fpr.blue('%s' % email.iterators._structure(msgdata) ) fpr.warn('%s' % fs.getvalue()) else: fpr.warn( 'For custom message currently MIME structure is not checked !' ) # view message data else: #print fpr.GRAY #dl = len(str(msgdata).splitlines()) dl = len(msgdata.as_string(unixfrom=False).splitlines()) if dl > tr: fpr('Message data is bigger than your screen (%s lines)' % dl) if raw_input( ' Would like to use system pager to view it [y/N]:> ' ) in ['y', 'Y']: fpr.blue('_' * (tc - 4)) print pager = Less(num_lines=tr) print msgdata.as_string(unixfrom=False) | pager else: fpr.blue('_' * (tc - 4)) print print msgdata.as_string(unixfrom=False) else: print msgdata.as_string(unixfrom=False) #print len(str(msgdata).splitlines()),tr #print msgdata #print fpr.RCL #else: # fpr.info('No content data was defined !') # if msgdata == Message: # print msgdata # elif smtp['use_mime'] == 0: # if s: # dbginfo('warn','MIME structure view is not supprted for customized content!') # # dl = len(msgdata.as_string(unixfrom=False).splitlines()) # print msgdata.as_string(unixfrom=False) # print 'len ', dl fpr.blue('_' * (tc - 4)) else: fpr.warn('No content data was defined !') fs.close()
def sig_handler(signal, frame): print print fpr.warn( 'Leaving the session? Press Ctrl+D to leave it, press Enter to return') print
def smtp_dha(cpt=1, rate=None, rcpts=[], method='RCPT TO',relays={} ,name='DHA-T-Single',v=False): dhar = dict() from pprint import pprint from core.data import cfgs,smtp,fpr,tc,DEBUG from core.func import dbginfo from core.msg.viewers import viewSmtpConv from core.msg.threads import get_tid dbginfo('DEBUG','name=%s, cpt=%s, method=%s, rate=%s, rcpts=%s' % (name,cpt,method,rate,rcpts) ) #verbnose dhost=smtp['connect']['hosts'][0] try: import sys import smtplib # # log debuglevel output from smtplib # # redirect stderr from smtplib to string # # # # - from smtplib import stderr # if cfgs['conv_logs'] and cl: # ostderr = smtplib.stderr # smtplib.stderr = StderrLogger() # run smtp session if v: fpr.white('Establishing the session ..') s = smtplib.SMTP(dhost['host'],dhost['port']) # if cfgs['conv_logs'] and cl: # s.set_debuglevel('debug') # HELO - introduce yourself if v: fpr.cyan('>>> %s %s' % ('EHLO',dhost['helo'])) (c,m) = s.ehlo(dhost['helo']) #r = s.helo(smtp['connect']['hosts'][0]['helo']) if v: #print (c,m) if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) if s.does_esmtp: fpr.white('ESMTP supported and have extn:') #print s.does_esmtp #print s.esmtp_features for (scmd,sarg) in s.esmtp_features.items(): fpr.white(' * %s %s' % (scmd,sarg)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) # STAARTTLS if 'starttls' in s.esmtp_features.keys(): if dhost['tls_mode'] == 'TLS': if v: fpr.white('TLS supported and requested') fpr.white('Establishing TLS session ..') fpr.cyan('>>> %s' % ('STARTTLS')) (c,m) = s.starttls() if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) # HELO - introducing yourself on encrypted session should be done as well if v: fpr.cyan('>>> %s %s' % ('EHLO',dhost['helo'])) (c,m) = s.ehlo(dhost['helo']) if v: #print (c,m) if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) if s.does_esmtp: fpr.white('ESMTP supported and have extn:') #print s.does_esmtp #print s.esmtp_features for (scmd,sarg) in s.esmtp_features.items(): fpr.white(' * %s %s' % (scmd,sarg)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) else: if v: fpr.white('TLS supported but not requested') fpr.white('Unencrypted session established') # SMTP AUTH if 'auth' in s.esmtp_features.keys(): if dhost['smtp_auth_user'] != '': if v: fpr.cyan('>>> %s %s' % ('AUTH PLAIN','*********')) (c,m) = s.login(dhost['smtp_auth_user'],dhost['smtp_auth_pass']) if v: if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) elif dhost['smtp_auth_user'] != '': if v: fpr.white('Authentication SET but not available (AUTH not supported)') fpr.white('Trying without AUTH') if method.lower() == 'rcpt to': # MAIL FROM sender = smtp['addrlist']['mail_from'] #rcpt = smtp['addrlist']['rcpt_to'] if v: fpr.cyan('>>> %s %s' % ('MAIL FROM:',sender)) (c,m) = s.docmd('MAIL FROM:',sender) if v: if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) # number of recipients to test # rpt - rcpt/thread # cpt - command/thread if cpt == None: cpt = 1 rpt = len(rcpts) cpt = rpt if v: fpr.white('Enumerating recipients ..') fpr.white(' * %s recipients to test with this thread' % len(rcpts)) fpr.white(' * method in use: %s' % method.lower()) #print rcpts for r in rcpts: if method.lower() == 'rcpt to': if v: fpr.cyan('>>> %s: <%s>' % (method,r)) (c,m) = s.docmd('%s:' % method,'<%s>' % r) else: # treat results returned from vrfy and expn similar # expn should have a separate condition as it could return # a list of recipients in case of mailing list but # in modern networks you should be really lucky to find such an SMTP server # supporting - good luck with that # - it should be implemented just as proof of concept rather than for real use if v: fpr.cyan('>>> %s <%s>' % (method,r)) (c,m) = s.docmd('%s' % method,'<%s>' % r) if 200 <= c <= 299: if v: fpr.green('<<< %s %s' %(c,m)) dhar.setdefault(r, { 'valid': True, 'code': c, 'msg': m, 'method': method.lower(), 'host': dhost['host'], 'thread': name } ) elif 500 <= c <= 599: if v: fpr.err('<<< %s %s' %(c,m)) dhar.setdefault(r, { 'valid': False, 'code': c, 'msg': m, 'method': method.lower(), 'host': dhost['host'], 'thread': name } ) else: if v: fpr.err('<<< %s %s' %(c,m)) dhar.setdefault(r, { 'valid': False, 'code': c, 'msg': m, 'method': method.lower(), 'host': dhost['host'], 'thread': name } ) # query timeout - wait before next command #sleep(1) # pprint(dhar) # quit smtp session if v: fpr.cyan('>>> %s' % ('QUIT:')) (c,m) = s.quit() if v: if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) fpr.white('Session closed successfully') elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) if v: print fpr('To check valid recipients back to the main submenu') #pprint(dhar) # the exception is triggered only when all recipoient failed :( except smtplib.SMTPRecipientsRefused, e: fpr.fail('Error: unable to sent message. All recipients refused.') smtp['replay']['threads']['fail'].append(name) #print 'exception smtplib.SMTPRecipientsRefused',a fpr.warn(str(e)) smtp['addrlist']['r_reject'].update(e.recipients)
def d_base64(op): # load from file if op == '1': fn = '' while True: bancls() fpr('Diagnostics: Base64 decoder') print fpr('Please provide a file name:') fn = raw_input(' []> ') print inputs = get_file_content(fn) print if inputs: #inputs = f.readlines() # include \n #inputs = f.read().splitlines() # exclude \n dbginfo('debug', inputs) print if not coders.isBase64(''.join(inputs)): fpr('File seems to be BASE64 encoded') else: fpr.warn('File does not seems to be Base64 encoded') print decb64 = coders.decode_attch(inputs) if isinstance(decb64, dict): fpr.ok('File content was decoded successful') else: fpr.fail('File content was not decoded') waitin() return decb64 elif raw_input(' Return to menu [y/N]> ') in ['y', 'Y']: break waitin() # load from input - paste it if op == '2': bancls() fpr('Diagnostics: Base64 decoder') print if raw_input(' Would you like to decode some content [y/N]> ') in [ 'y', 'Y' ]: print fpr('Please provide Base64 encoded content') fpr('Use Ctrl-D with new line to continue.') print fpr.blue('_' * (tc - 4)) print inputs = get_inputs() fpr.blue('_' * (tc - 4)) if inputs: dbglog(inputs) print if not coders.isBase64('\n'.join(inputs)): fpr('Input seems to be BASE64 encoded') else: fpr.warn('Input does not seems to be Base64 encoded') print decb64 = coders.decode_attch('\n'.join(inputs)) if isinstance(decb64, dict): fpr.ok('Input content was decoded successful') else: fpr.fail('Input content was not decoded') waitin() return decb64 waitin()
def chDHAThrDep(t=None,cpt=None): #VERIFY: In Python 2.x : int/int --> int and int/float --> float In Python 3.x : int/int can result in a float r=get_rcpts('NoR') t_s=None cpt_s=None if not r: fpr.err('Recipients not defined. Build a list of recipients first.') fpr.err('Flush the values if the recipient list has been modified.') return if t: smtp['dha']['threads']['not'] = int(t) if cpt: smtp['dha']['threads']['cpt'] = int(cpt) fpr.info('_'*(tc-4)) print fpr.warn('Your limits:') fpr.warn('t_set = %s : cpt_set = %s : r = %s' % (smtp['dha']['threads'].get('not',None), smtp['dha']['threads'].get('cpt',None),r) ) print # fpr.err('Maximum possible limits to met Essential Conditions:') # fpr.err('t = %s : rpm = %s : mpt = %s - r = %s' % (t,rpm,mpt,r) ) # fpr.info('_'*(tc-4)) print def setReals(t,cpt): if t and cpt : smtp['dha']['threads']['reals'].setdefault('not',t) smtp['dha']['threads']['reals'].setdefault('cpt',cpt) smtp['dha']['threads']['reals']['not']=t smtp['dha']['threads']['reals']['cpt']=cpt fpr.ok('Reals were set!') if r: # count the cpt - based on r and t # -------------------------------------------------------------------- # if t: fpr.green('%s : %s : %s' % (t,cpt,r) ) # cpt = r / t # t = r / cpt if t >= r: t_new = r cpt = 1 fpr.err('realistic returns would be: t = %s, cpt = %s for r = %s' % (t_new,cpt,r)) setReals(t_new,cpt) if t < r: # I - validate CPT - CPT < R cpt = float(r) / t fpr.green('counted cpt = %s' % cpt) # round up - if there is a remainder if (r % t > 0): cpt = r / t + (r % t > 0) fpr.green('rounding up cpt = %s' % cpt) # find the lowest T for rounded CpT t_new = float(r) / cpt fpr.green('counted new t = %s' % t_new) #if (r % cpt > 0): # if remainder # t_new = r / cpt + ( r % cpt > 0) # fpr.green('rounding up new t = %s' % t_new) # fpr.err('realistic returns would be: *t = %s, cpt = %s for r = %s' % # (int(t_new),int(cpt),r)) # setReals(int(t_new),int(cpt)) #else: fpr.err('realistic returns would be: *t = %s, cpt = %s for r = %s' % (int(t_new),int(cpt),r)) setReals(int(t_new),int(cpt)) else: fpr.err('realistic returns would be: t = %s, cpt = %s for r = %s' % (t,int(cpt),r)) setReals(int(t),int(cpt)) elif cpt: fpr.green('%s : %s : %s' % (t,cpt,r) ) # cpt = r / t # t = r / cpt if cpt >= r: cpt_new = r t = 1 fpr.err('realistic returns would be: t = %s, cpt = %s for r = %s' % (t,cpt_new,r)) setReals(t,cpt_new) if cpt < r: # I - validate T - t < R t = float(r) / cpt fpr.green('counted t = %s' % t) # round up - if there is a remainder if (r % cpt > 0): t = r / cpt + (r % cpt > 0) fpr.green('rounding up t = %s' % t) # find the lowest T for rounded CpT cpt_new = float(r) / t fpr.green('counted new cpt = %s' % cpt_new) fpr.err('realistic returns would be: *t = %s, cpt = %s for r = %s' % (int(t),int(cpt_new),r)) setReals(int(t),int(cpt_new)) else: fpr.err('realistic returns would be: t = %s, cpt = %s for r = %s' % (t,int(cpt),r)) setReals(int(t),int(cpt)) else: fpr.err('err') else: fpr.err('Recipients not defined. Build a list of recipients first.') fpr.err('Flush the values if the recipient list has been modified.')
def enumSMTPcmd(v=None,dhost=smtp['connect']['hosts'][0]): #TODO: if no EHLO , use HELO from pprint import pprint # secure extn - list of extn received after successfull STARTTLS commands scmds = { 'extn' : [], 'secure_extn': [], 'cmds': '', 'method': [], } #pprint(dhost) #pprint(scmds) print try: import sys import smtplib # run smtp session if v: fpr.white('Establishing the session with %s on port %s' % (dhost['host'],dhost['port'])) s = smtplib.SMTP(dhost['host'],dhost['port']) if v: fpr.cyan('>>> %s' % 'HELP') r = s.help() scmds['scmds'] = r if v: fpr.green('<<< %s' % r) # if cfgs['conv_logs'] and cl: # s.set_debuglevel('debug') # HELO - introduce yourself if v: fpr.cyan('>>> %s %s' % ('EHLO',dhost['helo'])) (c,m) = s.ehlo(dhost['helo']) #r = s.helo(smtp['connect']['hosts'][0]['helo']) #print (c,m) if 200 <= c <= 299: if v: fpr.green('<<< %s %s' %(c,m)) if s.does_esmtp: if v: fpr.white('ESMTP supported and have extn:') #print s.does_esmtp #print s.esmtp_features for (scmd,sarg) in s.esmtp_features.items(): if v: fpr.white(' * %s %s' % (scmd,sarg)) scmds['extn'].append((scmd,sarg)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) # STAARTTLS if 'starttls' in s.esmtp_features.keys(): if dhost['tls_mode'] == 'TLS': if v: fpr.white('TLS supported and requested') fpr.white('Establishing TLS session ..') fpr.cyan('>>> %s' % ('STARTTLS')) (c,m) = s.starttls() if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) # HELO - introducing yourself on encrypted session should be done as well if v: fpr.cyan('>>> %s %s' % ('EHLO',dhost['helo'])) (c,m) = s.ehlo(dhost['helo']) if v: #print (c,m) if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) if s.does_esmtp: fpr.white('ESMTP supported and have extn:') #print s.does_esmtp #print s.esmtp_features for (scmd,sarg) in s.esmtp_features.items(): fpr.white(' * %s %s' % (scmd,sarg)) scmds['secure_extn'].append((scmd,sarg)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) else: if v: fpr.white('TLS supported but not requested') fpr.white('Unencrypted session established') # # SMTP AUTH # if 'auth' in s.esmtp_features.keys(): # if smtp['connect']['hosts'][0]['smtp_auth_user'] != '': # if v: # fpr.cyan('>>> %s %s' % ('AUTH PLAIN','*********')) # (c,m) = s.login(smtp['connect']['hosts'][0]['smtp_auth_user'],smtp['connect']['hosts'][0]['smtp_auth_pass']) # if v: # if 200 <= c <= 299: # fpr.green('<<< %s %s' %(c,m)) # elif 500 <= c <= 599: # fpr.err('<<< %s %s' %(c,m)) # else: # if smtp['connect']['hosts'][0]['smtp_auth_user'] != '': # if v: # fpr.white('Authentication SET but not available (AUTH not supported)') # fpr.white('Trying without AUTH') # else: # if v: # fpr.white('Authentication not available (AUTH not supported)') # fpr.white('Trying without AUTH') #print rcpts r = 'postmaster' for sm in ['EXPN','VRFY']: if v: fpr.cyan('>>> %s <%s>' % (sm,r)) (c,m) = s.docmd('%s' % sm,'<%s>' % r) if 200 <= c <= 299: if v: fpr.green('<<< %s %s' %(c,m)) scmds['method'].append(sm) elif 500 <= c <= 599: if v: fpr.err('<<< %s %s' %(c,m)) else: if v: fpr.err('<<< %s %s' %(c,m)) if 'rcpt' in scmds['scmds'].lower(): scmds['method'].append('RCPT') # pprint(dhar) # quit smtp session if v: fpr.cyan('>>> %s' % ('QUIT:')) (c,m) = s.quit() if v: if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) fpr.white('Session closed successfully') elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) #pprint(scmds) return scmds # the exception is triggered only when all recipoient failed :( except smtplib.SMTPRecipientsRefused, e: fpr.fail('Error: unable to sent message. All recipients refused.') fpr.warn(str(e))
def smtp_sender(message, rpm=None, mpt=None, rate=None, rcpts=[], relays={}, name='T-Single'): #from core.data import smtp,fpr,tc from core.data import cfgs, smtp, fpr, tc, DEBUG from core.func import dbginfo from core.msg.viewers import viewSmtpConv from core.msg.threads import get_tid # TODO: allow conv logs use with threads # for now: use conv logs only with single thread # for 3.1 inject message cl = 0 if name == 'T-Single': cl = 1 # ---------------------------------------------------- # # log thread session import logging # create logger logger = logging.getLogger('threadslogs') logger.info('Starting thread: [%s]' % name) logger.debug('[%s]: Pid=%d' % (name, get_tid())) logger.debug('[%s]: rpm=%s ,mpt=%s, rate=%s, rcpts=%s' % (name, rpm, mpt, rate, rcpts)) # host logger.info('[%s]: H=%s:%s, smtp_auth=(%s,%s)' % (name, smtp['connect']['hosts'][0].get('host'), smtp['connect']['hosts'][0].get('port'), smtp['connect']['hosts'][0].get('smtp_auth_user'), smtp['connect']['hosts'][0].get('smtp_auth_pass'))) print # ---------------------------------------------------- # dbginfo( 'DEBUG', 'name=%s, rpm=%s ,mpt=%s, rate=%s, rcpts=%s' % (name, rpm, mpt, rate, rcpts)) #return 0 # ---------------------------------------------------- # from StringIO import StringIO class StderrLogger(object): def __init__(self): #self.logger = logging.getLogger('threadslogs') self.sio = StringIO() def write(self, message): #self.logger.debug(message) self.sio.write(message) # ---------------------------------------------------- # try: import sys import smtplib # log debuglevel output from smtplib # redirect stderr from smtplib to string # # - from smtplib import stderr if cfgs['conv_logs'] and cl: ostderr = smtplib.stderr smtplib.stderr = StderrLogger() # run smtp session s = smtplib.SMTP(smtp['connect']['hosts'][0]['host'], smtp['connect']['hosts'][0]['port']) if cfgs['conv_logs'] and cl: s.set_debuglevel('debug') # HELO - introduce yourself s.ehlo(smtp['connect']['hosts'][0]['helo']) # STAARTTLS if smtp['connect']['hosts'][0]['tls_mode'] == 'TLS': s.starttls() # SMTP AUTH if smtp['connect']['hosts'][0]['smtp_auth_user'] != '': s.login(smtp['connect']['hosts'][0]['smtp_auth_user'], smtp['connect']['hosts'][0]['smtp_auth_pass']) # MAIL FROM sender = smtp['addrlist']['mail_from'] #rcpt = smtp['addrlist']['rcpt_to'] # for single injection or when mpt value unknown use single message per connection if mpt == None: mpt = 1 rpm = len(rcpts) # split messages per connection for m in range(mpt): # m strt from 0 to mpt-1 # split rcpts per message si = m * rpm ei = m * rpm + rpm m_rcpts = rcpts[si:ei] #print (m,si,ei,m_rcpts) if m_rcpts: logger.debug('[%s]: F=%s, MPT=%s/%s R=%s' % (name, sender, (m + 1), mpt, m_rcpts)) # SEND # https://docs.python.org/2/library/email.message.html#email.message.Message # as_string([unixfrom]) # Return the entire message flattened as a string. When optional unixfrom is True, the envelope header is included in the returned string. unixfrom defaults to False. Flattening the message may trigger changes to the Message if defaults need to be filled in to complete the transformation to a string (for example, MIME boundaries may be generated or modified). response = s.sendmail(sender, m_rcpts, message.as_string(unixfrom=False)) if response: smtp['addrlist']['r_reject'].update(response) # dbginfo('debug', 'Sendmail response list:', str(response)) dbginfo('debug', 'Failed recipients:', str(smtp['addrlist']['r_reject'])) # The response returns a dictionary, with one entry for each recipient that # was refused. Each entry contains a tuple of the SMTP error code and the # accompanying error message sent by the server. # 'r_reject': {'': (501, '#5.1.1 bad address'), # "'*****@*****.**'": (550,'#5.1.0 Address rejected.'), # "'*****@*****.**'": (550,'#5.1.0 Address rejected.'), # "'*****@*****.**'": (550,'#5.1.0 Address rejected.'), # to be compatibile with other features build a r_valid dict # m_rcpts - all rcpts per tread for r in m_rcpts: if not r in response.keys(): # recipient is valid if not refused smtp['addrlist']['r_valid'].setdefault(r, (250, 'OK')) # s.sendmail(sender, rcpt, message.as_string(unixfrom=False)) # quit smtp session s.quit() #FIXME: # message sent success : nto true when threads with more than one message in it # fix this print info if name == 'T-Single': fpr.ok('Message was sent successfuly') smtp['replay']['threads']['ok'].append(name) # when only part of recipients/sender failed it looks like than # exception for recipientsRefused is not triggered # remember: to clear refu recipient list before you call out this function if response: smtp['addrlist']['r_reject'].update(response) dbginfo('debug', 'Sendmail response list:', str(response)) dbginfo('debug', 'Failed recipients:', str(smtp['addrlist']['r_reject'])) #from core.msg.viewers import viewRecipientsRefused # All recipients were refused. Nobody got the mail. The recipients attribute of # the exception object is a dictionary with information about the refused # recipients (like the one returned when at least one recipient was accepted). # the exception is triggered only when all recipoient failed :( except smtplib.SMTPRecipientsRefused, e: fpr.fail('Error: unable to sent message. All recipients refused.') smtp['replay']['threads']['fail'].append(name) #print 'exception smtplib.SMTPRecipientsRefused',a fpr.warn(str(e)) smtp['addrlist']['r_reject'].update(e.recipients)
def __init__(self, menu): # set self.menu = menu fpr(menu.get('head', 'Test Menu Options:')) if menu.get('info'): fpr.warn('_' * (tc - 4)) print fpr(menu.get('info')) fpr.warn('_' * (tc - 4)) print #print menu opts = menu.get('opts', []) offs = menu.get('offs', []) #print offs for (i, o) in opts: #print (i,o) if i in offs: fpr.DFLT = fpr.GRAY if i == 'nl': print elif i == 'sep': fpr(' %s' % o) elif i == 'txt': fpr(' %s' % o) else: if not DEBUG and i in offs: pass elif len(i) > 1: fpr(' %s) %s' % (i, o)) else: fpr(' %s) %s' % (i, o)) # reset tmp colour set fpr.DFLT = None print if utf8Term(): fpr(" %s return or q to quit" % self.esign) else: fpr(" Press Enter to return or q to quit") print ################################################################# self.op = raw_input(self.prompt) if self.op in offs: if not DEBUG: self.op = '' if self.op in ['q', 'x', 'Q', 'X']: print fpr('See You Later Alligator') sys.exit(0) if self.op == '': fpr('Return to Main Menu') #sys.exit(0) #break return else: print ################################################################# return
def mail_body_parser(body): if not hasattr(body, 'as_string'): fpr.err('Message can not be processed or not loaded !') return b = email.message_from_string(body.as_string()) btype = b.get_content_type() dbginfo('debug', 'btype is %s' % btype) print # parse the body and save split parts in dictionary dparts = dict() body_parser(dparts, b) fpr.cyan('=' * (tc - 4)) # pprint(dparts) if DEBUG: dbginfo('debug', str(dparts.keys())) fpr.cyan('=' * (tc - 4)) ## build a dictionary print if not dparts.keys(): fpr('No MIME parts found') return mimemulti = ['multipart/mixed', 'multipart/alternative'] print mimemulti while True: bancls() fpr('Message MIME structure') print fpr('_' * (tc - 4)) print bstrio = StringIO() _structure(b, bstrio) fpr.warn('%s' % bstrio.getvalue()) #fpr.warn(_structure(bpart)) fpr('_' * (tc - 4)) print fpr('MIME parts ready to review:') print for k in dparts.keys(): #print k #print type(k) if dparts[k]['type'] in mimemulti: fpr.info(' [%s] %s ' % (k, dparts[k]['type'][:69])) else: fpr(' [%s] %s ' % (k, dparts[k]['type'][:69])) print op = raw_input(' []> ') # dparts keys are int not strings if op.isdigit(): k = int(op) if op == '': break while k in dparts.keys(): bancls() fpr('MIME Headers: %s' % k) fpr('_' * (tc - 4)) print for (h, hv) in dparts[k]['mheaders']: fpr('%s: %s' % (h, hv)) fpr('_' * (tc - 4)) print # pprint(dparts) # waitin() if dparts[k].get('type') in mimemulti: fpr.warn('This part is not directly viewable') waitin() break elif dparts[k].get('payload'): fpr('Choose option:') print fpr(' 1) view payload') fpr(' 2) save payload') fpr.off(' 3) attach payload to composer [?future feature?]') print op = raw_input(' []> ') if op == '': waitin() break # --- view payload --- if op in ['1']: bancls() fpr('MIME Payload ') print fpr.warn('%s' % dparts[k].get('type')) print xe = 0 for (h, hv) in dparts[k].get('mheaders'): #fpr('%s: %s' % (h,hv)) if h.lower() == 'content-transfer-encoding': #part['encext'] = '.'+hv.lower() if hv in ['base64']: info( 'info', 'This payload is base64 encoded. You can view it as it is or try to decode it first.' ) print if get_yesno_input( ' Would like to decode the payload first [y/N]:> ' ): dp = decode_attch(dparts[k]['payload']) #pprint(dp) #print len(dp.get('raw')) #print len(str(dp)) if len(dp.get('raw')) > tr: #if True: if get_yesno_input( ' Would like to use system pager to view it [y/N]:> ' ): fpr('_' * (tc - 4)) print pager = Less(num_lines=tr) print dp.get('raw') | pager fpr('_' * (tc - 4)) else: fpr('_' * (tc - 4)) print fpr(dp.get('raw')) print fpr('_' * (tc - 4)) waitin() xe = 1 break # if viewed decoded part do not display encoded one if xe: break print if len(dparts[k].get('payload')) > tr: if get_yesno_input( ' Would like to use system pager to view it [y/N]:> ' ): fpr('_' * (tc - 4)) print pager = Less(num_lines=tr) print dparts[k]['payload'] | pager fpr('_' * (tc - 4)) else: fpr('_' * (tc - 4)) print fpr(dparts[k]['payload']) print fpr('_' * (tc - 4)) else: fpr('_' * (tc - 4)) print if type(dparts[k].get('payload')) is not 'str': fpr.err('An error occured') else: fpr(dparts[k].get('payload')) print fpr('_' * (tc - 4)) waitin() if op in ['2']: bancls() fpr('MIME Payload export') fpr('Choose option:') print fpr(' 1) save payload, as it is (no decoding)') fpr(' 2) save payload - base64 decoded') print op = raw_input(' []> ') print if op == '': waitin() break if op in ['1']: bancls() mpart_saver(dparts[k], 1) waitin() if op in ['2']: bancls() mpart_saver(dparts[k], 2) waitin() break else: fpr.warn( 'Wrr: Empty payloyd. Message malformed or parsing has failed.' ) waitin() break
def chThrDep(t=None, rpm=None, mpt=None): #VERIFY: In Python 2.x : int/int --> int and int/float --> float In Python 3.x : int/int can result in a float from core.data import smtp, fpr, tc, tr from core.func import waitin r = get_rcpts('NoR') #Warunki Konieczne - Essential Conditions # to met WK1, WK2, WK3 if not t: t = smtp['replay']['threads'].get('not', None) elif t and not (1 <= int(t) <= r): if r > 1: t = r if r == 1: #special case pass if t: smtp['replay']['threads']['not'] = int(t) if not rpm: rpm = smtp['replay']['threads'].get('rpm', None) elif rpm and not (1 <= int(rpm) <= r): rpm = int(r) if rpm: fpr.ok('Saving RpM as %s' % rpm) smtp['replay']['threads']['rpm'] = int(rpm) if not mpt: mpt = smtp['replay']['threads'].get('mpt', None) elif mpt and not (1 <= int(mpt) <= r): mpt = int(r) if mpt: fpr.ok('Saving MpT as %s' % mpt) smtp['replay']['threads']['mpt'] = int(mpt) if r: # specific feature: the result depends from number of recipients # -------------------------------------------------------------------- # if t and not rpm and not mpt: fpr.warn('%s : %s : %s - %s' % (t, rpm, mpt, r)) # allow to set t if no rpm or mpt values and number of rcpt > 1 # but t must be <= r, so if t greater then r => it will be equal to r if r > 1: smtp['replay']['threads']['not'] = int(t) fpr.ok('Saving NoT as %s' % t) return t # special case when r == 1 , not related to our Equation # for r = 1 allow to set T > 1 but do not allow than set rpm or mpt # in this special case the sam message is flooding a sepcific rcpt # with this smae message in multiple threads/connection ! if r == 1: #pass smtp['replay']['threads']['not'] = int(t) fpr.ok('Saving NoT as %s' % t) return t # set initial elif rpm and not t and not mpt: fpr.warn('%s : %s : %s - %s' % (t, rpm, mpt, r)) if r > 1: smtp['replay']['threads']['rpm'] = int(rpm) #return rpm #return True if r == 1: fpr.warn('It doesn\'t make sense to define RpM when NoR = 1') return False # elif mpt and not t and not rpm: fpr.warn('%s : %s : %s - %s' % (t, rpm, mpt, r)) if r > 1: smtp['replay']['threads']['mpt'] = int(mpt) #return mpt #return True if r == 1: fpr.warn('It doesn\'t make sense to define MpT when NoR = 1') return False else: fpr.err('Recipients not defined. Build a list of recipients first.') fpr.err('Flush the values if the recipient list has been modified.') return # Some maths :) # # rpm - recipient per message # r - number of recipients (all) # m - number of messages (all) # # rpm = r / m ==> m = r / rpm # mpt - messages per thread # t - number of threads # m - number of messages (all) # # mpt = m / t ==> m = mpt * t # r / rpm = mpt * t # # ==> t = r / (rpm * mpt) # # ==> rpm = r / (mpt * t) # # ==> mpt = r / (rpm * t) fpr.info('_' * (tc - 4)) print fpr.warn('Your limits:') fpr.warn('t = %s : rpm = %s : mpt = %s - r = %s' % (smtp['replay']['threads'].get( 'not', None), smtp['replay']['threads'].get('rpm', None), smtp['replay']['threads'].get('mpt', None), r)) print fpr.err('Maximum possible limits to met Essential Conditions:') fpr.err('t = %s : rpm = %s : mpt = %s - r = %s' % (t, rpm, mpt, r)) fpr.info('_' * (tc - 4)) print def chEque(): print if r: # compare float # https://ubuntuforums.org/showthread.php?t=840665 def float_eq(a, b, epsilon=0.00000001): fpr.cyan('<float_eq> %s' % abs(a - b)) if abs(a - b) < epsilon: return True return False m1 = float(r) / rpm m2 = mpt * float(t) fpr.cyan('r/rpm = %s, mpt * t = %s' % (m1, m2)) if float_eq(m1, m2): fpr.green('Equetion is met') waitin() return True else: fpr.err('Equetion is false') waitin() return False def setReals(t, rpm, mpt): if t and rpm and mpt: smtp['replay']['threads']['reals'].setdefault('not', t) smtp['replay']['threads']['reals'].setdefault('rpm', rpm) smtp['replay']['threads']['reals'].setdefault('mpt', mpt) smtp['replay']['threads']['reals']['not'] = t smtp['replay']['threads']['reals']['rpm'] = rpm smtp['replay']['threads']['reals']['mpt'] = mpt fpr.ok('Reals were set!') if r: # count the mpt - based on rpm and t # -------------------------------------------------------------------- # if t and rpm and not mpt: fpr.green('%s : %s : %s - %s' % (t, rpm, mpt, r)) # m = r / rpm # mpt = m / t # I - validate MPT - MPT <= R mpt = float(r) / (rpm * t) fpr.green('counting mpt = %s' % mpt) chEque() # round up - if there is a remainder if (r % (rpm * t) > 0): mpt = r / (rpm * t) + (r % (rpm * t) > 0) fpr.green('rounding up mpt = %s' % mpt) # find the lowest T for rounded MpT to met RpM t_new = float(r) / (rpm * mpt) #+ (r % (rpm * mpt) > 0) fpr.green('counting new t = %s' % t_new) if (r % (rpm * mpt) > 0): # if remainder t_new = r / (rpm * mpt) + (r % (rpm * mpt) > 0) fpr.green('rounding up new t = %s' % t_new) fpr.err( 'realistic returns would be: *t = %s, rpm = %s, mpt = %s for r = %s' % (int(t_new), rpm, int(mpt), r)) setReals(int(t_new), rpm, int(mpt)) else: fpr.err( 'realistic returns would be: t = %s, rpm = %s, mpt = %s for r = %s' % (t, rpm, int(mpt), r)) setReals(t, rpm, int(mpt)) # count the rpm - for mpt and t # -------------------------------------------------------------------- # elif t and mpt and not rpm: fpr.blue('%s : %s : %s - %s' % (t, rpm, mpt, r)) # m = mpt * t # m = r / rpm # TODO # WK: validate RPM , RPM <= R rpm = float(r) / (mpt * t) fpr.blue('counting: rpm = %s' % rpm) chEque() # if there is a remainder if (r % (mpt * t) > 0): rpm = r / (mpt * t) + (r % (mpt * t) > 0) fpr.blue('rounding up rpm = %s' % rpm) # find the lowest T for rounded MpT to met RpM t_new = float(r) / (rpm * mpt) #+ (r % (rpm * mpt) > 0) fpr.green('counting new t = %s' % t_new) if (r % (rpm * mpt) > 0): # if remainder t_new = r / (rpm * mpt) + (r % (rpm * mpt) > 0) fpr.green('rounding up new t = %s' % t_new) fpr.err( 'realistic returns would be: *t = %s, rpm = %s, mpt = %s for r = %s' % (int(t_new), int(rpm), mpt, r)) setReals(int(t_new), int(rpm), mpt) else: fpr.err( 'realistic returns would be: t = %s, rpm = %s, mpt = %s for r = %s' % (t, int(rpm), mpt, r)) setReals(t, int(rpm), mpt) # count the mpt ( use t = 1 ) # -------------------------------------------------------------------- # elif rpm and not t and not mpt: t = 1 fpr.purple('assuming t eq 1 for equation') fpr.purple('%s : %s : %s - %s' % (t, rpm, mpt, r)) mpt = float(r) / rpm fpr.purple('counting: mpt = %s' % mpt) chEque() #if there is a remainder if (r % rpm > 0): mpt = r / rpm + (r % rpm > 0) fpr.purple('rounding up mpt = %s' % mpt) # find the lowest T for rounded MpT to met RpM t_new = float(r) / (rpm * mpt) #+ (r % (rpm * mpt) > 0) fpr.green('counting new t = %s' % t_new) if (r % (rpm * mpt) > 0): # if remainder t_new = r / (rpm * mpt) + (r % (rpm * mpt) > 0) fpr.green('rounding up new t = %s' % t_new) fpr.err( 'realistic returns would be: *t = %s, rpm = %s, mpt = %s for r = %s' % (int(t_new), rpm, mpt, r)) setReals(int(t_new), rpm, mpt) else: fpr.err( 'realistic returns would be: t = %s, rpm = %s, mpt = %s for r = %s' % (t, rpm, int(mpt), r)) setReals(t, rpm, int(mpt)) # count the rpm ( use t = 1 ) # -------------------------------------------------------------------- # elif mpt and not t and not rpm: t = 1 fpr.purple('assuming t eq 1 for equation') fpr.purple('%s : %s : %s - %s' % (t, rpm, mpt, r)) rpm = float(r) / mpt fpr.purple('counting: rpm = %s' % rpm) t = 1 chEque() #if there is a remainder if (r % mpt > 0): rpm = r / mpt + (r % mpt > 0) fpr.purple('rounding up rpm = %s' % rpm) # find the lowest T for rounded MpT to met RpM t_new = float(r) / (rpm * mpt) #+ (r % (rpm * mpt) > 0) fpr.green('counting new t = %s' % t_new) if (r % (rpm * mpt) > 0): # if remainder t_new = r / (rpm * mpt) + (r % (rpm * mpt) > 0) fpr.green('rounding up new t = %s' % t_new) fpr.err( 'realistic returns would be: *t = %s, rpm = %s, mpt = %s for r = %s' % (int(t_new), int(rpm), mpt, r)) setReals(int(t_new), int(rpm), mpt) else: fpr.err( 'realistic returns would be: t = %s, rpm = %s, mpt = %s for r = %s' % (t, int(rpm), mpt, r)) setReals(t, int(rpm), mpt) # count t - for rpm and mpt # -------------------------------------------------------------------- # elif mpt and rpm and not t: fpr.white('%s : %s : %s - %s' % (t, rpm, mpt, r)) print type(mpt) # add 1 to round up a result # (r % (rpm * mpt) > 0) it will return True which is 1 # if there is a remainder and 0 if not t = float(r) / (rpm * mpt) #+ (r % (rpm * mpt) > 0) fpr.white('counted: t = %s' % t) chEque() # round up if (r % (rpm * mpt) > 0): t = r / (rpm * mpt) + (r % (rpm * mpt) > 0) fpr.white('rounding up t = %s' % t) # validate WK # t = <1,r> # if t < 1 if (float(r) / (rpm * mpt)) < 1: fpr.info('Now to met equetion for t=1 it is not possible for %s (R) recipients '\ 'to send %s (MpT) messeges in one thread with %s (RpM) recipient in message' % (r,mpt,rpm)) print fpr.info('New RpM value can be counted based on existing MpT or new MpT ' \ 'value can be counted based on existing RpM' ) print fpr.info('For simplicity it is assumed that RpM limits is more important so MpT ' \ 'is going to be recounted to met an equation') print mpt_new = float(r) / rpm fpr.white('New MpT to met equetion is %s' % mpt_new) mpt = mpt_new chEque() # now just round up mpt_new = r / rpm + (r % rpm > 0) fpr.white('rounding up new mpt = %s' % mpt_new) fpr.err( 'realistic returns would be: t = %s, rpm = %s, *mpt = %s for r = %s' % (int(t), rpm, int(mpt_new), r)) setReals(int(t), rpm, int(mpt_new)) else: # so if t > 1 and it was counted fpr.err( 'realistic returns would be: t = %s, rpm = %s, mpt = %s for r = %s' % (int(t), rpm, int(mpt), r)) setReals(int(t), rpm, int(mpt)) # only true if r / rpm = mpt * t # -------------------------------------------------------------------- # elif t and rpm and mpt: fpr.cyan('%s : %s : %s - %s' % (t, rpm, mpt, r)) if not chEque(): fpr.info('_' * (tc - 4)) print fpr.warn('It is not recommended trying to set NoT with RpM and MpT. ' \ 'Suggested action would be to flush these values.' ) fpr.info('_' * (tc - 4)) print waitin() return False else: fpr.err( 'realistic returns would be: t = %s, rpm = %s, mpt = %s for r = %s' % (t, rpm, mpt, r)) setReals(t_new, rpm, mpt) # for test waitin()
def splitHeaders(inputs, crlf=False): #TODO: split headers and parse one header per import email bancls() print fpr.warn('_' * (tc - 4)) print print inputs print fpr.warn('_' * (tc - 4)) print print '\r\n'.join(inputs) print fpr.warn('_' * (tc - 4)) print waitin() bancls() if crlf: # remove empty elements from list # no newlines are allowed between headers inputs = [x for x in inputs if x != ''] msg = email.message_from_string('\r\n'.join(inputs)) AUTHRE = re.compile('Authentication-Results', re.IGNORECASE) RECSPF = re.compile('Received-SPF', re.IGNORECASE) hh = { 'Received-SPF': list(), 'Authentication-Results': list(), } parser = email.parser.HeaderParser() headers = parser.parsestr(msg.as_string()) for hn, hv in headers.items(): if DDDEBUG: fpr.green('Found: %s\n%s' % (hn, hv)) m1 = re.match(AUTHRE, hn) m2 = re.match(RECSPF, hn) if m1: if DDDEBUG: print hn, hv hh['Authentication-Results'].append(hv) if m2: if DDDEBUG: print hn, hv hh['Received-SPF'].append(hv) # print "---------------------------------" # from pprint import pprint # pprint(hh) # print "---------------------------------" # print #build a list # print len(hh['Received-SPF']) # print len(hh['Authentication-Results']) pp = { 'Received-SPF': dict(), 'Authentication-Results': dict(), } for hn in ['Received-SPF', 'Authentication-Results']: x = 0 for h in hh[hn]: p = parse_spfHeaders2('%s: ' % hn + h) if DDDEBUG: pprint(p) pp.setdefault(hn, x) x += 1 pp[hn].setdefault(x, p) print "---------------------------------" pprint(pp) print "---------------------------------" return pp
print try: q = spf.query(i=dd.get('ip'), s=dd['id'].get('mfrom'), h=dd['id'].get('helo'), timeout=20, verbose=False, querytime=0) except Exception, e: fpr.err('Err: %s' % e) waitin() return if not dd['id'].get(spfid): print fpr.warn('Verification skipped. No identity found') waitin() return if not dd.get('ip'): print fpr.warn('Verification skipped. Missing client IP address!') waitin() return # if SPF Policy is defined manually skip DNS and use it if dd.get('policy'): #fpr('SPF record supplied by input is found! ') fpr('Policy origin: User input\n\n') if get_yesno_input( ' Run validation against supplied SPF record [y/N]: > '):
def parse_spfHeaders2(h): from email.message import Message import re if not h: return False #print type(h) #print h #h1 = h.replace('\n','') #print h1 # re.DOTALL '.'match everything inludinf newline # re.IGNORECASE is used at the splitHeaders() function first AUTHRE = re.compile('^(Authentication-Results):(.*)', re.DOTALL) RECSPF = re.compile('^(Received-SPF):(.*)', re.DOTALL) m1 = re.match(AUTHRE, h) m2 = re.match(RECSPF, h) if DDDEBUG: fpr.purple(h) dd = {'hn': '', 'hv': ''} #""" Authentication-Results """ if m1: dd['hn'] = m1.group(1) dd['hv'] = m1.group(2) fpr.info('_' * (tc - 4)) print fpr('Header-name : %s' % m1.group(1)) fpr('Header-value : %s' % m1.group(2)) fpr.info('_' * (tc - 4)) print try: import authres # FIXME: fast workaround for authres module # # remove "d=" tag from dmarc auth method as authres # does recognize only below ptype # -> elif ptype.lower() not in ['smtp', 'header', 'body', 'policy'] # and it raise a Syntax error for d= h = h.replace('\n', '') h = h.replace('\r', '') h = h.replace('\t', ' ') DTAG = re.compile('.*dmarc=.* \(.*\)* d=([a-z0-9\.\-]+)', re.IGNORECASE) md = re.match(DTAG, h) if md: fpr.warn('Stripping "d=" tag from dmarc method: d=%s' % md.group(1)) #fpr.green( '%s ---- %s' % (md.group(1), md.group())) h = re.sub('d=%s' % md.group(1), '', h) if DDDEBUG: print h #else: # print 'no d-tag' arh = authres.AuthenticationResultsHeader.parse(h) #if DDDEBUG: # from pprint import pprint # pprint(str(arh)) except Exception, e: fpr.err('Exception: %s' % e) p = {} if str(arh.authserv_id): p['authserv_id'] = str(arh.authserv_id) print len(arh.results) for i in arh.results: if DDDEBUG: pprint(i) fpr('method: %s' % str(i.method)) if str(i.method) == 'spf': p.setdefault('spf', {}) p['spf'].setdefault('mailfrom', {}) p['spf'].setdefault('helo', {}) p['spf'].setdefault('pra', {}) if DDDEBUG: fpr('result : %s' % str(i.result)) if hasattr(i, 'smtp_mailfrom'): fpr('smtp.mailfrom : %s' % str(i.smtp_mailfrom)) if hasattr(i, 'smtp_helo'): fpr('smtp.helo : %s' % str(i.smtp_helo)) if hasattr(i, 'smtp_pra'): fpr('smtp.pra : %s' % str(i.smtp_pra)) for j in i.properties: if j.name == 'mailfrom': p['spf']['mailfrom']['result'] = str(i.result) p['spf']['mailfrom']['type'] = str(j.type) p['spf']['mailfrom']['name'] = str(j.name) p['spf']['mailfrom']['value'] = str(j.value) if j.name == 'helo': p['spf']['helo']['result'] = str(i.result) p['spf']['helo']['type'] = str(j.type) p['spf']['helo']['name'] = str(j.name) p['spf']['helo']['value'] = str(j.value) if j.name == 'pra': p['spf']['pra']['result'] = str(i.result) p['spf']['pra']['type'] = str(j.type) p['spf']['pra']['name'] = str(j.name) p['spf']['pra']['value'] = str(j.value) if DDDEBUG: fpr.green(' type: %s' % str(j.type)) fpr(' name: %s' % str(j.name)) fpr(' value: %s' % str(j.value)) if str(i.method) == 'dkim': p.setdefault('dkim', {}) p['dkim']['result'] = str(i.result) if DDDEBUG: fpr('result : %s' % str(i.result)) fpr('header_i : %s' % str(i.header_i)) for j in i.properties: # dkim header identity p['dkim']['header_i'] = str(j.value) if DDDEBUG: fpr.green(' type: %s' % str(j.type)) fpr(' name: %s' % str(j.name)) fpr(' value: %s' % str(j.value)) if str(i.method) == 'dmarc': p.setdefault('dmarc', {}) p['dmarc']['result'] = str(i.result) if DDDEBUG: fpr('result : %s' % str(i.result)) p['h_value'] = dd['hv'] return p
def body_parser(dparts, bpart, x=0): # fpr('Message MIME structure') # print # fpr('_'*(tc-4)) # from email.iterators import _structure # fpr.blue('%s' % _structure(bpart) ) # #fpr.warn(_structure(bpart)) # fpr('_'*(tc-4)) print if bpart.is_multipart(): fpr.warn('~' * (tc - 4)) for part in bpart.walk(): print part.get_boundary() print part.get_content_type() print '== multipart ==' for payload in bpart.get_payload(): # if payload.is_multipart(): ... ptype = payload.get_content_type() print '--> ptype: ', ptype if ptype == 'multipart/alternative': #dparts[x] for subpart in payload.get_payload(): print '> subpart: ', subpart.get_content_type() x += 1 body_parser(dparts, subpart, x) elif ptype == 'multipart/related': print "---- m/realated ----" pprint(bpart) print dir(bpart) print bpart.get_params() print bpart.get_param('start', None) print bpart.get_param('type', None) for i, subpart in enumerate(bpart.get_payload()): print(i, subpart) print '> subpart: ', subpart.get_content_type() x += 1 body_parser(dparts, subpart, x) return #if (not start and i==0) or (start and start==subpart.get('Content-Id')): # _search_message_bodies(bodies, subpart) # return elif ptype == 'multipart/report': fpr.err('multipart/report is not supported') return elif ptype == 'multipart/signed': fpr.err('multipart/signed is not supported') retunr elif ptype == 'message/rfc822': # if ptype == fpr.err('message/rfc822 trying to parse') for subpart in payload.get_payload(): print '> m/rfc822 subpart: ', subpart.get_content_type() x += 1 body_parser(dparts, subpart, x) else: print '--else ptype=:', ptype, x x += 1 dparts[x] = dict() dparts[x]['mheaders'] = payload.items() dparts[x]['type'] = payload.get_content_type() dparts[x]['payload'] = payload.get_payload() dparts[x]['filename'] = payload.get_filename() else: print '--else no multipart' print bpart.get_content_type() print 'x=', x dparts[x] = dict() dparts[x]['mheaders'] = bpart.items() dparts[x]['type'] = bpart.get_content_type() dparts[x]['payload'] = bpart.get_payload() dparts[x]['filename'] = bpart.get_filename() #pprint(dparts[x]) #x +=1 #fpr('-- Non MIME Multipart Part --') """
def smtp_sender_new(message, rpm=None, mpt=None, rate=None, rcpts=[], relays={}, name='T-Single'): #from core.data import smtp,fpr,tc from core.data import cfgs, smtp, fpr, tc, DEBUG from core.func import dbginfo from core.msg.viewers import viewSmtpConv from core.msg.threads import get_tid dhost = smtp['connect']['hosts'][0] # name of Thread define if this function is run as part of single connection or multithread connection # use convesation logs onlyin single thread # for 3.1 inject message # TODO: enable conv logs for threads cl = 0 if name == 'T-Single': cl = 1 # ---------------------------------------------------- # # log thread session import logging # create logger logger = logging.getLogger('threadslogs') logger.info('Starting thread: [%s]' % name) logger.debug('[%s]: Pid=%s' % (name, get_tid())) logger.debug('[%s]: rpm=%s ,mpt=%s, rate=%s, rcpts=%s' % (name, rpm, mpt, rate, rcpts)) # host logger.info('[%s]: H=%s:%s, smtp_auth=(%s,%s)' % (name, dhost.get('host'), dhost.get('port'), dhost.get('smtp_auth_user'), dhost.get('smtp_auth_pass'))) print # ---------------------------------------------------- # dbginfo( 'DEBUG', 'name=%s, rpm=%s ,mpt=%s, rate=%s, rcpts=%s' % (name, rpm, mpt, rate, rcpts)) #return 0 # ---------------------------------------------------- # from StringIO import StringIO class StderrLogger(object): def __init__(self): #self.logger = logging.getLogger('threadslogs') self.sio = StringIO() def write(self, message): #self.logger.debug(message) self.sio.write(message) # ---------------------------------------------------- # try: import sys import smtplib # log debuglevel output from smtplib # redirect stderr from smtplib to string # # - from smtplib import stderr if cfgs['conv_logs'] and cl: ostderr = smtplib.stderr smtplib.stderr = StderrLogger() # run smtp session if name == 'T-Single': s = smtplib.SMTP(dhost['host'], dhost['port']) else: s = SMTPExt(dhost['host'], dhost['port']) if cfgs['conv_logs'] and cl: s.set_debuglevel('debug') # HELO - introduce yourself s.ehlo(dhost['helo']) #s.ehlo_or_helo_if_needed() # STAARTTLS fpr.warn(dhost['tls_mode']) if dhost['tls_mode'] == 'TLS': s.starttls() # HELO - introduce yourself s.ehlo(dhost['helo']) #s.ehlo_or_helo_if_needed() # SMTP AUTH if dhost.get('smtp_auth_user'): s.login(dhost.get('smtp_auth_user'), dhost.get('smtp_auth_pass')) # MAIL FROM sender = smtp['addrlist']['mail_from'] #rcpt = smtp['addrlist']['rcpt_to'] # for single injection or when mpt value unknown use single message per connection if mpt == None: mpt = 1 rpm = len(rcpts) # split messages per connection for m in range(mpt): # m strt from 0 to mpt-1 # split rcpts per message si = m * rpm ei = m * rpm + rpm m_rcpts = rcpts[si:ei] #print (m,si,ei,m_rcpts) if m_rcpts: logger.debug('[%s]: F=%s, MPT=%s/%s R=%s' % (name, sender, (m + 1), mpt, m_rcpts)) # SEND # https://docs.python.org/2/library/email.message.html#email.message.Message # as_string([unixfrom]) # Return the entire message flattened as a string. When optional unixfrom is True, # the envelope header is included in the returned string. unixfrom defaults to False. # Flattening the message may trigger changes to the Message if defaults need to be filled # in to complete the transformation to a string (for example, MIME boundaries may be # generated or modified). response = s.sendmail(sender, m_rcpts, message.as_string(unixfrom=False)) if response: smtp['addrlist']['r_reject'].update(response) #dbginfo('debug','Sendmail response list:',str(response)) #dbginfo('debug','Failed recipients:',str(smtp['addrlist']['r_reject'])) # s.sendmail(sender, rcpt, message.as_string(unixfrom=False)) #FIXME: # message sent success : nto true when threads with more than one message in it # fix this print info fpr.ok('Message was sent successfuly') smtp['replay']['threads']['ok'].append(name) # when only part of recipients/sender failed it looks like than # exception for recipientsRefused is not triggered # remember: to clear refu recipient list before you call out this function # when threds than this response is not fetchhe # it should be upper if response: smtp['addrlist']['r_reject'].update(response) # dbginfo('debug', 'Sendmail response list:', str(response)) dbginfo('debug', 'Failed recipients:', str(smtp['addrlist']['r_reject'])) # All recipients were refused. Nobody got the mail. The recipients attribute of # the exception object is a dictionary with information about the refused # recipients (like the one returned when at least one recipient was accepted). # the exception is triggered only when all recipoient failed :( except smtplib.SMTPRecipientsRefused, e: fpr.fail('Error: Message not sent. All recipients refused.') smtp['replay']['threads']['fail'].append(name) #print 'exception smtplib.SMTPRecipientsRefused',a fpr.warn(str(e)) smtp['addrlist']['r_reject'].update(e.recipients)