2025-01-24 11:26:48 +07:00
|
|
|
// 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"
|
|
|
|
)
|
|
|
|
|
|
|
|
// MessageDetails holds the details of an email message.
|
|
|
|
// This struct allows the caller to access and format the message's
|
|
|
|
// ID, sender information, subject, and body as needed.
|
|
|
|
type MessageDetails struct {
|
|
|
|
ID string
|
|
|
|
From []string
|
|
|
|
Subject string
|
|
|
|
Body string
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListMessages lists the messages in the specified mailbox based on the MessageConfig
|
|
|
|
func (c *IMAPClient) ListMessages(mailbox string, numMessages uint32, config MessageConfig) ([]MessageDetails, 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 []MessageDetails
|
|
|
|
for msg := range messages {
|
|
|
|
details := MessageDetails{}
|
|
|
|
|
|
|
|
if config.GrabID {
|
|
|
|
details.ID = msg.Envelope.MessageId
|
|
|
|
}
|
|
|
|
if config.GrabFrom {
|
|
|
|
for _, addr := range msg.Envelope.From {
|
|
|
|
details.From = append(details.From, addr.Address())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if config.GrabSubject {
|
|
|
|
details.Subject = msg.Envelope.Subject
|
|
|
|
}
|
|
|
|
if config.GrabBody {
|
|
|
|
for _, literal := range msg.Body {
|
|
|
|
buf := bytebufferpool.Get()
|
2025-01-24 05:18:55 +00:00
|
|
|
if _, err := buf.ReadFrom(literal); err == nil {
|
2025-01-24 11:26:48 +07:00
|
|
|
details.Body = buf.String()
|
|
|
|
}
|
2025-01-24 05:18:55 +00:00
|
|
|
buf.Reset() // Reset the buffer before returning it to the pool.
|
|
|
|
bytebufferpool.Put(buf)
|
2025-01-24 11:26:48 +07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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) ([]MessageDetails, 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)
|
|
|
|
}
|