Example #1
0
    def sent_with_spf(self, ipv4, sender, hostname):
        '''
        Given a sender email address, the IP address of an Outbound server, and its hostname, It will check if it
        complies with the SPF policy (if any)

        :param ipv4: IP address of the Outbound server delivering the email
        :param sender: email address of the sender
        :param hostname: hostname of the Outbound server.
        :return: Boolean, SPF compliant? YES:NO
                 String, code returned bt the validation function
                 String, text returned by the validation function
        '''
        try:
            spfsupport, spfcode, spfdesc = spf.check(i=ipv4,
                                                     s=sender,
                                                     h=hostname)
            self.logger.debug('SPDF: ' + str(spfsupport) + ', ' +
                              str(spfcode) + ', ' + str(spfdesc))
            if (spfsupport == 'pass' or spfsupport == 'softfail'
                    or spfsupport == 'neutral') and 250 == spfcode:
                return True, spfcode, (spfsupport + ' : ' + spfdesc)
        except Exception as ex:
            self.logger.error("Error validating compliance with SPF! " +
                              str(ex))
        return False, spfcode, spfdesc
Example #2
0
 def auth(self, message_data=None, peer_ip=None, message=None):
     mailfrom = Contact.create_contacts_from_message_field('from', message)[0]
     host = re.match('[^@]*@(.*)', mailfrom.email).group(1)
     result_status = spf.check(i=peer_ip, s=mailfrom.email, h=host)[0]
     if 'pass' in result_status:
         return True
     return False
Example #3
0
 def check_spf(self):
     """
     Check if sender is authorised by sender policy framework
     """
     if not ENABLE_SPF:
         return False
     return spf.check(i=socket.gethostbyname(DNS_NAME.get_fqdn()),s=self.email,h=DNS_NAME.get_fqdn())
Example #4
0
 def check(self, ip, sender):
     """
     Perform an SPF check for the given IP address against the given sender email address.
     """
     status, code, msg = spf.check(ip, sender, None)
     result = (ip, status, code, msg)
     self.results.append(result)
     return result
Example #5
0
 def check_spf(self):
     """
     Check if sender is authorised by sender policy framework
     """
     if not ENABLE_SPF:
         return False
     return spf.check(i=socket.gethostbyname(DNS_NAME.get_fqdn()),
                      s=self.email,
                      h=DNS_NAME.get_fqdn())
Example #6
0
	def run(self):
		# Get standard input 'email'
		email = self.getInput('email')
		# Get input from the execution of the MXRecord plugin
		records = self.getInput('MXRecord')

		# First information messages to say test is underway
		self.result.info('Starting SPF-test')

		results = []
		statusCounts = {Plugin.STATUS_OK: 0, Plugin.STATUS_WARNING: 0, Plugin.STATUS_ERROR: 0}
		star = False

		# Loop through all MX records and perform the SPF test
		for record in records['mx_record']:
			host = record['host']
			ip = record['ip']

			passCode = 250
			code = Plugin.STATUS_OK
			error = ""
			try:
				# Perform the actual SPF control using the spf module
				spf_res_ret, spf_res_code, spf_res_desc = spf.check(ip, email, host)

				# Check if the returned code is 250 and up the warning counter if it's not
				if spf_res_code != passCode:
					statusCounts[Plugin.STATUS_WARNING] += 1
				#
				elif spf_res_code == 250 and spf_res_ret != 'none' and star == False:
					star = True
			except socket.error, e:
				code = Plugin.STATUS_WARNING
				if e[0] == 101:
					error = "network unreachable"
				elif e[0] == 111:
					error = "connection refused"
				elif e[0] == 110 or e[0] == 'timed out' or e == 'timed out':
					error = "connection timed out"
				else:
					error = "unable to connect"

			# Add information message if the test failed for this MX. We only see SPF
			# as a bonus feature, that's why we don't add a warning here
			if error != '':
				self.result.info('SPF-test failed for %s (%s)', (host, ip))
			# We add a warning here bacause SPF exists but is not configured correctly
			elif spf_res_code != passCode:
				self.result.warning('SPF-test returned: %s (%s), %s for %s (%s), email: %s', (spf_res_ret, spf_res_code, spf_res_desc, host, ip, email))
			else:
				self.result.info('SPF-test returned: %s (%s), %s for %s (%s), email: %s', (spf_res_ret, spf_res_code, spf_res_desc, host, ip, email))

			# Add this test to the result from the SPF plugin
			results.append([host, ip, email, spf_res_ret, spf_res_code, spf_res_desc])
			statusCounts[code] += 1
