Correctly handle LISTMESSAGES and STATUS commands using SeqNum instead of UID

This commit is contained in:
2018-06-28 00:00:44 +01:00
parent 22f6eeacd7
commit 3e5ab5bb0a
5 changed files with 106 additions and 23 deletions

View File

@@ -45,15 +45,9 @@ func (m *Mailbox) Info() (*imap.MailboxInfo, error) {
// This function does not affect the state of any messages in the mailbox. See
// RFC 3501 section 6.3.10 for a list of items that can be requested.
func (m *Mailbox) Status(items []string) (*imap.MailboxStatus, error) {
log.Printf("Mailbox(%v).Status(%#v)", m.stored.Rel(), items)
return &imap.MailboxStatus{
Name: m.Name(),
Flags: []string{}, // FIXME: what do we need here?
PermanentFlags: []string{}, // FIXME: what do we need here?
//UnseenSeqNum: 0, // FIXME: what do we need here? What even is a seqnum?
Messages: 1, // FIXME: hardcoded
}, nil
status, err := m.buildStatus(items...)
log.Printf("Mailbox(%v).Status(%#v): %#v %#v", m.stored.Rel(), items, status, err)
return status, err
}
// SetSubscribed adds or removes the mailbox to the server's set of "active"
@@ -85,7 +79,7 @@ func (m *Mailbox) ListMessages(uid bool, seqset *imap.SeqSet, items []string, ch
var messages []store.Message
for _, set := range seqset.Set {
msgs, err := m.session.store.FindMessagesInRange(
msgs, err := m.session.store.FindMessagesInRangeBySeqNum(
m.stored, uint64(set.Start), uint64(set.Stop),
)
@@ -119,14 +113,13 @@ func (m *Mailbox) ListMessages(uid bool, seqset *imap.SeqSet, items []string, ch
body := map[*imap.BodySectionName]imap.Literal{}
imapMsg := imap.NewMessage(uint32(message.UID), items)
if err := fillItems(imapMsg, message); err != nil {
imapMsg := imap.NewMessage(uint32(message.SeqNum), items)
if err := m.fillMessageItems(imapMsg, message); err != nil {
return err
}
imapMsg.Envelope = envelope
imapMsg.Body = body
imapMsg.Uid = uint32(message.UID)
imapMsg.Size = uint32(message.Len())
log.Printf(" Sending message %#v", imapMsg)
@@ -137,14 +130,50 @@ func (m *Mailbox) ListMessages(uid bool, seqset *imap.SeqSet, items []string, ch
return nil
}
func fillItems(imapMsg *imap.Message, msg store.Message) error {
func (m *Mailbox) buildStatus(items ...string) (*imap.MailboxStatus, error) {
out := &imap.MailboxStatus{
Name: m.Name(),
}
for _, item := range items {
switch item {
case "FLAGS": // TODO: ???
out.Flags = []string{}
case "PERMANENTFLAGS": // TODO: ???
out.PermanentFlags = []string{}
// The number of messages in the mailbox.
case "MESSAGES":
out.Messages = uint32(m.session.store.CountMessages(m.stored))
// The number of messages with the \Recent flag set. TODO
case "RECENT":
// The next unique identifier value of the mailbox.
case "UIDNEXT":
out.UidNext = uint32(m.stored.NextUID())
// The unique identifier validity value of the mailbox
case "UIDVALIDITY":
out.UidValidity = uint32(m.stored.UIDValidity())
// The number of messages which do not have the \Seen flag set. TODO
case "UNSEEN":
default:
return nil, fmt.Errorf("Unknown status item: %v", item)
}
}
return out, nil
}
func (m *Mailbox) fillMessageItems(imapMsg *imap.Message, msg store.Message) error {
// FIXME: do I have to fill Items as well as the individual fields? Unclear
for k, _ := range imapMsg.Items {
switch k {
case "UID":
imapMsg.Items[k] = msg.UID
imapMsg.Uid = uint32(msg.UID)
imapMsg.Items[k] = uint32(msg.UID)
case "FLAGS":
imapMsg.Flags = []string{}
imapMsg.Items[k] = []string{}
case "RFC822.SIZE":
imapMsg.Size = uint32(msg.Len())
imapMsg.Items[k] = uint32(msg.Len())
case "RFC822.HEADER":
str, err := msg.HeaderString()
@@ -154,7 +183,7 @@ func fillItems(imapMsg *imap.Message, msg store.Message) error {
imapMsg.Items[k] = str
default:
return fmt.Errorf("Unknown item: %v", k)
return fmt.Errorf("Unknown message item: %v", k)
}
}