├── README.md ├── spf.py └── src ├── colors.py └── figlet.py /README.md: -------------------------------------------------------------------------------- 1 | # SPF-Finder 2 | SPF-Finder is a python script used to find Sender Policy Framework (SPF) record of a domain - it can find spf of domain in bulk. 3 | 4 | ![spf-finder](https://user-images.githubusercontent.com/103236128/200907370-ff25c116-6ef6-4762-bb43-991eef891684.png) 5 | 6 | ## Installation 7 | 8 | 1. You need python3, pip3, git 9 | 10 | 2. Fork/Clone/Download this repo 11 | ``` 12 | https://github.com/PrayanshParmar/SPF-Finder.git 13 | ``` 14 | 15 | 3. Navigate to the directory 16 | ``` 17 | cd SPF-Finder 18 | ``` 19 | 20 | ## SPF_Finder -h 21 | ``` 22 | Usage: python3 spf.py [-h] [-v] [-d] [-l] domain_name/input_file [-o] output_file 23 | ------------------------------------------------------------------------------------------------ 24 | Options: 25 | -h, --help Help section 26 | -v, --version Show version 27 | -d, --domain for single domain 28 | -l, --inputfile Input file of domain name (support only ".txt" extension) 29 | -o, --outputfile Output file name (support only ".txt" extension) 30 | ------------------------------------------------------------------------------------------------ 31 | ``` 32 | 33 | ## Usage 34 | 35 | ### For single scan 36 | `$ python3 spf.py -d domain` 37 | 38 | ### For Bulk scan without output_file 39 | `$ python3 spf.py -l input_file` 40 | - Only support `.txt` Input_file extension. 41 | - File must contain only `domain name one by one.` 42 | 43 | ![image](https://user-images.githubusercontent.com/103236128/200896923-48c03dc6-098a-4a8a-af26-0b43aafc3ba1.png) 44 | 45 | ### For Bulk scan with output_file 46 | `$ python3 spf.py -l input_file -o output_file` 47 | - Only support `.txt` Input_file and Output_file extension. 48 | - File must contain only `domain name one by one` as shown above. 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /spf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | from src import figlet 6 | from src import colors as co 7 | 8 | # --------------- Functions --------------- # 9 | def printintro(): 10 | co.printout(figlet.ascii_work, co.BLUE) 11 | co.printout("\n[WRN]",co.YELLOW) 12 | co.printout(" Use with caution.You are responsible for your actions\n") 13 | co.printout("[WRN]",co.YELLOW) 14 | co.printout(" Developer assume no liability and are not responsible for any misuse\n\n") 15 | 16 | 17 | def spf_bulk(domain,read=" "): 18 | tool= "nslookup -type=txt {} " 19 | com= tool.format(domain) 20 | run=os.popen(com) 21 | read=run.read() 22 | if '"v=spf1' in read: 23 | res0="[SPF record found] {}" 24 | res1=res0.format(domain) 25 | co.printout(res1,co.GREEN) 26 | return res1 27 | elif "text" in read: 28 | res01="[SPF record not found] {}" 29 | res1=res01.format(domain) 30 | co.printout(res1,co.YELLOW) 31 | return res1 32 | else: 33 | res0="An error occured,skipping {} " 34 | res1=res0.format(domain) 35 | co.printout(res1,co.RED) 36 | 37 | def spf_single(domain): 38 | tool= "nslookup -type=txt {} " 39 | com= tool.format(domain) 40 | run=os.popen(com) 41 | read=run.read() 42 | if '"v=spf1' in read: 43 | co.printout("SPF record found",co.GREEN) 44 | 45 | elif "text" in read: 46 | co.printout("SPF record not found",co.YELLOW) 47 | 48 | else: 49 | co.printout("An error occured!!",co.RED) 50 | 51 | 52 | def read_write(path1,path2,length): 53 | f=open(path1,"r") 54 | str1= " " 55 | O=open(path2,"w") 56 | for i in range(length): 57 | str1=f.readline() 58 | result=spf_bulk(str1) 59 | if result!=None: 60 | O.write(result) 61 | else: 62 | pass 63 | f.close() 64 | O.close() 65 | 66 | def read_print(path1,length): 67 | f=open(path1,"r") 68 | str1= " " 69 | for i in range(length): 70 | str1=f.readline() 71 | spf_bulk(str1) 72 | f.close() 73 | 74 | def len_f(path1): 75 | f=open(path1,"r") 76 | str1=f.readlines() 77 | length=len(str1) 78 | return length 79 | f.close() 80 | 81 | 82 | # -------------- Main -------------- # 83 | args=len(sys.argv) 84 | argv=sys.argv 85 | 86 | try: 87 | if args==1: 88 | print() 89 | print('''-h, --help for Help section''') 90 | 91 | elif args==2 and argv[1]=="-h" or argv[1]=="--help": 92 | print() 93 | help='''Usage: python3 spf.py [-h] [-v] [-d] [-l] domain_name/input_file [-o] output_file 94 | ------------------------------------------------------------------------------------------------ 95 | Options: 96 | -h, --help Help section 97 | -v, --version Show version 98 | -d, --domain for single domain 99 | -l, --inputfile Input file of domain name (support only ".txt" extension) 100 | -o, --outputfile Output file name (support only ".txt" extension) 101 | ------------------------------------------------------------------------------------------------ 102 | ''' 103 | co.printout(help,co.CYAN) 104 | 105 | elif args==2 and argv[1]=="-v" or argv[1]=="--version": 106 | co.printout('Version --> 1.0',co.CYAN) 107 | 108 | elif args==3 and argv[1]=="-d" or argv[1]=="--domain": 109 | domain=argv[2] 110 | printintro() 111 | spf_single(domain) 112 | 113 | elif args==3 and argv[1]=="-l" or argv[1]=="--inputfile": 114 | path1=argv[2] 115 | printintro() 116 | 117 | try: 118 | length=len_f(path1) 119 | read_print(path1,length) 120 | 121 | except (FileNotFoundError,FileExistsError): 122 | co.printout("File Not Found Error!!",co.RED) 123 | 124 | elif args==5 and argv[1]=="-l" or argv[1]=="--inputfile" and argv[3]=="-o" or argv[3]=="--outputfile": 125 | path1=argv[2] 126 | path2=argv[4] 127 | printintro() 128 | 129 | try: 130 | length=len_f(path1) 131 | read_write(path1,path2,length) 132 | 133 | except (FileNotFoundError,FileExistsError): 134 | co.printout("File Not Found Error!!",co.RED) 135 | else: 136 | co.printout("Invalid operation!!",co.RED) 137 | 138 | except IndexError: 139 | co.printout("Invalid operation!!",co.RED) 140 | -------------------------------------------------------------------------------- /src/colors.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) 4 | 5 | 6 | def has_colors(stream): 7 | if not (hasattr(stream, "isatty") and stream.isatty): 8 | return False 9 | try: 10 | import curses 11 | curses.setupterm() 12 | return curses.tigetnum("colors") > 2 13 | except: 14 | return False 15 | 16 | 17 | has_colors = has_colors(sys.stdout) 18 | 19 | 20 | def printout(text, colour=WHITE): 21 | if has_colors: 22 | seq = "\x1b[1;%dm" % (30 + colour) + text + "\x1b[0m" 23 | sys.stdout.write(seq) 24 | else: 25 | sys.stdout.write(text) -------------------------------------------------------------------------------- /src/figlet.py: -------------------------------------------------------------------------------- 1 | ascii_work=''' 2 | ____ ___ ____ ____ _ _ _ ___ ____ ____ 3 | [__ |__] |___ __ |___ | |\ | | \ |___ |__/ 4 | ___] | | | | | \| |__/ |___ | \ v1 5 | 6 | ''' --------------------------------------------------------------------------------