""" Brevo (ex-Sendinblue) integration. - Send transactional confirmation emails - Sync confirmed contacts to a Brevo list """ import logging import httpx from app.config import settings logger = logging.getLogger(__name__) BREVO_API = "https://api.brevo.com/v3" def _headers() -> dict[str, str]: return { "api-key": settings.BREVO_API_KEY, "Content-Type": "application/json", "Accept": "application/json", } async def send_confirmation_email(email: str, confirm_url: str) -> bool: """Send a double opt-in confirmation email. Returns True on success.""" if not settings.brevo_configured: logger.warning("Brevo not configured — skipping confirmation email for %s***", email[:3]) return False payload = { "sender": { "name": settings.BREVO_SENDER_NAME, "email": settings.BREVO_SENDER_EMAIL, }, "to": [{"email": email}], "subject": "Confirm your spot on the adiuvAI waitlist", "htmlContent": _confirmation_html(confirm_url), } try: async with httpx.AsyncClient(timeout=10) as client: resp = await client.post(f"{BREVO_API}/smtp/email", headers=_headers(), json=payload) resp.raise_for_status() logger.info("Confirmation email sent to %s***", email[:3]) return True except httpx.HTTPError: logger.exception("Failed to send confirmation email to %s***", email[:3]) return False async def add_contact_to_list(email: str) -> bool: """Add a confirmed contact to the Brevo waitlist list. Returns True on success.""" if not settings.brevo_configured: logger.warning("Brevo not configured — skipping contact sync for %s***", email[:3]) return False if settings.BREVO_LIST_ID == 0: logger.warning("BREVO_LIST_ID not set — skipping contact sync") return False payload = { "email": email, "listIds": [settings.BREVO_LIST_ID], "updateEnabled": True, } try: async with httpx.AsyncClient(timeout=10) as client: resp = await client.post(f"{BREVO_API}/contacts", headers=_headers(), json=payload) resp.raise_for_status() logger.info("Contact synced to Brevo list %d: %s***", settings.BREVO_LIST_ID, email[:3]) return True except httpx.HTTPError: logger.exception("Failed to sync contact to Brevo: %s***", email[:3]) return False def _confirmation_html(confirm_url: str) -> str: """Email template aligned with the adiuvAI landing page brand.""" return f"""\