Skip to content

Restore forgot-password email delivery in Docker deployments#236

Open
Atlas-SZ wants to merge 1 commit intodataelement:mainfrom
Atlas-SZ:next-pr-base-2026-03-30
Open

Restore forgot-password email delivery in Docker deployments#236
Atlas-SZ wants to merge 1 commit intodataelement:mainfrom
Atlas-SZ:next-pr-base-2026-03-30

Conversation

@Atlas-SZ
Copy link
Copy Markdown
Contributor

@Atlas-SZ Atlas-SZ commented Mar 30, 2026

Fixes #235

Summary

  • inject .env mail/reset settings into the Docker backend service with env_file
  • fix async email background-job execution when Starlette runs the task in a threadpool without a running event loop
  • add a regression test covering the no-running-loop path

Root Cause

There were two separate issues affecting forgot-password in Docker deployments:

  1. docker-compose.yml did not inject the SMTP and reset-password related values from .env into the backend container, so the backend could start without the expected
    mail configuration.
  2. The forgot-password email job was dispatched through a sync background-task bridge that called asyncio.create_task() from a Starlette threadpool worker, which raised
    RuntimeError: no running event loop and prevented the mail from being sent even though the API returned a success response.

Changes

  • added env_file: ./.env to the Docker backend service
  • updated run_background_email_job() to:
    • use asyncio.run() when no running event loop exists
    • keep the existing fire-and-forget path when a loop is available
  • added a regression test to ensure awaitable email jobs execute correctly from a sync context without an active event loop

Test Plan

  • cd backend && .venv/bin/python -m pytest tests/test_password_reset_and_notifications.py -k 'run_background_email_job_executes_awaitable_without_running_loop or hides_email_delivery_failures or send_system_email_uses_configured_timeout' -q
  • docker compose config | rg 'SYSTEM_EMAIL_FROM_ADDRESS|PUBLIC_BASE_URL|PASSWORD_RESET_TOKEN_EXPIRE_MINUTES'
  • Verify forgot-password end-to-end on the deployed Docker environment

Notes

  • This PR does not change the forgot-password response semantics.
  • This PR is scoped only to the Docker env injection issue and the background email task execution bug.

The Docker Compose backend service was not inheriting the SMTP and reset-password settings from .env, and the email background-task bridge tried to create an asyncio task from a Starlette threadpool worker. Together those two issues produced a success response without a delivered reset email.

This change injects the .env file into the backend container and makes async email jobs runnable both with and without an active event loop. It also adds a regression test for the no-running-loop path.

Constraint: Docker Compose only interpolates .env by default; it does not inject arbitrary keys into container environments
Rejected: Execute reset emails inline in the request path | adds avoidable latency and couples delivery to response timing
Rejected: Change forgot-password success masking behavior | out of scope and would alter account-enumeration protections
Confidence: high
Scope-risk: narrow
Directive: Keep async email jobs compatible with both request event loops and Starlette threadpool background tasks
Related: dataelement#235
Tested: cd backend && .venv/bin/python -m pytest tests/test_password_reset_and_notifications.py -k 'run_background_email_job_executes_awaitable_without_running_loop or hides_email_delivery_failures or send_system_email_uses_configured_timeout' -q
Tested: docker compose config | rg 'SYSTEM_EMAIL_FROM_ADDRESS|PUBLIC_BASE_URL|PASSWORD_RESET_TOKEN_EXPIRE_MINUTES'
Not-tested: Full backend test suite
Not-tested: Live forgot-password flow against deployed Docker backend
@Atlas-SZ
Copy link
Copy Markdown
Contributor Author

已实测,合并前辛苦再测一下。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Forgot password does not send email in Docker deployment

1 participant