Golang IMAP:在两个不同的文件夹中移动邮件导致 "The specified message set is invalid"
Golang IMAP: Move mails in two different folders results in "The specified message set is invalid"
用例:我们有一个邮箱,我们在其中接收来自客户的邮件。在进一步处理之前,我必须检查它们是否符合协议(主题必须匹配正则表达式,每封邮件只有一个附件等)
我有以下应用程序:
import (
"fmt"
"imaptest/src/db"
"io"
"log"
"path/filepath"
"strings"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
"github.com/emersion/go-message"
"github.com/iglin/go-config"
)
(...)
//Channel for the messages
messages := make(chan *imap.Message, 10)
//Channel for retrieve if an error appeared
done := make(chan error, 1)
go func() {
seqset := new(imap.SeqSet)
seqset.AddRange(1, mbox.Messages)
//Fetch the messages and push them into the channel
done <- c.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope, imap.FetchRFC822}, messages)
}()
//SeqSet for invalid messages
seqsetErrorMessages := new(imap.SeqSet)
//SeqSet for valid messages
seqsetValidMessages := new(imap.SeqSet)
for msg := range messages {
//Different checks like are there attachments
//Matches the subject with a specific regex
if isMessageValid(msg) {
//Message is valid
seqsetValidMessages.AddNum(msg.SeqNum)
} else {
//Message is invalid
seqsetErrorMessages.AddNum(msg.SeqNum)
}
}
//Check if there was an error when fetching the messages
if err := <-done; err != nil {
log.Fatal(err)
}
//Move all invalid messages to error
if !seqsetErrorMessages.Empty() {
if err := c.Move(seqsetErrorMessages, FOLDER_ERROR); err != nil {
log.Fatalf("Error on move to %s: %v", FOLDER_ERROR, err)
}
}
//Move all valid messages to toExport
if !seqsetValidMessages.Empty() {
if err := c.Move(seqsetValidMessages, FOLDER_OUT); err != nil {
log.Fatalf("Error on move to %s: %v", FOLDER_OUT, err)
}
}
FOLDER_OUT 和 FOLDER_ERROR 是此邮箱中现有文件夹的常量字符串。
在源文件夹的所有邮件都有效(或无效)的情况下,一切都是
很好,所有邮件都已移动。
但是如果我遇到同时存在有效邮件和无效邮件的情况,我会收到以下错误:
Error on move to error: The specified message set is invalid.
我还尝试使用“msg.Uid”和“c.UidMove()”代替“msg.Seqnum”和“c.Move()”,但这会导致同样的结果。
如何解决?
此处使用 UID 是正确答案,但请确保您有 UID。 “1,4,9”作为 MSN 集和 UID 集均有效,但两者不可互换。您不能从服务器请求 MSN 集,然后将其与 UID 命令一起使用。
如果邮箱中正好有两封邮件,并且您想将第一封邮件移至 FOLDER_ERROR,将第二封邮件移至 FOLDER_OUT,那么您看到的问题就很容易解释了。您发送一条命令“将邮箱中的第一条消息移至 FOLDER_ERROR”,服务器会执行此操作。然后你发送“将邮箱中的第二条消息移至FOLDER_OUT”,服务器告诉你“此邮箱中只有一条消息,是没有我可以发送的第二条消息可能会移动。
使用 UID 可以解决这个问题,因为它们很稳定。无论您移动其他哪些邮件,邮件都会保留其 UID。
用例:我们有一个邮箱,我们在其中接收来自客户的邮件。在进一步处理之前,我必须检查它们是否符合协议(主题必须匹配正则表达式,每封邮件只有一个附件等) 我有以下应用程序:
import (
"fmt"
"imaptest/src/db"
"io"
"log"
"path/filepath"
"strings"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
"github.com/emersion/go-message"
"github.com/iglin/go-config"
)
(...)
//Channel for the messages
messages := make(chan *imap.Message, 10)
//Channel for retrieve if an error appeared
done := make(chan error, 1)
go func() {
seqset := new(imap.SeqSet)
seqset.AddRange(1, mbox.Messages)
//Fetch the messages and push them into the channel
done <- c.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope, imap.FetchRFC822}, messages)
}()
//SeqSet for invalid messages
seqsetErrorMessages := new(imap.SeqSet)
//SeqSet for valid messages
seqsetValidMessages := new(imap.SeqSet)
for msg := range messages {
//Different checks like are there attachments
//Matches the subject with a specific regex
if isMessageValid(msg) {
//Message is valid
seqsetValidMessages.AddNum(msg.SeqNum)
} else {
//Message is invalid
seqsetErrorMessages.AddNum(msg.SeqNum)
}
}
//Check if there was an error when fetching the messages
if err := <-done; err != nil {
log.Fatal(err)
}
//Move all invalid messages to error
if !seqsetErrorMessages.Empty() {
if err := c.Move(seqsetErrorMessages, FOLDER_ERROR); err != nil {
log.Fatalf("Error on move to %s: %v", FOLDER_ERROR, err)
}
}
//Move all valid messages to toExport
if !seqsetValidMessages.Empty() {
if err := c.Move(seqsetValidMessages, FOLDER_OUT); err != nil {
log.Fatalf("Error on move to %s: %v", FOLDER_OUT, err)
}
}
FOLDER_OUT 和 FOLDER_ERROR 是此邮箱中现有文件夹的常量字符串。
在源文件夹的所有邮件都有效(或无效)的情况下,一切都是 很好,所有邮件都已移动。
但是如果我遇到同时存在有效邮件和无效邮件的情况,我会收到以下错误:
Error on move to error: The specified message set is invalid.
我还尝试使用“msg.Uid”和“c.UidMove()”代替“msg.Seqnum”和“c.Move()”,但这会导致同样的结果。
如何解决?
此处使用 UID 是正确答案,但请确保您有 UID。 “1,4,9”作为 MSN 集和 UID 集均有效,但两者不可互换。您不能从服务器请求 MSN 集,然后将其与 UID 命令一起使用。
如果邮箱中正好有两封邮件,并且您想将第一封邮件移至 FOLDER_ERROR,将第二封邮件移至 FOLDER_OUT,那么您看到的问题就很容易解释了。您发送一条命令“将邮箱中的第一条消息移至 FOLDER_ERROR”,服务器会执行此操作。然后你发送“将邮箱中的第二条消息移至FOLDER_OUT”,服务器告诉你“此邮箱中只有一条消息,是没有我可以发送的第二条消息可能会移动。
使用 UID 可以解决这个问题,因为它们很稳定。无论您移动其他哪些邮件,邮件都会保留其 UID。