import os import time import random import smtplib from datetime import datetime from functools import wraps from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart # Flask & Extensions from flask import Flask, request, jsonify from flask_limiter import Limiter from flask_cors import CORS from flask_limiter.util import get_remote_address from dotenv import load_dotenv # REQUIRED FOR HUGGING FACE SPACES (Proxy Fix) from werkzeug.middleware.proxy_fix import ProxyFix # ================= LOAD ENV ================= load_dotenv() app = Flask(__name__) # ================= HUGGING FACE CONFIGURATION ================= # Hugging Face runs behind a proxy (Nginx). We must tell Flask to trust # the X-Forwarded-For headers so Flask-Limiter sees the real user IP, # not the proxy IP. app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1) CORS(app) # ================= BASIC CONFIG ================= YOUR_WEB_APP_NAME = os.getenv("WEBAPPNAME", "xyzapp") CURRENT_YEAR = str(datetime.now().year) BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # Ensure your Templates folder exists in the Space files TEMPLATE_PATH = os.path.join(BASE_DIR, "Templates", "template1.html") REMOVE_WATERMARK = False # ================= RATE LIMIT ================= # With ProxyFix applied above, get_remote_address will now correctly # grab the real user's IP address. limiter = Limiter( key_func=get_remote_address, app=app, default_limits=["200 per hour"], storage_uri="memory://" # Explicitly use memory storage ) # ================= SMTP CONFIG ================= SMTP_SERVER = "smtp.gmail.com" SMTP_PORT = 587 GMAIL_EMAIL = os.getenv("GMAIL_EMAIL") APP_PASSWORD = os.getenv("APP_PASSWORD") FROM_EMAIL = os.getenv("FROM_EMAIL", GMAIL_EMAIL) # ================= SECURITY CONFIG ================= OTP_EXPIRY_SECONDS = 300 MAX_ATTEMPTS = 5 LOCK_TIME = 600 RESEND_COOLDOWN = 60 IP_MAX_ATTEMPTS = 10 IP_BLOCK_TIME = 60 # ================= STORES (IN-MEMORY) ================= # Note: In-memory stores will reset if the Space restarts/sleeps. otp_store = {} ip_store = {} # ================= HTML TEMPLATE ================= def load_template(path: str) -> str: # Fallback if file is missing to prevent crash if not os.path.exists(path): return "