Test and sync: a refused password is reported as “the server names no principal”, in English, and a test asserts it #28
Labels
No labels
bug
documentation
enhancement
performance
security
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo-dav#28
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo-dav at
97abc9779, following a 401 from the server throughprincipal()to what the person is shown.Related to #7.
A wrong or revoked password is the most likely thing to go wrong with this connection, and the plugin describes it as a discovery problem, in an untranslated sentence with a class name in front.
DavErroris documented as "The message is for the person" (src/postulo_dav/dav.py:69-70), and a plugin translates its own strings, but none of its messages go through gettext.src/postulo_dav/dav.py:126-137(Server.principal),src/postulo_dav/dav.py:90-91(_explain),:122and:150(the otherDavErrorsentences),src/postulo_dav/sync.py:354-355(DavSync.test),tests/test_dav.py:376-378.principal()tries/.well-known/<kind>and/, andexcept DavError: continuediscards every failure, a 401 or 403 included. With nothing found it raisesDavError(f"the server names no principal for {well_known}"). Run with a wrong password against the suite's server: both requests answered 401, Test showedDavError: the server names no principal for carddav, andDavSync().syncraised the same error, which the core stores on the connection asDavError: the server names no principal for carddav(plugins/syncing.py:85prefixes the class name).test_a_wrong_password_is_a_sentenceasserts"principal" in result.message, so the misleading wording is what the suite holds in place.principal(), treat 401 and 403 as an answer, not as "try the next place": raise at once aDavErrorsubclass whose message is a translated sentence saying the server refused the user name or password. Keep the status code on the error so the caller need not parse text.DavErrorsentences through gettext (_explain, "unreadable answer", "names no principal", "names no … home"), and add them to the catalogues.DavSync.test, showstr(error)for aDavErrorand keep the class-name prefix only for an exception nobody expected. InDavSync.sync, catchDavErrorand returnSyncReport(error=str(error)), so the core does not addDavError:in front.ConnectionUnusablefromsync:sync_connectiondoes not handle it (onlydocuments/archiving.py:140andnotifications/service.py:73do), so it would be shown as one more class name.Done when
tests/test_dav.py::test_a_wrong_password_is_a_sentenceasserts a message about the user name or password, with no class name, for bothtest()andsync(), and a second assertion undertranslation.override("fr-fr")sees the French sentence.uv run postulo-messages extractlists the new strings, with fr-fr and pt-pt filled.Fixed by pull request #35, merged as
fb8bbd7ae.