aboutsummaryrefslogtreecommitdiffstats
path: root/worker/jmap/search.go
blob: 024cc18191c594738c26ab3f19a2100e9c3a7a14 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package jmap

import (
	"strings"

	"git.sr.ht/~rjarry/aerc/worker/types"
	"git.sr.ht/~rockorager/go-jmap"
	"git.sr.ht/~rockorager/go-jmap/mail/email"
	"git.sr.ht/~rockorager/go-jmap/mail/mailbox"
)

func (w *JMAPWorker) translateSearch(
	mbox jmap.ID, criteria *types.SearchCriteria,
) email.Filter {
	cond := new(email.FilterCondition)

	if mbox == "" {
		// all mail virtual folder: display all but trash and spam
		var mboxes []jmap.ID
		if id, ok := w.roles[mailbox.RoleJunk]; ok {
			mboxes = append(mboxes, id)
		}
		if id, ok := w.roles[mailbox.RoleTrash]; ok {
			mboxes = append(mboxes, id)
		}
		cond.InMailboxOtherThan = mboxes
	} else {
		cond.InMailbox = mbox
	}
	if criteria == nil {
		return cond
	}

	// dates
	if !criteria.StartDate.IsZero() {
		cond.After = &criteria.StartDate
	}
	if !criteria.EndDate.IsZero() {
		cond.Before = &criteria.EndDate
	}

	// general search terms
	terms := strings.Join(criteria.Terms, " ")
	switch {
	case criteria.SearchAll:
		cond.Text = terms
	case criteria.SearchBody:
		cond.Body = terms
	default:
		cond.Subject = terms
	}

	filter := &email.FilterOperator{Operator: jmap.OperatorAND}
	filter.Conditions = append(filter.Conditions, cond)

	// keywords/flags
	for kw := range flagsToKeywords(criteria.WithFlags) {
		filter.Conditions = append(filter.Conditions,
			&email.FilterCondition{HasKeyword: kw})
	}
	for kw := range flagsToKeywords(criteria.WithoutFlags) {
		filter.Conditions = append(filter.Conditions,
			&email.FilterCondition{NotKeyword: kw})
	}

	// recipients
	addrs := &email.FilterOperator{
		Operator: jmap.OperatorOR,
	}
	for _, from := range criteria.From {
		addrs.Conditions = append(addrs.Conditions,
			&email.FilterCondition{From: from})
	}
	for _, to := range criteria.To {
		addrs.Conditions = append(addrs.Conditions,
			&email.FilterCondition{To: to})
	}
	for _, cc := range criteria.Cc {
		addrs.Conditions = append(addrs.Conditions,
			&email.FilterCondition{Cc: cc})
	}
	if len(addrs.Conditions) > 0 {
		filter.Conditions = append(filter.Conditions, addrs)
	}

	// specific headers
	headers := &email.FilterOperator{
		Operator: jmap.OperatorAND,
	}
	for h, values := range criteria.Headers {
		for _, v := range values {
			headers.Conditions = append(headers.Conditions,
				&email.FilterCondition{Header: []string{h, v}})
		}
	}
	if len(headers.Conditions) > 0 {
		filter.Conditions = append(filter.Conditions, headers)
	}

	return filter
}