diff --git a/InSpy.py b/InSpy.py
new file mode 100644
index 0000000..a29b215
--- /dev/null
+++ b/InSpy.py
@@ -0,0 +1,194 @@
+#!/usr/bin/env python2
+
+# InSpy - A LinkedIn employee enumerator
+# This script enumerates employees from any organization
+# using LinkedIn. Please note that this will not harvest all
+# employees within a given organization.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Author: Jonathan Broche
+# Contact: @g0jhonny
+# Version: 1.0.1
+# Date: 2015-11-22
+#
+# usage: ./inspy.py -c [-d dept/title] [-e email output format] [-i input file with dept/titles] [-o output file]
+# example: ./inspy.py -c abc -e flast@abc.com -o abc_employees.txt
+
+
+import requests, BeautifulSoup, argparse, signal, time, datetime, os
+
+start_time = time.time()
+
+class colors:
+ lightblue = "\033[1;36m"
+ blue = "\033[1;34m"
+ normal = "\033[0;00m"
+ red = "\033[1;31m"
+ yellow = "\033[1;33m"
+ white = "\033[1;37m"
+ green = "\033[1;32m"
+
+#----------------------------------------#
+# HARVEST USERS #
+#----------------------------------------#
+
+def inspy_enum(company, dept, ifile):
+ try:
+ dept_dictionary = ['sales', 'marketing', 'human resources', 'finance', 'accounting', 'inventory', 'quality assurance', 'insurance', 'licenses', 'operational', 'customer service', 'staff', 'research & development', 'management', 'administration', 'engineering', 'it', 'is', 'strategy', 'other']
+
+ employees = {}
+
+ if dept is not None:
+ dept_dictionary = [dept.lower()]
+
+ if ifile is not None:
+ try:
+ if os.path.exists(ifile):
+ with open(ifile, 'r') as f:
+ dept_dictionary = []
+ for line in f.readlines():
+ if line.rstrip():
+ dept_dictionary.append(line.rstrip())
+ except IOError as e:
+ print "{}[!]{} Problem opening the file. {}".format(e)
+
+ for dd in dept_dictionary:
+ print "{}[*]{} Searching for employees working at {} with '{}' in their title".format(colors.lightblue, colors.normal, company, dd)
+
+ try:
+ response = requests.get('https://www.linkedin.com/title/{}-at-{}'.format(dd.replace('-', ' '), company.replace('-', ' ')), timeout=2)
+ if response.status_code == 200:
+ soup = BeautifulSoup.BeautifulSoup(response.text)
+ else:
+ pass
+ except requests.exceptions.Timeout:
+ print "{}[!]{} Timeout enumerating the {} department".format(colors.red, colors.normal, dd)
+ except requests.exceptions.ConnectionError:
+ print "{}[!]{} Connection error.".format(colors.red, colors.normal)
+ except requests.exceptions.HTTPError:
+ print "{}[!]{} HTTP error.".format(colors.red, colors.normal)
+
+ #get employee names
+ for n, t in zip(soup.findAll('h3', { "class" : "name" }), soup.findAll('p', { "class" : "headline" })):
+ name = u''.join(n.getText()).encode('utf-8')
+ title = u''.join(t.getText()).encode('utf-8').replace('&', '&')
+
+ if not name in employees:
+ employees[name] = title
+
+ return employees
+ except Exception as e:
+ print "{}[!]{} Error harvesting users. {}".format(colors.red, colors.normal, e)
+
+#----------------------------------------#
+# EMAILS #
+#----------------------------------------#
+
+def format_email(names, eformat):
+ emails = []
+ for name in names:
+ spaces = []
+ for x,y in enumerate(name):
+ if ' ' in y:
+ spaces.append(x)
+
+ if eformat[:eformat.find('@')] == 'flast':
+ emails.append('{}{}{}'.format(name[0], name[(spaces[-1]+1):], eformat[eformat.find('@'):]))
+ elif eformat[:eformat.find('@')] == 'lfirst':
+ emails.append('{}{}{}'.format(name[spaces[-1]+1], name[0:spaces[0]], eformat[eformat.find('@'):]))
+ elif eformat[:eformat.find('@')] == 'first.last':
+ emails.append('{}.{}{}'.format(name[0:spaces[0]], name[(spaces[-1]+1):], eformat[eformat.find('@'):]))
+ elif eformat[:eformat.find('@')] == 'last.first':
+ emails.append('{}.{}{}'.format(name[(spaces[-1]+1):], name[0:spaces[0]], eformat[eformat.find('@'):]))
+
+ return [e.lower() for e in emails]
+
+#----------------------------------------#
+# OUTPUT #
+#----------------------------------------#
+
+def output(employees, email, company, ofile):
+ counter = 0
+ ge, be = {}, {}
+ print '\n'
+
+ if email:
+ for k, e in zip(employees, email):
+ if company in employees[k].lower():
+ if ',' in k:
+ be[e] = '{}, {}'.format(k, employees[k])
+ else:
+ ge[e] = '{}, {}'.format(k, employees[k])
+ print "{}[*]{} {}, {}, {}".format(colors.green, colors.normal, k.replace('&', '&'), employees[k].replace('&', '&'), e)
+ counter +=1
+ else:
+ for k in employees:
+ if company in employees[k].lower():
+ ge[k] = employees[k]
+ print "{}[*]{} {} {}".format(colors.green, colors.normal, k.replace('&', '&'), employees[k].replace('&', '&'))
+ counter +=1
+ if be:
+ print "\n{}[!]{} The following employees have commas in their names. Their emails were not accurate.".format(colors.red, colors.normal)
+ for k in be:
+ print "{}[*]{} {}".format(colors.yellow, colors.normal, be[k])
+
+ if ofile:
+ with open(ofile, 'w') as f:
+ f.write("\n" + "-" * 69 + "\n" + "InSpy Output" + "\n" + "-" * 69 + "\n\n")
+
+ if [e for e in ge.keys() if '@' in e]: #if emails in keys
+ f.write("\n" + "E-mails" + "\n" + "-" * 25 + "\n\n")
+ for k in ge.keys():
+ f.write(k+'\n')
+
+ f.write("\n" + "All" + "\n" + "-" * 25 + "\n\n")
+ for k in ge:
+ f.write('{}, {}\n'.format(ge[k], k))
+ else:
+ for k in ge:
+ f.write('{}, {}\n'.format(k, ge[k]))
+
+ print "\n{}[*]{} Done! {}{}{} employees found.".format(colors.lightblue, colors.normal, colors.green, counter, colors.normal)
+ print "{}[*]{} Completed in {:.1f}s\n".format(colors.lightblue, colors.normal, time.time()-start_time)
+
+#----------------------------------------#
+# MAIN #
+#----------------------------------------#
+
+def main():
+ print "\n " + "-" * 74 + "\n " + colors.white + "InSpy v1.0 - LinkedIn Employee Enumerator by Jonathan Broche (@g0jhonny)\n " + colors.normal + "-" * 74 + "\n "
+ parser = argparse.ArgumentParser(description='InSpy - A LinkedIn employee enumerator by Jonathan Broche (@g0jhonny)')
+ parser.add_argument('-c', '--company', required=True, help='Company name')
+ parser.add_argument('-d', '--dept', nargs='?', const='', help='Department or title to query employees against. Inspy searches through a predefined list by default.')
+ parser.add_argument('-e', '--emailformat', help='Email output format. Acceptable formats: first.last@xyz.com, last.first@xyz.com, flast@xyz.com, lastf@xyz.com')
+ parser.add_argument('-i', '--inputfilename', nargs='?', const='', help='File with list of departments or titles to query employees against (one item per line)')
+ parser.add_argument('-o', '--outfilename', nargs='?', const='', help='Output results to text file')
+ args = parser.parse_args()
+
+ employees = inspy_enum(args.company, args.dept, args.inputfilename)
+
+ if args.emailformat:
+ if args.emailformat.find('@') and args.emailformat[:args.emailformat.find('@')] in {'flast', 'lfirst', 'first.last', 'last.first'}:
+ if employees is not None:
+ e = format_email(employees.keys(), args.emailformat)
+ output(employees, e,args.company.lower(), args.outfilename)
+ else:
+ print "{}[!]{} Please provide a valid email address format (i.e., flast@xyz.com, lfirst@xyz.com, first.last@xyz.com, last.first@xyz.com)".format(colors.red, colors.normal)
+ else:
+ if employees is not None:
+ output(employees,'',args.company.lower(), args.outfilename)
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..3e53492
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Jonathan Broche
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..66828ab
--- /dev/null
+++ b/README.md
@@ -0,0 +1,93 @@
+# InSpy
+
+A python based LinkedIn employee enumerator. This script is great for social engineering assessments where clients ask one
+to provide employee emails.
+
+### Help
+
+```
+InSpy - A LinkedIn employee enumerator by Jonathan Broche (@g0jhonny)
+
+optional arguments:
+ -h, --help show this help message and exit
+ -c COMPANY, --company COMPANY
+ Company name
+ -d [DEPT], --dept [DEPT]
+ Department or title to query employees against. Inspy
+ searches through a predefined list by default.
+ -e EMAILFORMAT, --emailformat EMAILFORMAT
+ Email output format. Acceptable formats:
+ first.last@xyz.com, last.first@xyz.com, flast@xyz.com,
+ lastf@xyz.com
+ -i [INPUTFILENAME], --inputfilename [INPUTFILENAME]
+ File with list of departments or titles to query
+ employees against (one item per line)
+ -o [OUTFILENAME], --outfilename [OUTFILENAME]
+ Output results to text file
+```
+### Examples
+
+```
+./InSpy.py -c "acme corp"
+
+ --------------------------------------------------------------------------
+ InSpy v1.0 - LinkedIn User Enumerator by Jonathan Broche (@g0jhonny)
+ --------------------------------------------------------------------------
+
+[*] Searching for employees working at acme corp with 'sales' in their title
+[*] Searching for employees working at acme corp with 'hr' in their title
+[*] Searching for employees working at acme corp with 'marketing' in their title
+[*] Searching for employees working at acme corp with 'finance' in their title
+[*] Searching for employees working at acme corp with 'accounting' in their title
+[*] Searching for employees working at acme corp with 'director' in their title
+[*] Searching for employees working at acme corp with 'administrative' in their title
+[*] Searching for employees working at acme corp with 'lawyer' in their title
+[*] Searching for employees working at acme corp with 'it' in their title
+[*] Searching for employees working at acme corp with 'security' in their title
+
+
+[*] Proud Arkie Accounts Receivable specialist at Acme Corp.
+[*] Brian Russo Finance Manager at Acme corp
+[*] Paul Samuelson Director of Customer Support at ACME Corp. Production Resources
+[*] Steve Smith Developer at Acme Corp
+[*] Sarah Rhodes Director of Sales at Acme Corp
+[*] Frances Jones Assistant to the Director at Acme Corp
+ ...snip...
+
+[*] Done! 29 employees found.
+[*] Completed in 28.7s
+```
+
+Provide InSpy with the email format of the respective corporation and it'll output the emails for you.
+
+```
+./InSpy.py -c 'acme corp' -e flast@acme.com
+
+ --------------------------------------------------------------------------
+ InSpy v1.0 - LinkedIn User Enumerator by Jonathan Broche (@g0jhonny)
+ --------------------------------------------------------------------------
+
+[*] Searching for employees working at acme corp with 'sales' in their title
+[*] Searching for employees working at acme corp with 'hr' in their title
+[*] Searching for employees working at acme corp with 'marketing' in their title
+[*] Searching for employees working at acme corp with 'finance' in their title
+[*] Searching for employees working at acme corp with 'accounting' in their title
+[*] Searching for employees working at acme corp with 'director' in their title
+[*] Searching for employees working at acme corp with 'administrative' in their title
+[*] Searching for employees working at acme corp with 'lawyer' in their title
+[*] Searching for employees working at acme corp with 'it' in their title
+[*] Searching for employees working at acme corp with 'security' in their title
+
+
+[*] Proud Arkie, Accounts Receivable specialist at Acme Corp., parkie@acme.com
+[*] Brian Russo, Finance Manager at Acme corp, brusso@acme.com
+[*] Paul Samuelson, Director of Customer Support at ACME Corp. Production Resources, psamuelson@acme.com
+[*] Steve Smith, Developer at Acme Corp, ssmith@acme.com
+[*] Sarah Rhodes, Director of Sales at Acme Corp, srhodes@acme.com
+[*] Frances Jones, Assistant to the Director at Acme Corp, fjones@acme.com
+ ...snip...
+
+[*] Done! 29 employees found.
+[*] Completed in 29.0s
+
+```
\ No newline at end of file