Example #7
0
  def check_spf(self,domain,addr):

    if "_spf" not in self.results[domain]:
      self.results[domain]["_spf"] = {}

    mxs = self.results[domain][addr]["mx"]

    for mx in mxs:
      if mx not in self.results[domain]["_spf"]:
        asd = spf.check(i=addr,
                        s=domain,
                        h=mx)
        self.results[domain]["_spf"][mx] = asd[0]
Example #8
0
 def do_test(self):
     if 'client_address' and 'helo_name' and 'sender' in self.headers:
         results = spf.check(i=self.headers['client_address'], 
                             h=self.headers['helo_name'], 
                             s=self.headers['sender'], 
                             receiver=socket.gethostname())
         self.result['action'] = results[0]
         self.result['code'] = results[1]
         self.result['message'] = results[2]
         log.write("SPF check returns action='%s', code='%s', message='%s'"\
                     % (results[0], results[1], results[2]), LOG_DEBUG)
         return results
     else:
         log.write("Client address, helo name or sender missing from headers.",
                   LOG_WARNING)
         raise GLPluginException, "Incomplete headers."
Example #9
0
def main():
    """
    main function

    assigns arguments from docopt and calls spf.check() function
    """
    # gets arguments from docopt
    arguments = docopt(__doc__)
    # assigns docopt arguments
    ipaddr = arguments['<ipaddr>']
    host = arguments['<host>']
    sender = arguments['<sender>']
    verbose = arguments.get('--verbose')

    if verbose:
        print "script called with: "
        print arguments

    result = spf.check(i=ipaddr, s=sender, h=host)
    pprint(result)
Example #10
0
 def examine(self,suspect):  
     if not PYSPF_AVAILABLE:
         suspect.debug("pyspf not available, can not check")
         self._logger().warning("%s: SPF Check skipped, pyspf unavailable"%(suspect.id))
         suspect.set_tag('SPF.status','skipped')
         return DUNNO
     
     starttime=time.time()
     clientinfo=suspect.get_client_info(self.config)
     if clientinfo==None:
         suspect.debug("pyspf not available, can not check")
         self._logger().warning("%s: SPF Check skipped, could not get client info"%(suspect.id))
         suspect.set_tag('SPF.status','skipped')
         return DUNNO
     
     helo,ip,revdns=clientinfo
     tag,code,info=spf.check(i=ip,s=suspect.from_address,h=helo)   
     suspect.set_tag("SPF.status",tag)
     suspect.debug("SPF status: %s (%s)"%(tag,info))
     
     endtime=time.time()
     difftime=endtime-starttime
     suspect.tags['SPFCheck.time']="%.4f"%difftime
     return DUNNO
Example #11
0
 def auth(self, message_data=None, peer_ip=None, message=None):
     result_status = spf.check(i=peer_ip, s='@gmail.com', h='google.com')[0]
     if 'pass' in result_status:
         return True
     return False
Example #12
0
			if spfResult == 'Fail' or spfResult == 'Permerror':
				if action == 'quarantine':
					return(( 'QUARANTINE', 'SPF detected this as spam.' ))
				return(( 'REJECT', 'Sender failed SPF check' ))
			if spfResult == 'Temperror':
				if self.mode == 'smtp':
					return(( 'DEFER_IF_PERMIT',
							'SPF temporary failure: "%s"' % spfReason ))
				else:
					return(( 'DUNNO', '' ))

		#  SPF version 1 check
		else:
			try:
				res = spf.check(i = self.data['client_address'],
						s = self.data['sender_domain'], h = 'unknown')
			except Exception, e:
				syslog.syslog('ERROR: SPF check failed: %s' % str(e))
				return(( 'DUNNO', '' ))

			self.addHeaders.append('X-vPostMaster-SPF-Result: '
					'domain="%s" address="%s" result="%s"' %
					( self.data['sender_domain'], self.data['client_address'],
						res[0] ))
			if res[0] not in [ 'pass', 'unknown', 'error' ]:
				if self.debug >= 3:
					syslog.syslog(syslog.LOG_DEBUG,
							'checkSPF: Unknown response: "%s".' % repr(res))
				if action == 'quarantine':
					return(( 'QUARANTINE', 'SPF detected this as spam.' ))
				return(( 'REJECT', 'Sender failed SPF check' ))
