import logging import re import requests from fastapi import FastAPI from pydantic import BaseModel, Field import uvicorn # ======================= # Configuration Settings # ======================= # URL of the SMTP API endpoint (hosted on Vercel) SMTP_API_URL = "https://smtp-server-ten.vercel.app/smtp" # <--- change this to your deployed Vercel endpoint # ======================= # Logging Configuration # ======================= logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s") logger = logging.getLogger("bot_server") # ======================= # Global Conversation State # ======================= # Maps sender's WhatsApp number to conversation data. conversations = {} # ======================= # Helper Functions # ======================= # Regex for validating email addresses EMAIL_REGEX = re.compile(r"^[^@]+@[^@]+\.[^@]+$") def validate_email(email: str) -> bool: return re.match(EMAIL_REGEX, email) is not None def send_email_via_api(from_addr: str, to_addr: str, subject: str, body: str) -> bool: """ Calls the external SMTP API endpoint to send an email. """ payload = { "from": from_addr, "to": to_addr, "subject": subject, "body": body, } logger.debug("Calling SMTP API with payload: %s", payload) try: response = requests.post(SMTP_API_URL, json=payload, timeout=10) response.raise_for_status() result = response.json() logger.info("SMTP API response: %s", result) return result.get("success", False) except Exception as e: logger.error("Error calling SMTP API: %s", e) return False # ======================= # Pydantic Models for Bot Requests # ======================= class Text(BaseModel): body: str class Message(BaseModel): text: Text class BotRequest(BaseModel): from_: str = Field(..., alias="from") message: Message # ======================= # FastAPI Bot Application # ======================= app = FastAPI() @app.post("/bot") async def bot_endpoint(request_data: BotRequest): payload = request_data.dict(by_alias=True) logger.debug("Received request payload: %s", payload) sender_number = request_data.from_ message_body = request_data.message.text.body.strip() logger.info("Processing message from %s: '%s'", sender_number, message_body) state = conversations.get(sender_number, {}) if not state: conversations[sender_number] = {"step": "from"} response_msg = "Welcome to SMTP Assistant! Please provide your 'From' email address." else: step = state.get("step") logger.debug("Current step for %s: %s", sender_number, step) if step == "from": if validate_email(message_body): state["from"] = message_body state["step"] = "to" response_msg = "Thanks! Now, please provide the recipient's email address." else: response_msg = "Invalid email format. Please provide a valid 'From' email address." elif step == "to": if validate_email(message_body): state["to"] = message_body state["step"] = "subject" response_msg = "Great! Please provide the email subject." else: response_msg = "Invalid email format. Please provide a valid recipient email address." elif step == "subject": state["subject"] = message_body state["step"] = "body" response_msg = "Almost done! Please provide the email body." elif step == "body": state["body"] = message_body from_addr = state.get("from") to_addr = state.get("to") subject = state.get("subject") body = state.get("body") logger.info("Attempting to send email from %s to %s with subject '%s'", from_addr, to_addr, subject) if send_email_via_api(from_addr, to_addr, subject, body): response_msg = f"Email sent successfully from {from_addr} to {to_addr}." else: response_msg = "Failed to send email. Please try again later." del conversations[sender_number] logger.info("Cleared conversation state for %s", sender_number) else: response_msg = "Unrecognized step. Let's start over. Please provide your 'From' email address." conversations[sender_number] = {"step": "from"} logger.debug("Response message to %s: %s", sender_number, response_msg) return {"status": "success", "message": response_msg} if __name__ == "__main__": uvicorn.run("bot_server:app", host="0.0.0.0", port=5000, reload=True)