beppause/smtp-ethical-hack
0
1"""
2GradioApp class for creating the user interface for email sending.
3"""
4import gradio as gr
5import re
6from typing import List, Optional
7from email_sender import EmailSender, EmailConfig
8
9
10def validate_email(email: str) -> bool:
11 """Validate email format using simple regex. Supports 'Name <email@domain.com>' format."""
12 # Extract email from 'Name <email@domain.com>' format if present
13 email_match = re.search(r'<([^>]+)>', email)
14 if email_match:
15 email = email_match.group(1)
16 else:
17 # If no angle brackets, use the whole string
18 email = email.strip()
19
20 pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
21 return bool(re.match(pattern, email))
22
23
24def extract_email_address(full_address: str) -> str:
25 """Extract email address from 'Name <email@domain.com>' format."""
26 if not full_address:
27 return ""
28
29 email_match = re.search(r'<([^>]+)>', full_address)
30 if email_match:
31 return email_match.group(1)
32 else:
33 return full_address.strip()
34
35
36class GradioApp:
37 """Gradio interface for email sending with SMTP dialogue logging."""
38
39 def __init__(self):
40 """Initialize the Gradio application."""
41 self.email_sender = EmailSender(log_callback=self._update_log)
42 self.log_output = ""
43
44 def _update_log(self, message: str):
45 """Update the log output with new messages."""
46 self.log_output += message + "\n"
47
48 def _send_email(
49 self,
50 smtp_server: str,
51 smtp_port: int,
52 username: str,
53 password: str,
54 use_tls: bool,
55 ssl_verify: bool,
56 from_addr: str,
57 to_addr: str,
58 subject: str,
59 body: str,
60 attachments: Optional[List[str]]
61 ) -> str:
62 """
63 Handle email sending process.
64
65 Args:
66 smtp_server: SMTP server address
67 smtp_port: SMTP server port
68 username: SMTP username
69 password: SMTP password
70 use_tls: Whether to use TLS
71 from_addr: Sender email address
72 to_addr: Recipient email address (comma-separated for multiple)
73 subject: Email subject
74 body: Email body
75 attachments: List of attachment file paths
76
77 Returns:
78 str: Result message
79 """
80 # Clear previous log
81 self.log_output = ""
82 self.email_sender.clear_log()
83
84 try:
85 # Parse recipient addresses
86 to_addrs = [addr.strip() for addr in to_addr.split(',') if addr.strip()]
87
88 if not to_addrs:
89 return "ERROR: No recipient email addresses provided"
90
91 # Validate email addresses
92 if from_addr and not validate_email(from_addr):
93 return "ERROR: Invalid sender email address format"
94
95 for addr in to_addrs:
96 if not validate_email(addr):
97 return f"ERROR: Invalid recipient email address format: {addr}"
98
99 # Validate port
100 try:
101 port = int(smtp_port)
102 if port <= 0 or port > 65535:
103 return "ERROR: Invalid port number (must be 1-65535)"
104 except ValueError:
105 return "ERROR: Port must be a valid number"
106
107 # Create email configuration
108 config = EmailConfig(
109 smtp_server=smtp_server,
110 smtp_port=port,
111 username=username,
112 password=password,
113 use_tls=use_tls,
114 ssl_verify=ssl_verify
115 )
116
117 # Connect to SMTP server
118 self._update_log("=== STARTING SMTP SESSION ===")
119 if not self.email_sender.connect(config):
120 return "ERROR: Failed to connect to SMTP server"
121
122 # Send email
123 success = self.email_sender.send_email(
124 from_addr=from_addr,
125 to_addrs=to_addrs,
126 subject=subject,
127 body=body,
128 attachments=attachments
129 )
130
131 # Disconnect
132 self.email_sender.disconnect()
133 self._update_log("=== SMTP SESSION COMPLETED ===")
134
135 if success:
136 return "SUCCESS: Email sent successfully!"
137 else:
138 return "ERROR: Failed to send email"
139
140 except Exception as e:
141 self._update_log(f"UNEXPECTED ERROR: {str(e)}")
142 return f"ERROR: {str(e)}"
143
144 def create_interface(self):
145 """Create and return the Gradio interface."""
146 with gr.Blocks(title="SMTP Ethical Hack - Email Sender Testing", theme="soft") as demo:
147 gr.Markdown("# ๐ง SMTP Ethical Hack - Email Sender Testing")
148 gr.Markdown("""
149 ## ๐ฏ Scopo del programma
150 Questo strumento permette di testare server SMTP per verificare se consentono l'invio di email con **mittente personalizzato** (spoofing).
151
152 ### โ ๏ธ Utilizzo etico
153 Questo tool รจ destinato esclusivamente a:
154 - Testing di sicurezza e configurazione dei server SMTP
155 - Verifica delle policy anti-spoofing
156 - Scopi educativi e di analisi tecnica
157
158 ### ๐ Come funziona
159 1. Inserisci le credenziali del server SMTP
160 2. Specifica un mittente personalizzato (anche diverso dalle credenziali)
161 3. Visualizza il dialogo completo SMTP per analisi
162 4. Verifica se il server accetta il mittente spoofato
163
164 **Esempio:** Puoi testare se un server consente di inviare come `bill.gates@microsoft.com` anche senza esserne il proprietario.
165 """)
166
167 with gr.Row():
168 with gr.Column(scale=1):
169 # SMTP Configuration
170 with gr.Group("SMTP Configuration"):
171 smtp_server = gr.Textbox(
172 label="SMTP Server",
173 value="authsmtp.register.it",
174 placeholder="smtp.example.com"
175 )
176 smtp_port = gr.Number(
177 label="SMTP Port",
178 value=587,
179 precision=0
180 )
181 use_tls = gr.Checkbox(
182 label="Use TLS",
183 value=True
184 )
185 ssl_verify = gr.Checkbox(
186 label="Verify SSL Certificate",
187 value=False,
188 info="Disable if you get SSL certificate errors"
189 )
190 username = gr.Textbox(
191 label="Username",
192 placeholder="your.email@example.com"
193 )
194 password = gr.Textbox(
195 label="Password",
196 type="password",
197 placeholder="Your SMTP password"
198 )
199
200 # Email Content
201 with gr.Group("Email Content"):
202 from_addr = gr.Textbox(
203 label="From (Sender)",
204 value="Bill Gates <bill.gates@microsoft.com>",
205 placeholder="Tedeschi Mauro <m.tedeschi@maseritalia.com>",
206 info="Can be different from username for testing. Use 'Name <email@domain.com>' format"
207 )
208 to_addr = gr.Textbox(
209 label="To (Recipients)",
210 placeholder="recipient1@example.com, recipient2@example.com",
211 info="Comma-separated for multiple recipients"
212 )
213 subject = gr.Textbox(
214 label="Subject",
215 placeholder="Email subject"
216 )
217 body = gr.Textbox(
218 label="Body",
219 placeholder="Email body text",
220 lines=5
221 )
222 attachments = gr.File(
223 label="Attachments",
224 file_count="multiple",
225 type="filepath"
226 )
227
228 # Send Button
229 send_btn = gr.Button("Send Email", variant="primary")
230
231 with gr.Column(scale=1):
232 # SMTP Log Output
233 with gr.Group("SMTP Dialogue Log"):
234 log_output = gr.Textbox(
235 label="SMTP Communication",
236 lines=20,
237 max_lines=50,
238 interactive=False,
239 show_copy_button=True
240 )
241
242 # Result Output
243 result_output = gr.Textbox(
244 label="Result",
245 interactive=False
246 )
247
248 # Set up event handlers
249 send_btn.click(
250 fn=self._send_email,
251 inputs=[
252 smtp_server,
253 smtp_port,
254 username,
255 password,
256 use_tls,
257 ssl_verify,
258 from_addr,
259 to_addr,
260 subject,
261 body,
262 attachments
263 ],
264 outputs=result_output
265 ).then(
266 fn=lambda: self.log_output,
267 outputs=log_output,
268 show_progress=False
269 )
270
271 # Clear log when inputs change
272 inputs = [smtp_server, smtp_port, username, password, use_tls, ssl_verify,
273 from_addr, to_addr, subject, body, attachments]
274
275 for input_component in inputs:
276 input_component.change(
277 fn=lambda: "",
278 outputs=log_output,
279 show_progress=False
280 )
281 input_component.change(
282 fn=lambda: "",
283 outputs=result_output,
284 show_progress=False
285 )
286
287 return demo
288
289 def launch(self, **kwargs):
290 """Launch the Gradio interface."""
291 demo = self.create_interface()
292 demo.launch(**kwargs)
293 