# Admin email verification on Hostycare

Every new login requires the existing Admin password, any configured authenticator,
and an email code sent only to clipimagesmedia@gmail.com. Admin email/username is support@moxiedigital.in.
Codes expire after 5 minutes, allow 5 attempts, and can be requested once per minute.
Failed email delivery never opens an Admin session.

In cPanel > Setup Python App > Environment variables, configure:

| Name | Value |
|---|---|
| MX_PUBLIC_BASE_URL | https://smptbulkmailer.moxiedigital.in |
| MX_OTP_SMTP_EMAIL | Your authenticated sender mailbox |
| MX_OTP_SMTP_HOST | Your sender provider's SMTP host |
| MX_OTP_SMTP_PORT | 465 for SSL or 587 for STARTTLS |
| MX_OTP_SMTP_PASSWORD | Sender mailbox/app password; configure privately in cPanel |
| MX_WEB_ADMIN_SECRET | A unique random server secret of at least 32 characters; keep stable across restarts |

On the first start of this release, the owner-requested password is applied once
as a salted PBKDF2 verifier and older sessions are revoked. The plaintext password
is not included. Future restarts preserve passwords changed through recovery.
Forgot password sends a verification code only to clipimagesmedia@gmail.com;
after verification, choose and confirm a new password of at least 12 characters.
Recovery revokes all existing sessions and requires a fresh login plus email OTP.

Upload/extract this ZIP in the Python application's root. Keep passenger_wsgi.py
as startup and application as entry point. Install requirements-web-admin.txt
and restart the Python app. Use HTTPS. Do not publish an OTP or SMTP password.

This ZIP deliberately excludes Firebase service account keys. Keep your existing
key outside public_html and configure GOOGLE_APPLICATION_CREDENTIALS to its private
absolute server path. Do not remove an existing key before relocating/configuring it.
Remove old downloadable ZIP archives containing private keys from the public folder.
Use a private application root outside public_html, mapped via Setup Python App.
No private key, database, or source ZIP should be served as a static download.

OTP state is stored in ~/.mx_admin_login/otp.sqlite3 with restrictive permissions,
not in public_html. Restarting a worker does not reset attempt counters.
Changing MX_WEB_ADMIN_SECRET invalidates in-progress OTP verification.

Test: login with password, confirm the email arrives, verify the code, and check
that a wrong/expired/reused code cannot log in. Hosted SMTP delivery must be tested
after configuring your sender; no live delivery was performed during packaging.
