const MAILSINK = process.env.MAILSINK_URL || 'http://localhost:8025' export async function waitForLatestOtc(toAddress, { attempts = 20, delayMs = 500 } = {}) { for (let i = 0; i < attempts; i++) { const res = await fetch(`${MAILSINK}/api/v1/messages`) if (res.ok) { const data = await res.json() const msg = (data.messages || []).find( (m) => (m.To || []).some((t) => t.Address === toAddress), ) if (msg) { const full = await fetch(`${MAILSINK}/api/v1/message/${msg.ID}`) if (!full.ok) continue const body = await full.json() // Search the plain-text part first — the OTC mail is plain text // (see backend/app/email_otc.py), and scanning Text before HTML // keeps the \d{6} match from latching onto a stray number that a // future HTML template might carry (style widths, year, etc.). const text = body.Text || '' const html = body.HTML || '' const code = text.match(/\b(\d{6})\b/) || html.match(/\b(\d{6})\b/) if (code) return code[1] } } await new Promise((r) => setTimeout(r, delayMs)) } throw new Error(`no OTC email for ${toAddress} arrived in Mailpit`) } export async function clearMailpit() { await fetch(`${MAILSINK}/api/v1/messages`, { method: 'DELETE' }) }