"""Author RAG — Contact Form API. Route: POST /api/contact → validate form fields → send email to support inbox Replaces the fake setTimeout in the Next.js Contact component. """ import structlog from fastapi import APIRouter, Depends, HTTPException, Request from pydantic import BaseModel, EmailStr, Field from app.config import get_settings from app.services.email_service import EmailService logger = structlog.get_logger(__name__) cfg = get_settings() router = APIRouter(prefix="/contact", tags=["Contact"]) class ContactRequest(BaseModel): first_name: str = Field(..., min_length=1, max_length=100) last_name: str = Field(..., min_length=1, max_length=100) email: EmailStr message: str = Field(..., min_length=10, max_length=5000) # Optional — prefilled if they clicked "Get Started" from a specific plan plan_interest: str | None = Field(None, max_length=50) @router.post("/") async def submit_contact( body: ContactRequest, request: Request, ): """Handle contact form submission from the Next.js marketing website. Sends an email to the support inbox defined by SUPPORT_EMAIL in config. Always returns 200 to prevent spam enumeration. """ subject = f"New contact: {body.first_name} {body.last_name}" if body.plan_interest: subject += f" [interested in {body.plan_interest}]" body_text = ( f"Name: {body.first_name} {body.last_name}\n" f"Email: {body.email}\n" f"Plan interest: {body.plan_interest or 'not specified'}\n" f"IP: {request.client.host if request.client else 'unknown'}\n\n" f"Message:\n{body.message}" ) try: email_svc = EmailService() target = cfg.SUPPORT_EMAIL or cfg.EMAIL_FROM_ADDRESS if target: email_svc._send( to=str(target), subject=subject, body=body_text, ) logger.info( "Contact form submitted", email=body.email, plan=body.plan_interest, ) else: logger.warning("SUPPORT_EMAIL not configured — contact form email dropped") except Exception as e: # Log but don't surface the error to the user logger.error("Contact form email failed", error=str(e)) return {"message": "Thanks! We'll be in touch within one business day."}