add smtp module and testing
This commit is contained in:
+135
-46
@@ -14,6 +14,7 @@ from app.services.config_page import (
|
||||
is_ticktick_oauth_ready,
|
||||
save_config_updates,
|
||||
)
|
||||
from app.services.email import EmailConfigurationError, EmailDeliveryError, is_smtp_ready, send_smtp_test_email
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
templates = Jinja2Templates(directory=str(Path(__file__).resolve().parents[2] / "templates"))
|
||||
@@ -33,6 +34,49 @@ def _ticktick_oauth_notice(status_value: str | None) -> tuple[str | None, str |
|
||||
return None, None
|
||||
|
||||
|
||||
def _smtp_test_notice(status_value: str | None) -> tuple[str | None, str | None]:
|
||||
if status_value == "success":
|
||||
return "SMTP test email sent successfully.", None
|
||||
if status_value == "config-error":
|
||||
return None, "SMTP test failed. Check required SMTP settings before sending a test email."
|
||||
if status_value == "failed":
|
||||
return None, "SMTP test failed. Check saved SMTP settings and server reachability."
|
||||
return None, None
|
||||
|
||||
|
||||
def _build_config_context(
|
||||
*,
|
||||
auth_db_session: Session,
|
||||
settings: Settings,
|
||||
current_auth: AuthenticatedSession,
|
||||
config_saved: bool,
|
||||
config_error: str | None,
|
||||
password_change_error: str | None,
|
||||
ticktick_oauth_notice: str | None,
|
||||
ticktick_oauth_error: str | None,
|
||||
smtp_test_notice: str | None,
|
||||
smtp_test_error: str | None,
|
||||
) -> dict[str, object]:
|
||||
return {
|
||||
"app_name": settings.app_name,
|
||||
"app_env": settings.app_env,
|
||||
"current_username": current_auth.user.username,
|
||||
"csrf_token": current_auth.session.csrf_token,
|
||||
"force_password_change": current_auth.user.force_password_change,
|
||||
"password_change_error": password_change_error,
|
||||
"config_error": config_error,
|
||||
"config_saved": config_saved,
|
||||
"config_sections": build_config_sections(auth_db_session, settings),
|
||||
"ticktick_oauth_ready": is_ticktick_oauth_ready(settings),
|
||||
"ticktick_redirect_uri": settings.ticktick_redirect_uri,
|
||||
"ticktick_oauth_notice": ticktick_oauth_notice,
|
||||
"ticktick_oauth_error": ticktick_oauth_error,
|
||||
"smtp_test_ready": is_smtp_ready(settings),
|
||||
"smtp_test_notice": smtp_test_notice,
|
||||
"smtp_test_error": smtp_test_error,
|
||||
}
|
||||
|
||||
|
||||
@router.get("/", response_class=HTMLResponse)
|
||||
def home(
|
||||
request: Request,
|
||||
@@ -66,22 +110,19 @@ def config_page(
|
||||
ticktick_oauth_notice, ticktick_oauth_error = _ticktick_oauth_notice(
|
||||
request.query_params.get("ticktick_oauth")
|
||||
)
|
||||
|
||||
context = {
|
||||
"app_name": settings.app_name,
|
||||
"app_env": settings.app_env,
|
||||
"current_username": current_auth.user.username,
|
||||
"csrf_token": current_auth.session.csrf_token,
|
||||
"force_password_change": current_auth.user.force_password_change,
|
||||
"password_change_error": None,
|
||||
"config_error": None,
|
||||
"config_saved": request.query_params.get("saved") == "1",
|
||||
"config_sections": build_config_sections(auth_db_session, settings),
|
||||
"ticktick_oauth_ready": is_ticktick_oauth_ready(settings),
|
||||
"ticktick_redirect_uri": settings.ticktick_redirect_uri,
|
||||
"ticktick_oauth_notice": ticktick_oauth_notice,
|
||||
"ticktick_oauth_error": ticktick_oauth_error,
|
||||
}
|
||||
smtp_test_notice, smtp_test_error = _smtp_test_notice(request.query_params.get("smtp_test"))
|
||||
context = _build_config_context(
|
||||
auth_db_session=auth_db_session,
|
||||
settings=settings,
|
||||
current_auth=current_auth,
|
||||
config_saved=request.query_params.get("saved") == "1",
|
||||
config_error=None,
|
||||
password_change_error=None,
|
||||
ticktick_oauth_notice=ticktick_oauth_notice,
|
||||
ticktick_oauth_error=ticktick_oauth_error,
|
||||
smtp_test_notice=smtp_test_notice,
|
||||
smtp_test_error=smtp_test_error,
|
||||
)
|
||||
return templates.TemplateResponse(request, "config.html", context)
|
||||
|
||||
|
||||
@@ -99,21 +140,18 @@ async def config_submit(
|
||||
csrf_token = form.get("csrf_token")
|
||||
if csrf_token != current_auth.session.csrf_token:
|
||||
logger.warning("Rejected config update due to CSRF validation failure")
|
||||
context = {
|
||||
"app_name": settings.app_name,
|
||||
"app_env": settings.app_env,
|
||||
"current_username": current_auth.user.username,
|
||||
"csrf_token": current_auth.session.csrf_token,
|
||||
"force_password_change": current_auth.user.force_password_change,
|
||||
"password_change_error": None,
|
||||
"config_error": "invalid config update request",
|
||||
"config_saved": False,
|
||||
"config_sections": build_config_sections(auth_db_session, settings),
|
||||
"ticktick_oauth_ready": is_ticktick_oauth_ready(settings),
|
||||
"ticktick_redirect_uri": settings.ticktick_redirect_uri,
|
||||
"ticktick_oauth_notice": None,
|
||||
"ticktick_oauth_error": None,
|
||||
}
|
||||
context = _build_config_context(
|
||||
auth_db_session=auth_db_session,
|
||||
settings=settings,
|
||||
current_auth=current_auth,
|
||||
config_saved=False,
|
||||
config_error="invalid config update request",
|
||||
password_change_error=None,
|
||||
ticktick_oauth_notice=None,
|
||||
ticktick_oauth_error=None,
|
||||
smtp_test_notice=None,
|
||||
smtp_test_error=None,
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
"config.html",
|
||||
@@ -126,21 +164,18 @@ async def config_submit(
|
||||
except ConfigSaveError:
|
||||
logger.warning("Rejected config update due to invalid submitted values")
|
||||
refreshed_settings = get_settings()
|
||||
context = {
|
||||
"app_name": refreshed_settings.app_name,
|
||||
"app_env": refreshed_settings.app_env,
|
||||
"current_username": current_auth.user.username,
|
||||
"csrf_token": current_auth.session.csrf_token,
|
||||
"force_password_change": current_auth.user.force_password_change,
|
||||
"password_change_error": None,
|
||||
"config_error": "invalid config submission",
|
||||
"config_saved": False,
|
||||
"config_sections": build_config_sections(auth_db_session, refreshed_settings),
|
||||
"ticktick_oauth_ready": is_ticktick_oauth_ready(refreshed_settings),
|
||||
"ticktick_redirect_uri": refreshed_settings.ticktick_redirect_uri,
|
||||
"ticktick_oauth_notice": None,
|
||||
"ticktick_oauth_error": None,
|
||||
}
|
||||
context = _build_config_context(
|
||||
auth_db_session=auth_db_session,
|
||||
settings=refreshed_settings,
|
||||
current_auth=current_auth,
|
||||
config_saved=False,
|
||||
config_error="invalid config submission",
|
||||
password_change_error=None,
|
||||
ticktick_oauth_notice=None,
|
||||
ticktick_oauth_error=None,
|
||||
smtp_test_notice=None,
|
||||
smtp_test_error=None,
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
"config.html",
|
||||
@@ -149,3 +184,57 @@ async def config_submit(
|
||||
)
|
||||
|
||||
return RedirectResponse(url="/config?saved=1", status_code=status.HTTP_303_SEE_OTHER)
|
||||
|
||||
|
||||
@router.post("/config/smtp/test", response_class=HTMLResponse)
|
||||
async def smtp_test_submit(
|
||||
request: Request,
|
||||
auth_db_session: Session = Depends(get_auth_db),
|
||||
settings: Settings = Depends(get_app_settings),
|
||||
current_auth: AuthenticatedSession | None = Depends(get_current_auth_session),
|
||||
) -> Response:
|
||||
if current_auth is None:
|
||||
return RedirectResponse(url="/login", status_code=status.HTTP_303_SEE_OTHER)
|
||||
|
||||
form = await request.form()
|
||||
csrf_token = form.get("csrf_token")
|
||||
if csrf_token != current_auth.session.csrf_token:
|
||||
logger.warning("Rejected SMTP test due to CSRF validation failure")
|
||||
context = _build_config_context(
|
||||
auth_db_session=auth_db_session,
|
||||
settings=settings,
|
||||
current_auth=current_auth,
|
||||
config_saved=False,
|
||||
config_error=None,
|
||||
password_change_error=None,
|
||||
ticktick_oauth_notice=None,
|
||||
ticktick_oauth_error=None,
|
||||
smtp_test_notice=None,
|
||||
smtp_test_error="invalid SMTP test request",
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
"config.html",
|
||||
context,
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
try:
|
||||
send_smtp_test_email(settings)
|
||||
except EmailConfigurationError as exc:
|
||||
logger.warning("SMTP test email rejected due to configuration: %s", exc)
|
||||
return RedirectResponse(
|
||||
url="/config?smtp_test=config-error",
|
||||
status_code=status.HTTP_303_SEE_OTHER,
|
||||
)
|
||||
except EmailDeliveryError as exc:
|
||||
logger.warning("SMTP test email failed: %s", exc)
|
||||
return RedirectResponse(
|
||||
url="/config?smtp_test=failed",
|
||||
status_code=status.HTTP_303_SEE_OTHER,
|
||||
)
|
||||
|
||||
return RedirectResponse(
|
||||
url="/config?smtp_test=success",
|
||||
status_code=status.HTTP_303_SEE_OTHER,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user