#!/usr/bin/env python3 # maravento.com """ ------------ emailscan.py ------------ Recursively crawls a public website and reports every page where a given email address appears in the HTML source. Follows all internal links up to a configurable page limit. Compatible with static sites and SharePoint / GovCo portals. Usage: python emailscan.py Replace: BASE_URL and TARGET_EMAIL """ import re import requests from bs4 import BeautifulSoup from urllib.parse import urljoin, urlparse from collections import deque from datetime import datetime # ============================================================ # CONFIGURATION — edit these values before running # ============================================================ BASE_URL = "https://www.anysite.com" # Target website URL TARGET_EMAIL = "anymail@anysite.com" # Email address to search for MAX_PAGES = 500 # Maximum number of pages to crawl (set to None for unlimited) REQUEST_TIMEOUT = 15 # Seconds to wait per request REQUEST_DELAY = 0 # Seconds between requests (0 = no delay) VERIFY_SSL = True # Set to False only for sites with self-signed certs # ============================================================ HEADERS = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/120.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.9", } SKIP_EXTENSIONS = ( ".jpg", ".jpeg", ".png", ".gif", ".svg", ".ico", ".pdf", ".docx", ".xlsx", ".zip", ".mp4", ".css", ".js", ".woff", ".woff2", ".ttf", ".eot", ".otf", ) def normalize_url(url): p = urlparse(url) return p.scheme + "://" + p.netloc + p.path + (("?" + p.query) if p.query else "") def same_domain(url, base_domain): return urlparse(url).netloc == base_domain def email_in_html(email, html): pattern = r'(?4}] {current_url}") found, new_links = process_page(current_url, TARGET_EMAIL, session) if found: matches.append(current_url) print(f" āœ… EMAIL FOUND!") for link in new_links: if link not in visited and link not in pending_set: pending.append(link) pending_set.add(link) if REQUEST_DELAY > 0: time.sleep(REQUEST_DELAY) print("\n" + "="*65) print(f"šŸ“Š SUMMARY") print(f" Pages scanned : {count}") print(f" Pages with email : {len(matches)}") print("="*65) if matches: print("\nšŸ“‹ URLs where the email appears:\n") for u in matches: print(f" • {u}") timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"scan_results_{timestamp}.txt" try: with open(filename, "w", encoding="utf-8") as f: f.write(f"Email searched: {TARGET_EMAIL}\n") f.write(f"Site scanned: {BASE_URL}\n") f.write(f"Pages scanned: {count}\n") f.write(f"Pages with email: {len(matches)}\n\n") for u in matches: f.write(u + "\n") print(f"\nšŸ’¾ Results saved to: {filename}") except OSError as e: print(f"\nāš ļø Could not save results to file: {e}") print(" Results found (not saved):\n") for u in matches: print(f" • {u}") else: print("\nāš ļø Email not found on any visited page.") print(" Possible reasons:") print(" - Content is loaded via JavaScript (SPA/React/Angular)") print(" - Email only appears inside PDFs or attached documents") print(" - The site blocks automated crawling") if __name__ == "__main__": scan()