Skip to content

Commit

Permalink
Debounce module (smicallef#1085)
Browse files Browse the repository at this point in the history
* Debounce module
  • Loading branch information
krishnasism committed Oct 3, 2020
1 parent 751a65b commit 83c9171
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 0 deletions.
113 changes: 113 additions & 0 deletions modules/sfp_debounce.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# Name: sfp_debounce
# Purpose: Spiderfoot plugin to check if an email is
# disposable using Debounce API.
#
# Author: Krishnasis Mandal <krishnasis@hotmail.com>
#
# Created: 2020-10-01
# Copyright: (c) Steve Micallef
# Licence: GPL
# -------------------------------------------------------------------------------

import json
from spiderfoot import SpiderFootEvent, SpiderFootPlugin


class sfp_debounce(SpiderFootPlugin):

meta = {
'name': "Debounce",
'summary': "Check whether an email is disposable",
'flags': [""],
'useCases': ["Footprint", "Investigate", "Passive"],
'categories': ["Search Engines"],
'dataSource': {
'website': "https://debounce.io/",
'model': "FREE_NOAUTH_UNLIMITED",
'references': [
"https://debounce.io/free-disposable-check-api/"
],
'favIcon': "https://debounce.io/wp-content/uploads/2018/01/favicon-2.png",
'logo': "https://debounce.io/wp-content/uploads/2018/01/debounce-logo-2.png",
'description': "DeBounce provides a free & powerful API endpoint for checking "
"a domain or email address against a realtime up-to-date list of disposable domains."
"CORS is enabled for all originating domains, "
"so you can call the API directly from your client-side code.",
}
}

opts = {
}

optdescs = {
}

results = None
errorState = False

def setup(self, sfc, userOpts=dict()):
self.sf = sfc
self.results = self.tempStorage()

for opt in list(userOpts.keys()):
self.opts[opt] = userOpts[opt]

def watchedEvents(self):
return [
"EMAILADDR"
]

def producedEvents(self):
return [
"EMAILADDR_DISPOSABLE",
"RAW_RIR_DATA"
]

def queryEmailAddr(self, qry):
res = self.sf.fetchUrl(
f"https://disposable.debounce.io?email={qry}",
timeout=self.opts['_fetchtimeout'],
useragent="SpiderFoot"
)

if res['content'] is None:
self.sf.info(f"No Debounce info found for {qry}")
return None

try:
return json.loads(res['content'])
except Exception as e:
self.sf.error(f"Error processing JSON response from Debounce: {e}")

return None

# Handle events sent to this module
def handleEvent(self, event):
eventName = event.eventType
srcModuleName = event.module
eventData = event.data

if self.errorState:
return

self.sf.debug(f"Received event, {eventName}, from {srcModuleName}")

self.results[eventData] = True

data = self.queryEmailAddr(eventData)

if data is None:
return

isDisposable = data.get('disposable')

if isDisposable == "true":
evt = SpiderFootEvent("RAW_RIR_DATA", str(data), self.__name__, event)
self.notifyListeners(evt)

evt = SpiderFootEvent("EMAILADDR_DISPOSABLE", eventData, self.__name__, event)
self.notifyListeners(evt)

# End of sfp_debounce class
1 change: 1 addition & 0 deletions spiderfoot/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ class SpiderFootDb:
['DOMAIN_WHOIS', 'Domain Whois', 1, 'DATA'],
['EMAILADDR', 'Email Address', 0, 'ENTITY'],
['EMAILADDR_COMPROMISED', 'Hacked Email Address', 0, 'DESCRIPTOR'],
['EMAILADDR_DISPOSABLE', 'Disposable Email Address', 0, 'DESCRIPTOR'],
['EMAILADDR_GENERIC', 'Email Address - Generic', 0, 'ENTITY'],
['ERROR_MESSAGE', 'Error Message', 0, 'DATA'],
['ETHEREUM_ADDRESS', 'Ethereum Address', 0, 'ENTITY'],
Expand Down
80 changes: 80 additions & 0 deletions test/unit/modules/test_sfp_debounce.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# test_sfp_debounce.py
import unittest

from modules.sfp_debounce import sfp_debounce
from sflib import SpiderFoot
from spiderfoot import SpiderFootEvent, SpiderFootTarget


class TestModuledebounce(unittest.TestCase):
"""
Test modules.sfp_debounce
"""

default_options = {
'_debug': False, # Debug
'__logging': True, # Logging in general
'__outputfilter': None, # Event types to filter from modules' output
'_useragent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0', # User-Agent to use for HTTP requests
'_dnsserver': '', # Override the default resolver
'_fetchtimeout': 5, # number of seconds before giving up on a fetch
'_internettlds': 'https://publicsuffix.org/list/effective_tld_names.dat',
'_internettlds_cache': 72,
'_genericusers': "abuse,admin,billing,compliance,devnull,dns,ftp,hostmaster,inoc,ispfeedback,ispsupport,list-request,list,maildaemon,marketing,noc,no-reply,noreply,null,peering,peering-notify,peering-request,phish,phishing,postmaster,privacy,registrar,registry,root,routing-registry,rr,sales,security,spam,support,sysadmin,tech,undisclosed-recipients,unsubscribe,usenet,uucp,webmaster,www",
'__version__': '3.3-DEV',
'__database': 'spiderfoot.test.db', # note: test database file
'__modules__': None, # List of modules. Will be set after start-up.
'_socks1type': '',
'_socks2addr': '',
'_socks3port': '',
'_socks4user': '',
'_socks5pwd': '',
'_torctlport': 9051,
'__logstdout': False
}

def test_opts(self):
module = sfp_debounce()
self.assertEqual(len(module.opts), len(module.optdescs))

def test_setup(self):
"""
Test setup(self, sfc, userOpts=dict())
"""
sf = SpiderFoot(self.default_options)

module = sfp_debounce()
module.setup(sf, dict())

def test_watchedEvents_should_return_list(self):
module = sfp_debounce()
self.assertIsInstance(module.watchedEvents(), list)

def test_producedEvents_should_return_list(self):
module = sfp_debounce()
self.assertIsInstance(module.producedEvents(), list)

@unittest.skip("todo")
def test_handleEvent(self):
"""
Test handleEvent(self, event)
"""
sf = SpiderFoot(self.default_options)

module = sfp_debounce()
module.setup(sf, dict())

target_value = 'example target value'
target_type = 'EMAILADDR'
target = SpiderFootTarget(target_value, target_type)
module.setTarget(target)

event_type = 'ROOT'
event_data = 'example data'
event_module = ''
source_event = ''
evt = SpiderFootEvent(event_type, event_data, event_module, source_event)

result = module.handleEvent(evt)

self.assertIsNone(result)

0 comments on commit 83c9171

Please sign in to comment.