Files
SemapForm/app/main.py
2025-10-10 09:53:49 +02:00

112 lines
4.1 KiB
Python
Executable File

import os
import re
import smtplib
from email.mime.text import MIMEText
from typing import Optional
from xml.etree.ElementTree import Element, SubElement, tostring
from dotenv import load_dotenv
from fastapi import FastAPI, Form, HTTPException, Request, status
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
load_dotenv()
app = FastAPI()
templates = Jinja2Templates(directory="app/templates")
# Serve static files (CSS, images)
app.mount("/static", StaticFiles(directory="app/static"), name="static")
# add somewhere near the top-level constants
EMAIL_REGEX = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")
# SMTP / email configuration via environment
SMTP_HOST = os.getenv("SMTP_HOST", "smtp")
SMTP_PORT = int(os.getenv("SMTP_PORT", "25"))
SENDER_MAIL = os.getenv("SENDER_MAIL", "noreply@example.com")
MAIL_TO = os.getenv("MAIL_TO", "destination@example.com")
MAIL_USERNAME = os.getenv("MAIL_USERNAME")
MAIL_PASSWORD = os.getenv("MAIL_PASSWORD")
print(
f"Using SMTP server {SMTP_HOST}:{SMTP_PORT} with user {MAIL_USERNAME}"
f" to send from {SENDER_MAIL} to {MAIL_TO}"
)
@app.get("/", response_class=HTMLResponse)
async def show_form(request: Request):
return templates.TemplateResponse("form.html", {"request": request})
@app.post("/submit")
async def handle_form(
request: Request,
name: str = Form(...),
lastname: str = Form(...),
title: Optional[str] = Form(None),
telno: str = Form(...),
mail: str = Form(...),
apparatsname: str = Form(...),
subject: str = Form(...),
semester_type: str = Form(...), # "summer" or "winter"
semester_year: str = Form(...),
dauerapparat: bool = Form(False),
authorname: list[str] = Form(...),
year: list[str] = Form(...),
booktitle: list[str] = Form(...),
signature: Optional[list[str]] = Form(None),
):
# Build XML
root = Element("form_submission")
static_data = SubElement(root, "static")
SubElement(static_data, "name").text = name
SubElement(static_data, "lastname").text = lastname
# Title is optional
SubElement(static_data, "title").text = title or ""
SubElement(static_data, "telno").text = telno
SubElement(static_data, "mail").text = mail
SubElement(static_data, "apparatsname").text = apparatsname
SubElement(static_data, "subject").text = subject
SubElement(static_data, "semester").text = f"{semester_type} {semester_year}"
SubElement(static_data, "dauerapparat").text = "true" if dauerapparat else "false"
# inside handle_form(), right after parameters are received, before building XML:
# Basic email validation (server-side)
if not EMAIL_REGEX.match(mail):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid email address format.",
)
books = SubElement(root, "books")
for i in range(len(authorname)):
book = SubElement(books, "book")
SubElement(book, "authorname").text = authorname[i]
SubElement(book, "year").text = year[i]
SubElement(book, "title").text = booktitle[i]
# Signature is optional; write empty string if not provided
sig_value = ""
if signature and i < len(signature):
sig_raw = signature[i] or ""
sig_value = sig_raw.strip()
SubElement(book, "signature").text = sig_value
xml_data = tostring(root, encoding="unicode")
# Send mail
msg = MIMEText(xml_data, "xml")
msg["Subject"] = "Antrag für neuen Semesterapparat"
msg["From"] = SENDER_MAIL
msg["To"] = MAIL_TO
with smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT) as server:
server.connect(SMTP_HOST, SMTP_PORT)
# Login only if credentials are provided
if MAIL_USERNAME and MAIL_PASSWORD:
server.login(MAIL_USERNAME, MAIL_PASSWORD)
server.send_message(msg, from_addr=SENDER_MAIL, to_addrs=[MAIL_TO])
return RedirectResponse("/", status_code=303)