added IMAP, LetsEncrypt, update layout

This commit is contained in:
2026-08-12 21:14:19 +01:00
parent 6e103959b0
commit 70fa1a5f2c
222 changed files with 42947 additions and 14038 deletions
+54
View File
@@ -0,0 +1,54 @@
package mailstore
import "strings"
// FilterAction is the outcome of evaluating a mailbox's filter rules against one
// incoming message.
type FilterAction struct {
Folder string // non-empty: store here instead of INBOX
MarkRead bool
Drop bool // don't store at all
}
// ApplyRules evaluates a mailbox's filter rules in priority order and returns the
// first match's action (zero value if none match, meaning "store in INBOX, unread").
// headers should have "from"/"to"/"subject" keys — rules run at delivery time, before
// the message is encrypted and stored, so real header values are available, not just
// the plaintext cache columns used for fast IMAP listing.
func (s *Store) ApplyRules(mailboxID int64, headers map[string]string) (FilterAction, error) {
rules, err := s.DB.ListRulesForMailbox(mailboxID)
if err != nil {
return FilterAction{}, err
}
for _, r := range rules {
if !r.IsActive {
continue
}
if !matchCondition(r.ConditionOp, headers[r.ConditionField], r.ConditionValue) {
continue
}
switch r.Action {
case "move_to_folder":
return FilterAction{Folder: r.ActionValue}, nil
case "delete":
return FilterAction{Drop: true}, nil
case "mark_read":
return FilterAction{MarkRead: true}, nil
}
}
return FilterAction{}, nil
}
func matchCondition(op, value, target string) bool {
value = strings.ToLower(value)
target = strings.ToLower(target)
switch op {
case "contains":
return strings.Contains(value, target)
case "equals":
return value == target
case "starts_with":
return strings.HasPrefix(value, target)
}
return false
}