11import  smtplib 
22from  email .message  import  EmailMessage 
33from  . import  config 
4+ from  datetime  import  datetime , timezone , timedelta 
45
56def  send_email (to_email , subject , html_content ):
67    """Sends an email using the configured SMTP settings.""" 
7-      # Config is now loaded from config.py 
8+    
89    if  not  config .SMTP_USER  or  not  config .SMTP_PASSWORD :
910        print (f"[ERROR] SMTP not configured. Skipping email to { to_email }  )
1011        return  False 
@@ -25,46 +26,54 @@ def send_email(to_email, subject, html_content):
2526        return  True 
2627    except  smtplib .SMTPAuthenticationError :
2728        print (f"\n  Authentication failed for { config .SMTP_USER }  )
28-         print ("    Please check that your GMAIL_APP_PASSWORD is correct." )
29+         print ("  Please check that your GMAIL_APP_PASSWORD is correct." )
2930        return  False 
3031    except  Exception  as  e :
3132        print (f"\n  Failed to send email to { to_email } { e }  )
3233        return  False 
3334
3435
3536def  build_html_email (username , title , link , solved , quote = None , hints = None ):
36-     """Builds a responsive email with optional AI hints  and quotes .""" 
37+     """Builds a responsive email with optional AI hints, quotes,  and a live countdown GIF .""" 
3738
3839    if  hints  is  None :
3940        hints  =  []
4041
42+     timer_html  =  "" 
43+ 
4144    if  solved :
4245        preheader_text  =  f"Great job on solving { title }  
4346        heading  =  f"🎉 Great Job, { username }  
4447        subtext  =  f"You’ve completed today’s LeetCode challenge: <strong>{ title }  
4548        button_text  =  "View Challenge" 
46-         button_color  =  "#4CAF50"  # Green 
47-         
48-         # Use the AI quote for the footer 
49+         button_color  =  "#4CAF50"  
4950        footer  =  f"<em>“{ quote }   if  quote  else  "<em>Keep up the great work!</em>" 
50-         
5151        hints_html  =  "" 
5252
5353    else :
5454        preheader_text  =  f"Don't forget to solve { title }  
55-         heading  =  f"⚠️  Hey { username }  
55+         heading  =  f"Hey <a href='https://leetcode.com/u/ { username } ' target='_blank' style='text-decoration: none;'> { username } </a> , time to code!" 
5656        subtext  =  f"Today's problem, <strong>{ title }  
5757        button_text  =  f"Solve '{ title }  
58-         button_color  =  "#000000"  # Black 
59-         
60-         # Use the AI quote for the footer 
58+         button_color  =  "#000000"  
6159        footer  =  f"<em>“{ quote }   if  quote  else  "<em>“Small daily improvements lead to big results.” 🌱</em>" 
6260
63-         # --- NEW HINTS SECTION --- 
61+         deadline_iso  =  get_deadline_for_potd ()
62+         gif_url  =  f"https://i.countdownmail.com/4khdvf.gif?end_date_time={ deadline_iso }  
63+                 
64+         timer_html  =  f""" 
65+             <tr> 
66+                 <td align="center" style="padding: 10px 0 10px 0;"> 
67+                     <a href="{ link }  
68+                         <img src="{ gif_url }  
69+                     </a> 
70+                 </td> 
71+             </tr> 
72+         """ 
73+         
74+         # --- Hints Section --- 
6475        if  hints :
65-             # Build an HTML list of hints 
6676            hints_list_items  =  "" .join ([f'<li style="margin-bottom: 10px; line-height: 1.6;">{ h }   for  h  in  hints ])
67-             
6877            hints_html  =  f""" 
6978            <table border="0" cellpadding="0" cellspacing="0" width="100%" style="margin-top: 30px;"> 
7079                <tr> 
@@ -78,7 +87,7 @@ def build_html_email(username, title, link, solved, quote=None, hints=None):
7887            </table> 
7988            """ 
8089        else :
81-             hints_html  =  ""   # No hints if the list is empty 
90+             hints_html  =  "" 
8291
8392    # --- HTML & CSS Template --- 
8493    return  f""" 
@@ -91,16 +100,7 @@ def build_html_email(username, title, link, solved, quote=None, hints=None):
91100            <meta name="x-apple-disable-message-reformatting"> 
92101            <title>LeetCode Reminder</title> 
93102
94-             <!--[if mso]> 
95-                 <style> 
96-                     * {{ 
97-                         font-family: sans-serif !important; 
98-                     }} 
99-                 </style> 
100-             <![endif]--> 
101- 
102103            <style> 
103-                 /* CSS resets and base styles */ 
104104                html, body {{ 
105105                    margin: 0 auto !important; 
106106                    padding: 0 !important; 
@@ -110,90 +110,72 @@ def build_html_email(username, title, link, solved, quote=None, hints=None):
110110                    font-family: 'Helvetica Neue', Arial, sans-serif; 
111111                    color: #333; 
112112                }} 
113- 
114-                 /* Center the email */ 
115113                .wrapper {{ 
116114                    width: 100%; 
117115                    background-color: #f1f1f1; 
118116                }} 
119- 
120-                 /* Main container */ 
121117                .container {{ 
122118                    width: 600px; 
123119                    margin: 0 auto; 
124120                    background-color: #ffffff; 
125121                    border-radius: 8px; 
126122                    border: 1px solid #ddd; 
127123                }} 
128- 
129-                 /* Responsive styles */ 
130124                @media screen and (max-width: 600px) {{ 
131125                    .container {{ 
132126                        width: 100% !important; 
133127                        margin: 0 !important; 
134128                        border: none !important; 
135-                         border-radius: 0 !important ; 
129+                         border-radius: 0 !Dimportant ; 
136130                    }} 
137131                    .content {{ 
138132                        padding: 25px !important; 
139133                    }} 
140134                    .button-link {{ 
141135                        display: block !important; 
142136                        width: 100% !important; 
143-                         box-sizing: border-box; /* Ensures padding doesn't break width */  
137+                         box-sizing: border-box; 
144138                    }} 
145139                }} 
146140            </style> 
147141        </head> 
148142        <body style="margin: 0; padding: 0 !important; background-color: #f1f1f1;"> 
149-             <!-- Visually hidden preheader text --> 
150143            <div style="display: none; font-size: 1px; line-height: 1px; max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden; mso-hide: all; font-family: sans-serif;"> 
151144                { preheader_text }  
152145            </div> 
153146
154147            <center class="wrapper"> 
155148                <div style="max-width: 600px; margin: 0 auto;"> 
156-                     <!--[if (gte mso 9)|(IE)]> 
157-                     <table align="center" border="0" cellspacing="0" cellpadding="0" width="600" style="width:600px;"> 
158-                     <tr> 
159-                     <td align="center" valign="top"> 
160-                     <![endif]--> 
161-                      
162149                    <table align="center" border="0" cellpadding="0" cellspacing="0" width="100%" class="container" style="max-width: 600px; margin: 20px auto; background: #ffffff; border-radius: 8px; border: 1px solid #ddd;"> 
163-                         <!-- Logo/Header (Optional, but good practice) --> 
164150                        <tr> 
165-                             <td align="center" style="padding: 20px 0 10px  0; font-size: 20px; font-weight: 600; color: #000;"> 
151+                             <td align="center" style="padding: 20px 0 15px  0; font-size: 20px; font-weight: 600; color: #000;"> 
166152                               <img src="https://i.postimg.cc/qRgJjC6P/Leet-Code-logo-black.png" alt="" width="20px" height="20px"> 
167153                                LeetCode Daily Reminder 
168154                            </td> 
169155                        </tr> 
170-                          
171-                         <!-- Main Content --> 
156+                         { timer_html }  
172157                        <tr> 
173158                            <td class="content" style="padding: 30px 40px;"> 
174-                                 <h1 style="margin: 0 0 20px 0; font-size: 24px; font-weight: 600; color: #000;">{ heading }  
159+                                 <h1 style="margin: 0 0 20px 0; font-size: 24px; font-weight: 600; color: #000; text-align: center; ">{ heading }  
175160                                <p style="margin: 0 0 30px 0; font-size: 16px; line-height: 1.6;"> 
176161                                    { subtext }  
177162                                </p> 
178163                                 
179-                                 <!-- CTA Button --> 
180164                                <table border="0" cellpadding="0" cellspacing="0" width="100%"> 
181165                                    <tr> 
182-                                         <td align="left "> 
166+                                         <td align="center "> 
183167                                            <a href="{ link } { button_color }  
184168                                                { button_text }  
185169                                            </a> 
186170                                        </td> 
187171                                    </tr> 
188172                                </table> 
189173                                 
190-                                 <!-- **** NEW: HINTS BLOCK INJECTED HERE **** --> 
191174                                { hints_html }  
192175                                 
193176                            </td> 
194177                        </tr> 
195178                         
196-                         <!-- Footer Quote --> 
197179                        <tr> 
198180                            <td class="content" style="padding: 0 40px 30px 40px; border-top: 1px solid #eee;"> 
199181                                <p style="margin: 20px 0 0 0; font-size: 14px; color: #555; text-align: left;"> 
@@ -203,17 +185,38 @@ def build_html_email(username, title, link, solved, quote=None, hints=None):
203185                        </tr> 
204186                    </table> 
205187
206-                     <!--[if (gte mso 9)|(IE)]> 
207-                     </td> 
208-                     </tr> 
209-                     </table> 
210-                     <![endif]--> 
211-                 </div> 
188+                     </div> 
212189            </center> 
213190        </body> 
214191        </html> 
215192            """ 
216193
194+ def  get_deadline_for_potd (hour = 17 , minute = 0 ):
195+     """ 
196+     Returns a deadline in UTC ISO format (YYYY-MM-DDTHH:MM:SSZ)  
197+     based on the current time in PST.  
198+      
199+     Parameters: 
200+     hour (int): The hour in PST to use for the deadline (default: 17) 
201+     minute (int): The minute in PST to use for the deadline (default: 0) 
202+ 
203+     Returns: 
204+     str: The deadline in UTC ISO format 
205+     """ 
206+     tz_pst  =  timezone (timedelta (hours = - 8 ))  # PST 
207+ 
208+     now_utc  =  datetime .now (timezone .utc )
209+     now_pst  =  now_utc .astimezone (tz_pst )
210+ 
211+     today_deadline_pst  =  now_pst .replace (hour = hour , minute = minute , second = 0 , microsecond = 0 )
212+ 
213+     if  now_pst  >=  today_deadline_pst :
214+         today_deadline_pst  +=  timedelta (days = 1 )
215+ 
216+     deadline_utc  =  today_deadline_pst .astimezone (timezone .utc )
217+     return  deadline_utc .isoformat ()
218+ 
219+ 
217220#To Do - add a function that send admin email when bot is stopped 
218221#def stop_bot_admin_email(): 
219222
0 commit comments