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/emersion/go-smtp"
26	"github.com/foxcpp/maddy/framework/buffer"
27)
28
29// DeliveryTarget interface represents abstract storage for the message data
30// (typically persistent) or other kind of component that can be used as a
31// final destination for the message.
32//
33// Modules implementing this interface should be registered with "target."
34// prefix in name.
35type DeliveryTarget interface {
36	// Start starts the delivery of a new message.
37	//
38	// The domain part of the MAIL FROM address is assumed to be U-labels with
39	// NFC normalization and case-folding applied. The message source should
40	// ensure that by calling address.CleanDomain if necessary.
41	Start(ctx context.Context, msgMeta *MsgMetadata, mailFrom string) (Delivery, error)
42}
43
44type Delivery interface {
45	// AddRcpt adds the target address for the message.
46	//
47	// The domain part of the address is assumed to be U-labels with NFC normalization
48	// and case-folding applied. The message source should ensure that by
49	// calling address.CleanDomain if necessary.
50	//
51	// Implementation should assume that no case-folding or deduplication was
52	// done by caller code. Its implementation responsibility to do so if it is
53	// necessary. It is not recommended to reject duplicated recipients,
54	// however. They should be silently ignored.
55	//
56	// Implementation should do as much checks as possible here and reject
57	// recipients that can't be used.  Note: MsgMetadata object passed to Start
58	// contains BodyLength field. If it is non-zero, it can be used to check
59	// storage quota for the user before Body.
60	AddRcpt(ctx context.Context, rcptTo string, opts smtp.RcptOptions) error
61
62	// Body sets the body and header contents for the message.
63	// If this method fails, message is assumed to be undeliverable
64	// to all recipients.
65	//
66	// Implementation should avoid doing any persistent changes to the
67	// underlying storage until Commit is called. If that is not possible,
68	// Abort should (attempt to) rollback any such changes.
69	//
70	// If Body can't be implemented without per-recipient failures,
71	// then delivery object should also implement PartialDelivery interface
72	// for use by message sources that are able to make sense of per-recipient
73	// errors.
74	//
75	// Here is the example of possible implementation for maildir-based
76	// storage:
77	// Calling Body creates a file in tmp/ directory.
78	// Commit moves the created file to new/ directory.
79	// Abort removes the created file.
80	Body(ctx context.Context, header textproto.Header, body buffer.Buffer) error
81
82	// Abort cancels message delivery.
83	//
84	// All changes made to the underlying storage should be aborted at this
85	// point, if possible.
86	Abort(ctx context.Context) error
87
88	// Commit completes message delivery.
89	//
90	// It generally should never fail, since failures here jeopardize
91	// atomicity of the delivery if multiple targets are used.
92	Commit(ctx context.Context) error
93}