summaryrefslogtreecommitdiffstats
path: root/src/lib-lda/mail-deliver.h
blob: 5396a827774c8def33c19785c22fb31456443ac2 (plain)
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#ifndef MAIL_DELIVER_H
#define MAIL_DELIVER_H

#include "guid.h"
#include "mail-types.h"
#include "mail-error.h"
#include "smtp-params.h"

#include <sys/time.h>

struct smtp_address;
struct mail_storage;
struct mail_save_context;
struct mailbox;

enum mail_deliver_error {
	MAIL_DELIVER_ERROR_NONE = 0,

	/* Temporary error */
	MAIL_DELIVER_ERROR_TEMPORARY,
	/* Delivery rejected */
	MAIL_DELIVER_ERROR_REJECTED,
	/* Out of storage quota for mailbox or user */
	MAIL_DELIVER_ERROR_NOQUOTA,
	/* Internal error (BUG) */
	MAIL_DELIVER_ERROR_INTERNAL,
};

struct mail_deliver_session {
	pool_t pool;

	/* List of INBOX GUIDs where this mail has already been saved to */
	ARRAY(guid_128_t) inbox_guids;
};

struct mail_deliver_input {
	const struct lda_settings *set;
	const struct smtp_submit_settings *smtp_set;
	struct mail_deliver_session *session;
	struct event *event_parent;

	unsigned int session_time_msecs;
	struct timeval delivery_time_started;

	/* Session ID, used as log line prefix if non-NULL. */
	const char *session_id;
	/* Mail to save */
	struct mail *src_mail;

	/* Envelope sender, if known. */
	const struct smtp_address *mail_from;
	/* MAIL parameters */
	struct smtp_params_mail mail_params;

	/* Envelope recipient (final recipient) */
	const struct smtp_address *rcpt_to;
	/* RCPT parameters (can contain original recipient) */
	struct smtp_params_rcpt rcpt_params;
	/* Destination user */
	struct mail_user *rcpt_user;
	/* Mailbox where mail should be saved, unless e.g. Sieve does
	   something to it. */
	const char *rcpt_default_mailbox;

	bool save_dest_mail:1;
};

struct mail_deliver_fields {
	const char *message_id;
	const char *subject;
	const char *from;
	const char *from_envelope;
	const char *storage_id;

	uoff_t psize, vsize;

	bool filled:1;
};

struct mail_deliver_context {
	pool_t pool;
	const struct lda_settings *set;
	const struct smtp_submit_settings *smtp_set;
	struct mail_deliver_session *session;
	struct event *event;

	unsigned int session_time_msecs;
	struct timeval delivery_time_started;

	struct mail_duplicate_db *dup_db;

	/* Session ID, used as log line prefix if non-NULL. */
	const char *session_id;
	/* Mail to save */
	struct mail *src_mail;

	/* Envelope sender, if known. */
	const struct smtp_address *mail_from;
	/* MAIL parameters */
	struct smtp_params_mail mail_params;

	/* Envelope recipient (final recipient) */
	const struct smtp_address *rcpt_to;
	/* RCPT parameters (can contain original recipient) */
	struct smtp_params_rcpt rcpt_params;
	/* Destination user */
	struct mail_user *rcpt_user;
	/* Mailbox where mail should be saved, unless e.g. Sieve does
	   something to it. */
	const char *rcpt_default_mailbox;

	/* Filled with destination mail, if save_dest_mail=TRUE.
	   The caller must free the mail, its transaction and close
	   the mailbox. */
	struct mail *dest_mail;

	/* Recorded field values for the transaction */
	struct mail_deliver_fields fields;

	/* Error message for a temporary failure. This is necessary only when
	   there is no storage where to get the error message from. */
	const char *tempfail_error;

	bool tried_default_save;
	bool saved_mail;
	bool save_dest_mail;
	/* Delivery failed because user is out of quota / disk space */
	bool mailbox_full;
	/* Send DSN instead of MDN */
	bool dsn;
};

struct mail_deliver_save_open_context {
	struct mail_user *user;
	bool lda_mailbox_autocreate;
	bool lda_mailbox_autosubscribe;
};

typedef int deliver_mail_func_t(struct mail_deliver_context *ctx,
				struct mail_storage **storage_r);

extern deliver_mail_func_t *deliver_mail;

const struct var_expand_table *
mail_deliver_ctx_get_log_var_expand_table(struct mail_deliver_context *ctx,
					  const char *message);
void mail_deliver_log(struct mail_deliver_context *ctx, const char *fmt, ...)
	ATTR_FORMAT(2, 3);

const struct smtp_address *
mail_deliver_get_address(struct mail *mail, const char *header);
const struct smtp_address *
mail_deliver_get_return_address(struct mail_deliver_context *ctx);
const char *mail_deliver_get_new_message_id(struct mail_deliver_context *ctx);

struct mail_deliver_session *mail_deliver_session_init(void);
void mail_deliver_session_deinit(struct mail_deliver_session **session);

void mail_deliver_init(struct mail_deliver_context *ctx,
		       struct mail_deliver_input *input);
void mail_deliver_deinit(struct mail_deliver_context *ctx);

/* Try to open mailbox for saving. Returns 0 if ok, -1 if error. The box may
   be returned even with -1, and the caller must free it then. */
int mail_deliver_save_open(struct mail_deliver_save_open_context *ctx,
			   const char *name, struct mailbox **box_r,
			   enum mail_error *error_r, const char **error_str_r);
int mail_deliver_save(struct mail_deliver_context *ctx, const char *mailbox,
		      enum mail_flags flags, const char *const *keywords,
		      struct mail_storage **storage_r) ATTR_NULL(4);
void mail_deliver_deduplicate_guid_if_needed(struct mail_deliver_session *session,
					     struct mail_save_context *save_ctx);

int mail_deliver(struct mail_deliver_context *ctx,
		 enum mail_deliver_error *error_code_r,
		 const char **error_r);

/* Sets the deliver_mail hook and returns the previous hook,
   which the new_hook should call if it's non-NULL. */
deliver_mail_func_t *mail_deliver_hook_set(deliver_mail_func_t *new_hook);

/* Must be called before any storage is created. */
void mail_deliver_hooks_init(void);

#endif