Skip to content

feat(mailboxes, domains): read and answer mailbox mail, and manage the sender logo - #9

Merged
BSalaeddin merged 1 commit into
mainfrom
feat/mailbox-conversations-and-domain-logo
Oct 22, 2026
Merged

BSalaeddin merged 1 commit into
mainfrom
feat/mailbox-conversations-and-domain-logo

Conversation

@BSalaeddin

Copy link
Copy Markdown
Contributor

This is the Python half of DevinoSolutions/sendly-js#18, tracked as T-6107. It implements the 8 operations listed in NOT_YET_IMPLEMENTED since #8, and the list is empty again.

Mailbox mail. These sit under the opt-in mailbox-conversations:read and mailbox-conversations:reply scopes, which no existing key carries:

  • mailboxes.list_conversations(id, query) and iter_list_conversations (follows nextCursor as cursor, and stops on a repeated cursor)
  • get_conversation(id, conversation_id)
  • reply_to_conversation(id, conversation_id, body): there is no recipient or sender to name
  • download_attachment(id, attachment_id) → SendlyFile(data: bytes, content_type, content_disposition), exported from sendly

Sender logo (BIMI): domains.get_logo_v1, upload_logo_v1, delete_logo_v1 and get_logo_readiness_v1.

Client change. The HTTP call moved into a private _send(), shared by request() (unchanged) and a new request_bytes(). On a failure, request_bytes() raises the same typed errors.

Contract suite

  • It now reads request_bytes call sites as well as request ones.
  • It recognises the legacy cursor page (data: {items, nextCursor}) by shape, so iter_list_conversations is checked against a real cursor list instead of being flagged as a stray iterator.

Tests

  • test_mailbox_conversations.py: the filters, the multi-page walk, the stuck-cursor stop, the reply body, bytes that are not valid UTF-8 surviving intact, and a 403 surfacing as SendlyPermissionError.
  • test_domain_logo.py: the four calls, plus a 422 rebuild refusal.

Checks: pytest (289), ruff check and format, and mypy src are clean. README and CHANGELOG are updated. Not released.

…e sender logo

Implements the eight operations the last spec re-sync listed in
NOT_YET_IMPLEMENTED, which is empty again (in step with sendly-js#18):
mailboxes.list_conversations / iter_list_conversations,
get_conversation, reply_to_conversation and download_attachment, under
the opt-in mailbox-conversations scopes; and domains.get_logo_v1,
upload_logo_v1, delete_logo_v1 and get_logo_readiness_v1.

download_attachment needs the body as bytes, so the HTTP call is split
out of request() and shared with a new request_bytes(), which still
raises the same typed errors. The contract suite now reads request_bytes
call sites too, and recognises the legacy cursor page
({items, nextCursor}) by shape, so the iterator is checked rather than
flagged as stray.
@BSalaeddin
BSalaeddin merged commit 6799ab7 into main Oct 22, 2026
2 checks passed
@BSalaeddin
BSalaeddin deleted the feat/mailbox-conversations-and-domain-logo branch October 22, 2026 02:44
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.

1 participant