如何获取 IMAP 消息的已读/未读状态

huangapple go评论73阅读模式
英文:

How to get seen/unseen status of IMAP message

问题

我已经阅读了go的文档以及一般的imap文档,但似乎找不到获取特定消息状态(已读或未读)的正确方法。

以下是我目前的代码:

// 
//设置'c'和'cmd'的代码...
//
for cmd.InProgress() {
    //等待下一个响应(无超时)
    c.Recv(-1)

    //处理命令数据
    for _, rsp = range cmd.Data {
        if err != nil {
            fmt.Println(err)
        }
        header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"])  // 包含主题和发件人数据
        uid := imap.AsNumber(rsp.MessageInfo().Attrs["UID"])  // 消息唯一标识符
        body := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.TEXT"])  // 消息正文
        //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>
英文:

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 &#39;c&#39; and &#39;cmd&#39; ...
//
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[&quot;RFC822.HEADER&quot;])  // Contains subject, from data
        uid := imap.AsNumber(rsp.MessageInfo().Attrs[&quot;UID&quot;])  // Message unique id
        body := imap.AsBytes(rsp.MessageInfo().Attrs[&quot;RFC822.TEXT&quot;])  // Message body
        //seenState := imap.AsBytes(rsp.MessageInfo().Attrs[&quot;Flags&quot;])
        if msg, err := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
            if err != nil {
                fmt.Println(err)
            }
            //START CUSTOM
            if strings.Contains(msg.Header.Get(&quot;Subject&quot;), genUUID()){
                fmt.Println(rsp.Label)
                fmt.Println(rsp.MessageInfo().Attrs[&quot;Flags&quot;])
                fmt.Println(c.Status(&quot;INBOX&quot;, string(uid)))
            }
            //END CUSTOM

For output I get:

FETCH
&lt;nil&gt;
LAOYU10 STATUS &quot;INBOX&quot; (&#222;) &lt;nil&gt;

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
&lt;nil&gt;
SIHLB7 STATUS &quot;INBOX&quot; (&#219;) &lt;nil&gt;
FETCH
&lt;nil&gt;
SIHLB8 STATUS &quot;INBOX&quot; (&#220;) &lt;nil&gt;
FETCH
&lt;nil&gt;
SIHLB9 STATUS &quot;INBOX&quot; (&#221;) &lt;nil&gt;
FETCH
&lt;nil&gt;
SIHLB10 STATUS &quot;INBOX&quot; (&#222;) &lt;nil&gt;

答案1

得分: 2

请注意,确保在您的 IMAP 请求中实际请求了 flags 字段。如果您发出的是 fetch 命令,则需要将 &quot;FLAGS&quot; 作为参数传递给 Fetch,另外,Attrs 中的 flags 属性是区分大小写的,所以您需要使用 rsp.MessageInfo().Attrs[&quot;FLAGS&quot;]。以下是在 Gmail 中使用 go-imap 库使用 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 not been read!\n", imap.AsNumber(rsp.MessageInfo().Attrs["UID"]))
		}
	}
}

希望对您有所帮助!

英文:

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 &quot;FLAGS&quot; as an argument to Fetch, additionally, the flags attribute in Attrs is case sensitive, so you'll need rsp.MessageInfo().Attrs[&quot;FLAGS&quot;]. 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 (
&quot;code.google.com/p/go-imap/go1/imap&quot;
&quot;crypto/rand&quot;
&quot;crypto/tls&quot;
&quot;fmt&quot;
&quot;os&quot;
&quot;time&quot;
)
func main() {
label := &quot;INBOX&quot;
email := os.Getenv(&quot;GMAIL_EMAIL&quot;)
passwd := os.Getenv(&quot;GMAIL_PASSWD&quot;)
conf := &amp;tls.Config{
Rand: rand.Reader,
}
c, err := imap.DialTLS(&quot;imap.gmail.com:993&quot;, conf)
if err != nil {
panic(&quot;Failed to connect&quot;)
}
defer c.Logout(30 * time.Second)
c.Data = nil
if c.Caps[&quot;STARTTLS&quot;] {
c.StartTLS(nil)
}
// Authenticate
if c.State() == imap.Login {
c.Login(email, passwd)
}
if c.State() != imap.Auth {
panic(&quot;Authentication error&quot;)
}
c.Select(label, true)
set, _ := imap.NewSeqSet(&quot;*&quot;)
cmd, err := c.Fetch(set, &quot;FLAGS&quot;, &quot;UID&quot;)
if err != nil {
panic(&quot;Bad fetch command&quot;)
}
_, err = cmd.Result(imap.OK)
if err != nil {
panic(&quot;Bad fetch response&quot;)
}
for _, rsp := range cmd.Data {
seen := false
for _, flag := range imap.AsList(rsp.MessageInfo().Attrs[&quot;FLAGS&quot;]) {
if flag == &quot;\\Seen&quot; {
seen = true
}
}
if seen {
fmt.Printf(&quot;Message %d has been read!\n&quot;, imap.AsNumber(rsp.MessageInfo().Attrs[&quot;UID&quot;]))
} else {
fmt.Printf(&quot;Message %d has been not been read!\n&quot;, imap.AsNumber(rsp.MessageInfo().Attrs[&quot;UID&quot;]))
}
}
}

答案2

得分: 1

这会打印出<nil>,因为没有设置任何标志,这意味着该消息是“未读”的。

英文:
fmt.Println(rsp.MessageInfo().Attrs[&quot;Flags&quot;])

That prints &lt;nil&gt; for you because no flags are set, which means the message is "unseen".

答案3

得分: 1

每个消息在IMAP中都有一个标志列表,其中之一被称为\seen(大小写不敏感,IMAP中的大多数内容都是如此)。如果标志列表不包含该标志,则该消息是未读的。

@jstedfast的答案解释了如何获取标志列表。其余的工作是在空格处进行拆分,并检查列表中的任何单词是否等于\seen。

英文:

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.

huangapple
  • 本文由 发表于 2015年9月24日 04:09:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/32748602.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定