I've read over the go documentation as well as the general imap documentation but can't seem to find the correct way to get the status of a particular message - to know if it is marked as read or unread.
Here's what I've got so far:
//
//Code that set up 'c' and 'cmd' ...
//
for cmd.InProgress() {
// Wait for the next response (no timeout)
c.Recv(-1)
// Process command data
for _, rsp = range cmd.Data {
if err != nil {
fmt.Println(err)
}
header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"]) // Contains subject, from data
uid := imap.AsNumber(rsp.MessageInfo().Attrs["UID"]) // Message unique id
body := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.TEXT"]) // Message body
//seenState := imap.AsBytes(rsp.MessageInfo().Attrs["Flags"])
if msg, err := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
if err != nil {
fmt.Println(err)
}
//START CUSTOM
if strings.Contains(msg.Header.Get("Subject"), genUUID()){
fmt.Println(rsp.Label)
fmt.Println(rsp.MessageInfo().Attrs["Flags"])
fmt.Println(c.Status("INBOX", string(uid)))
}
//END CUSTOM
For output I get:
FETCH
<nil>
LAOYU10 STATUS "INBOX" (Þ) <nil>
The documentation that I've cited has led me to believe that at least one of my methods should be printing if the message is marked as unseen. What am I missing?
EDIT: I am testing against an inbox (gmail) with four messages. The first two are read and second two are unread. Here is the output for all four messages.
FETCH
<nil>
SIHLB7 STATUS "INBOX" (Û) <nil>
FETCH
<nil>
SIHLB8 STATUS "INBOX" (Ü) <nil>
FETCH
<nil>
SIHLB9 STATUS "INBOX" (Ý) <nil>
FETCH
<nil>
SIHLB10 STATUS "INBOX" (Þ) <nil>
A Couple things to note, make sure you're actually requesting the flags field in your imap request. If you're issuing a fetch, then you'll have to pass in "FLAGS"
as an argument to Fetch
, additionally, the flags attribute in Attrs
is case sensitive, so you'll need rsp.MessageInfo().Attrs["FLAGS"]
. Below is a working example of using imap in Gmail with the go-imap library, run it with GMAIL_EMAIL=email.address GMAIL_PASSWD=mypassword go run go_file.go
package main
import (
"code.google.com/p/go-imap/go1/imap"
"crypto/rand"
"crypto/tls"
"fmt"
"os"
"time"
)
func main() {
label := "INBOX"
email := os.Getenv("GMAIL_EMAIL")
passwd := os.Getenv("GMAIL_PASSWD")
conf := &tls.Config{
Rand: rand.Reader,
}
c, err := imap.DialTLS("imap.gmail.com:993", conf)
if err != nil {
panic("Failed to connect")
}
defer c.Logout(30 * time.Second)
c.Data = nil
if c.Caps["STARTTLS"] {
c.StartTLS(nil)
}
// Authenticate
if c.State() == imap.Login {
c.Login(email, passwd)
}
if c.State() != imap.Auth {
panic("Authentication error")
}
c.Select(label, true)
set, _ := imap.NewSeqSet("*")
cmd, err := c.Fetch(set, "FLAGS", "UID")
if err != nil {
panic("Bad fetch command")
}
_, err = cmd.Result(imap.OK)
if err != nil {
panic("Bad fetch response")
}
for _, rsp := range cmd.Data {
seen := false
for _, flag := range imap.AsList(rsp.MessageInfo().Attrs["FLAGS"]) {
if flag == "\\Seen" {
seen = true
}
}
if seen {
fmt.Printf("Message %d has been read!
", imap.AsNumber(rsp.MessageInfo().Attrs["UID"]))
} else {
fmt.Printf("Message %d has been not been read!
", imap.AsNumber(rsp.MessageInfo().Attrs["UID"]))
}
}
}
fmt.Println(rsp.MessageInfo().Attrs["Flags"])
That prints <nil>
for you because no flags are set, which means the message is "unseen".
Each message has a list of flags in IMAP, one of which is called \seen (case insensitive, as are most things in IMAP). If the flags list does not contain that flag, the message is unseen.
The answer from @jstedfast explains how to get the flags list. The rest is a matter of splitting at whitespace and checking whether any word in the list equals \seen.