I am trying to do a search for specific sender or specific flag. When I select Inbox and do a search on specific string the search api freezes. I am not sure what am I doing wrong. I am not able to find much examples too.
criteria := imap.NewSearchCriteria()
criteria.WithoutFlags = []string{"\\Seen"}
uids, err := c.Search(criteria)
if err != nil {
log.Println(err)
}
seqset := new(imap.SeqSet)
seqset.AddNum(uids...)
section := &imap.BodySectionName{}
items := []imap.FetchItem{imap.FetchEnvelope, imap.FetchFlags, imap.FetchInternalDate, section.FetchItem()}
messages := make(chan *imap.Message)
go func() {
done <- c.Fetch(seqset, items, messages)
}()
msg := <-messages //its getting stuck at this point. Nothing happens i dont get messages.
When your search can return more than one message, you need to make sure to read everything from the messages
channel, otherwise the program will hang. So instead of:
msg := <-messages
loop over the channel like so:
for msg := range messages {
// process msg
}
Here's my working sample, which pulls connection details from the environment. It's a modified version of the example from emersion's imap lib:
package main
import (
"crypto/tls"
"flag"
"fmt"
"log"
"os"
"time"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
)
func main() {
hours := flag.Int("hours", 24, "look this many hours in the past for messages")
flag.Parse()
if *hours > 0 {
*hours = *hours * -1
}
host := os.Getenv("IMAP_HOST")
port := os.Getenv("IMAP_PORT")
user := os.Getenv("IMAP_USER")
pass := os.Getenv("IMAP_PASS")
tlsn := os.Getenv("IMAP_TLS_SERVERNAME")
if port == "" {
port = "993"
}
connStr := fmt.Sprintf("%s:%s", host, port)
tlsc := &tls.Config{}
if tlsn != "" {
tlsc.ServerName = tlsn
}
c, err := client.DialTLS(connStr, tlsc)
if err != nil {
log.Fatal(err)
}
log.Println("Connected")
defer c.Logout()
if err := c.Login(user, pass); err != nil {
log.Fatal(err)
}
log.Println("Authenticated")
mbox, err := c.Select("INBOX", false)
if err != nil {
log.Fatal(err)
}
log.Println("Flags for INBOX:", mbox.Flags)
criteria := imap.NewSearchCriteria()
//criteria.WithFlags = []string{imap.SeenFlag}
criteria.Since = time.Now().Add(time.Duration(*hours) * time.Hour)
uids, err := c.Search(criteria)
if err != nil {
log.Println(err)
}
seqset := new(imap.SeqSet)
seqset.AddNum(uids...)
log.Printf("Search complete, found %d messages", len(uids))
section := &imap.BodySectionName{}
items := []imap.FetchItem{imap.FetchEnvelope, imap.FetchFlags, imap.FetchInternalDate, section.FetchItem()}
messages := make(chan *imap.Message)
done := make(chan error, 1)
go func() {
done <- c.Fetch(seqset, items, messages)
log.Println("Fetch complete")
}()
for msg := range messages {
if msg != nil {
log.Printf("got message with address %p\n", msg)
} else {
log.Println("no messages matched criteria")
}
}
if err := <-done; err != nil {
log.Fatal(err)
}
}