mail2couch/go/mail/imap.go

147 lines
3.4 KiB
Go
Raw Normal View History

package mail
import (
"fmt"
"log"
"time"
"github.com/emersion/go-imap/v2/imapclient"
"mail2couch/config"
)
// ImapClient wraps the IMAP client
type ImapClient struct {
*imapclient.Client
}
// Message represents an email message retrieved from IMAP
type Message struct {
UID uint32
From []string
To []string
Subject string
Date time.Time
Body string
Headers map[string][]string
Attachments []Attachment
}
// Attachment represents an email attachment
type Attachment struct {
Filename string
ContentType string
Content []byte
}
// NewImapClient creates a new IMAP client from the configuration
func NewImapClient(source *config.MailSource) (*ImapClient, error) {
addr := fmt.Sprintf("%s:%d", source.Host, source.Port)
client, err := imapclient.DialTLS(addr, nil)
if err != nil {
return nil, fmt.Errorf("failed to dial IMAP server: %w", err)
}
if err := client.Login(source.User, source.Password).Wait(); err != nil {
return nil, fmt.Errorf("failed to login: %w", err)
}
return &ImapClient{client}, nil
}
// ListMailboxes lists all available mailboxes
func (c *ImapClient) ListMailboxes() ([]string, error) {
var mailboxes []string
cmd := c.List("", "*", nil)
infos, err := cmd.Collect()
if err != nil {
return nil, err
}
for _, info := range infos {
mailboxes = append(mailboxes, info.Mailbox)
}
return mailboxes, nil
}
// GetMessages retrieves messages from a specific mailbox (simplified version)
func (c *ImapClient) GetMessages(mailbox string, since *time.Time) ([]*Message, error) {
// Select the mailbox
mbox, err := c.Select(mailbox, nil).Wait()
if err != nil {
return nil, fmt.Errorf("failed to select mailbox %s: %w", mailbox, err)
}
if mbox.NumMessages == 0 {
return []*Message{}, nil
}
// For now, just return placeholder messages to test the flow
var messages []*Message
numToFetch := mbox.NumMessages
if numToFetch > 5 {
numToFetch = 5 // Limit to 5 messages for testing
}
for i := uint32(1); i <= numToFetch; i++ {
msg := &Message{
UID: i,
From: []string{"test@example.com"},
To: []string{"user@example.com"},
Subject: fmt.Sprintf("Message %d from %s", i, mailbox),
Date: time.Now(),
Body: fmt.Sprintf("This is a placeholder message %d from mailbox %s", i, mailbox),
Headers: make(map[string][]string),
}
// Add a sample attachment for testing (every 3rd message)
if i%3 == 0 {
msg.Attachments = []Attachment{
{
Filename: fmt.Sprintf("sample_%d.txt", i),
ContentType: "text/plain",
Content: []byte(fmt.Sprintf("Sample attachment content for message %d", i)),
},
}
}
messages = append(messages, msg)
}
return messages, nil
}
// ShouldProcessMailbox checks if a mailbox should be processed based on filters
func (c *ImapClient) ShouldProcessMailbox(mailbox string, filter *config.FolderFilter) bool {
// If include list is specified, mailbox must be in it
if len(filter.Include) > 0 {
found := false
for _, included := range filter.Include {
if mailbox == included {
found = true
break
}
}
if !found {
return false
}
}
// If exclude list is specified, mailbox must not be in it
for _, excluded := range filter.Exclude {
if mailbox == excluded {
return false
}
}
return true
}
// Logout logs the client out
func (c *ImapClient) Logout() {
if err := c.Client.Logout(); err != nil {
log.Printf("Failed to logout: %v", err)
}
}