Ë
    äyjfc  ã                   ó~  — d dl mZmZmZmZmZmZ d dlmZm	Z	m
Z
 d dlmZ d dlmZ d dlmZmZmZmZmZmZmZ d dlZd dlZd dlZd dlZd dlmZmZmZ d dlm Z  d d	l!m"Z" d d
l#m$Z$ d dl%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/ d dl0m1Z1m2Z2 d dl3m4Z4 d dl5m6Z6m7Z7m8Z8 dZ9 ejt                  dd«      jw                  «       dk(  Z< ejt                  dd«      jw                  «       dk(  Z= ejt                  dd«      jw                  «       dk(  Z> e1«       Z? e-e9j�                  dd«      e<d¬«      ZA e2eA¬«      ZBd„ ZC e«       ZDeDj‹                  e«       eDj‹                  eed¬«        e eF«      jŽ                  ZHeHdz  ZIeHdz  ZJeHdz  ZK e eLeI«      ¬ «      ZM ejœ                  «       ZOd!ddd"œZPd#„ ZQdgd$eLd%eLd&eLfd'„ZRd(eSfd)„ZTd*eUd+eLfd,„ZVd*eUd+eLd-eLd(eSfd.„ZWd/e d&eLfd0„ZX G d1„ d2e?«      ZYd3eLd(eeL   fd4„ZZeDj·                  d5e¬6«      	 	 	 dhd7ed8eeL   d9eeL   d:eeL   fd;„«       Z\eDj»                  d5«       ed<«       ed<«       ed«      fd7ed:eLd=eLd8eeL   fd>„«       Z^eDj»                  d?«      d7efd@„«       Z_eDj·                  dAe¬6«      	 	 did7ed%eeL   dBeeL   fdC„«       Z`eDj»                  dA«       ed<«       ed<«       ed<«      fd7edDeLdEeLdFeLfdG„«       ZaeDj·                  dHe¬6«      d7efdI„«       Zbh dJ£ZceDj·                  dKe¬6«      	 	 	 	 djd7edLeUdMeeL   dNeeL   dOeeL   f
dP„«       ZdeDj·                  dQe¬6«      d7efdR„«       ZeeDj·                  dS«      dT„ «       ZfeDj»                  dU«      dV„ «       ZgeDj»                  dW«       ed<«      fdXedYefdZ„«       ZheDj»                  d[«       ed<«       ed«       ed«      fdXed*eUd+eeL   d-eeL   fd\„«       ZieDj·                  d]e¬6«      d7ed*eUfd^„«       Zje=re?jÖ                  jÙ                  eA¬«       d_amd`„ Zne>r en«        ndameodak(  r%d dlpZp epjâ                  dbdcddd eLeH«      gdeg¬f«       yy)ké    )ÚFastAPIÚRequestÚFormÚFileÚ
UploadFileÚBackgroundTasks)ÚHTMLResponseÚRedirectResponseÚJSONResponse)ÚJinja2Templates)ÚSessionMiddleware)ÚAdminAuthMiddlewareÚSESSION_SECRETÚchange_admin_passwordÚcheck_admin_loginÚis_authenticatedÚsafe_next_pathÚverify_adminN)ÚListÚDictÚOptional)ÚPath)Ú	urlencode)Úuuid4)
ÚColumnÚIntegerÚStringÚTextÚBooleanÚFloatÚDateTimeÚcreate_engineÚtextÚinspect)Údeclarative_baseÚsessionmaker)Úfunc)Úclassify_new_imap_emailsÚlearn_from_feedbackÚprocess_uploaded_spam_csvzjpostgresql+asyncpg://postgres:p4python@postgres.cqf3qroocfwm.us-east-1.rds.amazonaws.com:5432/email_filterÚSQL_ECHOÚfalseÚtrueÚAUTO_CREATE_TABLESÚENSURE_FEEDBACK_COLUMNz+asyncpgÚ T)ÚechoÚpool_pre_ping)Úbindc                  óÌ  — t        «       } 	 | j                  t        «      j                  t        j                  j                  d «      «      j                  t        j                  j                  «       «      j                  «       }|xs g 	 | j                  «        S # t        $ r(}t        d|«       g cY d }~| j                  «        S d }~ww xY w# | j                  «        w xY w)NzDB error while fetching emails:)ÚSessionLocalÚqueryÚ	EmailSpamÚfilterÚimap_uidÚisnotÚorder_byÚreceived_atÚdescÚallÚcloseÚ	ExceptionÚprint)ÚdbÚemailsÚes      ú'/var/www/html/newmanjeet/manjet/main.pyÚget_all_emails_from_dbrF   +   s¨   € Ü	‹€Bðà�H‰H”YÓß‰V”I×&Ñ&×,Ñ,¨TÓ2Ó3ß‰X”i×+Ñ+×0Ñ0Ó2Ó3ß‰S‹Uð	 	ð Š|˜Ðð
 	�‰�
øô	 ò ÜÐ/°Ô3ØŒ	à
�‰�
ûð	ûð 	�‰�
ús0   ŒA?B Â	CÂ&C	Â3CÂ4C Ã	CÃC ÃC#Úmanjet_session)Ú
secret_keyÚsession_cookieÚ	templatesÚuploadsÚmodels)Ú	directoryÚidle©ÚstateÚmessageÚfilenamec                  ó¼   — t         5  t        j                  «       } d d d «       d j                  d«      xs dv r| j	                  ddddœ«       | S # 1 sw Y   Œ7xY w)NÚ	RefreshedrQ   r0   rN   rO   )ÚTRAINING_STATUS_LOCKÚTRAINING_STATUSÚcopyÚgetÚupdate)Ústatuss    rE   Úget_training_statusr[   P   sO   € Þ	Ü ×%Ñ%Ó'ˆ÷ 
à�v—z‘z )Ó,Ò2°Ñ3Ø�‰ °2À2ÑFÔGØ€M÷	 
Ð	ús   ‡AÁArP   rQ   rR   c                 ól   — t         5  t        j                  | ||dœ«       d d d «       y # 1 sw Y   y xY w)NrO   )rU   rV   rY   rO   s      rE   Úset_training_statusr]   X   s-   € Þ	Ü×ÑØØØ ñ 
ô 	÷ 
×	Ñ	ús   ‡*ª3Úreturnc                  ó¶   — t        «       } 	 | j                  t        d«      «      j                  «       d u| j	                  «        S # | j	                  «        w xY w)NzÀ
                SELECT 1
                FROM email_filter
                WHERE imap_uid IS NOT NULL
                  AND model_accuracy IS NOT NULL
                LIMIT 1
                )r5   Úexecuter#   Úfirstr?   )rB   s    rE   Úfilter_results_existrb   a   sL   € Ü	‹€BðØ�z‰zÜðóó

÷ ‰%‹'˜ð
ð 	�‰�
øˆ�‰�
ús   Œ)A ÁAÚemail_idÚclassificationc                 ó”   — 	 t        | |t        t        ¬«       t        d| «       y # t        $ r}t        d| d|«       Y d }~y d }~ww xY w)N)rc   Úfeedback_labelÚsession_factoryÚ	model_dirz)Updated model from feedback for email_id:z-Background model learning failed for email_idÚ:)r)   r5   Ú	MODEL_DIRrA   r@   )rc   rd   rD   s      rE   Ú#run_feedback_learning_in_backgroundrk   s   sM   € ð	QÜØØ)Ü(Üõ		
ô 	Ð9¸8ÕDøÜò QÜÐ=¸xÈÈa×PÑPûðQús   ‚#& ¦	A¯AÁAÚfeedbackc                 ó   — t        «       }	 |j                  t        d«      ||| dœ«      j                  «       }|s"|j	                  «        	 |j                  «        y|j                  «        	 |j                  «        y# t        $ rà}|j	                  «        t        d|«       	 |j                  t        d«      || dœ«      j                  «       }|s%|j	                  «        Y d }~|j                  «        y|j                  «        Y d }~|j                  «        y# t        $ r:}|j	                  «        t        d|«       Y d }~Y d }~|j                  «        yd }~ww xY wd }~ww xY w# |j                  «        w xY w)	Na`  
                UPDATE email_filter
                SET predicted_label = :classification,
                    feedback_label = :classification,
                    feedback = :feedback,
                    is_reviewed = TRUE
                WHERE id = :email_id
                  AND imap_uid IS NOT NULL
                RETURNING id
                )rd   rl   rc   FTz1Full feedback save failed, trying minimal update:a  
                    UPDATE email_filter
                    SET predicted_label = :classification,
                        is_reviewed = TRUE
                    WHERE id = :email_id
                      AND imap_uid IS NOT NULL
                    RETURNING id
                    )rd   rc   zMinimal feedback save failed:)	r5   r`   r#   ra   Úrollbackr?   Úcommitr@   rA   )rc   rd   rl   rB   ÚrowrD   Úfallback_errors          rE   Úsave_classification_feedbackrr   €   sO  € ô
 
‹€Bð7Ø�j‰jÜð	óð #1Ø$Ø$ñó
÷$ ‰%‹'ð% 	ñ& Ø�K‰KŒMØðB 	�‰�
ðA 	�	‰	ŒØð> 	�‰�
øô= ò Ø
�‰ŒÜÐAÀ1ÔEð	Ø—*‘*Üðó	ð '5Ø (ñó÷ ‰e‹gð ñ  Ø—‘”Ûð 	�‰�
ð �I‰IŒKÛð 	�‰�
øô ò 	Ø�K‰KŒMÜÐ1°>ÔBßà
�‰�
ûð	þð3ûð< 	�‰�
úse   Œ?A? ÁA? Á?	E(ÂE#Â%>DÃ#E+ Ã8DÄE+ Ä	E Ä&EÅE#ÅE+ ÅE Å E#Å#E(Å(E+ Å+E=Úcsv_pathc                 ó¨  — 	 t        dd|› d�|«       t        | t        t        ¬«      }d|› d|j                  › d|j
                  › d|j                  › d	|j                  d
z  d›d|j                  › d|j                  › d|j                  › d�}t        d||«       y # t        $ r,}t        d|«       t        dt        |«      |«       Y d }~y d }~ww xY w)NÚrunningúTraining model from ú...)rs   rg   rh   zTraining complete for z. Trained on z usable rows from z CSV rows and reclassified z existing emails. Accuracy: éd   z.1fz	%. Spam: z, Ham: z, Undecided: Ú.Ú	completedzCSV upload/training failed:Úerror)r]   r*   r5   rj   Útraining_rowsÚ
total_rowsÚreclassified_rowsÚaccuracyÚ
spam_countÚ	ham_countÚundecided_countr@   rA   Ústr)rs   rR   ÚresultrQ   rD   s        rE   Ú$train_uploaded_dataset_in_backgroundr…   À   sò   € ð7Ü˜IÐ)=¸h¸ZÀsÐ'KÈXÔVÜ*ØÜ(Üô
ˆð % X J¨m¸F×<PÑ<PÐ;Qð RØ×%Ñ%Ð&Ð&AÀ&×BZÑBZÐA[ð \ØŸ™¨3Ñ.¨sÐ3ð 4Ø×&Ñ&Ð' w¨v×/?Ñ/?Ð.@ÀÈf×NdÑNdÐMeÐefðhð 	ô 	˜K¨°(Õ;øÜò 7ÜÐ+¨QÔ/Ü˜G¤S¨£V¨X×6Ñ6ûð7ús   ‚BB Â	CÂ%"CÃCc                   óB  — e Zd ZdZ eedd¬«      Z eed¬«      Z eed¬«      Z	 ee
d¬«      Z eed¬«      Z eed¬«      Z eed¬«      Z ee
d¬«      Z eed¬«      Z ee
d¬«      Z eed¬«      Z eed¬«      Z e ed¬«       ej0                  «       ¬«      Zy	)
r7   Úemail_filterT)Úprimary_keyÚindexF)Únullable)Údefault)Útimezone)Úserver_defaultN)Ú__name__Ú
__module__Ú__qualname__Ú__tablename__r   r   Úidr   Úsender_emailÚsubjectr   Úbodyr    Úspam_probabilityÚpredicted_labelrf   rl   r   Úis_reviewedÚemail_summaryÚmodel_accuracyr9   r!   r'   Únowr<   © ó    rE   r7   r7   Ô   s³   „ Ø"€Má	� T°Ô	6€BÙ˜&¨5Ô1€LÙ�V dÔ+€GÙ�$ Ô&€Dá˜e¨dÔ3ÐÙ˜V¨dÔ3€OÙ˜F¨TÔ2€NÙ�d TÔ*€HÙ˜¨%Ô0€Ká˜4¨$Ô/€MÙ˜E¨DÔ1€NÙ�f tÔ,€HÙ™¨4Ô0ÀÀÇÁÃÔL�Kr�   r7   r”   c                 ó¶   — g }| j                  «       }g d¢}|D ]=  }t        j                  ||t        j                  «      sŒ)|j	                  d|› d�«       Œ? |S )z*Check email subject for spam-like patterns)zF\b(win|winner|won|prize|free|urgent|limited time|act now|click here)\bz\$[\d,]+z!!!+z"\b(viagra|cialis|pharmacy|pills)\bz(\b(guaranteed|risk-free|no obligation)\bz>\b(click|download|claim|verify)\b.*\b(now|immediately|today)\bz&Subject contains suspicious pattern: 'Ú')ÚlowerÚreÚsearchÚ
IGNORECASEÚappend)r”   Úspam_patternsÚsubject_lowerÚspam_keywordsÚpatterns        rE   Úanalyze_email_subjectr©   ê   sZ   € à€MØ—M‘M“O€Mò€Mó !ˆÜ�9‰9�W˜m¬R¯]©]Õ;Ø× Ñ Ð#IÈ'ÈÐRSÐ!TÕUð !ð Ðr�   z/admin/login)Úresponse_classÚrequestÚnextr{   Úusernamec              ƒ   ó�   K  — t        | «      rt        t        |«      d¬«      S t        j	                  | d| |||xs ddd dœ«      S ­w)Né/  ©Ústatus_codeúadmin_login.htmlr0   )r«   r{   r¬   r­   ÚpasswordÚerror_field)r   r
   r   rJ   ÚTemplateResponse)r«   r¬   r{   r­   s       rE   Úadmin_login_pager¶     sU   è ø€ ô ˜Ô Ü¤¨tÓ 4À#ÔFÐFÜ×%Ñ% gØàØØØ š BØØñ	
ó
ð 
ùs   ‚AA.r³   c              ƒ   óÊ   K  — t        ||«      \  }}|r%d| j                  d<   t        t        |«      d¬«      S |dk(  rd}nd}t        j                  | d| |||||d	œd
¬«      S ­w)NTÚis_adminr¯   r°   Úwrong_usernamez>Wrong username. Please check your email address and try again.z!Wrong password. Please try again.r²   )r«   r{   r´   r¬   r­   r³   i‘  )r   Úsessionr
   r   rJ   rµ   )r«   r­   r³   r¬   ÚsuccessÚ
error_codeÚerror_messages          rE   Úadmin_login_submitr¾     sˆ   è ø€ ô ,¨H°hÓ?Ñ€GˆZÙØ&*ˆ�‰˜
Ñ#Ü¤¨tÓ 4À#ÔFÐFàÐ%Ò%ØX‰à;ˆä×%Ñ% gØàØ"Ø%ØØ Ø ñ	
ð ð &ó ð ùs   ‚A!A#z/admin/logoutc              ƒ   óX   K  — | j                   j                  «        t        dd¬«      S ­w)NÚ/r¯   r°   )rº   Úclearr
   ©r«   s    rE   Úadmin_logoutrÃ   7  s#   è ø€ à‡O�O×ÑÔÜ˜C¨SÔ1Ð1ùs   ‚(*z/admin/change-passwordÚmessage_typec              ƒ   óH   K  — t         j                  | d| ||xs ddœ«      S ­w)Núchange_password.htmlr{   ©r«   rQ   rÄ   ©rJ   rµ   rÇ   s      rE   Úchange_password_pagerÉ   =  s3   è ø€ ô ×%Ñ% gØàØØ(Ò3¨Gñ	
óð ùs   ‚ "Úcurrent_passwordÚnew_passwordÚconfirm_passwordc              ƒ   ó‚   K  — t        |||«      \  }}|rdnd}t        j                  | d| ||dœ|rd¬«      S d¬«      S ­w)Nr»   r{   rÆ   rÇ   éÈ   i�  r°   )r   rJ   rµ   )r«   rÊ   rË   rÌ   ÚokÚresult_messagerÄ   s          rE   Úchange_password_submitrÑ   M  sq   è ø€ ô /ØØØóÑ€Bˆñ
 !#‘9¨€LÜ×%Ñ% gØàØ%Ø(ñ	
ñ
 �Cð &ó ð ð $'ð &ó ð ùs   ‚=?rÀ   c              ƒ   ól   K  — t        | «      rt        dd¬«      S t        j                  | dd| i«      S ­w)Nú/dashboard/spamr¯   )Úurlr±   zlanding.htmlr«   )r   r
   rJ   rµ   rÂ   s    rE   Úlanding_pagerÕ   h  s<   è ø€ ä˜Ô ÜÐ$5À3ÔGÐGÜ×%Ñ% gØØ	�GÐóð ùs   ‚24>   ÚhamÚspamÚ	undecidedrÓ   Úpager8   Úupload_statusÚupload_messagec              ƒ   ób  K  — |rd|v rd }d }d}|dz
  |z  }d„ }	 t        t        t        «       t        «       }	t        |	«      }
t        «       }	 |j                  t        j                  «      j                  t        j                  j                  d «      «      j                  t        j                  j                  d «      «      j                  t        j                  j                  «       «      j!                  «       }|j#                  «        |rt%        |j                  dz  d«      }d}nd }d}|rm|	D �cg c]  } ||j&                  «      ‘Œ }}t)        d	„ |D «       «      }t)        d
„ |D «       «      }t)        d„ |D «       «      }t)        d„ |D «       «      }|
|z
  }nd}d}d}d}|xs dj+                  «       j-                  «       }|t.        vrd }|r|sd }|	}|r$|	D �cg c]  } ||j&                  «      |k(  r|‘Œ }}||||z    }g }|D ]Ž  }|r ||j&                  «      nd }|r|j0                  nd }|�t%        |dz  d«      nd }|j3                  |j                  |j4                  |j6                  |j8                  |r|nd||j:                  xs ddœ«       Œ� t        |«      }|r||z   dz
  |z  nd}|
||||dœ}t<        j?                  | d| ||||||||tA        «       ||dœ«      S # t        $ r}t	        d|«       Y d }~�ŒÙd }~ww xY w# |j#                  «        w xY wc c}w c c}w ­w)NrT   é   é   c                 óF   — | r| j                  «       j                  «       S d S ©N)Ústripr    )Úlabels    rE   Únormalize_labelz'spam_dashboard.<locals>.normalize_label‡  s   € Ù(-ˆu�{‰{‹}×"Ñ"Ó$Ð7°4Ð7r�   z(Could not classify newly fetched emails:rx   TFc              3   ó,   K  — | ]  }|d k(  sŒ	d–— Œ y­w)r×   rÞ   Nrœ   ©Ú.0Úls     rE   Ú	<genexpr>z!spam_dashboard.<locals>.<genexpr>©  s   è ø€ Ð>¡J˜q°!°v³+œ¡Jùó   ‚
�c              3   ó,   K  — | ]  }|d k(  sŒ	d–— Œ y­w)rÖ   rÞ   Nrœ   rå   s     rE   rè   z!spam_dashboard.<locals>.<genexpr>ª  s   è ø€ Ð<¡:˜a°°e³œ¡:ùré   c              3   ó,   K  — | ]  }|d k(  sŒ	d–— Œ y­w)rØ   rÞ   Nrœ   rå   s     rE   rè   z!spam_dashboard.<locals>.<genexpr>«  s   è ø€ ÐH© A°q¸KÓ7Gœa©ùré   c              3   ó&   K  — | ]	  }|�Œd–— Œ y ­w)NrÞ   rœ   rå   s     rE   rè   z!spam_dashboard.<locals>.<genexpr>¬  s   è ø€ Ð"F©j¨¸A¹I¤1©jùs   ‚Šr   r0   Ú
unfiltered)rc   Úsenderr”   Úsummaryrâ   Úml_scorerl   )Útotalr×   rÖ   rØ   Ú
classifiedzspam_dashboard.html)r«   rC   ÚstatsrÙ   Útotal_pagesrš   Úfilter_results_availablerÚ   rÛ   Útraining_statusÚactive_filterÚfiltered_total)!r(   r5   rj   r@   rA   rF   Úlenr6   r7   rš   r8   r9   r:   r;   r’   r=   ra   r?   Úroundr—   Úsumrá   r    ÚLABEL_FILTERSr–   r¤   r“   r”   r•   rl   rJ   rµ   r[   ) r«   rÙ   r8   rÚ   rÛ   ÚPER_PAGEÚoffsetrã   rD   Ú
all_emailsÚtotal_emailsrB   Úlatest_accuracy_rowÚmodel_accuracy_percentrõ   Ú
all_labelsr€   r�   r‚   Únot_classified_countÚclassified_countr÷   Údisplay_emailsÚemailÚ	db_emailsÚenhanced_emailsÚdisplay_labelÚ	spam_probrð   rø   rô   ró   s                                    rE   Úspam_dashboardr  x  s[  è ø€ ñ ˜+¨Ñ7ØˆØˆà€HØ�Q‰h˜(Ñ"€Fò8ð=Ü ¤¬yÔ9ô
 (Ó)€JÜ�z“?€Lä	‹€Bð	à�H‰H”Y×-Ñ-Ó.ß‰V”I×&Ñ&×,Ñ,¨TÓ2Ó3ß‰V”I×,Ñ,×2Ñ2°4Ó8Ó9ß‰X”i—l‘l×'Ñ'Ó)Ó*ß‰U‹Wð 	ð 	�‰Œ
áÜ!&Ð':×'IÑ'IÈCÑ'OÐQRÓ!SÐØ#'Ñ à!%ÐØ#(Ð ñ  ÙBLÓMÁ*¸Q‘o a×&7Ñ&7Õ8À*ˆ
ÐMÜÑ>¡JÓ>Ó>ˆ
ÜÑ<¡:Ó<Ó<ˆ	ÜÑH©ÓHÓHˆÜ"Ñ"F©jÓ"FÓFÐØ'Ð*>Ñ>Ñàˆ
Øˆ	ØˆØÐà’\˜r×(Ñ(Ó*×0Ñ0Ó2€MØœMÑ)ØˆÙÑ5Øˆà€NÙñ $ó
á#�Ù˜u×4Ñ4Ó5¸ÒFò Ø#ð 	ð 
ð ˜v f¨xÑ&7Ð8€Ià€OÛˆÙBZ™¨×(=Ñ(=Ô>Ð`dˆÙ.F�E×*Ò*ÈDˆ	Ø09Ð0E”5˜ S™¨!Ô,È4ˆà×ÑØŸ™Ø×(Ñ(Ø—}‘}Ø—z‘zÙ&3‘]¸Ø ØŸ™Ò,¨"ñ 
õ 	ð ô  ˜Ó(€NÙAO�> HÑ,¨qÑ0°XÒ=ÐUV€Kð ØØØ$Ø&ñ€Eô ×%Ñ% gØàØ%ØØØ&Ø4Ø(@Ø*Ø,Ü2Ó4Ø*Ø,ñ	
óð øôk ò =ÜÐ8¸!×<Ò<ûð=ûð" 	�‰�
üò Nùò(
ùs`   ‚L/›K- ¯L/ÁB0L Ã?8L/Ä7L%ÅBL/Ç"L*È C-L/Ë-	LË6LÌL/ÌLÌL/ÌL"Ì"L/z/dashboard/spam/addc              ƒ   ó<   K  — t         j                  | dd| i«      S ­w)Nzspam_add.htmlr«   rÈ   rÂ   s    rE   Úspam_add_pager  ÷  s&   è ø€ ä×%Ñ% gØØ	�GÐóð ùs   ‚z/dashboard/spam/upload-statusc               ƒ   ó0   K  — t        t        «       «      S ­wrà   )r   r[   rœ   r�   rE   Úspam_upload_statusr  ÿ  s   è ø€ äÔ+Ó-Ó.Ð.ùs   ‚z/dashboard/spam/clear-analysisc               ƒ   óè  K  — t        «       } | j                  d«      dk(  rt        dddœ«      }t        d|› �d¬«      S t	        «       }	 |j                  t        d	«      «       |j                  «        	 |j                  «        t        dz  t        dz  fD ]  }	 |j                  d¬«       Œ t        ddd«       t        dddœ«      }t        d|› �d¬«      S # t        $ rT}|j                  «        t        d
|«       t        dddœ«      }t        d|› �d¬«      cY d }~|j                  «        S d }~ww xY w# |j                  «        w xY w# t        $ r}t        d||«       Y d }~ŒÓd }~ww xY w­w)NrP   ru   r{   z@Training is still running. Please wait before clearing analysis.©rÚ   rÛ   ú/dashboard/spam?r¯   r°   zã
                UPDATE email_filter
                SET spam_probability = NULL,
                    predicted_label = NULL,
                    model_accuracy = NULL
                WHERE imap_uid IS NOT NULL
                zCould not clear analysis:z+Could not clear analysis. Please try again.zfinal_model.pklzfinal_vectorizer.pklT)Ú
missing_okzCould not remove model file:rN   r0   r»   zQAnalysis cleared. Emails are still saved; upload a dataset to analyze them again.)r[   rX   r   r
   r5   r`   r#   ro   r@   rn   rA   r?   rj   Úunlinkr]   )Úcurrent_statusr6   rB   rD   Ú
model_files        rE   Úclear_spam_analysisr    s€  è ø€ ä(Ó*€NØ×Ñ˜'Ó" iÒ/ÜØ$Ø`ñ
ó ˆô  Ð"2°5°'Ð :ÈÔLÐLä	‹€BðØ
�
‰
Üðóô
	
ð 	�	‰	�ð 	�‰Œ
ä Ð#4Ñ4´iÐBXÑ6XÓYˆ
ð	AØ×Ñ¨ÐÕ.ð Zô ˜  BÔ'ÜØ"Ømñó €Eô Ð.¨u¨gÐ6ÀCÔHÐHøô- ò MØ
�‰ŒÜÐ)¨1Ô-ÜØ$ØKñ
ó ˆô  Ð"2°5°'Ð :ÈÔLÔLà
�‰�
ûðMûð 	�‰�
ûô
 ò 	AÜÐ0°*¸a×@Ñ@ûð	Aüsr   ‚AE2Á
*C Á5%E2ÂEÂ--E2Ã	D7Ã#9D2ÄD7ÄD: Ä!E2Ä2D7Ä7D: Ä:EÅE2Å	E/ÅE*Å%E2Å*E/Å/E2z/dashboard/spam/uploadÚbackground_tasksÚdatasetc              ƒ   óX  K  — t        «       }|j                  d«      dk(  rt        dddœ«      }t        d|› �d¬«      S t	        «       rt        dd	dœ«      }t        d|› �d¬«      S |j
                  xs d
}|j                  «       j                  d«      st        dddœ«      }t        d|› �d¬«      S t        j                  dd¬«       t        j                  ddt        |«      j                  «      }t        t        «       j                  › d|› �z  }	 |j!                  d«      5 }t#        j$                  |j&                  |«       d d d «       t)        dd|› d�|«       | j+                  t,        ||«       t        dddœ«      }|j&                  j5                  «        t        d|› �d¬«      S # 1 sw Y   ŒixY w# t.        $ rC}t1        d|«       t)        dt3        |«      |«       t        dt3        |«      dœ«      }Y d }~Œ}d }~ww xY w# |j&                  j5                  «        w xY w­w)NrP   ru   r{   z<A dataset is already training. Please wait for it to finish.r  r  r¯   r°   zMAnalysis already exists. Clear analysis before training with another dataset.r0   z.csvzPlease upload a CSV file.T)ÚparentsÚexist_okz[^a-zA-Z0-9_.-]Ú_Úwbrv   rw   ÚinfozXUpload received. Training is running in the background and existing emails will be kept.zCSV upload failed:)r[   rX   r   r
   rb   rR   r    ÚendswithÚUPLOADS_DIRÚmkdirr¡   Úsubr   Únamer   ÚhexÚopenÚshutilÚcopyfileobjÚfiler]   Úadd_taskr…   r@   rA   rƒ   r?   )	r  r  r  r6   rR   Ú	safe_nameÚupload_pathÚbufferrD   s	            rE   Úupload_spam_datasetr/  5  s  è ø€ ô
 )Ó*€NØ×Ñ˜'Ó" iÒ/ÜØ$Ø\ñ
