11#!/usr/bin/env python3
2- """Read latest email from a given sender via IMAP, searching multiple folders."""
2+ """Read latest email from a given sender via IMAP, searching multiple folders.
3+
4+ Environment variables:
5+ EMAIL_USERNAME - IMAP login username (required)
6+ EMAIL_PASSWORD - IMAP login password (required)
7+ IMAP_SERVER - IMAP server hostname (default: imap.gmail.com)
8+ IMAP_PORT - IMAP server port (default: 993)
9+
10+ Non-Gmail servers will only match INBOX, Promotions, and Updates folders;
11+ Gmail-specific folders like [Gmail]/All Mail are skipped gracefully.
12+ """
313import imaplib
414import email
515import os
16+ import re
617import sys
718from email .header import decode_header
819
920IMAP_SERVER = os .environ .get ("IMAP_SERVER" , "imap.gmail.com" )
10- IMAP_PORT = int (os .environ .get ("IMAP_PORT" , "993" ))
21+ try :
22+ IMAP_PORT = int (os .environ .get ("IMAP_PORT" , "993" ))
23+ except ValueError :
24+ print ("ERROR: IMAP_PORT must be an integer" , file = sys .stderr )
25+ sys .exit (1 )
1126
1227
1328def decode_str (s , enc = None ):
@@ -32,7 +47,6 @@ def get_body(msg):
3247 if ct == "text/html" and "attachment" not in cd :
3348 payload = part .get_payload (decode = True )
3449 if payload :
35- import re
3650 text = payload .decode ("utf-8" , errors = "ignore" )
3751 text = re .sub (r'<[^>]+>' , ' ' , text )
3852 text = re .sub (r'\s+' , ' ' , text ).strip ()
@@ -64,8 +78,12 @@ def main():
6478 password = os .environ .get ("EMAIL_PASSWORD" , "" )
6579 username = os .environ .get ("EMAIL_USERNAME" , "" )
6680
81+ if not username :
82+ print ("ERROR: EMAIL_USERNAME not set" , file = sys .stderr )
83+ sys .exit (1 )
84+
6785 if not password :
68- print ("ERROR: EMAIL_PASSWORD not set" )
86+ print ("ERROR: EMAIL_PASSWORD not set" , file = sys . stderr )
6987 sys .exit (1 )
7088
7189 try :
0 commit comments