Files
opencloud/vendor/github.com/emersion/go-imap/v2/imapclient/thread.go
Pascal Bleser 2b080a6c38 test(groupware): add testcontainers based jmap test
* adds pkg/jmap/jmap_integration_test.go

 * uses ghcr.io/stalwartlabs/stalwart:v0.13.2-alpine

 * can be disabled by setting one of the following environment
   variables, in the same fashion as ca0493b28
   - CI=woodpecker
   - CI_SYSTEM_NAME=woodpecker
   - USE_TESTCONTAINERS=false

 * dependencies:
   - bump github.com/go-test/deep from 1.1.0 to 1.1.1
   - add github.com/cention-sany/utf7
   - add github.com/dustinkirkland/golang-petname
   - add github.com/emersion/go-imap/v2
   - add github.com/emersion/go-message
   - add github.com/emersion/go-sasl
   - add github.com/go-crypt/crypt
   - add github.com/go-crypt/x
   - add github.com/gogs/chardet
   - add github.com/inbucket/html2text
   - add github.com/jhilleryerd/enmime/v2
   - add github.com/ssor/bom
   - add gopkg.in/loremipsum.v1
2026-06-11 15:01:36 +02:00

86 lines
1.9 KiB
Go

package imapclient
import (
"fmt"
"github.com/emersion/go-imap/v2"
"github.com/emersion/go-imap/v2/internal/imapwire"
)
// ThreadOptions contains options for the THREAD command.
type ThreadOptions struct {
Algorithm imap.ThreadAlgorithm
SearchCriteria *imap.SearchCriteria
}
func (c *Client) thread(numKind imapwire.NumKind, options *ThreadOptions) *ThreadCommand {
cmd := &ThreadCommand{}
enc := c.beginCommand(uidCmdName("THREAD", numKind), cmd)
enc.SP().Atom(string(options.Algorithm)).SP().Atom("UTF-8").SP()
writeSearchKey(enc.Encoder, options.SearchCriteria)
enc.end()
return cmd
}
// Thread sends a THREAD command.
//
// This command requires support for the THREAD extension.
func (c *Client) Thread(options *ThreadOptions) *ThreadCommand {
return c.thread(imapwire.NumKindSeq, options)
}
// UIDThread sends a UID THREAD command.
//
// See Thread.
func (c *Client) UIDThread(options *ThreadOptions) *ThreadCommand {
return c.thread(imapwire.NumKindUID, options)
}
func (c *Client) handleThread() error {
cmd := findPendingCmdByType[*ThreadCommand](c)
for c.dec.SP() {
data, err := readThreadList(c.dec)
if err != nil {
return fmt.Errorf("in thread-list: %v", err)
}
if cmd != nil {
cmd.data = append(cmd.data, *data)
}
}
return nil
}
// ThreadCommand is a THREAD command.
type ThreadCommand struct {
commandBase
data []ThreadData
}
func (cmd *ThreadCommand) Wait() ([]ThreadData, error) {
err := cmd.wait()
return cmd.data, err
}
type ThreadData struct {
Chain []uint32
SubThreads []ThreadData
}
func readThreadList(dec *imapwire.Decoder) (*ThreadData, error) {
var data ThreadData
err := dec.ExpectList(func() error {
var num uint32
if len(data.SubThreads) == 0 && dec.Number(&num) {
data.Chain = append(data.Chain, num)
} else {
sub, err := readThreadList(dec)
if err != nil {
return err
}
data.SubThreads = append(data.SubThreads, *sub)
}
return nil
})
return &data, err
}