@@ -88,33 +88,75 @@ def show_status_help(self):
8888 help_dialog .setStandardButtons (QtWidgets .QMessageBox .Ok )
8989 help_dialog .exec_ ()
9090
91+ import concurrent .futures
92+
93+ class SingleVerificationWorker (QtCore .QObject ):
94+ finished = QtCore .pyqtSignal (str , bool )
95+
96+ def __init__ (self , email ):
97+ super ().__init__ ()
98+ self .email = email
99+
100+ def run (self ):
101+ try :
102+ domain = self .email .split ('@' )[1 ]
103+ if not has_mx_record (domain ):
104+ self .finished .emit ("Domain does not have MX records" , False )
105+ return
106+
107+ if not verify_email_smtp (self .email ):
108+ self .finished .emit ("SMTP verification failed! Email is not valid." , False )
109+ else :
110+ self .finished .emit ("Email is valid and appears to be reachable" , True )
111+ except Exception as e :
112+ self .finished .emit (f"Error: { str (e )} " , False )
113+
91114class BulkVerificationThread (QtCore .QThread ):
92115 result_signal = QtCore .pyqtSignal (str , str )
93116 all_done = QtCore .pyqtSignal ()
94117
95118 def __init__ (self , emails ):
96119 super ().__init__ ()
97120 self .emails = emails
121+ self .is_running = True
98122
99123 def run (self ):
100- for email in self .emails :
101- if not email :
102- continue
124+ with concurrent .futures .ThreadPoolExecutor (max_workers = 5 ) as executor :
125+ future_to_email = {executor .submit (self .verify_single_email , email ): email for email in self .emails if email }
126+
127+ for future in concurrent .futures .as_completed (future_to_email ):
128+ if not self .is_running :
129+ executor .shutdown (wait = False , cancel_futures = True )
130+ break
131+
132+ email = future_to_email [future ]
133+ try :
134+ status = future .result ()
135+ except Exception as e :
136+ status = f"Error: { str (e )} "
103137
104- try :
105- if not is_valid_email_syntax (email ):
106- status = "Invalid (Syntax)"
107- elif not has_mx_record (email .split ('@' )[1 ]):
108- status = "Invalid (No MX)"
109- elif not verify_email_smtp (email ):
110- status = "Invalid (SMTP)"
111- else :
112- status = "Valid"
113- except Exception as e :
114- status = f"Error: { str (e )} "
138+ self .result_signal .emit (email , status )
115139
116- self .result_signal .emit (email , status )
117- self .all_done .emit () # Signal completion after all emails
140+ self .all_done .emit ()
141+
142+ def verify_single_email (self , email ):
143+ try :
144+ if not is_valid_email_syntax (email ):
145+ return "Invalid (Syntax)"
146+
147+ domain = email .split ('@' )[1 ]
148+ if not has_mx_record (domain ):
149+ return "Invalid (No MX)"
150+
151+ if not verify_email_smtp (email ):
152+ return "Invalid (SMTP)"
153+
154+ return "Valid"
155+ except Exception as e :
156+ return f"Error: { str (e )} "
157+
158+ def stop (self ):
159+ self .is_running = False
118160
119161class EmailValidatorApp (QtWidgets .QWidget ):
120162 def __init__ (self ):
@@ -124,7 +166,8 @@ def __init__(self):
124166 self .verifying_timer = QtCore .QTimer ()
125167 self .verifying_counter = 1
126168 self .verifying_timer .timeout .connect (self .update_verifying_text )
127- self .verification_thread = None
169+ self .bulk_thread = None
170+ self .single_worker_thread = None
128171
129172 def init_ui (self ):
130173 self .setWindowTitle ("KnowEmail" )
@@ -232,10 +275,14 @@ def bulk_verify(self):
232275 self .results_dialog .show ()
233276
234277 # Start verification in background
235- self .verification_thread = BulkVerificationThread (emails )
236- self .verification_thread .result_signal .connect (self .update_results )
237- self .verification_thread .all_done .connect (self .show_completion_popup ) # Add this
238- self .verification_thread .start ()
278+ if self .bulk_thread and self .bulk_thread .isRunning ():
279+ self .bulk_thread .stop ()
280+ self .bulk_thread .wait ()
281+
282+ self .bulk_thread = BulkVerificationThread (emails )
283+ self .bulk_thread .result_signal .connect (self .update_results )
284+ self .bulk_thread .all_done .connect (self .show_completion_popup )
285+ self .bulk_thread .start ()
239286
240287 def show_completion_popup (self ):
241288 QtWidgets .QMessageBox .information (
@@ -266,25 +313,38 @@ def validate_email(self):
266313 if not is_valid_email_syntax (email ):
267314 QtWidgets .QMessageBox .warning (self , "Error" , "Invalid email syntax" )
268315 return
316+
269317 self .verifying_counter = 1
270318 self .verifying_timer .start (500 )
271319 self .result_label .setText ("Verifying..." )
272- QtCore .QTimer .singleShot (100 , lambda : self .verify_in_background (email ))
320+ self .validate_button .setEnabled (False )
321+ self .email_input .setEnabled (False )
322+
323+ # Create worker and thread for async execution
324+ self .single_worker_thread = QtCore .QThread ()
325+ self .worker = SingleVerificationWorker (email )
326+ self .worker .moveToThread (self .single_worker_thread )
327+
328+ # Connect signals
329+ self .single_worker_thread .started .connect (self .worker .run )
330+ self .worker .finished .connect (self .handle_single_verification_result )
331+ self .worker .finished .connect (self .single_worker_thread .quit )
332+ self .worker .finished .connect (self .worker .deleteLater )
333+ self .single_worker_thread .finished .connect (self .single_worker_thread .deleteLater )
334+
335+ self .single_worker_thread .start ()
336+
337+ def handle_single_verification_result (self , message , is_valid ):
338+ self .verifying_timer .stop ()
339+ self .result_label .setText ("" )
340+ self .validate_button .setEnabled (True )
341+ self .email_input .setEnabled (True )
342+
343+ self .show_popup (message )
273344
274345 def verify_in_background (self , email ):
275- domain = email .split ('@' )[1 ]
276- if not has_mx_record (domain ):
277- self .show_popup ("Domain does not have MX records" )
278- return
279- try :
280- if not verify_email_smtp (email ):
281- self .show_popup ("SMTP verification failed! Email is not valid." )
282- else :
283- self .show_popup ("Email is valid and appears to be reachable" )
284- except Exception as e :
285- self .show_popup (f"Error: { str (e )} " )
286- finally :
287- self .verifying_timer .stop ()
346+ # Deprecated: Logic moved to SingleVerificationWorker
347+ pass
288348
289349 def show_popup (self , message ):
290350 self .verifying_timer .stop ()
0 commit comments