ó ˆô  Ð"2°5°'Ð :ÈÔLÐLäÔÜØ$Ømñ
ó ˆô  Ð"2°5°'Ð :ÈÔLÐLà×ÑÒ% 2€HØ�>‰>Ó×$Ñ$ VÔ,ÜØ$Ø9ñ
ó ˆô  Ð"2°5°'Ð :ÈÔLÐLä×Ñ˜d¨TÐÔ2Ü—‘Ð)¨3´°X³×0CÑ0CÓD€IÜ¤5£7§;¡; -¨q°°Ð <Ñ<€KðØ×Ñ˜dÔ# vÜ×Ñ˜wŸ|™|¨VÔ4÷ $ä˜IÐ)=¸h¸ZÀsÐ'KÈXÔVØ×!Ñ!Ô"FÈÐU]Ô^ÜØ#Øxñ
ó ˆð 	�‰×ÑÔäÐ.¨u¨gÐ6ÀCÔHÐH÷% $Ð#ûô ò ÜÐ" AÔ&Ü˜G¤S¨£V¨XÔ6ÜØ$Ü! !›fñ
ó �ûðûð 	�‰×ÑÕüsT   ‚DH*ÄF< Ä'!F0Å>F< Æ*H*Æ0F9Æ5F< Æ<	HÇ9HÇ>H ÈHÈH ÈH'È'H*z/dashboard/spam/classifyc              ƒ   ó$  K  — 	 |xs dj                  «       j                  «       }|xs dj                  «       }|dvrt        d|› d�d¬«      S |st        d|› d�d¬«      S t        d||t	        |«      dœ«       t        |||«      st        d	|«       t        d|› d
�d¬«      S t        d|«       |dv r| j                  t        ||«       t        d|› d�d¬«      S # t        $ r'}t        d|«       t        d|› d
�d¬«      cY d }~S d }~ww xY w­w)Nr0   )r×   rÖ   rØ   z/dashboard/spam/email/z?form_error=1r¯   r°   zPOST /dashboard/spam/classify)rc   rd   Úfeedback_lenz;No row found or could not save classification for email_id:z?db_error=1z+Saved classification/feedback for email_id:>   rÖ   r×   z?feedback_saved=1z"Unexpected classify handler error:)	rá   r    r
   rA   rù   rr   r+  rk   r@   )r  rc   rd   rl   rD   s        rE   Úclassify_emailr2  �  sC  è ø€ ð!aØ(Ò.¨B×5Ñ5Ó7×=Ñ=Ó?ˆØ’N ×)Ñ)Ó+ˆàÐ!=Ñ=Ü#Ð&<¸X¸JÀmÐ$TÐbeÔfÐfÙÜ#Ð&<¸X¸JÀmÐ$TÐbeÔfÐfäØ+Ø!°^ÔUXÐYaÓUbÑcô	
