feat(api): add contact form endpoint for website enquiries
Add POST /api/v1/contact endpoint to handle contact form submissions from the marketing website. Includes: - ContactSchema for validation with HTML sanitization - Honeypot field for spam protection - Rate limiting (5 per hour) - Email notification to info@secuird.tech via NotificationService
This commit is contained in:
@@ -5,7 +5,9 @@ from flask import Blueprint
|
||||
api_v1_bp = Blueprint("api_v1", __name__)
|
||||
|
||||
# Import route modules to register them
|
||||
from gatehouse_app.api.v1 import auth, users, organizations, policies, external_auth, departments, principals, ssh, zerotier, sudo, oidc
|
||||
from gatehouse_app.api.v1 import auth, users, organizations, policies, external_auth, departments, principals, ssh, zerotier, sudo, oidc, contact
|
||||
from gatehouse_app.api.v1 import superadmin
|
||||
|
||||
api_v1_bp.register_blueprint(ssh.ssh_bp)
|
||||
api_v1_bp.register_blueprint(superadmin.superadmin_bp)
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
"""Contact form endpoint for website enquiries."""
|
||||
import logging
|
||||
|
||||
from flask import request, current_app
|
||||
from marshmallow import ValidationError
|
||||
|
||||
from gatehouse_app.api.v1 import api_v1_bp
|
||||
from gatehouse_app.extensions import limiter
|
||||
from gatehouse_app.utils.response import api_response
|
||||
from gatehouse_app.schemas.contact_schema import ContactSchema
|
||||
from gatehouse_app.services.notification_service import NotificationService
|
||||
from gatehouse_app.services.email_templates import build_contact_enquiry_html
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Hardcoded destination for all contact submissions
|
||||
CONTACT_DESTINATION = "info@secuird.tech"
|
||||
|
||||
|
||||
@api_v1_bp.route("/contact", methods=["POST"])
|
||||
@limiter.limit("5 per hour")
|
||||
def contact():
|
||||
"""Handle contact form submissions from the marketing website.
|
||||
|
||||
Accepts: email, name, company, enquiry_type, message, interest_area, _hp.
|
||||
Sends an email to info@secuird.tech with the enquiry details.
|
||||
Silently discards submissions where the honeypot field (_hp) is filled.
|
||||
"""
|
||||
try:
|
||||
schema = ContactSchema()
|
||||
data = schema.load(request.get_json() or {})
|
||||
except ValidationError as err:
|
||||
return api_response(
|
||||
success=False,
|
||||
message="Invalid request data",
|
||||
status=400,
|
||||
error_type="VALIDATION_ERROR",
|
||||
error_details=err.messages,
|
||||
)
|
||||
|
||||
# Honeypot check — silently succeed without sending
|
||||
if data.get("_hp"):
|
||||
logger.info(f"[Contact] Honeypot triggered, ip={request.remote_addr}")
|
||||
return api_response(message="Thank you for your message!")
|
||||
|
||||
enquiry_type = data.get("enquiry_type") or "general"
|
||||
email = data.get("email") or ""
|
||||
|
||||
# Build and send email
|
||||
html_body = build_contact_enquiry_html(
|
||||
enquiry_type=enquiry_type,
|
||||
submitter_email=email,
|
||||
name=data.get("name"),
|
||||
company=data.get("company"),
|
||||
interest_area=data.get("interest_area"),
|
||||
message=data.get("message"),
|
||||
)
|
||||
|
||||
NotificationService._send_email_async(
|
||||
to_address=CONTACT_DESTINATION,
|
||||
subject=f"Secuird Website: {enquiry_type.replace('_', ' ').title()} from {email}",
|
||||
body=f"New contact enquiry ({enquiry_type}) from {email}",
|
||||
html_body=html_body,
|
||||
)
|
||||
|
||||
logger.info(f"[Contact] enquiry_type={enquiry_type} ip={request.remote_addr}")
|
||||
|
||||
return api_response(message="Thank you for your message!")
|
||||
Reference in New Issue
Block a user