Added files.

This commit is contained in:
2025-12-08 06:42:29 +02:00
commit a65a31fdac
109 changed files with 16539 additions and 0 deletions

164
imapclient/status.go Normal file
View File

@@ -0,0 +1,164 @@
package imapclient
import (
"fmt"
"strings"
"github.com/emersion/go-imap/v2"
"github.com/emersion/go-imap/v2/internal/imapwire"
)
func statusItems(options *imap.StatusOptions) []string {
m := map[string]bool{
"MESSAGES": options.NumMessages,
"UIDNEXT": options.UIDNext,
"UIDVALIDITY": options.UIDValidity,
"UNSEEN": options.NumUnseen,
"DELETED": options.NumDeleted,
"SIZE": options.Size,
"APPENDLIMIT": options.AppendLimit,
"DELETED-STORAGE": options.DeletedStorage,
"HIGHESTMODSEQ": options.HighestModSeq,
}
var l []string
for k, req := range m {
if req {
l = append(l, k)
}
}
return l
}
// Status sends a STATUS command.
//
// A nil options pointer is equivalent to a zero options value.
func (c *Client) Status(mailbox string, options *imap.StatusOptions) *StatusCommand {
if options == nil {
options = new(imap.StatusOptions)
}
if options.NumRecent {
panic("StatusOptions.NumRecent is not supported in imapclient")
}
cmd := &StatusCommand{mailbox: mailbox}
enc := c.beginCommand("STATUS", cmd)
enc.SP().Mailbox(mailbox).SP()
items := statusItems(options)
enc.List(len(items), func(i int) {
enc.Atom(items[i])
})
enc.end()
return cmd
}
func (c *Client) handleStatus() error {
data, err := readStatus(c.dec)
if err != nil {
return fmt.Errorf("in status: %v", err)
}
cmd := c.findPendingCmdFunc(func(cmd command) bool {
switch cmd := cmd.(type) {
case *StatusCommand:
return cmd.mailbox == data.Mailbox
case *ListCommand:
return cmd.returnStatus && cmd.pendingData != nil && cmd.pendingData.Mailbox == data.Mailbox
default:
return false
}
})
switch cmd := cmd.(type) {
case *StatusCommand:
cmd.data = *data
case *ListCommand:
cmd.pendingData.Status = data
cmd.mailboxes <- cmd.pendingData
cmd.pendingData = nil
}
return nil
}
// StatusCommand is a STATUS command.
type StatusCommand struct {
commandBase
mailbox string
data imap.StatusData
}
func (cmd *StatusCommand) Wait() (*imap.StatusData, error) {
return &cmd.data, cmd.wait()
}
func readStatus(dec *imapwire.Decoder) (*imap.StatusData, error) {
var data imap.StatusData
if !dec.ExpectMailbox(&data.Mailbox) || !dec.ExpectSP() {
return nil, dec.Err()
}
err := dec.ExpectList(func() error {
if err := readStatusAttVal(dec, &data); err != nil {
return fmt.Errorf("in status-att-val: %v", dec.Err())
}
return nil
})
return &data, err
}
func readStatusAttVal(dec *imapwire.Decoder, data *imap.StatusData) error {
var name string
if !dec.ExpectAtom(&name) || !dec.ExpectSP() {
return dec.Err()
}
var ok bool
switch strings.ToUpper(name) {
case "MESSAGES":
var num uint32
ok = dec.ExpectNumber(&num)
data.NumMessages = &num
case "UIDNEXT":
var uidNext imap.UID
ok = dec.ExpectUID(&uidNext)
data.UIDNext = uidNext
case "UIDVALIDITY":
ok = dec.ExpectNumber(&data.UIDValidity)
case "UNSEEN":
var num uint32
ok = dec.ExpectNumber(&num)
data.NumUnseen = &num
case "DELETED":
var num uint32
ok = dec.ExpectNumber(&num)
data.NumDeleted = &num
case "SIZE":
var size int64
ok = dec.ExpectNumber64(&size)
data.Size = &size
case "APPENDLIMIT":
var num uint32
if dec.Number(&num) {
ok = true
} else {
ok = dec.ExpectNIL()
num = ^uint32(0)
}
data.AppendLimit = &num
case "DELETED-STORAGE":
var storage int64
ok = dec.ExpectNumber64(&storage)
data.DeletedStorage = &storage
case "HIGHESTMODSEQ":
ok = dec.ExpectModSeq(&data.HighestModSeq)
default:
if !dec.DiscardValue() {
return dec.Err()
}
}
if !ok {
return dec.Err()
}
return nil
}