Phase 5 follow-up: discover the \Sent mailbox; record the approved real send (AUD-71)
The approved real test reply was sent and the thread updated (same X-GM-THRID as the original). The live test exposed one bug: the thread check hardcoded Gmail's sent mailbox as "[Gmail]/Sent Mail", but this account exposes it as "[Google Mail]/Sent Mail". - internal/mailfetch: LIST parser, ListMailboxes, and SentMailbox that finds the mailbox flagged \Sent (RFC 6154) with name fallbacks. - internal/mailops: VerifyThreadUpdated selects the discovered \Sent mailbox instead of a hardcoded name. - cmd/email-agent: -check-thread <id> exercises the check against real Gmail without sending mail. - Tests for LIST parsing, sent-mailbox discovery, and the discovery error path. - docs/phase5-replies.md: record send-as verification, the sent reply's thread id, the app confirmation (sent_reply_in_thread=true), and the fix. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -31,9 +31,6 @@ const (
|
||||
LabelDelete = "Delete"
|
||||
LabelSaved = "Saved"
|
||||
repliedPrefix = "Replied-to/"
|
||||
// LabelSent is Gmail's IMAP name for the Sent mailbox. Phase 5 checks it to
|
||||
// confirm a reply joined the original thread.
|
||||
LabelSent = "[Gmail]/Sent Mail"
|
||||
)
|
||||
|
||||
// ErrNotConfigured means Gmail credentials are missing, so no mailbox action can
|
||||
@@ -50,6 +47,9 @@ type Conn interface {
|
||||
StoreFlags(uid uint32, op string, flag string) error
|
||||
SearchGmailID(gmailID string) ([]uint32, error)
|
||||
SearchGmailThreadID(threadID string) ([]uint32, error)
|
||||
// SentMailbox returns the server's \Sent mailbox (Gmail may call it
|
||||
// "[Gmail]/Sent Mail" or "[Google Mail]/Sent Mail").
|
||||
SentMailbox() (string, error)
|
||||
Logout() error
|
||||
}
|
||||
|
||||
@@ -164,12 +164,16 @@ func (c *Client) VerifyThreadUpdated(ctx context.Context, threadID string) (bool
|
||||
}
|
||||
defer func() { _ = conn.Logout() }()
|
||||
|
||||
if _, err := conn.Select(LabelSent); err != nil {
|
||||
return false, fmt.Errorf("select %q: %w", LabelSent, err)
|
||||
sent, err := conn.SentMailbox()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("find the sent mailbox: %w", err)
|
||||
}
|
||||
if _, err := conn.Select(sent); err != nil {
|
||||
return false, fmt.Errorf("select %q: %w", sent, err)
|
||||
}
|
||||
uids, err := conn.SearchGmailThreadID(threadID)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("search thread %s in %q: %w", threadID, LabelSent, err)
|
||||
return false, fmt.Errorf("search thread %s in %q: %w", threadID, sent, err)
|
||||
}
|
||||
return len(uids) > 0, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user