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 } // 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), } 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) } }