Example #13
0
 def _evaluate_spf(self):
     return spf.check(
         h=self.user.helo[0],
         i=self.user.helo[1],
         s=self.user.orig.addrstr[1:-1]) #cut off < and >
def check_spf(ip, mail_from, helo):
    res, _, reason = spf.check(ip, mail_from, helo)
    return SPFAuthenticationResult(result=res, reason=reason, smtp_mailfrom=mail_from, smtp_helo=helo)
def checkMail (message):	

    outputFileHandle = None

    try:
        outputFileHandle = open('dmarcCheck.html', 'w')
    except:
        print "file error"
        sys.exit()


    htmlDMARCBox = ""
    htmlDKIMBox = ""
    htmlSPFBox = ""
    receivedHeader = ""
    fromHeader = ""	

    #Read the message from the inbox
    headers = email.parser.Parser().parsestr(message)


    for field in headers.items():
	    if field[0] == "Received" and "[" in field[1] and "]" in field[1]:
		    receivedHeader = field[1]

    pattern = re.compile(r'\[.*]')
    result = re.search(pattern, receivedHeader).group(0)

    pattern = re.compile(r'from .*? ')
    result2 = re.search(pattern, receivedHeader).group(0)

    subject = headers['subject']

    #Variables needed for spf check

    #We need only the email address
    if "<" in headers['from'] and ">" in headers['from']:
	    pattern = re.compile(r'\<.*>')
	    fromHeader = re.search(pattern, headers['from']).group(0)
	    fromHeader = fromHeader[1:-1]
    else:
	    fromHeader = headers['from']


    ipaddr = result[1:-1]
    host = result2[5:-1]


    # Perfom SPF and DKIM checks
    spfResult = spf.check(i=ipaddr,s=fromHeader,h=host)
    dkimResult = dkim.verify(message ,None)


    #Create HTML conentent according to the results of the test
    if (spfResult[0] == 'pass'):
	    htmlSPFBox = """<tr class="success">
				    <td>SPF check passed <br><strong>↳</strong>""" + spfResult[2] + """</td>
			    </tr>"""
    else:
	    htmlSPFBox = """<tr class="danger">
				    <td>SPF check failed <br><strong>↳</strong>""" + spfResult[2] + """</td>	
			    </tr>"""
	
    if (dkimResult == True):
	    htmlDKIMBox = """<tr class="success">
				    <td>DKIM check passed</td>
			    </tr>"""
    else:
	    htmlDKIMBox = """<tr class="danger">
				    <td>DKIM check failed</td>
			    </tr>"""
	
    if (spfResult[0] == 'pass' or dkimResult == True):
	    htmlDMARCBox = """<tr class="success">
				    <td>DMARC check passed</td>
			    </tr>"""
    else:
	    htmlDMARCBox = """<tr class="danger">
				    <td>DMARC check failed</td>
			    </tr>"""		

	
    html = """
    <div class="well well-lg">
        <h4><p class="text-center"><strong>DMARC test</strong></p></h4>
        <table class="table table-condensed">
	        <thead>
		        <tr>
			        <th>Result</th>
		        </tr>
		        <tr></tr>
	        </thead>
	        <tbody>
		        <tr>
			        <td>Subject: """ + subject + """</td>
		        </tr>
		        <tr><td></td></tr>
		        """ + htmlDKIMBox + htmlSPFBox + """<tr><td></td></tr>""" + htmlDMARCBox + """
	        </tbody>

        </table>
    </div>
    """
    outputFileHandle.write(html)
    outputFileHandle.close()