ô
 ,¨H°nÀhÔOÜÐOÐQYÔZÜ#Ð&<¸X¸JÀkÐ$RÐ`cÔdÐdäÐ;¸XÔFà˜_Ñ,Ø×%Ñ%Ü3ØØôô  Ø$ X JÐ.?Ð@Øô
ð 	
øô ò aÜÐ2°AÔ6ÜÐ"8¸¸
À+Ð NÐ\_Ô`Õ`ûðaüsZ   ‚D„A
C ÁDÁC Á!DÁ"AC Â$DÂ%7C ÃDÃ	DÃ&DÄDÄDÄDÄDz /dashboard/spam/email/{email_id}c              ƒ   óš  K  — t        «       }	 |j                  t        «      j                  t        j                  |k(  «      j                  t        j
                  j                  d «      «      j                  «       }|j                  «        |st        dd¬«      S |j                  d u}|j                  xs dj                  «       j                  «       }|j                  xs d}t        t!        j"                  d|t         j$                  «      «      }|r|j&                  nd }|�t)        |dz  d«      nd }	|j                  |j*                  xs d|j,                  ||||	|r|nd	|j.                  xs d||j0                  ||d
k(  t        |j2                  «      dœ}
t4        j7                  | d| |
dœ«      S # |j                  «        w xY w­w)NrÓ   r¯   r°   r0   z<[a-z][\s\S]*>rx   rÞ   z
No Subjectrí   rØ   )r’   r”   rî   r•   rï   Úis_htmlrð   râ   rl   r–   r<   rõ   Úshow_classify_formr˜   zemail_details.html)r«   r  )r5   r6   r7   r8   r’   r9   r:   ra   r?   r
   rš   r—   rá   r    r•   Úboolr¡   r¢   r£   r–   rú   r”   r“   rl   r<   r˜   rJ   rµ   )r«   rc   rB   r  rõ   r—   r•   r4  r  rð   Úenhanced_emails              rE   Úemail_detailsr8  »  s—  è ø€ ä	‹€Bðà�H‰H”YÓß‰V”I—L‘L HÑ,Ó-ß‰V”I×&Ñ&×,Ñ,¨TÓ2Ó3ß‰U‹Wð	 	ð 	�‰Œ
