mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 12:46:46 +00:00
Unseen is first sequence number of unseen message not count of messages
This commit is contained in:
@ -15,7 +15,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
// Code generated by ./release-notes.sh at Mon Apr 6 08:14:14 CEST 2020. DO NOT EDIT.
|
||||
// Code generated by ./release-notes.sh at Mon Apr 6 10:56:36 CEST 2020. DO NOT EDIT.
|
||||
|
||||
package bridge
|
||||
|
||||
|
||||
@ -125,11 +125,12 @@ func (im *imapMailbox) Status(items []imap.StatusItem) (*imap.MailboxStatus, err
|
||||
message.ThunderbirdNonJunkFlag,
|
||||
}
|
||||
|
||||
dbTotal, dbUnread, err := im.storeMailbox.GetCounts()
|
||||
l.Debugln("DB: total", dbTotal, "unread", dbUnread, "err", err)
|
||||
dbTotal, dbUnread, dbUnreadSeqNum, err := im.storeMailbox.GetCounts()
|
||||
l.Debugln("DB: total", dbTotal, "unread", dbUnread, "unreadSeqNum", dbUnreadSeqNum, "err", err)
|
||||
if err == nil {
|
||||
status.Messages = uint32(dbTotal)
|
||||
status.Unseen = uint32(dbUnread)
|
||||
status.UnseenSeqNum = uint32(dbUnreadSeqNum)
|
||||
}
|
||||
|
||||
if status.UidNext, err = im.storeMailbox.GetNextUID(); err != nil {
|
||||
|
||||
@ -68,7 +68,7 @@ type storeMailboxProvider interface {
|
||||
GetAPIIDsFromSequenceRange(start, stop uint32) ([]string, error)
|
||||
GetLatestAPIID() (string, error)
|
||||
GetNextUID() (uint32, error)
|
||||
GetCounts() (dbTotal, dbUnread uint, err error)
|
||||
GetCounts() (dbTotal, dbUnread, dbUnreadSeqNum uint, err error)
|
||||
GetUIDList(apiIDs []string) *uidplus.OrderedSeq
|
||||
GetUIDByHeader(header *mail.Header) uint32
|
||||
GetDelimiter() string
|
||||
|
||||
@ -76,18 +76,20 @@ func (store *Store) imapDeleteMessage(address, mailboxName string, sequenceNumbe
|
||||
store.imapSendUpdate(update)
|
||||
}
|
||||
|
||||
func (store *Store) imapMailboxStatus(address, mailboxName string, total, unread uint) {
|
||||
func (store *Store) imapMailboxStatus(address, mailboxName string, total, unread, unreadSeqNum uint) {
|
||||
store.log.WithFields(logrus.Fields{
|
||||
"address": address,
|
||||
"mailbox": mailboxName,
|
||||
"total": total,
|
||||
"unread": unread,
|
||||
"address": address,
|
||||
"mailbox": mailboxName,
|
||||
"total": total,
|
||||
"unread": unread,
|
||||
"unreadSeqNum": unreadSeqNum,
|
||||
}).Trace("IDLE status")
|
||||
update := new(imapBackend.MailboxUpdate)
|
||||
update.Update = imapBackend.NewUpdate(address, mailboxName)
|
||||
update.MailboxStatus = imap.NewMailboxStatus(mailboxName, []imap.StatusItem{imap.StatusMessages, imap.StatusUnseen})
|
||||
update.MailboxStatus.Messages = uint32(total)
|
||||
update.MailboxStatus.Unseen = uint32(unread)
|
||||
update.MailboxStatus.UnseenSeqNum = uint32(unreadSeqNum)
|
||||
store.imapSendUpdate(update)
|
||||
}
|
||||
|
||||
|
||||
@ -105,8 +105,8 @@ func checkMessageUpdate(username, mailbox string, seqNum, uid int) func(interfac
|
||||
return func(update interface{}) bool {
|
||||
switch u := update.(type) {
|
||||
case *imapBackend.MessageUpdate:
|
||||
return (u.Update.Username == username &&
|
||||
u.Update.Mailbox == mailbox &&
|
||||
return (u.Update.Username() == username &&
|
||||
u.Update.Mailbox() == mailbox &&
|
||||
u.Message.SeqNum == uint32(seqNum) &&
|
||||
u.Message.Uid == uint32(uid))
|
||||
default:
|
||||
@ -119,8 +119,8 @@ func checkMessageDelete(username, mailbox string, seqNum int) func(interface{})
|
||||
return func(update interface{}) bool {
|
||||
switch u := update.(type) {
|
||||
case *imapBackend.ExpungeUpdate:
|
||||
return (u.Update.Username == username &&
|
||||
u.Update.Mailbox == mailbox &&
|
||||
return (u.Update.Username() == username &&
|
||||
u.Update.Mailbox() == mailbox &&
|
||||
u.SeqNum == uint32(seqNum))
|
||||
default:
|
||||
return false
|
||||
|
||||
@ -81,7 +81,7 @@ func syncDraftsIfNecssary(tx *bolt.Tx, mb *Mailbox) { //nolint[funlen]
|
||||
|
||||
// If the drafts mailbox total is non-zero, it means it has already been used
|
||||
// and there is no need to continue. Otherwise, we may need to do an initial sync.
|
||||
total, _, err := mb.txGetCounts(tx)
|
||||
total, _, _, err := mb.txGetCounts(tx)
|
||||
if err != nil || total != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
@ -28,15 +28,15 @@ import (
|
||||
)
|
||||
|
||||
// GetCounts returns numbers of total and unread messages in this mailbox bucket.
|
||||
func (storeMailbox *Mailbox) GetCounts() (total, unread uint, err error) {
|
||||
func (storeMailbox *Mailbox) GetCounts() (total, unread, unseenSeqNum uint, err error) {
|
||||
err = storeMailbox.db().View(func(tx *bolt.Tx) error {
|
||||
total, unread, err = storeMailbox.txGetCounts(tx)
|
||||
total, unread, unseenSeqNum, err = storeMailbox.txGetCounts(tx)
|
||||
return err
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (storeMailbox *Mailbox) txGetCounts(tx *bolt.Tx) (total, unread uint, err error) {
|
||||
func (storeMailbox *Mailbox) txGetCounts(tx *bolt.Tx) (total, unread, unseenSeqNum uint, err error) {
|
||||
// For total it would be enough to use `bolt.Bucket.Stats().KeyN` but
|
||||
// we also need to retrieve the count of unread emails therefore we are
|
||||
// looping all messages in this mailbox by `bolt.Cursor`
|
||||
@ -48,16 +48,19 @@ func (storeMailbox *Mailbox) txGetCounts(tx *bolt.Tx) (total, unread uint, err e
|
||||
total++
|
||||
rawMsg := metaBucket.Get(apiID)
|
||||
if rawMsg == nil {
|
||||
return 0, 0, ErrNoSuchAPIID
|
||||
return 0, 0, 0, ErrNoSuchAPIID
|
||||
}
|
||||
// Do not unmarshal whole JSON to speed up the looping.
|
||||
// Instead, we assume it will contain JSON int field `Unread`
|
||||
// where `1` means true (i.e. message is unread)
|
||||
if bytes.Contains(rawMsg, []byte(`"Unread":1`)) {
|
||||
if unseenSeqNum == 0 {
|
||||
unseenSeqNum = total
|
||||
}
|
||||
unread++
|
||||
}
|
||||
}
|
||||
return total, unread, err
|
||||
return total, unread, unseenSeqNum, err
|
||||
}
|
||||
|
||||
type mailboxCounts struct {
|
||||
|
||||
@ -376,7 +376,7 @@ func (storeMailbox *Mailbox) txDeleteMessage(tx *bolt.Tx, apiID string) error {
|
||||
}
|
||||
|
||||
func (storeMailbox *Mailbox) txMailboxStatusUpdate(tx *bolt.Tx) error {
|
||||
total, unread, err := storeMailbox.txGetCounts(tx)
|
||||
total, unread, unreadSeqNum, err := storeMailbox.txGetCounts(tx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot get counts for mailbox status update")
|
||||
}
|
||||
@ -385,6 +385,7 @@ func (storeMailbox *Mailbox) txMailboxStatusUpdate(tx *bolt.Tx) error {
|
||||
storeMailbox.labelName,
|
||||
total,
|
||||
unread,
|
||||
unreadSeqNum,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ func (store *Store) isSynced(countsOnAPI []*pmapi.MessagesCount) (bool, error) {
|
||||
)
|
||||
}
|
||||
|
||||
mboxTot, mboxUnread, err := mbox.GetCounts()
|
||||
mboxTot, mboxUnread, _, err := mbox.GetCounts()
|
||||
if err != nil {
|
||||
errW := errors.Wrap(err, "cannot count messages")
|
||||
store.log.
|
||||
|
||||
@ -10,6 +10,9 @@ Feature: IMAP get mailbox info
|
||||
Scenario: Mailbox info contains mailbox name
|
||||
When IMAP client gets info of "INBOX"
|
||||
Then IMAP response contains "2 EXISTS"
|
||||
And IMAP response contains "UNSEEN 1"
|
||||
# Messages are inserted in opposite way to keep increasing UID.
|
||||
# Sequence numbers are then opposite than listed above.
|
||||
# Unseen should have first unseen message.
|
||||
And IMAP response contains "UNSEEN 2"
|
||||
And IMAP response contains "UIDNEXT 3"
|
||||
And IMAP response contains "UIDVALIDITY"
|
||||
|
||||
@ -93,7 +93,7 @@ func mailboxForAddressOfUserHasNumberOfMessages(mailboxName, bddAddressID, bddUs
|
||||
start := time.Now()
|
||||
for {
|
||||
afterLimit := time.Since(start) > ctx.EventLoopTimeout()
|
||||
total, _, _ := mailbox.GetCounts()
|
||||
total, _, _, _ := mailbox.GetCounts()
|
||||
if total == uint(countOfMessages) {
|
||||
break
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user