Example #16
0
    def run(self):
        # Get standard input 'email'
        email = self.getInput('email')
        # Get input from the execution of the MXRecord plugin
        records = self.getInput('MXRecord')

        # First information messages to say test is underway
        self.result.info('Starting SPF-test')

        results = []
        statusCounts = {
            Plugin.STATUS_OK: 0,
            Plugin.STATUS_WARNING: 0,
            Plugin.STATUS_ERROR: 0
        }
        star = False

        # Loop through all MX records and perform the SPF test
        for record in records['mx_record']:
            host = record['host']
            ip = record['ip']

            passCode = 250
            code = Plugin.STATUS_OK
            error = ""
            try:
                # Perform the actual SPF control using the spf module
                spf_res_ret, spf_res_code, spf_res_desc = spf.check(
                    ip, email, host)

                # Check if the returned code is 250 and up the warning counter if it's not
                if spf_res_code != passCode:
                    statusCounts[Plugin.STATUS_WARNING] += 1
                #
                elif spf_res_code == 250 and spf_res_ret != 'none' and star == False:
                    star = True
            except socket.error, e:
                code = Plugin.STATUS_WARNING
                if e[0] == 101:
                    error = "network unreachable"
                elif e[0] == 111:
                    error = "connection refused"
                elif e[0] == 110 or e[0] == 'timed out' or e == 'timed out':
                    error = "connection timed out"
                else:
                    error = "unable to connect"

            # Add information message if the test failed for this MX. We only see SPF
            # as a bonus feature, that's why we don't add a warning here
            if error != '':
                self.result.info('SPF-test failed for %s (%s)', (host, ip))
            # We add a warning here bacause SPF exists but is not configured correctly
            elif spf_res_code != passCode:
                self.result.warning(
                    'SPF-test returned: %s (%s), %s for %s (%s), email: %s',
                    (spf_res_ret, spf_res_code, spf_res_desc, host, ip, email))
            else:
                self.result.info(
                    'SPF-test returned: %s (%s), %s for %s (%s), email: %s',
                    (spf_res_ret, spf_res_code, spf_res_desc, host, ip, email))

            # Add this test to the result from the SPF plugin
            results.append(
                [host, ip, email, spf_res_ret, spf_res_code, spf_res_desc])
            statusCounts[code] += 1
Example #17
0
def checkMail (mailbox, outputFileHandle):	


	htmlDMARCBox = ""
	htmlDKIMBox = ""
	htmlSPFBox = ""


	#Read the message from the inbox
	mailBoxFileHandle = open(mailbox,'r+')
	message = mailBoxFileHandle.read()
	headers = Parser().parsestr(message)



	receivedHeader =  headers['Received']
	#print headers.items()

	pattern = re.compile(r'\[.*]')
	result = re.search(pattern, receivedHeader).group(0)

	pattern = re.compile(r'from .*? ')
	result2 = re.search(pattern, receivedHeader).group(0)


	subject = headers['subject']

	#Variables needed for spf check
	fromHeader = headers['from']
	ipaddr = result[1:-1]
	host = result2[5:-1]




	# Perfom SPF and DKIM checks
	spfResult = spf.check(i=ipaddr,s=fromHeader,h=host)
	dkimResult = dkim.verify(message ,None)


	#Create HTML conentent according to the results of the test
	if (spfResult[0] == 'pass'):
		htmlSPFBox = """<tr class="success">
					<td>SPF check passed <br><strong>↳</strong>""" + spfResult[2] + """</td>
				</tr>"""
	else:
		htmlSPFBox = """<tr class="danger">
					<td>SPF check failed <br><strong>↳</strong>""" + spfResult[2] + """</td>	
				</tr>"""
		
	if (dkimResult == True):
		htmlDKIMBox = """<tr class="success">
					<td>DKIM check passed</td>
				</tr>"""
	else:
		htmlDKIMBox = """<tr class="danger">
					<td>DKIM check failed</td>
				</tr>"""
		
	if (spfResult[0] == 'pass' or dkimResult == True):
		htmlDMARCBox = """<tr class="success">
					<td>DMARC check passed</td>
				</tr>"""
	else:
		htmlDMARCBox = """<tr class="danger">
					<td>DMARC check failed</td>
				</tr>"""		
	
		
	html = """
	<div class="well well-lg">
		<h4><p class="text-center"><strong>DMARC test</strong></p></h4>
		<table class="table table-condensed">
			<thead>
				<tr>
					<th>Result</th>
				</tr>
				<tr></tr>
			</thead>
			<tbody>
				<tr>
					<td>Subject: """ + subject + """</td>
				</tr>
				<tr><td></td></tr>
				""" + htmlDKIMBox + htmlSPFBox + """<tr><td></td></tr>""" + htmlDMARCBox + """
			</tbody>

		</table>
	</div>
	"""

	outputFileHandle.write(html)
	outputFileHandle.close()

	# Empty the mail box for the the next test, remove this line if 
	# you whish to keep the email. 
	# (Hackish way of emtying the file contents)
	open(mailbox, 'w').close()