harden(mail): address PR #935 round-4 review
No blockers raised; hardening + clarity: - client/mail.py: URL-encode the caller-supplied attachment_id (quote(..., safe="")) — defense-in-depth against path traversal. - server/mail.py: measure attachment content in UTF-8 bytes (not characters) for the size cap and the sentinel message. - scanner.py: bound _mail_cap_logged (insertion-ordered dict + oldest-first eviction at 50k, mirroring _consent_backstop_done) so the cap-log dedup set can't leak in a long-running multi-tenant process; reword the cap log to not imply MAIL_SCAN_MAX_PER_MAILBOX is operator-tunable (it's the Mail OCS max). - models/mail.py: comment why GetAttachmentResponse doesn't nest MailAttachment (different OCS endpoint shape). - mail_content.py: document format_mail_addresses' empty-entry skip contract. _potentially_deleted doc_type-in-key remains tracked as Deck #376 (pre-existing cross-cutting; reviewer confirmed deferral). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
891d07db12
commit
0856d59956
@@ -173,7 +173,13 @@ class GetMessageResponse(BaseResponse):
|
||||
|
||||
|
||||
class GetAttachmentResponse(BaseResponse):
|
||||
"""Response model for getting a single attachment."""
|
||||
"""Response model for getting a single attachment.
|
||||
|
||||
Intentionally does NOT nest ``MailAttachment``: the Mail OCS *get-attachment*
|
||||
endpoint returns a different shape (``name``/``mime``/``size``/``content``)
|
||||
than the attachment entries on a message listing, which ``MailAttachment``
|
||||
models (``id``/``fileName``/``cid``/``disposition``, and no ``content``).
|
||||
"""
|
||||
|
||||
name: str | None = Field(None, description="Attachment file name")
|
||||
mime: str | None = Field(None, description="MIME type")
|
||||
|
||||
Reference in New Issue
Block a user