Files
LambdaMail/services/protocols/internal/application/port/conversations.go
T
Lucas RayanandClaude Sonnet 5.5 67d0c8aa5a feat(protocols): conversations - thread_id and in_reply_to written at delivery, list and read APIs
A reply now joins the conversation of the message it answers (Message-ID,
In-Reply-To, References), falling back to the subject for replies with no
headers. /mail/threads lists a folder as conversations and /mail/thread/{id}
returns one. Replying from the webmail flags the answered message.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:38:36 -03:00

69 lines
3.0 KiB
Go

package port
import (
"context"
"time"
)
// WebmailParticipant is someone who wrote in a conversation.
type WebmailParticipant struct {
Name string `json:"name"`
Address string `json:"address"`
// Me marks the mailbox owner, so the list can say "me" instead of a name
// the reader knows perfectly well.
Me bool `json:"me"`
}
// WebmailThread is one row of the conversation list: the newest message in the
// folder being looked at, with what the rest of the conversation adds.
type WebmailThread struct {
ThreadID string `json:"thread_id"`
UID uint32 `json:"uid"`
Subject string `json:"subject"`
SenderAddress string `json:"sender_address"`
FromName string `json:"from_display_name"`
Snippet string `json:"snippet"`
ReceivedAt time.Time `json:"received_at"`
HasAttachments bool `json:"has_attachments"`
MessageCount int `json:"message_count"`
UnseenCount int `json:"unseen_count"`
Seen bool `json:"seen"`
Flagged bool `json:"flagged"`
Answered bool `json:"answered"`
Participants []WebmailParticipant `json:"participants"`
}
// WebmailThreadMessage is one message inside a conversation.
type WebmailThreadMessage struct {
UID uint32 `json:"uid"`
Folder string `json:"folder"`
Subject string `json:"subject"`
SenderAddress string `json:"sender_address"`
FromName string `json:"from_display_name"`
Snippet string `json:"snippet"`
ReceivedAt time.Time `json:"received_at"`
HasAttachments bool `json:"has_attachments"`
Seen bool `json:"seen"`
Flagged bool `json:"flagged"`
// Answered is true when the mailbox owner replied, whether the \Answered
// flag was set or the reply is simply there in the conversation - a reply
// written in another mail program leaves no flag, only the message.
Answered bool `json:"answered"`
// Own marks a message the mailbox owner wrote.
Own bool `json:"own"`
}
// ConversationReader serves the conversation views.
type ConversationReader interface {
// ListThreads returns the conversations that have a message in the folder,
// newest first by that message.
ListThreads(ctx context.Context, mailboxID, folderName, search string, limit, offset int) ([]WebmailThread, error)
// ThreadMessages returns every message of one conversation, oldest first.
// folderName is the folder being viewed: a conversation's messages in Trash
// and Junk are left out unless that is the folder.
ThreadMessages(ctx context.Context, mailboxID, folderName, threadID string) ([]WebmailThreadMessage, error)
// MarkAnsweredByMessageID sets \Answered on the message a reply was written
// to, wherever in the mailbox it is filed.
MarkAnsweredByMessageID(ctx context.Context, mailboxID, messageID string) error
}