package email import ( "fmt" "io" "log" "net/mail" "strings" "github.com/emersion/go-imap" "github.com/emersion/go-imap/client" ) func FetchEmails() ([]Email, error) { config, err := NewConfigFromEnv() if err != nil { return nil, err } imapClient, err := config.ConnectToServer(IMAP_SERVICE) if err != nil { return nil, err } defer imapClient.Logout() return fetchEmails(imapClient) } func concatAddresses(addresses []*imap.Address) string { result := []string{} for _, address := range addresses { if len(address.PersonalName) > 0 { result = append(result, fmt.Sprintf("%s <%s>", address.PersonalName, address.Address())) } else { result = append(result, address.Address()) } } return strings.Join(result, "; ") } func fetchEmails(imapClient *client.Client) ([]Email, error) { result := []Email{} // Select the mailbox you want to read _, err := imapClient.Select("INBOX", false) if err != nil { return nil, err } criteria := imap.NewSearchCriteria() criteria.WithoutFlags = []string{imap.SeenFlag} uids, err := imapClient.Search(criteria) if err != nil { log.Printf("Search error: %s\n", err) } if len(uids) > 0 { // Define the range of emails to fetch seqSet := new(imap.SeqSet) seqSet.AddNum(uids...) // Fetch the required message attributes messages := make(chan *imap.Message, 10) fetchErr := make(chan error, 1) section := &imap.BodySectionName{} items := []imap.FetchItem{section.FetchItem(), imap.FetchEnvelope} go func() { fetchErr <- imapClient.Fetch(seqSet, items, messages) }() // Drain the channel on early return so the goroutine can always exit. defer func() { for range messages { } }() for msg := range messages { if len(msg.Envelope.From) == 0 { continue } toAddress := concatAddresses(msg.Envelope.To) fromAddress := msg.Envelope.From[0].Address() r := msg.GetBody(section) if r == nil { return result, fmt.Errorf("server didn't returned message body") } m, err := mail.ReadMessage(r) if err != nil { return result, err } body, err := io.ReadAll(m.Body) email := NewEmail( []string{toAddress}, []string{}, fromAddress, msg.Envelope.Subject, string(body), ) result = append(result, *email) } if err := <-fetchErr; err != nil { return result, fmt.Errorf("fetch error: %w", err) } } return result, nil }