
    mdi                         S SK r S SKJrJr  S SKrS SKJrJrJr  S SK	J
r
  S SKJr  S SKrS SKJrJr  S SKrS SKrS SKr " S S\
5      rSS	\4S
 jjr " S S5      rS r\S:X  a  \" 5         gg)    N)ConfidentialClientApplicationPublicClientApplication)ListDictOptional)
HTMLParser)unescape)datetimetimezonec                   D   ^  \ rS rSrSrU 4S jrS rS rS rS r	Sr
U =r$ )	HTMLTextExtractor   zExtract text from HTML contentc                 >   > [         TU ]  5         / U l        S U l        g N)super__init__textcurrent_tag)self	__class__s    /var/www/html/troy/fetch.pyr   HTMLTextExtractor.__init__   s    	    c                 T    Xl         US:X  a  U R                  R                  S5        g g )Nbr
)r   r   append)r   tagattrss      r   handle_starttag!HTMLTextExtractor.handle_starttag   s&    $;IIT" r   c                 T    US;   a  U R                   R                  S5        S U l        g )N)pdivtrlir   )r   r   r   )r   r   s     r   handle_endtagHTMLTextExtractor.handle_endtag   s%    **IIT"r   c                 :    U R                   R                  U5        g r   )r   r   )r   datas     r   handle_dataHTMLTextExtractor.handle_data   s    		r   c                 T    SR                  U R                  5      R                  5       $ )N )joinr   strip)r   s    r   get_textHTMLTextExtractor.get_text!   s    wwtyy!''))r   )r   r   )__name__
__module____qualname____firstlineno____doc__r   r    r'   r+   r1   __static_attributes____classcell__)r   s   @r   r   r      s$    ( 
#
 
