# HTML OTP Parsing Notes Use this when IMAP fetch succeeds but naive regex extraction returns the wrong verification code. ## Problem pattern Some transactional emails contain multiple `\d{6}` candidates in one message because the HTML includes: - the visible OTP block, - responsive/mobile duplicate markup, - unrelated build/tracking numbers embedded in template fragments. If you do `re.findall(r'\\b\\d{6}\\b', body)[0]`, you may grab a stale or irrelevant number. ## Preferred extraction order 1. **Subject line first** if it explicitly contains the OTP. 2. **OTP-specific markup** next: - `123456` - `.otp-code` - monospace / headline blocks near words like `verification code`, `验证码`, `OTP`, `code` 3. **Generic body regex** only as fallback. 4. If multiple distinct codes remain, prefer the one from the **latest message** that appears in OTP-specific markup, not the first raw body match. ## Minimal robust pattern ```python from email.header import decode_header import email as em import re def decode_subject(msg): parts = [] for value, enc in decode_header(msg.get('Subject', '')): if isinstance(value, bytes): parts.append(value.decode(enc or 'utf-8', errors='replace')) else: parts.append(value) return ''.join(parts) def extract_code(subject, body): # 1) explicit subject code m = re.search(r'\b(\d{4,8})\b', subject) if m: return m.group(1) # 2) OTP-specific HTML / text blocks patterns = [ r'otp-code[^>]*>\s*(\d{4,8})\s*<', r']*>\s*(\d{4,8})\s*', r'(?:verification code|验证码|OTP|code)[^\d]{0,40}(\d{4,8})', ] for pat in patterns: m = re.search(pat, body, re.I | re.S) if m: return m.group(1) # 3) generic fallback codes = re.findall(r'\b(\d{4,8})\b', body) codes = [c for c in codes if not (2020 <= int(c) <= 2035)] return codes[0] if codes else None ``` ## Session-derived example shape Observed shape: one provider email produced several six-digit matches from a single HTML message. The visible OTP and the first regex hit did not reliably align. The safe fix was to stop trusting `codes[0]` and rank candidates by subject / OTP markup / latest message.