imap/client/list_messages.go

105 lines
2.7 KiB
Go
Raw Normal View History

// Copyright (c) 2025 H0llyW00dzZ All rights reserved.
//
// By accessing or using this software, you agree to be bound by the terms
// of the License Agreement, which you can find at LICENSE files.
package client
import (
"fmt"
"github.com/emersion/go-imap"
"github.com/valyala/bytebufferpool"
)
const (
// KeyID is the key for the message ID
KeyID = "id"
// KeyFrom is the key for the sender's address
KeyFrom = "from"
// KeySubject is the key for the message subject
KeySubject = "subject"
// KeyBody is the key for the message body
KeyBody = "body"
)
// ListMessages lists the messages in the specified mailbox based on the MessageConfig
func (c *IMAPClient) ListMessages(mailbox string, numMessages uint32, config MessageConfig) ([]map[string]any, error) {
if c.client == nil {
return nil, fmt.Errorf("client is not connected")
}
mbox, err := c.client.Select(mailbox, false)
if err != nil {
return nil, fmt.Errorf("failed to select %s: %v", mailbox, err)
}
from := uint32(1)
to := mbox.Messages
if mbox.Messages > numMessages {
from = mbox.Messages - numMessages + 1
}
seqset := new(imap.SeqSet)
seqset.AddRange(from, to)
items := []imap.FetchItem{imap.FetchEnvelope}
if config.GrabBody {
items = append(items, imap.FetchItem("BODY.PEEK[]"))
}
messages := make(chan *imap.Message, numMessages)
done := make(chan error, 1)
go func() {
done <- c.client.Fetch(seqset, items, messages)
}()
var results []map[string]any
for msg := range messages {
details := make(map[string]any)
if config.GrabID && msg.Envelope.MessageId != "" {
details[KeyID] = msg.Envelope.MessageId
}
if config.GrabFrom {
var from []string
for _, addr := range msg.Envelope.From {
from = append(from, addr.Address())
}
details[KeyFrom] = from
}
if config.GrabSubject && msg.Envelope.Subject != "" {
details[KeySubject] = msg.Envelope.Subject
}
if config.GrabBody {
for _, literal := range msg.Body {
buf := bytebufferpool.Get()
if _, err := buf.ReadFrom(literal); err == nil {
details[KeyBody] = buf.String()
}
buf.Reset() // Reset the buffer before returning it to the pool.
bytebufferpool.Put(buf)
}
}
results = append(results, details)
}
if err := <-done; err != nil {
return nil, fmt.Errorf("failed to fetch messages: %v", err)
}
return results, nil
}
// ListUserMessages lists messages for a specific user based on the MessageConfig
func (m *MultiUserIMAP) ListUserMessages(username, mailbox string, numMessages uint32, config MessageConfig) ([]map[string]any, error) {
m.mu.Lock()
defer m.mu.Unlock()
client, exists := m.clients[username]
if !exists {
return nil, fmt.Errorf("user not found: %s", username)
}
return client.ListMessages(mailbox, numMessages, config)
}