maddy

Fork https://github.com/foxcpp/maddy

git clone git://git.lin.moe/go/maddy.git

 1/*
 2Maddy Mail Server - Composable all-in-one email server.
 3Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors
 4
 5This program is free software: you can redistribute it and/or modify
 6it under the terms of the GNU General Public License as published by
 7the Free Software Foundation, either version 3 of the License, or
 8(at your option) any later version.
 9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program.  If not, see <https://www.gnu.org/licenses/>.
17*/
18
19package imap_filter
20
21import (
22	"github.com/emersion/go-message/textproto"
23	"github.com/foxcpp/maddy/framework/buffer"
24	"github.com/foxcpp/maddy/framework/config"
25	modconfig "github.com/foxcpp/maddy/framework/config/module"
26	"github.com/foxcpp/maddy/framework/log"
27	"github.com/foxcpp/maddy/framework/module"
28)
29
30// Group wraps multiple modifiers and runs them serially.
31//
32// It is also registered as a module under 'modifiers' name and acts as a
33// module group.
34type Group struct {
35	instName string
36	Filters  []module.IMAPFilter
37	log      log.Logger
38}
39
40func NewGroup(_, instName string, _, _ []string) (module.Module, error) {
41	return &Group{
42		instName: instName,
43		log:      log.Logger{Name: "imap_filters", Debug: log.DefaultLogger.Debug},
44	}, nil
45}
46
47func (g *Group) IMAPFilter(accountName string, rcptTo string, meta *module.MsgMetadata, hdr textproto.Header, body buffer.Buffer) (folder string, flags []string, err error) {
48	if g == nil {
49		return "", nil, nil
50	}
51	var (
52		finalFolder string
53		finalFlags  = make([]string, 0, len(g.Filters))
54	)
55	for _, f := range g.Filters {
56		folder, flags, err := f.IMAPFilter(accountName, rcptTo, meta, hdr, body)
57		if err != nil {
58			g.log.Error("IMAP filter failed", err)
59			continue
60		}
61		if folder != "" && finalFolder == "" {
62			finalFolder = folder
63		}
64		finalFlags = append(finalFlags, flags...)
65	}
66	return finalFolder, finalFlags, nil
67}
68
69func (g *Group) Init(cfg *config.Map) error {
70	for _, node := range cfg.Block.Children {
71		mod, err := modconfig.IMAPFilter(cfg.Globals, append([]string{node.Name}, node.Args...), node)
72		if err != nil {
73			return err
74		}
75
76		g.Filters = append(g.Filters, mod)
77	}
78
79	return nil
80}
81
82func (g *Group) Name() string {
83	return "modifiers"
84}
85
86func (g *Group) InstanceName() string {
87	return g.instName
88}
89
90func init() {
91	module.Register("imap_filters", NewGroup)
92}