-
v0.34.0 — Gmail sending (G4) Stable
released this
2026-08-23 10:36:15 -05:00 | 100 commits to main since this release[0.34.0] — 2026-08-23
G4: sending on the Gmail tenant.
send_message,reply_messageand
forward_message, behindMAIL_SEND_ENABLED, which is off by default and
registers nothing when it is. Live pass indocs/operations.md— 37 checks, and
it found a defect in a G2 tool rather than in its own.Added
-
The three send tools, and the shortest send path in this project. Probe 9
found Gmail writes[Gmail]/Sent Mailitself on submission, so this tenant
appends nothing — no Sent folder to resolve, noAPPENDUIDto parse, no
second verdict that can fail on its own. The deletions are the feature: the
obvious port fromicloudmailwould leave a second copy in Sent every time
this server mails anybody, in the folder the user opens to find out what was
sent for them. The live pass counts the copies, and one is the passing answer. -
One verdict, and a sentence saying whose copy it is.
SendOutcome.saved_to_sentisNoneon this tenant andto_dictemits
sent_copyinstead of the boolean. Both values would be lies —falsesays
the user's record is missing when it is not,trueclaims an operation this
server never performed — and a JSONnullis worse than either, since
anything testing it for truth reads it as false. -
Sending is NOT gated on
MAIL_WRITABLE_FOLDERShere, because no folder is
written. A deployment with an empty write allowlist can still mail a stranger,
and that is stated in the instructions rather than left to be discovered. The
one thing it costs is that a reply cannot flag its original\Answered, so
marked_answered: falseis the ORDINARY outcome on that deployment — the tool
description says not to read it as a failure, and the live pass asserts both
halves. -
tests/test_mail_smtp.py, which nothing had ever driven. Every send test
on either tenant replacessubmitwith a fake, so the lines deciding which
account authenticates and whether the credential crosses before STARTTLS were
reachable only from production. Found by the break-the-guard pass: swapping
mail_addressback toicloud_mail_addressbroke Gmail's send entirely and
every test still passed.
Fixed
-
A STORE that changes nothing is no longer reported as a vanished message —
on BOTH tenants.add_flagsof a flag the message already carries answers
{}, with no untagged FETCH, and that was read as "the message is gone". So
update_message(read=true)on an already-read message told the user their
mail had probably been deleted from another device: a failure reported
about a success, on the most ordinary call the tool has. Shipped in 0.25.0 on
icloudmailand 0.31.0 ongmail.A vanished UID answers
{}too, so the two states are indistinguishable from
the STORE alone. The fix asks: on an empty answer the client FETCHes the flags
back, and only a FETCH that also returns nothing means gone. Not a
provider table — the two servers disagree even here, since removing a flag
that was never set answers{}on Gmail and answers with the flag list on
iCloud.Neither suite could fail this way, because a fake that answers a STORE answers
it every time. The Gmail fake now carriessilent_storeandvanishedas
separate switches, and the two tests using them are a pair: a no-op must
succeed, a vanished message must still refuse.
Changed
-
icloudmail/smtp.pyismail/smtp.py, shared by both mail tenants and
authenticating withConfig.mail_address. Same movemail/errors.pymade in
0.29.0 and for the same reason: the alternative wasgmail/importing
icloudmail/. Submission came out identical on both accounts — what is
genuinely provider-specific is what happens to the copy afterwards, and that
stays in each tenant's client. -
The Gmail instructions no longer say a server that can send is READ-ONLY, and
no longer tell the model it cannot send once the gate is on. Built from the
settings the tools are registered on, the same way the unsubscribe and
label-admin clauses already were — this is the third gate to reach that
branch, which is why the refusal list is now assembled rather than written out. -
Preflight gains a Gmail
sendline that verifies nothing, deliberately.
The mail tenant's checks whether Sent and Drafts exist and are writable; this
tenant writes no folder to send, and the credential was already proved by the
IMAP login — the same app password serves both hosts. It is a grant line, and
it does not dial SMTP.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-