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 module
20
21import (
22	"context"
23
24	"github.com/emersion/go-message/textproto"
25	"github.com/foxcpp/maddy/framework/buffer"
26)
27
28// Modifier is the module interface for modules that can mutate the
29// processed message or its meta-data.
30//
31// Currently, the message body can't be mutated for efficiency and
32// correctness reasons: It would require "rebuffering" (see buffer.Buffer doc),
33// can invalidate assertions made on the body contents before modification and
34// will break DKIM signatures.
35//
36// Only message header can be modified. Furthermore, it is highly discouraged for
37// modifiers to remove or change existing fields to prevent issues outlined
38// above.
39//
40// Calls on ModifierState are always strictly ordered.
41// RewriteRcpt is newer called before RewriteSender and RewriteBody is never called
42// before RewriteRcpts. This allows modificator code to save values
43// passed to previous calls for use in later operations.
44//
45// Modules implementing this interface should be registered with "modify." prefix in name.
46type Modifier interface {
47	// ModStateForMsg initializes modifier "internal" state
48	// required for processing of the message.
49	ModStateForMsg(ctx context.Context, msgMeta *MsgMetadata) (ModifierState, error)
50}
51
52type ModifierState interface {
53	// RewriteSender allows modifier to replace MAIL FROM value.
54	// If no changes are required, this method returns its
55	// argument, otherwise it returns a new value.
56	//
57	// Note that per-source/per-destination modifiers are executed
58	// after routing decision is made so changed value will have no
59	// effect on it.
60	//
61	// Also note that MsgMeta.OriginalFrom will still contain the original value
62	// for purposes of tracing. It should not be modified by this method.
63	RewriteSender(ctx context.Context, mailFrom string) (string, error)
64
65	// RewriteRcpt replaces RCPT TO value.
66	// If no changed are required, this method returns its argument as slice,
67	// otherwise it returns a slice with 1 or more new values.
68	//
69	// MsgPipeline will take of populating MsgMeta.OriginalRcpts. RewriteRcpt
70	// doesn't do it.
71	RewriteRcpt(ctx context.Context, rcptTo string) ([]string, error)
72
73	// RewriteBody modifies passed Header argument and may optionally
74	// inspect the passed body buffer to make a decision on new header field values.
75	//
76	// There is no way to modify the body and RewriteBody should avoid
77	// removing existing header fields and changing their values.
78	RewriteBody(ctx context.Context, h *textproto.Header, body buffer.Buffer) error
79
80	// Close is called after the message processing ends, even if any of the
81	// Rewrite* functions return an error.
82	Close() error
83}