* *r   r   log_filec                    Sn[         R                  R                  U5      (       d  [         R                  " U5        [         R                  R	                  X5      n[
        R                  " [
        R                  SS[
        R                  " U5      [
        R                  " 5       /S9  [
        R                  " [        5      nUR                  S5        UR                  S5        UR                  SU 35        UR                  S5        U$ )z<
Set up logging configuration
Logs to both file and console
logsz)%(asctime)s - %(levelname)s - %(message)sz%Y-%m-%d %H:%M:%S)levelformatdatefmthandlers<============================================================z2Email Checker Script Started (Microsoft Graph API)z
Log file: )ospathexistsmakedirsr/   loggingbasicConfigINFOFileHandlerStreamHandler	getLoggerr3   info)r:   log_dirlog_pathloggers       r   setup_loggingrP   %   s     G77>>'""
Gww||G.H ll:#)!!#
	 x(F
KK
KKDE
KK*XJ'(
KKMr   c                       \ rS rSr S S\S\S\S\S\\   4
S jjrS	 rS
\S\4S jrS!S\	S\\   4S jjr
S"S\S\S\\   S\	4S jjrS\S\4S jrS\S\\\4   4S jr   S#S\S\S\	S\S\\   S\\   4S jjrSrg)$EmailCheckerD   Nemail_address	client_idclient_secret	tenant_id	authorityc                    Xl         X l        X0l        X@l        U=(       d    SU 3U l        SU l        SU l        [        R                  " [        5      U l
        S/U l        U(       a  [        U5      S:X  a  UR                  S5      S:X  a  U R                  R                  S5        U R                  R                  S	5        U R                  R                  S
5        U R                  R                  S5        U R                  R                  S5        gUS;   a7  U R                  R                  S5        U R                  R                  S5        gg)a  
Initialize email checker using Microsoft Graph API

Args:
    email_address: Your email address (user principal name)
    client_id: Azure AD Application (Client) ID
    client_secret: Azure AD Application Client Secret (the VALUE, not the Secret ID!)
    tenant_id: Azure AD Tenant ID (or 'common' for multi-tenant)
    authority: Optional custom authority URL (defaults to https://login.microsoftonline.com/{tenant_id})
z"https://login.microsoftonline.com/z https://graph.microsoft.com/v1.0Nz$https://graph.microsoft.com/.default$   -   uc   ⚠️  WARNING: Your CLIENT_SECRET looks like a Secret ID (UUID format) instead of a Secret Value!z?   Secret IDs look like: '46804c3d-9b84-40b4-8972-d0b493ffa4d1'zU   Secret Values look like: '0eB8Q~zpWLgBaBjbuSEdCcWw0PqebXY...' (long random string)z2   Please use the Secret VALUE, not the Secret ID!zF   See GET_SECRET.md for instructions on how to get the correct value.)YOUR_SECRET_VALUE_HEREr.   NuZ   ❌ ERROR: CLIENT_SECRET is not set! Please update fetch.py with your actual secret value.z&   See GET_SECRET.md for instructions.)rT   rU   rV   rW   rX   graph_endpointaccess_tokenrF   rK   r3   rO   scopelencountwarningerror)r   rT   rU   rV   rW   rX   s         r   r   EmailChecker.__init__E   s    +"*""V(J9+&V@ ''1<=
 S/25-:M:Mc:RVW:WKK  !F  GKK abKK wxKK TUKK hiBBKKz{KKFG Cr   c                    U R                   R                  S5        U R                   R                  SU R                   35        U R                   R                  SU R                   35        U R                   R                  S5         [	        U R                  U R
                  U R                  SS9nU R                   R                  S5        U R                   R                  S5        U R                   R                  S	U R                   35        UR                  U R                  S
9nU R                   R                  S5        SU;   a&  US   U l        U R                   R                  S5        gUR                  SUR                  SS5      5      nUR                  S/ 5      nU R                   R                  SU 35        U R                   R                  SU 35        U R                   R                  SU 35        S[        U5      ;   d  S[        U5      R                  5       ;   a  U R                   R                  S5        g S[        U5      ;   d  S[        U5      R                  5       ;   a  U R                   R                  S5        g S[        U5      ;   a  U R                   R                  S5        g S[        U5      ;   a  U R                   R                  S5        g ! [        R                  R                   aC  nU R                   R                  S!U 35        U R                   R                  S"5         S#nAg S#nAf[        R                  R                    aC  nU R                   R                  S$U 35        U R                   R                  S%5         S#nAg S#nAf["         a'  nU R                   R                  S&U 3SS'9   S#nAg S#nAff = f)(z.Get access token using client credentials flowz6Attempting to authenticate with Microsoft Graph API...Authority: Client ID: z)Creating ConfidentialClientApplication...   )rU   client_credentialrX   timeoutz2ConfidentialClientApplication created successfullyz#Calling acquire_token_for_client...zScopes: )scopesz'acquire_token_for_client call completedr_   "Successfully obtained access tokenTerror_descriptionrd   Unknown errorerror_codesFailed to obtain access token: zError code: zFull error details: AADSTS7000215invalid_client_secretz8Invalid client secret. Please verify your CLIENT_SECRET.AADSTS700016invalid_clientz0Invalid client ID. Please verify your CLIENT_ID.AADSTS90002z0Invalid tenant ID. Please verify your TENANT_ID.AADSTS65005zdApplication does not have required permissions. Please grant Mail.Read permission and admin consent.FzTimeout during authentication: zKThe authentication request timed out. Please check your network connection.Nz(Connection error during authentication: z\Could not connect to Microsoft authentication service. Please check your network connection.Error during authentication: exc_info)rO   rL   rX   rU   r   rV   r`   acquire_token_for_clientr_   getrd   strlowerrequests
exceptionsTimeoutConnectionError	Exception)r   appresultrd   
error_codees         r   get_access_tokenEmailChecker.get_access_tokenf   s'   QR;t~~&678;t~~&678DE1	/.."&"4"4..	C KKQR KKBCKKx

|45111DFKKFG'$*>$:!  !EF

#6

7O8\]#ZZr:
!!$CE7"KL!!L"=>!!$8"AB #c&k15LPSTYPZP`P`Pb5bKK%%&`a  $s6{26F#e*JZJZJ\6\KK%%&XY  #c&k1KK%%&XY  #c&k1KK%%  'M  N""** 	KK ?sCDKKkl""22 	KK HLMKK|} 	KK =aSADQ	sK   C'K$ 0CK$ AK$ *K$ 9*K$ $O9M  !O!9NO,OOusernamepasswordc                 *   U R                   R                  S5        U R                   R                  SU R                   35        U R                   R                  SU R                   35         [	        U R                  U R                  S9nUR                  UUS/S9nSU;   a&  US   U l        U R                   R                  S5        g	UR                  S
UR                  SS5      5      nU R                   R                  SU 35        U R                   R                  SU 35        S[        U5      ;   d  S[        U5      ;   a  U R                   R                  S5        g! [         a'  nU R                   R                  SU 3S	S9   SnAgSnAff = f)z
Alternative: Get access token using Resource Owner Password Credentials (ROPC) flow
Note: This requires username and password, and may not work if MFA is enabled
z4Attempting to authenticate with username/password...rg   rh   )rU   rX   z%https://graph.microsoft.com/Mail.Read)r   r   rl   r_   rm   Trn   rd   ro   rq   zError details: AADSTS50076MFAzTMulti-factor authentication is required. Please use client credentials flow instead.Frx   ry   N)rO   rL   rX   rU   r   "acquire_token_by_username_passwordr_   r|   rd   r}   r   )r   r   r   r   r   rd   r   s          r   get_access_token_with_password+EmailChecker.get_access_token_with_password   sn   
 	OP;t~~&678;t~~&678	)....C ;;!!?@ < F '$*>$:!  !EF

#6

7O8\]!!$CE7"KL!!OF8"<= CK/5CK3GKK%%&|} 	KK =aSADQ	s    -AE! 	BE! !
F+FFuse_passwordc                     U(       a?  U(       d  U R                   R                  S5        gU R                  U R                  U5      $ U R	                  5       $ )z
Connect to Microsoft Graph API

Args:
    use_password: If True, use username/password flow. If False, use client credentials flow.
    password: Required if use_password is True
z7Password is required when using password authenticationF)rO   rd   r   rT   r   )r   r   r   s      r   connectEmailChecker.connect   sH     !!"[\66t7I7I8TT((**r   endpointmethodparamsretry_on_401c                 L   U R                   (       d  U R                  R                  S5        gU R                   U 3nSU R                    3SS.n US:X  a  [        R
                  " XVUS9nO;US:X  a  [        R                  " XVUS	9nOU R                  R                  S
U 35        gUR                  5         UR                  5       $ ! [        R                  R                   Ga  nUR                  R                  S:X  Ga  U(       Ga  U R                  R                  S5        U R                  5       (       GaW  U R                  R                  S5        SU R                    3US'    US:X  a  [        R
                  " XVUS9nOUS:X  a  [        R                  " XVUS	9nWR                  5         UR                  5       s SnA$ ! [        R                  R                   ay  n	U R                  R                  SU	 35        [!        U	R                  S5      (       a2  U R                  R                  SU	R                  R"                   35         Sn	A	 SnAgSn	A	f[$         a+  n	U R                  R                  SU	 3SS9   Sn	A	 SnAgSn	A	ff = fU R                  R                  S5        [!        UR                  S5      (       a2  U R                  R                  SUR                  R"                   35         SnAgU R                  R                  SU 35        [!        UR                  S5      (       a2  U R                  R                  SUR                  R"                   35         SnAgSnAf[$         a'  nU R                  R                  SU 3SS9   SnAgSnAff = f)a	  
Make a request to Microsoft Graph API

Args:
    endpoint: Graph API endpoint (e.g., "/users/{email}/messages")
    method: HTTP method (GET, POST, etc.)
    params: Query parameters
    retry_on_401: If True, automatically re-authenticate and retry on 401 errors
z0No access token available. Call connect() first.NzBearer zapplication/json)AuthorizationzContent-TypeGET)headersr   POST)r   jsonzUnsupported HTTP method: i  zRReceived 401 Unauthorized - token may be expired. Attempting to re-authenticate...z1Re-authentication successful. Retrying request...r   zHTTP error on retry: r   z
Response: zError on retry: Try   z/Re-authentication failed. Cannot retry request.zHTTP error: z Error making Graph API request: )r_   rO   rd   r^   r   r|   postraise_for_statusr   r   	HTTPErrorresponsestatus_coderc   r   rL   hasattrr   r   )
r   r   r   r   r   urlr   r   r   retry_es
             r   make_graph_requestEmailChecker.make_graph_request   s      KKPQ$$%hZ0&t'8'8&9:.

0	#<<VL6!#==FK!!$=fX"FG%%'==?""",, !	zz%%,##$xy<<>>KK$$%XY189J9J8K/LGO,$!U?'/||CQW'XH#v-'/}}SPV'WH 113'}}.#..88 $)),A'*KL"7#3#3V<< KK--
7;K;K;P;P:Q.RS#t$ $)),<WI*FQU)V#t$ KK%%&WXqzz622))Jqzz6G*HI!!L"451::v..KK%%
1::??2C&DE 	KK @DtT	sr   AC (C N#'BM/)AG?N#J#A+IM/J$J
M/
JA+M/?A+M//N#<NN#
email_datareturnc           	         SnUR                  S0 5      nU(       d?  U R                  R                  S[        [	        UR                  5       5      5      -   5        gUR                  SS5      nUR                  SS5      nU(       d  U R                  R                  SU 35        US:X  a;  [        5       nUR                  U5        UR                  5       nUR                  5       $ UnUR                  5       $ )	z,Extract email body from Graph API email datar.   bodyz/No 'body' field in email data. Keys available: contentTyper   contentz'Body content is empty. Body structure: html)
r|   rO   rc   r}   listkeysr   feedr1   r0   )r   r   	body_textbody_content	body_type
body_valueparsers          r   get_email_bodyEmailChecker.get_email_body  s    	 "~~fb1 KK QTWX\]g]l]l]nXoTp pq $$]F;	!%%i4
KK"I, XY&(FKK
#)I    #I  r   r   c                 p  ^ SSSSSSSSSSUS.m[         R                  " SU[         R                  5      nU(       aD  UR                  S5      R	                  5       TS'   U R
                  R                  STS    35        OU R
                  R                  S5        [         R                  " SU[         R                  5      nU(       aD  UR                  S5      R	                  5       TS	'   U R
                  R                  S
TS	    35        OU R
                  R                  S5        [         R                  " SU[         R                  5      nU(       aD  UR                  S5      R	                  5       TS'   U R
                  R                  STS    35        OU R
                  R                  S5        [         R                  " SU[         R                  5      nU(       a^  UR                  S5      R	                  5       n[         R                  " SSU5      nUTS'   U R
                  R                  STS    35        OU R
                  R                  S5        [         R                  " SU[         R                  5      nU(       a  UR                  S5      R	                  5       nUR                  5       S:w  a  UTS'   U R
                  R                  STS    35        [         R                  " SU5      n	U	(       a]  U	R                  S5      TS'   U	R                  S5      R	                  5       TS'   U R
                  R                  STS    STS    35        OU R
                  R                  S 5        [         R                  " S!U[         R                  5      n
U
(       aZ  U
R                  S5      R	                  5       nUR                  5       S:w  a&  UTS"'   U R
                  R                  S#TS"    35        OU R
                  R                  S$5        [         R                  " S%U[         R                  5      nU(       aq  [         R                  " S&UR                  S5      5      nU(       aC  UR                  S5      R	                  5       TS''   U R
                  R                  S(TS'    35        OU R
                  R                  S)5        [         R                  " S*U[         R                  5      nU(       aZ  UR                  S5      R	                  5       nUR                  5       S:w  a&  UTS+'   U R
                  R                  S,TS+    35        OU R
                  R                  S-5        [        U4S. jTR                  5        5       5      nU R
                  R                  S/U S035        T$ )1z
Extract booking details from email body based on Twine email format
Extracts: Name, Phone, Email, Address, Date & Time, Drop Off Location, 
Number of Passengers, Pick Up Location
N)namephoneemailaddress	date_timedatetimedrop_off_locationnumber_of_passengerspick_up_locationraw_bodyzName([^\n]+)   r   zExtracted Name: z&Could not extract Name from email bodyzPhone([^\n]+)r   zExtracted Phone: z'Could not extract Phone from email bodyz6Email([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,})r   zExtracted Email: z'Could not extract Email from email bodyzAddress([^\n]+)z\s+ r   zExtracted Address: z)Could not extract Address from email bodyzDate\s*[&\s]*Time([^\n]+)z	[unknown]r   zExtracted Date & Time: z(\d{4}-\d{2}-\d{2})\s+(.+)r      r   zSplit into Date: z, Time: z-Could not extract Date & Time from email bodyz#Drop\s*[-\s]*Off\s*Location([^\n]+)r   zExtracted Drop Off Location: z3Could not extract Drop Off Location from email bodyz&Number\s+of\s+Passengers?([^\n\d]*\d+)z(\d+)r   z Extracted Number of Passengers: z6Could not extract Number of Passengers from email bodyz"Pick\s*[-\s]*Up\s*Location([^\n]+)r   zExtracted Pick Up Location: z2Could not extract Pick Up Location from email bodyc              3   D   >#    U H  oc  M  UTS   :w  d  M  Sv   M     g 7f)Nr   r    ).0vdetailss     r   	<genexpr>5EmailChecker.extract_email_details.<locals>.<genexpr>  s%     h)9AaqT[\fTgOgaa)9s     	 z
Extracted z fields from email body)research
IGNORECASEgroupr0   rO   debugrc   subr~   matchsumvaluesrL   )r   r   
name_matchphone_matchemail_matchaddress_matchr   datetime_matchr   dt_splitdropoff_matchdropoffpassenger_matchnumber_matchpickup_matchpickupextracted_countr   s                    @r   extract_email_details"EmailChecker.extract_email_details:  s    !%$( $
6 YYbmmD
(..q1779GFOKK 00ABCKK HI ii 0$F*00399;GGKK 1''2B1CDEKK IJ ii Y[_acanano*00399;GGKK 1''2B1CDEKK IJ 		"4dBMMJ#))!,224GffVS'2G!(GIKK 3GI4F3GHIKK KL #?r}}U&,,Q/557I K/'0$!!$;GK<P;Q"RS 88$A9M&.nnQ&7GFO&.nnQ&7&=&=&?GFOKK%%(9'&/9J(SZ[aSbRc&deKK OP 		"H$PRP]P]^#))!,224G}}+-/6+,!!$A'J]B^A_"`aKK UV ))$MtUWUbUbc99X/D/DQ/GHL2>2D2DQ2G2M2M2O./!!$DWMcEdDe"fgKK XY yy!Fbmm\!''*002F||~,.4*+!!$@I[A\@]"^_KK TU h)9hh:o%66MNOr   sender_emailfolderunread_onlytop	from_datec           
         U R                   (       d  U R                  R                  S5        / $  / nSnU(       an  [        U5      S:X  a  U S3nO#UnUR	                  S5      (       d  SU;  a  US-   nUR                  SU 35        U R                  R                  SU S	U S
35        U(       a  UR                  S5        U(       a  SR                  U5      OSnSU R                   SU S3n	USSS.n
U(       a  XS'   U R                  R                  SU 35        U(       a  U R                  R                  SU S35        U(       a  U R                  R                  S5        U R                  R                  SU S35        U R                  XS9nU(       d  U R                  R                  S5        / $ UR                  S/ 5      nU R                  R                  S[        U5       S35        U(       a  U R                  R                  SU 35        / nS nS nU GH  nUR                  S!0 5      nUR                  S"0 5      R                  S#S$5      R                  5       nUUR                  5       :w  a  US%-  nMa  U(       Ga  U(       Ga  UR                  S&S$5      nU(       a   UR                  SS'5      nUR                  SS'5      n[        R                  " U5      n[        R                  " U5      nUR                  c  UR                  [         R"                  S(9nUR                  c  UR                  [         R"                  S(9nUU:  a*  US%-  nU R                  R%                  S)U S*U S
35        GM_  OU R                  R)                  S.5        GM~  UR                  U5        GM     U R                  R                  S/[        U5       S0U S135        US :  a  U R                  R                  S2U S335        US :  a  U R                  R                  S2U S435        / n[+        US%5       GH  u  nnUR                  S5S65      nU R                  R                  S7U S8[        U5       S9U S
35        UR                  S:S;5      nUR                  S!0 5      nUR                  S"0 5      R                  S#S<5      nUR                  S"0 5      R                  S=S$5      nUR                  S&S$5      nU R                  R                  S>U 35        U R                  R                  S?U S@U SA35        U R                  R                  SBU 35         U R                  SU R                   SCU 3SDSE0S9nU(       aF  UR                  SE5      (       a0  UR                  SE5      USE'   U R                  R%                  SF5        OU R                  R)                  SG5         U R                  R%                  SJ5        U R-                  U5      n U R                  R%                  SK[        U 5       SL35        U (       a"  U R                  R                  SMU SSN  35        OU R                  R)                  SO5        U R                  R                  SP5        U R/                  U 5      n!UUU(       a  U S@U SA3OUUU U!SQ.n"UR                  U"5        U R                  R                  SR5        U R                  R                  SSU 35        U R                  R                  STU 35        U R                  R                  SUU S@U SA35        U R                  R                  SVU 35        U R                  R                  SW5        U R                  R                  SXU!R                  S=SY5       35        U R                  R                  SZU!R                  S[SY5       35        U R                  R                  S\U!R                  S]SY5       35        U R                  R                  S^U!R                  S#SY5       35        U!R                  S_5      (       a.  U R                  R                  S`U!R                  S_5       35        O\U R                  R                  SaU!R                  SbSY5       35        U R                  R                  ScU!R                  SdSY5       35        U R                  R                  SeU!R                  SfSY5       35        U R                  R                  SgU!R                  ShSY5       35        U R                  R                  SiU!R                  SjSY5       35        U R                  R                  SR5        [1        SkSR 35        [1        SSU 35        [1        STU 35        [1        SUU S@U SA35        [1        SVU 35        [1        SW5        [1        SXU!R                  S=SY5       35        [1        SZU!R                  S[SY5       35        [1        S\U!R                  S]SY5       35        [1        S^U!R                  S#SY5       35        U!R                  S_5      (       a  [1        S`U!R                  S_5       35        O<[1        SaU!R                  SbSY5       35        [1        ScU!R                  SdSY5       35        [1        SeU!R                  SfSY5       35        [1        SgU!R                  ShSY5       35        [1        SiU!R                  SjSY5       35        [1        SR Sk35        GM     U R                  R                  Sl[        U5       Sm35        U$ ! [&         a.  nU R                  R)                  S+U S,U S-35         SnAG	Me  SnAff = f! [&         a*  nU R                  R)                  SHU SI35         SnAGNSnAff = f! [&         a)  nU R                  R                  SnU 3SoSp9  / s SnA$ SnAff = f)qa  
Check emails from a specific sender using Microsoft Graph API

Args:
    sender_email: Email address to search for
    folder: Email folder to search (default: inbox)
    unread_only: If True, only check unread emails
    top: Maximum number of emails to retrieve (default: 100)
    from_date: Filter emails from this date onwards (format: "YYYY-MM-DD" or "YYYY-MM-DDTHH:MM:SSZ")
              Example: "2025-12-16" or "2025-12-16T00:00:00Z"

Returns:
    List of dictionaries containing email details
z(Not authenticated. Call connect() first.N
   z
T00:00:00ZZ+zreceivedDateTime ge zFiltering emails from z onwards (ISO: )zisRead eq falsez and z/users/z/mailFolders/z	/messagesz,id,subject,from,receivedDateTime,body,isReadzreceivedDateTime desc)z$top$selectz$orderbyz$filterzSearching for emails in folder zDate filter: from z onwardsz Filtering for UNREAD emails onlyzWill filter by sender 'z' in Python after fetching)r   z(Failed to retrieve emails from Graph APIvaluez
Retrieved z email(s) from Graph APIz;Python-side date filter will be applied: emails must be >= r   fromemailAddressr   r.   r   receivedDateTimez+00:00)tzinfozFiltering out email from z	 (before zCould not parse date z: z. Skipping email.zHEmail has no receivedDateTime but date filter is active. Skipping email.zFound z email(s) from z after filteringzFiltered out z email(s) by senderz email(s) by dateidunknownzProcessing email /z (ID: subjectz
No SubjectUnknownr   zEmail Subject: zEmail From: z <>zEmail Date: z
/messages/r   r   zFetched full message bodyz7Could not fetch full message body, using body from listz"Error fetching full message body: z, using body from listzExtracting email body...zEmail body length: z charactersz&Email body preview (first 500 chars):
i  zEmail body is empty!z-Extracting booking details from email body...)r   r   r   r   r   extracted_detailsrA   z
Email ID: z	Subject: zFrom: zDate: z
Extracted Booking Details:z  Name: zN/Az	  Phone: r   z	  Email: r   z  Address: r   z  Date & Time: z  Date: r   z  Time: r   z  Pick Up Location: r   z  Drop Off Location: r   z  Number of Passengers: r   r   zSuccessfully processed z	 email(s)zError checking emails: Try   )r_   rO   rd   ra   endswithr   rL   r/   rT   r   r|   r~   replacer
   fromisoformatr   r   utcr   r   rc   	enumerater   r   print)#r   r   r   r   r   r   filter_partsfrom_date_isofilter_queryr   r   response_dataemails_dataemails_foundfiltered_by_date_countfiltered_by_sender_countr   	from_info	from_addrreceived_dateemail_date_strfilter_date_str
email_datefilter_dater   processed_emailsidxemail_idr   	from_namer   full_messager   r   
email_infos#                                      r   check_emails_from_sender%EmailChecker.check_emails_from_sender  s"   "   KKHII^	 L M y>R''0k$<M$-M(11#663m;S(5(; ##&:=/$JK  #9)OTaSbbc!de ##$56 :F7<<54L !!3!3 4M&SH I3F $0y!KK>vhGH  #5i[!IJ  !CDKK6|nD^_` !33H3LM !!"LM	'++GR8KKKz#k*:);;STU  #^_l^m!no L%&"'($)
&NN626	%MM."=AA)RPVVX	  2 2 44,1, $.NN3Er$JM$% .;-B-B3-QN.;.C.CC.RO)1)?)?)OJ*2*@*@*QK  *008-7-?-?x||-?-T
*119.9.A.A.A.V  *K7 6! ; 6 $ 1 14Mj\Ybcnboop2q r (  8 ++,vw ##J/S *V KKvc,&7%8~Uefg'!+  =1I0JJ]!^_%)  =1G0HHY!Z[  "#,\1#=Z%>>$	:  #4SE3|;L:MVT\S]]^!_` %..LA&NN626	%MM."=AA)YW	%MM."=AA&"M	!~~&8"=  ?7)!<=  <	{"YKq!IJ  <v!67h#'#:#:!$"4"4!5ZzJ )62 $; $L $(8(8(@(@-9-=-=f-E
6*))*EF++,ef
 !!"<=**:6!!$7D	{+"NO KK$$'NtTXUXzl%[\KK''(>?   !PQ44T: #&<EykI;a89  )0
 !''
3   (  :hZ!89  9WI!67  6)Byk!CD  6$1  !?@  8GKK,F+G!HI  9W[[%-H,I!JK  9W[[%-H,I!JK  ;w{{9e/L.M!NO;;{++KK$$w{{;7O6P%QRKK$$xFE0J/K%LMKK$$xFE0J/K%LM  #7DVX]8^7_!`a  #8EXZ_9`8a!bc  #;GKKH^`e<f;g!hi  ( 6(m$
8*-.	'+,ykI;a89tfo&46VU!; <=>	'++gu"=!>?@	'++gu"=!>?@GKK	5$A#BCD;;{++OGKK,D+EFGHW[[%?$@ABHW[[%?$@AB,W[[9KU-S,TUV-gkk:Mu.U-VWX0=SUZ1[0\]^m$E $>H KK6s;K7L6MYWX##o  ) % KK//2GVXYZX[[l0mn$%^ ! hKK''*LQCOe(fgghT  	KK 7s;dKI	s   Fo 7C1o )Cm:Go A.no nU0o 
n"n<o no 
n?n:4o :n??o 
o5o0*o50o5)	r_   rX   rU   rV   rT   r^   rO   r`   rW   r   )FN)r   NT)scheduling@usetwine.cominboxFd   N)r3   r4   r5   r6   r}   r   r   r   r   boolr   r   r   r   anyr   intr   r  r8   r   r   r   rR   rR   D   s!   <@Hc Hc H# HH,4SMHB8t%s %c %N+D +HSM + D3 D DXVZ^ Drv DL! !# !:z# z$sCx. zx <ULQLPsS s),sEIs&)s<DSMsUYZ^U_s sr   rR   c                  4   [        5       n SnSnSnSnSnSnU R                  S5        U R                  SU 35        U R                  S	U 35        [        UUUUS
9nU(       a:  UR                  SUS9(       d$  U R	                  S5        U R	                  S5        / $ O9UR                  5       (       d$  U R	                  S5        U R	                  S5        / $  U R                  S5        UR                  SSSSS9nU R                  S5        U R                  S[        U5       35        U R                  S5        [        SS 35        [        S[        U5       35        [        S S35        U$ ! [         a  n	U R	                  SU	 3SS9  / s Sn	A	$ Sn	A	ff = f)zY
Main function - checks emails from scheduling@usetwine.com and extracts booking details
zinfo@troyrides.comz$cc46473e-a7d7-4f74-8045-97f57672db79z(0eB8Q~zpWLgBaBjbuSEdCcWw0PqebXYIZH8DMcfhz$0b737fe7-8092-4deb-8adc-2c25370f9d55FNz6Initializing email checker with Microsoft Graph API...zEmail: zTenant ID: )rT   rU   rV   rW   T)r   r   z?Failed to authenticate with Microsoft Graph API using password.zEPlease check your credentials or use client credentials flow instead.z0Failed to authenticate with Microsoft Graph API.z:Please check your Client ID, Client Secret, and Tenant ID.zStarting email check process...r  r  z
2025-12-17)r   r   r   r   rA   z+Email check completed. Total emails found: r   zTotal emails found: zError processing emails: ry   )	rP   rL   rR   r   rd   r  ra   r  r   )
rO   EMAIL_ADDRESS	CLIENT_IDCLIENT_SECRET	TENANT_IDUSE_PASSWORD_AUTHPASSWORDcheckeremailsr   s
             r   mainr,    s   
 _F )M6I
 ?M6I H
KKHI
KK'-)*
KK+i[)* ##	G D8DLLZ[LL`aI E
   LLKLLLUVI 	56112"	 2 
 	FA#f+OPF6(m$S[M23m  04tD	s   BE. .
F8FFF__main__)zemail_checker.log)r   msalr   r   r   typingr   r   r   html.parserr   r   r	   rF   r
   r   rB   base64r   r   r}   rP   rR   r,  r3   r   r   r   <module>r2     si     G 	 ' ' "   ' 	  *
 *0C >e	 e	PGT zF r   