áÜÐ 1¸sÔCÐCà$×3Ñ3¸4Ð?ÐØ×,Ñ,Ò2°×9Ñ9Ó;×AÑAÓC€Oð �:‰:Ò˜€DÜ”2—9‘9Ð.°´b·m±mÓDÓE€Gñ +C�×&Ò&È€IØ,5Ð,AŒu�Y ‘_ aÔ(Àt€Hð �h‰hØ—=‘=Ò0 LØ×$Ñ$ØØØØÙ$3‘¸Ø—N‘NÒ( bØ%Ø×(Ñ(Ø$<Ø-°Ñ<Ü˜E×-Ñ-Ó.ñ€Nô" ×%Ñ% gØàØ#ñ	
óð øðC 	�‰�
üs   ‚GŽA/F6 Á=D9GÆ6GÇGFc                  ó$  — t        «       } 	 | j                  t        d«      «       | j                  t        d«      «       | j                  «        | j                  «        	 t        t        «      }|j                  d«      D �cg c]  }|j                  d«      ‘Œ }}d|v ay # t        $ r&}| j                  «        t        d|«       Y d }~Œ|d }~ww xY w# | j                  «        w xY wc c}w # t        $ r}t        d|«       daY d }~y d }~ww xY w)	NzSET LOCAL lock_timeout = '5s'z?ALTER TABLE email_filter ADD COLUMN IF NOT EXISTS feedback TEXTz!Could not ensure feedback column:r‡   r%  rl   z+Could not verify feedback column existence:F)r5   r`   r#   ro   r@   rn   rA   r?   r$   ÚengineÚget_columnsrX   ÚFEEDBACK_COLUMN_EXISTS)rB   rD   ÚinspÚcÚcolss        rE   Úensure_feedback_columnr@  õ  sã   € ä	‹€BðØ
�
‰
”4Ð7Ó8Ô9Ø
�
‰
”4ÐYÓZÔ[Ø
�	‰	Œð
 	�‰Œ
ð'Ü”v‹ˆØ'+×'7Ñ'7¸Ô'GÓHÑ'G !�—‘�f•Ð'GˆÐHØ!+¨tÐ!3Ñøô ò 6Ø
�‰ŒÜÐ1°1×5Ñ5ûð6ûð 	�‰�
üò
 Iøäò 'ÜÐ;¸QÔ?Ø!&Õûð'úsT   ŒAB" Á!"C. ÂC)ÂC. Â"	CÂ+CÃC ÃCÃC ÃC&Ã)C. Ã.	DÃ7D
