Bug #153 » README.md
type: redmine-readme
project: Canofy Process Standardization
subject: Tolerate slow or restricted OTP mailbox sites during the NSDL login
story_key: nsdl-otp-mailbox-resilience
generated_at: 2026-10-15T16:16:51+05:30
story_type: bug
attachments:
- file: nsdl-otp-mailbox-resilience_20261015-1616__test_transient.py
description: Local test with a simulated slow Frappe site (test values only)
Tolerate slow or restricted OTP mailbox sites during the NSDL login
A slow answer from the Frappe site holding the OTP mailbox no longer aborts the NSDL login, and the request timeout is configurable.
1. Summary
When the OTP mailbox was moved to a different Frappe site (slc), Phase A failed in two ways. First, the API user could see a count of Communications but an empty list, because the site hides Communications of an Email Account that is not assigned to the user. After the user fixed that, a second problem appeared: the site needed 19 to 21 seconds per query (about 119,000 Communications), and the mailbox code allowed 30 seconds and treated one timeout as fatal, so a single slow answer ended the login after NSDL had already issued the OTP. Timeouts are now retried until the wait ends, and the timeout value is a setting. The user then switched the mailbox back to eapx, which answers in a second or two.
2. Requirement
| # | Requirement | Source | Status |
|---|---|---|---|
| R1 | A slow Frappe answer must not abort a login whose OTP was already requested | observed failure | Done |
| R2 | Real errors (permission, not found, bad configuration) must still fail at once | design | Done |
| R3 | Request timeout configurable | design | Done |
| R4 | Diagnose why no OTP mail was found on the new site | user (2026-10-14) | Done (two causes, see below) |
3. Decisions
| Decision | Options considered | Why this one | Date |
|---|---|---|---|
| Treat timeouts as transient only while waiting for the mail | Retry everything; retry timeouts only | A 403 or 404 means misconfiguration and must not loop | 2026-10-14 |
| Baseline snapshot | No retry; up to 3 tries | The snapshot runs before the Login click, where a failure is still cheap | 2026-10-14 |
| Timeout default | 30 s kept; 90 s in the template | 30 s stays the code default; the template sets 90 s for both functions | 2026-10-14 |
| Mailbox site | Keep slc; return to eapx
|
eapx was reliable in earlier runs (user's choice) |
2026-10-14 |
4. Logic & Workflow
click Login -> poll Communication -> answer? check for OTP : timeout or connection error -> log, keep polling until the wait ends -> end as "no OTP mail" if nothing else
- A timeout or connection error raises
OtpMailboxTransientError, a subclass ofOtpMailboxError. - While waiting for the mail the error is logged and polling continues. If every attempt times out, the result is a clean "no OTP mail" rather than a crash.
- The baseline snapshot before the Login click is retried up to 3 times.
- Other errors stay fatal.
Diagnosis on 2026-10-14:
| Observation | Cause |
|---|---|
| HTTP 403 reading the Email Account | API user lacked access; fixed by the user |
| Count of Communications returned, list empty | Frappe's per-record filter: the Email Account was not in the API user's Email Accounts table; fixed by the user |
| Queries took 19 to 21 s | Large Communication table (about 119,000 rows) on the slc site |
pull_emails returned 417 for the API user |
The Lambda cannot force an import and depends on the site's own mail scheduler |
5. Files & Components Changed
| File / resource | Type | Change | Purpose |
|---|---|---|---|
shared/otp_mailbox.py |
Code |
OtpMailboxTransientError; retry while waiting; baseline retry |
Resilience |
shared/nsdl_login.py |
Code | Reads and validates the new setting | Configuration |
template.yaml |
SAM template |
NSDL_OTP_REQUEST_TIMEOUT_SECONDS: "90" on both functions |
Setting |
6. Configuration & Deployment
| Setting | Allowed | Default | Template |
|---|---|---|---|
NSDL_OTP_REQUEST_TIMEOUT_SECONDS |
10 to 300 | 30 | 90 |
For a new mailbox site: the API user needs read access to Communication and Email Account, and the Email Account must be listed in that user's Email Accounts table. Deployed through the pipeline after the pull request was merged (2026-10-14).
7. Testing
| Test | Data / Site | Expected | Actual | Status |
|---|---|---|---|---|
| Survive repeated timeouts | Simulated Frappe | Mail still returned | Returned after 2 timeouts | Pass |
| Timeouts for the whole wait | Simulated Frappe | Clean "no OTP mail" | As expected | Pass |
| Permission error | Simulated 403 | Fatal at once | Fatal | Pass |
| Baseline retry | Simulated Frappe | Survives 2 timeouts, gives up after 3 | As expected | Pass |
Earlier OTP and no-data suites, Ruff, compile, sam validate
|
Local | Pass | Pass | Pass |
Live run on the slc mailbox |
Real NSDL | Login | Failed before the fix (see Summary) | Fail, fixed in code |
Live Phase A after switching back to eapx (before this fix was deployed) |
Real NSDL, 2026-10-14 | Login | OTP mail after 60 s, accepted at request 1 without resend; login 79 s | Pass |
| Live Phase B run, same day (this fix was not yet deployed in that run) | Real NSDL | Login | OTP mail took 282 s to reach Frappe; the run used 14 min 40 s of the 15-minute limit | Pass, with little margin |
8. Known Limitations & Open Items
- The
slcsite's slow Communication queries were not investigated; a missing index or archiving was suggested to its owner. Not confirmed. - The
slcEmail Account (Office 365 over IMAP) had never synced; whether it needs OAuth was not confirmed. - Intermittent missing OTP mails on later mornings are tracked in
nsdl-eventbridge-scheduling.
9. Status
| Item | Value |
|---|---|
| Branch | feature/AI-TBD-nsdl-otp-login |
| Commits | e2a1c02 |
| PR | Created and merged by the user; number not confirmed |
| Deployed to | TEST stack |
10. References
Related stories: nsdl-email-otp-login, nsdl-login-otp-captcha-update, nsdl-eventbridge-scheduling.