如何获取 IMAP 邮件的 seen/unseen 状态
How to get seen/unseen status of IMAP message
我通读了 documentation as well as the general imap documentation 但似乎无法找到获取特定邮件状态的正确方法 - 了解它是标记为已读还是未读。
这是我目前得到的:
//
//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
对于输出我得到:
FETCH
<nil>
LAOYU10 STATUS "INBOX" (Þ) <nil>
我引用的文档使我相信,如果消息被标记为看不见,至少我的方法之一应该是打印。我错过了什么?
编辑:
我正在针对包含四封邮件的收件箱 (gmail) 进行测试。前两个已读,后两个未读。这是所有四条消息的输出。
FETCH
<nil>
SIHLB7 STATUS "INBOX" (Û) <nil>
FETCH
<nil>
SIHLB8 STATUS "INBOX" (Ü) <nil>
FETCH
<nil>
SIHLB9 STATUS "INBOX" (Ý) <nil>
FETCH
<nil>
SIHLB10 STATUS "INBOX" (Þ) <nil>
fmt.Println(rsp.MessageInfo().Attrs["Flags"])
为您打印 <nil>
因为没有设置标志,这意味着消息是 "unseen".
每封邮件在 IMAP 中都有一个标志列表,其中之一称为 \seen(不区分大小写,IMAP 中的大多数内容都是如此)。如果标志列表不包含该标志,则该消息是看不见的。
@jstedfast 的回答解释了如何获取标志列表。剩下的就是在空格处拆分并检查列表中的任何单词是否等于 \seen.
有几点需要注意,请确保您确实在 imap 请求中请求标志字段。如果你发出一个获取,那么你必须将 "FLAGS"
作为参数传递给 Fetch
,此外,Attrs
中的标志属性是区分大小写的,所以你会需要 rsp.MessageInfo().Attrs["FLAGS"]
。下面是一个在 Gmail 中使用 imap 和 go-imap 库的工作示例,运行 它与 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!\n", imap.AsNumber(rsp.MessageInfo().Attrs["UID"]))
} else {
fmt.Printf("Message %d has been not been read!\n", imap.AsNumber(rsp.MessageInfo().Attrs["UID"]))
}
}
}
我通读了 documentation as well as the general imap documentation 但似乎无法找到获取特定邮件状态的正确方法 - 了解它是标记为已读还是未读。
这是我目前得到的:
//
//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
对于输出我得到:
FETCH
<nil>
LAOYU10 STATUS "INBOX" (Þ) <nil>
我引用的文档使我相信,如果消息被标记为看不见,至少我的方法之一应该是打印。我错过了什么?
编辑: 我正在针对包含四封邮件的收件箱 (gmail) 进行测试。前两个已读,后两个未读。这是所有四条消息的输出。
FETCH
<nil>
SIHLB7 STATUS "INBOX" (Û) <nil>
FETCH
<nil>
SIHLB8 STATUS "INBOX" (Ü) <nil>
FETCH
<nil>
SIHLB9 STATUS "INBOX" (Ý) <nil>
FETCH
<nil>
SIHLB10 STATUS "INBOX" (Þ) <nil>
fmt.Println(rsp.MessageInfo().Attrs["Flags"])
为您打印 <nil>
因为没有设置标志,这意味着消息是 "unseen".
每封邮件在 IMAP 中都有一个标志列表,其中之一称为 \seen(不区分大小写,IMAP 中的大多数内容都是如此)。如果标志列表不包含该标志,则该消息是看不见的。
@jstedfast 的回答解释了如何获取标志列表。剩下的就是在空格处拆分并检查列表中的任何单词是否等于 \seen.
有几点需要注意,请确保您确实在 imap 请求中请求标志字段。如果你发出一个获取,那么你必须将 "FLAGS"
作为参数传递给 Fetch
,此外,Attrs
中的标志属性是区分大小写的,所以你会需要 rsp.MessageInfo().Attrs["FLAGS"]
。下面是一个在 Gmail 中使用 imap 和 go-imap 库的工作示例,运行 它与 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!\n", imap.AsNumber(rsp.MessageInfo().Attrs["UID"]))
} else {
fmt.Printf("Message %d has been not been read!\n", imap.AsNumber(rsp.MessageInfo().Attrs["UID"]))
}
}
}