-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathemail_validation.py
More file actions
290 lines (241 loc) · 11.6 KB
/
email_validation.py
File metadata and controls
290 lines (241 loc) · 11.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
MottaHunter Email Validation Module
Developed by MottaSec Ghost for the MottaHunter toolkit
This module handles email permutation generation and SMTP-based validation.
As MottaSec Fox says: "Trust, but verify!"
Author: MottaSec Ghost
Website: https://mottasec.com
Contact: ghost@mottasec.com
"""
import random
import time
from dns.resolver import resolve
import smtplib
from typing import List, Tuple
# ANSI color codes for terminal - MottaSec style!
GREEN = "\033[92m" # Success - MottaSec Fox approved
RED = "\033[91m" # Failure - MottaSec Ghost says no
BLUE = "\033[94m" # Info - MottaSec Aces intel
RESET = "\033[0m" # Reset to default color
def motta_generate_permutations(first_name: str, last_name: str, domain: str, level: int) -> List[str]:
"""
Generate email permutations based on the selected level.
Returns a list of complete email addresses (user@domain).
MottaSec Fox has carefully crafted these permutation patterns
based on extensive research of common email formats.
Args:
first_name: First name to use in permutations
last_name: Last name to use in permutations
domain: Domain to append to usernames
level: Permutation level (1=light, 2=medium, 3=heavy)
Returns:
List of email address permutations
"""
# Ensure domain is lowercase for consistency
domain = domain.lower()
# Basic permutations (level 1) - MottaSec Ghost's essentials
permutations = [
f"{first_name.lower()}{last_name.lower()}@{domain}",
f"{first_name.lower()}.{last_name.lower()}@{domain}",
f"{first_name[0].lower()}{last_name.lower()}@{domain}",
f"{first_name[0].lower()}.{last_name.lower()}@{domain}",
f"{first_name[0].lower()}_{last_name.lower()}@{domain}",
f"{first_name.lower()}-{last_name.lower()}@{domain}",
]
# Add medium level permutations - MottaSec Fox's favorites
if level >= 2:
permutations.extend([
f"{first_name.lower()}@{domain}",
f"{last_name.lower()}@{domain}",
f"{first_name.lower()}_{last_name.lower()}@{domain}",
f"{last_name.lower()}.{first_name.lower()}@{domain}",
f"{last_name.lower()}_{first_name.lower()}@{domain}",
f"{last_name.lower()}{first_name.lower()}@{domain}",
])
# Add heavy level permutations - MottaSec Aces' advanced patterns
if level >= 3:
permutations.extend([
f"{first_name[0].lower()}{last_name[:3].lower()}@{domain}",
f"{first_name[0].lower()}.{last_name[:3].lower()}@{domain}",
f"{first_name[:3].lower()}{last_name[0].lower()}@{domain}",
f"{last_name[:3].lower()}{first_name[0].lower()}@{domain}",
f"{first_name.lower()}{last_name[0].lower()}@{domain}",
f"{last_name.lower()}{first_name[0].lower()}@{domain}",
])
return list(dict.fromkeys(permutations)) # Remove duplicates while preserving order
def motta_validate_email_smtp(email: str, sender_email: str, mx_server: str, debug: int) -> bool:
"""
Validate an email address via SMTP.
MottaSec Jedis know that SMTP validation is the most reliable way
to check if an email address exists without actually sending mail.
Args:
email: Email address to validate
sender_email: Email to use as MAIL FROM
mx_server: MX server to connect to
debug: Debug level (0=minimal, 1=moderate, 2=verbose)
Returns:
True if email exists, False otherwise
"""
try:
if debug >= 1:
print(f"{BLUE}🔌 Connecting to MX server: {mx_server}...{RESET}")
with smtplib.SMTP(mx_server, 25, timeout=10) as smtp:
if debug == 2:
smtp.set_debuglevel(1)
smtp.helo("mottasec.com") # MottaSec Fox's calling card
smtp.mail(sender_email)
response = smtp.rcpt(email)
if debug >= 1:
print(f"{BLUE}📨 RCPT TO response for {email}: {response}{RESET}")
return response[0] == 250
except Exception as e:
if debug >= 1:
print(f"{RED}⚠️ SMTP Error for {email}: {e}{RESET}")
return False
def motta_validate_info_address(domain: str, sender_email: str, mx_server: str, debug: int,
no_check: bool = False, check_email: str = None) -> Tuple[bool, bool]:
"""
Validate the existence of info@domain and check catch-all.
MottaSec Ghost's trick: Always check a standard email and a random one
to determine if the domain has catch-all enabled.
Args:
domain: Target domain
sender_email: Email to use as MAIL FROM
mx_server: MX server to connect to
debug: Debug level (0=minimal, 1=moderate, 2=verbose)
no_check: If True, skip checking default email
check_email: Custom email to check instead of info@domain
Returns:
Tuple of (is_valid, is_catch_all)
"""
try:
# Skip check if requested - MottaSec Fox respects user preferences
if no_check:
if debug >= 1:
print(f"\n{BLUE}🦊 MottaSec Fox: Skipping default email check as requested{RESET}")
return True, False
# Use custom email if provided, otherwise use info@domain
test_email = check_email if check_email else f"info@{domain}"
result = motta_validate_email_smtp(test_email, sender_email, mx_server, debug)
print("\n") # Empty line before
if result:
print(f"{GREEN}✅ MottaSec Fox confirms: {test_email} is valid.{RESET}")
else:
print(f"{RED}❌ MottaSec Ghost reports: {test_email} is invalid.{RESET}")
print("\n") # Empty line after
# Check for catch-all - MottaSec Aces' special technique
random_string = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz', k=10))
test_email = f"mottasec-{random_string}@{domain}"
is_catch_all = motta_validate_email_smtp(test_email, sender_email, mx_server, debug)
if is_catch_all:
print(f"{RED}⚠️ MottaSec Fox Alert: Domain {domain} is a catch-all domain!{RESET}")
return result, is_catch_all
except Exception as e:
print(f"{RED}🚨 MottaSec Error validating {test_email}: {e}{RESET}")
return False, False
def motta_validate_email_permutations(permutations: List[str], domain: str, sender_email: str,
delay: List[int], debug: int, no_check: bool = False,
check_email: str = None) -> None:
"""
Validate a list of email permutations via SMTP.
MottaSec Jedis always validate their findings thoroughly!
Args:
permutations: List of complete email addresses to validate
domain: Domain for MX lookup
sender_email: Email to use as MAIL FROM
delay: List of [min, max] delay in seconds
debug: Debug level (0=minimal, 1=moderate, 2=verbose)
no_check: If True, skip checking default email
check_email: Custom email to check instead of info@domain
"""
try:
mx_records = resolve(domain, 'MX')
if not mx_records:
print(f"{RED}🚨 MottaSec Fox Alert: No MX records found for {domain}{RESET}")
return
mx_server = mx_records[0].exchange.to_text()
if debug >= 1:
print(f"{BLUE}🔍 MottaSec Fox found MX server: {mx_server}{RESET}")
# Validate info@domain and check catch-all
info_valid, is_catch_all = motta_validate_info_address(
domain, sender_email, mx_server, debug, no_check, check_email
)
if not info_valid or is_catch_all:
return
# Validate each permutation - MottaSec Fox's hunting ground
valid_count = 0
for email in permutations:
is_valid = motta_validate_email_smtp(email, sender_email, mx_server, debug)
# Add empty lines for readability
print("\n")
if is_valid:
valid_count += 1
print(f"{GREEN}✅ MottaSec Fox found: {email} is valid.{RESET}")
else:
print(f"{RED}❌ MottaSec Ghost reports: {email} is invalid.{RESET}")
print("\n")
# Add delay with timestamp - MottaSec Ninja stealth technique
delay_duration = random.uniform(*delay)
print(f"{BLUE}⏱️ MottaSec Fox is waiting for {delay_duration:.2f} seconds at {time.strftime('%Y-%m-%d %H:%M:%S')}...{RESET}")
time.sleep(delay_duration)
# Summary - MottaSec Aces like good reports
print(f"\n{BLUE}📊 MottaSec Summary: Found {valid_count} valid email(s) out of {len(permutations)} tested.{RESET}")
except Exception as e:
print(f"{RED}🚨 MottaSec Error: Failed to retrieve MX server for {domain}: {e}{RESET}")
def motta_validate_scraped_emails(emails: List[str], domain: str, sender_email: str,
delay: List[int], debug: int, no_check: bool = False,
check_email: str = None) -> None:
"""
Validate a list of scraped emails via SMTP.
MottaSec Ghost always verifies what it finds!
Args:
emails: List of email addresses to validate
domain: Domain for MX lookup
sender_email: Email to use as MAIL FROM
delay: List of [min, max] delay in seconds
debug: Debug level (0=minimal, 1=moderate, 2=verbose)
no_check: If True, skip checking default email
check_email: Custom email to check instead of info@domain
"""
try:
mx_records = resolve(domain, 'MX')
if not mx_records:
print(f"{RED}🚨 MottaSec Fox Alert: No MX records found for {domain}{RESET}")
return
mx_server = mx_records[0].exchange.to_text()
if debug >= 1:
print(f"{BLUE}🔍 MottaSec Fox found MX server: {mx_server}{RESET}")
# Validate info@domain and check catch-all
info_valid, is_catch_all = motta_validate_info_address(
domain, sender_email, mx_server, debug, no_check, check_email
)
if not info_valid or is_catch_all:
return
# Validate each email - MottaSec Ghost's verification process
valid_count = 0
for email in emails:
is_valid = motta_validate_email_smtp(email, sender_email, mx_server, debug)
# Add empty lines for readability
print("\n")
if is_valid:
valid_count += 1
print(f"{GREEN}✅ MottaSec Ghost confirms: {email} is valid.{RESET}")
else:
print(f"{RED}❌ MottaSec Ghost reports: {email} is invalid.{RESET}")
print("\n")
# Add delay with timestamp - MottaSec Ninja stealth technique
delay_duration = random.uniform(*delay)
print(f"{BLUE}⏱️ MottaSec Ghost is waiting for {delay_duration:.2f} seconds at {time.strftime('%Y-%m-%d %H:%M:%S')}...{RESET}")
time.sleep(delay_duration)
# Summary - MottaSec Aces like good reports
print(f"\n{BLUE}📊 MottaSec Summary: Found {valid_count} valid email(s) out of {len(emails)} tested.{RESET}")
except Exception as e:
print(f"{RED}🚨 MottaSec Error: Failed to retrieve MX server for {domain}: {e}{RESET}")
# Aliases for backward compatibility
generate_permutations = motta_generate_permutations
validate_email_smtp = motta_validate_email_smtp
validate_info_address = motta_validate_info_address
validate_email_permutations = motta_validate_email_permutations
validate_scraped_emails = motta_validate_scraped_emails