# HTML Email Rendering Order ## CRITICAL: Regex substitution order When converting Markdown email body to HTML, the order of operations matters: **WRONG (produces literal `## Title` in HTML):** 1. Convert `\n` to `
` FIRST 2. Then try to match `^## (.+)$` — FAILS because lines are now `
`-delimited **RIGHT (renders styled `

` in HTML):** 1. Regex-substitute headers FIRST (`^## (.+)$` → `

\1

` with `re.MULTILINE`) 2. Regex-substitute horizontal rules (`^---$` → `
`) 3. Convert bold (`**text**` → ``) 4. Convert newlines LAST (`\n` → `
`) ```python import re html = body html = re.sub(r'^## (.+)$', r'

\1

', html, flags=re.MULTILINE) html = re.sub(r'^### (.+)$', r'

\1

', html, flags=re.MULTILINE) html = re.sub(r'^---$', r'
', html, flags=re.MULTILINE) html = re.sub(r'\*\*(.+?)\*\*', r'\1', html) html = html.replace('\n', '
') ``` ## Always use multipart/alternative - Plain text part first (keeps raw markdown — degrades gracefully) - HTML part second (email clients render the last part they understand) - Wrapped in full `` with inline `