Ä
DÚ__main__zmain:appz0.0.0.0i:  Úvenv)ÚhostÚportÚreloadÚreload_dirsÚreload_excludes)r0   r0   )NNN)NN)rÞ   NNN)rÚfastapir   r   r   r   r   r   Úfastapi.responsesr	   r
   r   Úfastapi.templatingr   Ústarlette.middleware.sessionsr   Úauthr   r   r   r   r   r   r   r¡   Úosr(  Ú	threadingÚtypingr   r   r   Úpathlibr   Úurllib.parser   Úuuidr   Ú
sqlalchemyr   r   r   r   r   r    r!   r"   r#   r$   Úsqlalchemy.ormr%   r&   Úsqlalchemy.sqlr'   Úspam_trainingr(   r)   r*   ÚDATABASE_URLÚgetenvr    r+   r.   r/   ÚBaseÚreplacer:  r5   rF   ÚappÚadd_middlewareÚ__file__ÚparentÚBASE_DIRÚTEMPLATES_DIRr"  rj   rƒ   rJ   ÚLockrU   rV   r[   r]   r6  rb   Úintrk   rr   r…   r7   r©   rX   r¶   Úpostr¾   rÃ   rÉ   rÑ   rÕ   rü   r  r  r  r  r/  r2  r8  ÚmetadataÚ
create_allr<  r@  rŽ   ÚuvicornÚrunrœ   r�   rE   Ú<module>rh     sü  ðß M× Mß JÑ JÝ .Ý ;÷÷ ñ ó 
Û 	Û Û ß 'Ñ 'Ý Ý "Ý ß l× l× lß 9Ý ß bÑ bð |€Øˆ2�9‰9�Z Ó)×/Ñ/Ó1°VÑ;€Ø�R—Y‘YÐ3°WÓ=×CÑCÓEÈÑOÐ Ø"˜Ÿ™Ð#;¸WÓE×KÑKÓMÐQWÑWÐ áÓ€á	Ø×Ñ˜ RÓ(Ø	Øô
€ñ  Ô(€òñ$ ƒi€Ø × Ñ Ð&Ô 'Ø × Ñ Ð$°ÐP`Ð Ô añ �‹>× Ñ €Ø˜;Ñ&€Ø˜Ñ"€Ø�xÑ€	Ù¡c¨-Ó&8Ô9€	à%�y—~‘~Ó'Ð àØØñ€òñ˜sð ¨Sð Àó ð˜dó ð$
Q°#ð 
QÀsó 
Qð=Øð=àð=ð ð=ð 
ó	=ð@7°4ð 7À3ó 7ô(M�ô Mð, 3ð ¨4°©9ó ð0 ‡�ˆ¨€Ó5ð ØØ"ñ	Øðà
�3‰-ðð �C‰=ðð �s‰mò	ó 6ðð* ‡�ˆ.Óñ ˜“IÙ˜“IÙ˜t›*ñ	Øðàðð ðð �3‰-ò	ó ðð< ‡�ˆ/Óð2 ò 2ó ð2ð
 ‡�Ð	!°,€Ó?ð "Ø"&ñØðà�c‰]ðð ˜3‘-òó @ðð ‡�Ð
"Ó#ñ ! ›IÙ˜S›	Ù  ›Iñ	Øðàðð ðð ò	ó $ðð4 ‡�ˆ˜\€Ó*ð ò ó +ðò -€ð ‡�Ð	¨<€Ó8ð Ø Ø#'Ø$(ñxØðxà
ðxð �S‰Mðxð ˜C‘=ð	xð
 ˜S‘Mòxó 9ðxð| ‡�Ð	¨|€Ó<ð ò ó =ðð ‡�Ð	(Ó)ñ/ó *ð/ð ‡�Ð
*Ó+ñ-Ió ,ð-Ið` ‡�Ð
"Ó#ñ ˜s›)ñ2IØ%ð2Iàò2Ió $ð2Iðr ‡�Ð
$Ó%ñ ˜“IÙ$(¨£JÙ" 4›jñ	'aØ%ð'aàð'að ˜S‘Mð'að �s‰mò	'aó &ð'aðV ‡�Ð	+¸L€ÓIð1 ð 1°Cò 1ó Jð1ñh Ø‡M�M×Ñ &ÐÔ)àÐ ò'ñ, ÙÕà!ÐàˆzÒÛà€G‡K�KØØØØÙ˜“]�OØ˜öð r�   