"""SMS delivery via the SAR Link SMS gateway. POST {SMS_API_URL} X-API-Key: {SMS_API_KEY} {"to": "+9607712345", "text": "..."} With `SMS_API_URL`/`SMS_API_KEY` unset (dev) nothing is sent and the message is logged instead, so the OTP flows stay usable without the gateway. """ import logging import requests from django.conf import settings logger = logging.getLogger(__name__) TIMEOUT_SECONDS = 10 def send_sms(mobile: str, text: str) -> bool: if not settings.SMS_API_URL or not settings.SMS_API_KEY: logger.warning("SMS not configured; would send to %s: %s", mobile, text) return False try: response = requests.post( settings.SMS_API_URL, json={"to": mobile, "text": text}, headers={ "X-API-Key": settings.SMS_API_KEY, "Content-Type": "application/json", }, timeout=TIMEOUT_SECONDS, ) response.raise_for_status() except requests.RequestException: logger.exception("Failed to send SMS to %s", mobile) return False logger.info("Sent SMS to %s", mobile) return True def send_otp(mobile: str, code: str, purpose: str) -> bool: minutes = max(1, settings.OTP_TTL_SECONDS // 60) what = "registration" if purpose == "registration" else "login" return send_sms( mobile, f"{code} is your SAR Link {what} code. It expires in {minutes} minutes.", ) def send_registration_submitted(mobile: str) -> bool: return send_sms( mobile, "Thanks for registering with SAR Link. Your application is being " "reviewed and we'll text you once it's approved.", ) def send_registration_approved(mobile: str) -> bool: return send_sms( mobile, f"Your SAR Link registration is approved. Sign in at {settings.FRONTEND_URL}", ) def send_registration_rejected(mobile: str, reason: str = "") -> bool: tail = f" Reason: {reason}" if reason else "" return send_sms( mobile, f"Your SAR Link registration could not be approved.{tail}" )