Spaces:
Running
Running
| """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) | |
| 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."} | |