1 /* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
2
3 #include "lib.h"
4 #include "ioloop.h"
5 #include "array.h"
6 #include "str.h"
7 #include "str-sanitize.h"
8 #include "time-util.h"
9 #include "unichar.h"
10 #include "var-expand.h"
11 #include "message-address.h"
12 #include "smtp-address.h"
13 #include "lda-settings.h"
14 #include "mail-storage.h"
15 #include "mail-namespace.h"
16 #include "mail-storage-private.h"
17 #include "mail-duplicate.h"
18 #include "mail-deliver.h"
19
20 #define DUPLICATE_DB_NAME "lda-dupes"
21
22 #define MAIL_DELIVER_USER_CONTEXT(obj) \
23 MODULE_CONTEXT_REQUIRE(obj, mail_deliver_user_module)
24 #define MAIL_DELIVER_STORAGE_CONTEXT(obj) \
25 MODULE_CONTEXT_REQUIRE(obj, mail_deliver_storage_module)
26
27 struct event_category event_category_mail_delivery = {
28 .name = "local-delivery",
29 };
30
31 struct mail_deliver_user {
32 union mail_user_module_context module_ctx;
33 struct mail_deliver_context *deliver_ctx;
34 bool want_storage_id;
35 };
36
37 deliver_mail_func_t *deliver_mail = NULL;
38
39 struct mail_deliver_mailbox {
40 union mailbox_module_context module_ctx;
41 };
42
43 struct mail_deliver_transaction {
44 union mailbox_transaction_module_context module_ctx;
45
46 struct mail_deliver_fields deliver_fields;
47 };
48
49 static const char *lda_log_wanted_headers[] = {
50 "From", "Message-ID", "Subject",
51 NULL
52 };
53 static enum mail_fetch_field lda_log_wanted_fetch_fields =
54 MAIL_FETCH_PHYSICAL_SIZE | MAIL_FETCH_VIRTUAL_SIZE;
55 static MODULE_CONTEXT_DEFINE_INIT(mail_deliver_user_module,
56 &mail_user_module_register);
57 static MODULE_CONTEXT_DEFINE_INIT(mail_deliver_storage_module,
58 &mail_storage_module_register);
59
60 static struct message_address *
mail_deliver_get_message_address(struct mail * mail,const char * header)61 mail_deliver_get_message_address(struct mail *mail, const char *header)
62 {
63 struct message_address *addr;
64 const char *str;
65
66 if (mail_get_first_header(mail, header, &str) <= 0)
67 return NULL;
68 addr = message_address_parse(pool_datastack_create(),
69 (const unsigned char *)str,
70 strlen(str), 1, 0);
71 if (addr == NULL || addr->mailbox == NULL || addr->domain == NULL ||
72 *addr->mailbox == '\0' || *addr->domain == '\0')
73 return NULL;
74 return addr;
75 }
76
77 const struct smtp_address *
mail_deliver_get_address(struct mail * mail,const char * header)78 mail_deliver_get_address(struct mail *mail, const char *header)
79 {
80 struct message_address *addr;
81 struct smtp_address *smtp_addr;
82
83 addr = mail_deliver_get_message_address(mail, header);
84 if (addr == NULL ||
85 smtp_address_create_from_msg_temp(addr, &smtp_addr) < 0)
86 return NULL;
87 return smtp_addr;
88 }
89
90 static void
mail_deliver_update_event(struct mail_deliver_context * ctx)91 mail_deliver_update_event(struct mail_deliver_context *ctx)
92 {
93 event_add_str(ctx->event, "message_id", ctx->fields.message_id);
94 event_add_str(ctx->event, "message_subject", ctx->fields.subject);
95 event_add_str(ctx->event, "message_from", ctx->fields.from);
96 if (ctx->fields.psize != UOFF_T_MAX)
97 event_add_int(ctx->event, "message_size", ctx->fields.psize);
98 if (ctx->fields.vsize != UOFF_T_MAX)
99 event_add_int(ctx->event, "message_vsize", ctx->fields.vsize);
100 }
101
102 static void
update_str_field(pool_t pool,const char ** old_str,const char * new_str)103 update_str_field(pool_t pool, const char **old_str, const char *new_str)
104 {
105 if (new_str == NULL || new_str[0] == '\0')
106 *old_str = NULL;
107 else if (*old_str == NULL || strcmp(*old_str, new_str) != 0)
108 *old_str = p_strdup(pool, new_str);
109 }
110
111 static void
mail_deliver_fields_update(struct mail_deliver_fields * fields,pool_t pool,struct mail * mail)112 mail_deliver_fields_update(struct mail_deliver_fields *fields, pool_t pool,
113 struct mail *mail)
114 {
115 const char *message_id = NULL, *subject = NULL, *from_envelope = NULL;
116 static struct message_address *from_addr;
117 const char *from;
118
119 if (fields->filled)
120 return;
121 fields->filled = TRUE;
122
123 if (mail_get_message_id(mail, &message_id) > 0)
124 message_id = str_sanitize(message_id, 200);
125 update_str_field(pool, &fields->message_id, message_id);
126
127 if (mail_get_first_header_utf8(mail, "Subject", &subject) > 0)
128 subject = str_sanitize(subject, 80);
129 update_str_field(pool, &fields->subject, subject);
130
131 from_addr = mail_deliver_get_message_address(mail, "From");
132 from = (from_addr == NULL ? NULL :
133 t_strconcat(from_addr->mailbox, "@", from_addr->domain, NULL));
134 update_str_field(pool, &fields->from, from);
135
136 if (mail_get_special(mail, MAIL_FETCH_FROM_ENVELOPE, &from_envelope) > 0)
137 from_envelope = str_sanitize(from_envelope, 80);
138 update_str_field(pool, &fields->from_envelope, from_envelope);
139
140 if (mail_get_physical_size(mail, &fields->psize) < 0)
141 fields->psize = 0;
142 if (mail_get_virtual_size(mail, &fields->vsize) < 0)
143 fields->vsize = 0;
144 }
145
146 const struct var_expand_table *
mail_deliver_ctx_get_log_var_expand_table(struct mail_deliver_context * ctx,const char * message)147 mail_deliver_ctx_get_log_var_expand_table(struct mail_deliver_context *ctx,
148 const char *message)
149 {
150 unsigned int delivery_time_msecs;
151
152 /* If a mail was saved/copied, the fields are already filled and the
153 following call is ignored. Otherwise, only the source mail exists. */
154 mail_deliver_fields_update(&ctx->fields, ctx->pool, ctx->src_mail);
155 /* This call finishes a mail delivery. With Sieve there may be multiple
156 mail deliveries. */
157 ctx->fields.filled = FALSE;
158
159 mail_deliver_update_event(ctx);
160
161 io_loop_time_refresh();
162 delivery_time_msecs = timeval_diff_msecs(&ioloop_timeval,
163 &ctx->delivery_time_started);
164
165 const struct var_expand_table stack_tab[] = {
166 { '$', message, NULL },
167 { 'm', ctx->fields.message_id != NULL ?
168 ctx->fields.message_id : "unspecified", "msgid" },
169 { 's', ctx->fields.subject, "subject" },
170 { 'f', ctx->fields.from, "from" },
171 { 'e', ctx->fields.from_envelope, "from_envelope" },
172 { 'p', dec2str(ctx->fields.psize), "size" },
173 { 'w', dec2str(ctx->fields.vsize), "vsize" },
174 { '\0', dec2str(delivery_time_msecs), "delivery_time" },
175 { '\0', dec2str(ctx->session_time_msecs), "session_time" },
176 { '\0', smtp_address_encode(ctx->rcpt_params.orcpt.addr), "to_envelope" },
177 { '\0', ctx->fields.storage_id, "storage_id" },
178 { '\0', NULL, NULL }
179 };
180 return p_memdup(unsafe_data_stack_pool, stack_tab, sizeof(stack_tab));
181 }
182
mail_deliver_log(struct mail_deliver_context * ctx,const char * fmt,...)183 void mail_deliver_log(struct mail_deliver_context *ctx, const char *fmt, ...)
184 {
185 va_list args;
186 string_t *str;
187 const struct var_expand_table *tab;
188 const char *msg, *error;
189
190 if (*ctx->set->deliver_log_format == '\0')
191 return;
192
193 va_start(args, fmt);
194 msg = t_strdup_vprintf(fmt, args);
195
196 str = t_str_new(256);
197 tab = mail_deliver_ctx_get_log_var_expand_table(ctx, msg);
198 if (var_expand(str, ctx->set->deliver_log_format, tab, &error) <= 0) {
199 e_error(ctx->event,
200 "Failed to expand deliver_log_format=%s: %s",
201 ctx->set->deliver_log_format, error);
202 }
203
204 e_info(ctx->event, "%s", str_c(str));
205 va_end(args);
206 }
207
mail_deliver_session_init(void)208 struct mail_deliver_session *mail_deliver_session_init(void)
209 {
210 struct mail_deliver_session *session;
211 pool_t pool;
212
213 pool = pool_alloconly_create("mail deliver session", 1024);
214 session = p_new(pool, struct mail_deliver_session, 1);
215 session->pool = pool;
216 return session;
217 }
218
mail_deliver_session_deinit(struct mail_deliver_session ** _session)219 void mail_deliver_session_deinit(struct mail_deliver_session **_session)
220 {
221 struct mail_deliver_session *session = *_session;
222
223 *_session = NULL;
224 pool_unref(&session->pool);
225 }
226
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)227 int mail_deliver_save_open(struct mail_deliver_save_open_context *ctx,
228 const char *name, struct mailbox **box_r,
229 enum mail_error *error_r, const char **error_str_r)
230 {
231 struct mailbox *box;
232 enum mailbox_flags flags = MAILBOX_FLAG_POST_SESSION;
233
234 *box_r = NULL;
235 *error_r = MAIL_ERROR_NONE;
236 *error_str_r = NULL;
237
238 if (!uni_utf8_str_is_valid(name)) {
239 *error_str_r = "Mailbox name not valid UTF-8";
240 *error_r = MAIL_ERROR_PARAMS;
241 return -1;
242 }
243
244 if (ctx->lda_mailbox_autocreate)
245 flags |= MAILBOX_FLAG_AUTO_CREATE;
246 if (ctx->lda_mailbox_autosubscribe)
247 flags |= MAILBOX_FLAG_AUTO_SUBSCRIBE;
248 *box_r = box = mailbox_alloc_for_user(ctx->user, name, flags);
249
250 if (mailbox_open(box) == 0)
251 return 0;
252 *error_str_r = mailbox_get_last_internal_error(box, error_r);
253 return -1;
254 }
255
mail_deliver_check_duplicate(struct mail_deliver_session * session,struct mailbox * box)256 static bool mail_deliver_check_duplicate(struct mail_deliver_session *session,
257 struct mailbox *box)
258 {
259 struct mailbox_metadata metadata;
260 const guid_128_t *guid;
261
262 if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0) {
263 /* just play it safe and assume a duplicate */
264 return TRUE;
265 }
266
267 /* there shouldn't be all that many recipients,
268 so just do a linear search */
269 if (!array_is_created(&session->inbox_guids))
270 p_array_init(&session->inbox_guids, session->pool, 8);
271 array_foreach(&session->inbox_guids, guid) {
272 if (memcmp(metadata.guid, *guid, sizeof(metadata.guid)) == 0)
273 return TRUE;
274 }
275 array_push_back(&session->inbox_guids, &metadata.guid);
276 return FALSE;
277 }
278
mail_deliver_deduplicate_guid_if_needed(struct mail_deliver_session * session,struct mail_save_context * save_ctx)279 void mail_deliver_deduplicate_guid_if_needed(struct mail_deliver_session *session,
280 struct mail_save_context *save_ctx)
281 {
282 struct mailbox_transaction_context *trans =
283 mailbox_save_get_transaction(save_ctx);
284 struct mailbox *box = mailbox_transaction_get_mailbox(trans);
285 guid_128_t guid;
286
287 if (strcmp(mailbox_get_name(box), "INBOX") != 0)
288 return;
289
290 /* avoid storing duplicate GUIDs to delivered mails to INBOX. this
291 happens if mail is delivered to same user multiple times within a
292 session. the problem with this is that if GUIDs are used as POP3
293 UIDLs, some clients can't handle the duplicates well. */
294 if (mail_deliver_check_duplicate(session, box)) {
295 guid_128_generate(guid);
296 mailbox_save_set_guid(save_ctx, guid_128_to_string(guid));
297 }
298 }
299
mail_deliver_init(struct mail_deliver_context * ctx,struct mail_deliver_input * input)300 void mail_deliver_init(struct mail_deliver_context *ctx,
301 struct mail_deliver_input *input)
302 {
303 i_zero(ctx);
304 ctx->set = input->set;
305 ctx->smtp_set = input->smtp_set;
306
307 ctx->session = input->session;
308 ctx->pool = input->session->pool;
309 pool_ref(ctx->pool);
310
311 ctx->session_time_msecs = input->session_time_msecs;
312 ctx->delivery_time_started = input->delivery_time_started;
313 ctx->session_id = p_strdup(ctx->pool, input->session_id);
314 ctx->src_mail = input->src_mail;
315 ctx->save_dest_mail = input->save_dest_mail;
316
317 ctx->mail_from = smtp_address_clone(ctx->pool, input->mail_from);
318 smtp_params_mail_copy(ctx->pool, &ctx->mail_params,
319 &input->mail_params);
320 ctx->rcpt_to = smtp_address_clone(ctx->pool, input->rcpt_to);
321 smtp_params_rcpt_copy(ctx->pool, &ctx->rcpt_params,
322 &input->rcpt_params);
323 ctx->rcpt_user = input->rcpt_user;
324 ctx->rcpt_default_mailbox = p_strdup(ctx->pool,
325 input->rcpt_default_mailbox);
326
327 ctx->event = event_create(input->event_parent);
328 event_add_category(ctx->event, &event_category_mail_delivery);
329
330 mail_deliver_fields_update(&ctx->fields, ctx->pool, ctx->src_mail);
331 mail_deliver_update_event(ctx);
332
333 if (ctx->rcpt_to != NULL) {
334 event_add_str(ctx->event, "rcpt_to",
335 smtp_address_encode(ctx->rcpt_to));
336 }
337 smtp_params_rcpt_add_to_event(&ctx->rcpt_params, ctx->event);
338 }
339
mail_deliver_deinit(struct mail_deliver_context * ctx)340 void mail_deliver_deinit(struct mail_deliver_context *ctx)
341 {
342 event_unref(&ctx->event);
343 pool_unref(&ctx->pool);
344 }
345
346 static struct mail *
mail_deliver_open_mail(struct mailbox * box,uint32_t uid,enum mail_fetch_field wanted_fields,struct mailbox_transaction_context ** trans_r)347 mail_deliver_open_mail(struct mailbox *box, uint32_t uid,
348 enum mail_fetch_field wanted_fields,
349 struct mailbox_transaction_context **trans_r)
350 {
351 struct mailbox_transaction_context *t;
352 struct mail *mail;
353
354 *trans_r = NULL;
355
356 if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FAST) < 0)
357 return NULL;
358
359 t = mailbox_transaction_begin(box, 0, __func__);
360 mail = mail_alloc(t, wanted_fields, NULL);
361
362 if (!mail_set_uid(mail, uid)) {
363 mail_free(&mail);
364 mailbox_transaction_rollback(&t);
365 }
366 *trans_r = t;
367 return mail;
368 }
369
mail_deliver_save(struct mail_deliver_context * ctx,const char * mailbox,enum mail_flags flags,const char * const * keywords,struct mail_storage ** storage_r)370 int mail_deliver_save(struct mail_deliver_context *ctx, const char *mailbox,
371 enum mail_flags flags, const char *const *keywords,
372 struct mail_storage **storage_r)
373 {
374 struct mail_deliver_save_open_context open_ctx;
375 struct mailbox *box;
376 enum mailbox_transaction_flags trans_flags;
377 struct mailbox_transaction_context *t;
378 struct mail_save_context *save_ctx;
379 struct mailbox_header_lookup_ctx *headers_ctx;
380 struct mail_keywords *kw;
381 struct mail *dest_mail;
382 enum mail_error error;
383 const char *mailbox_name, *errstr, *guid;
384 struct mail_transaction_commit_changes changes;
385 bool default_save;
386 int ret = 0;
387
388 i_assert(ctx->dest_mail == NULL);
389
390 default_save = strcmp(mailbox, ctx->rcpt_default_mailbox) == 0;
391 if (default_save)
392 ctx->tried_default_save = TRUE;
393
394 i_zero(&open_ctx);
395 open_ctx.user = ctx->rcpt_user;
396 open_ctx.lda_mailbox_autocreate = ctx->set->lda_mailbox_autocreate;
397 open_ctx.lda_mailbox_autosubscribe = ctx->set->lda_mailbox_autosubscribe;
398
399 mailbox_name = str_sanitize(mailbox, 80);
400 if (mail_deliver_save_open(&open_ctx, mailbox, &box,
401 &error, &errstr) < 0) {
402 if (box != NULL) {
403 *storage_r = mailbox_get_storage(box);
404 mailbox_free(&box);
405 }
406 mail_deliver_log(ctx, "save failed to open mailbox %s: %s",
407 mailbox_name, errstr);
408 return -1;
409 }
410 *storage_r = mailbox_get_storage(box);
411
412 trans_flags = MAILBOX_TRANSACTION_FLAG_EXTERNAL;
413 if (ctx->save_dest_mail)
414 trans_flags |= MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS;
415 t = mailbox_transaction_begin(box, trans_flags, __func__);
416
417 kw = str_array_length(keywords) == 0 ? NULL :
418 mailbox_keywords_create_valid(box, keywords);
419 save_ctx = mailbox_save_alloc(t);
420 if (ctx->mail_from != NULL) {
421 mailbox_save_set_from_envelope(save_ctx,
422 smtp_address_encode(ctx->mail_from));
423 }
424 mailbox_save_set_flags(save_ctx, flags, kw);
425
426 headers_ctx = mailbox_header_lookup_init(box, lda_log_wanted_headers);
427 dest_mail = mailbox_save_get_dest_mail(save_ctx);
428 mail_add_temp_wanted_fields(dest_mail, lda_log_wanted_fetch_fields, NULL);
429 mailbox_header_lookup_unref(&headers_ctx);
430 mail_deliver_deduplicate_guid_if_needed(ctx->session, save_ctx);
431
432 if (mailbox_save_using_mail(&save_ctx, ctx->src_mail) < 0)
433 ret = -1;
434 if (kw != NULL)
435 mailbox_keywords_unref(&kw);
436
437 if (ret < 0)
438 mailbox_transaction_rollback(&t);
439 else
440 ret = mailbox_transaction_commit_get_changes(&t, &changes);
441
442 if (ret == 0) {
443 ctx->saved_mail = TRUE;
444 if (ctx->save_dest_mail) {
445 /* copying needs the message body. with maildir we also
446 need to get the GUID in case the message gets
447 expunged. get these early so the copying won't fail
448 later on. */
449 i_assert(array_count(&changes.saved_uids) == 1);
450 const struct seq_range *range =
451 array_front(&changes.saved_uids);
452 i_assert(range->seq1 == range->seq2);
453 ctx->dest_mail = mail_deliver_open_mail(box, range->seq1,
454 MAIL_FETCH_STREAM_BODY | MAIL_FETCH_GUID, &t);
455 if (ctx->dest_mail == NULL) {
456 i_assert(t == NULL);
457 } else if (mail_get_special(ctx->dest_mail, MAIL_FETCH_GUID, &guid) < 0) {
458 mail_free(&ctx->dest_mail);
459 mailbox_transaction_rollback(&t);
460 }
461 }
462 mail_deliver_log(ctx, "saved mail to %s", mailbox_name);
463 pool_unref(&changes.pool);
464 } else {
465 mail_deliver_log(ctx, "save failed to %s: %s", mailbox_name,
466 mail_storage_get_last_internal_error(*storage_r, &error));
467 }
468
469 if (ctx->dest_mail == NULL)
470 mailbox_free(&box);
471 return ret;
472 }
473
474 const struct smtp_address *
mail_deliver_get_return_address(struct mail_deliver_context * ctx)475 mail_deliver_get_return_address(struct mail_deliver_context *ctx)
476 {
477 struct message_address *addr;
478 struct smtp_address *smtp_addr;
479 const char *path;
480 int ret;
481
482 if (!smtp_address_isnull(ctx->mail_from))
483 return ctx->mail_from;
484
485 if ((ret=mail_get_first_header(ctx->src_mail,
486 "Return-Path", &path)) <= 0) {
487 if (ret < 0) {
488 struct mailbox *box = ctx->src_mail->box;
489 e_warning(ctx->event,
490 "Failed read return-path header: %s",
491 mailbox_get_last_internal_error(box, NULL));
492 }
493 return NULL;
494 }
495 if (message_address_parse_path(pool_datastack_create(),
496 (const unsigned char *)path,
497 strlen(path), &addr) < 0 ||
498 smtp_address_create_from_msg(ctx->pool, addr, &smtp_addr) < 0) {
499 e_warning(ctx->event, "Failed to parse return-path header");
500 return NULL;
501 }
502 return smtp_addr;
503 }
504
mail_deliver_get_new_message_id(struct mail_deliver_context * ctx)505 const char *mail_deliver_get_new_message_id(struct mail_deliver_context *ctx)
506 {
507 static int count = 0;
508 struct mail_user *user = ctx->rcpt_user;
509 const struct mail_storage_settings *mail_set =
510 mail_user_set_get_storage_set(user);
511
512 return t_strdup_printf("<dovecot-%s-%s-%d@%s>",
513 dec2str(ioloop_timeval.tv_sec),
514 dec2str(ioloop_timeval.tv_usec),
515 count++, mail_set->hostname);
516 }
517
mail_deliver_is_tempfailed(struct mail_deliver_context * ctx,struct mail_storage * storage)518 static bool mail_deliver_is_tempfailed(struct mail_deliver_context *ctx,
519 struct mail_storage *storage)
520 {
521 enum mail_error error;
522
523 if (ctx->tempfail_error != NULL)
524 return TRUE;
525 if (storage != NULL) {
526 (void)mail_storage_get_last_error(storage, &error);
527 return error == MAIL_ERROR_TEMP;
528 }
529 return FALSE;
530 }
531
532 static int
mail_do_deliver(struct mail_deliver_context * ctx,struct mail_storage ** storage_r)533 mail_do_deliver(struct mail_deliver_context *ctx,
534 struct mail_storage **storage_r)
535 {
536 int ret;
537
538 *storage_r = NULL;
539 if (deliver_mail == NULL)
540 ret = -1;
541 else {
542 ctx->dup_db = mail_duplicate_db_init(ctx->rcpt_user,
543 DUPLICATE_DB_NAME);
544 if (deliver_mail(ctx, storage_r) <= 0) {
545 /* if message was saved, don't bounce it even though
546 the script failed later. */
547 ret = ctx->saved_mail ? 0 : -1;
548 } else {
549 /* success. message may or may not have been saved. */
550 ret = 0;
551 }
552 mail_duplicate_db_deinit(&ctx->dup_db);
553 if (ret < 0 && mail_deliver_is_tempfailed(ctx, *storage_r))
554 return -1;
555 }
556
557 if (ret < 0 && !ctx->tried_default_save) {
558 /* plugins didn't handle this. save into the default mailbox. */
559 ret = mail_deliver_save(ctx, ctx->rcpt_default_mailbox, 0, NULL,
560 storage_r);
561 if (ret < 0 && mail_deliver_is_tempfailed(ctx, *storage_r))
562 return -1;
563 }
564 if (ret < 0 && strcasecmp(ctx->rcpt_default_mailbox, "INBOX") != 0) {
565 /* still didn't work. try once more to save it
566 to INBOX. */
567 ret = mail_deliver_save(ctx, "INBOX", 0, NULL, storage_r);
568 }
569 return ret;
570 }
571
mail_deliver(struct mail_deliver_context * ctx,enum mail_deliver_error * error_code_r,const char ** error_r)572 int mail_deliver(struct mail_deliver_context *ctx,
573 enum mail_deliver_error *error_code_r,
574 const char **error_r)
575 {
576 struct mail_deliver_user *muser =
577 MAIL_DELIVER_USER_CONTEXT(ctx->rcpt_user);
578 struct event_passthrough *e;
579 struct mail_storage *storage = NULL;
580 enum mail_deliver_error error_code = MAIL_DELIVER_ERROR_NONE;
581 const char *error = NULL;
582 int ret;
583
584 i_assert(muser->deliver_ctx == NULL);
585
586 mail_deliver_fields_update(&ctx->fields, ctx->pool, ctx->src_mail);
587 mail_deliver_update_event(ctx);
588
589 muser->want_storage_id =
590 var_has_key(ctx->set->deliver_log_format, '\0', "storage_id");
591
592 muser->deliver_ctx = ctx;
593
594 e = event_create_passthrough(ctx->event)->
595 set_name("mail_delivery_started");
596 e_debug(e->event(), "Local delivery started");
597
598 ret = mail_do_deliver(ctx, &storage);
599
600 if (ret >= 0)
601 i_assert(ret == 0); /* ret > 0 has no defined meaning */
602 else if (ctx->tempfail_error != NULL) {
603 error = ctx->tempfail_error;
604 error_code = MAIL_DELIVER_ERROR_TEMPORARY;
605 } else if (storage != NULL) {
606 enum mail_error mail_error;
607
608 error = mail_storage_get_last_error(storage, &mail_error);
609 if (mail_error == MAIL_ERROR_NOQUOTA) {
610 error_code = MAIL_DELIVER_ERROR_NOQUOTA;
611 } else {
612 error_code = MAIL_DELIVER_ERROR_TEMPORARY;
613 }
614 } else {
615 /* This shouldn't happen */
616 e_error(ctx->event, "BUG: Saving failed to unknown storage");
617 error = "Temporary internal error";
618 error_code = MAIL_DELIVER_ERROR_INTERNAL;
619 }
620
621 e = event_create_passthrough(ctx->event)->
622 set_name("mail_delivery_finished");
623 if (ret == 0) {
624 e_debug(e->event(), "Local delivery finished successfully");
625 } else {
626 e->add_str("error", error);
627 e_debug(e->event(), "Local delivery failed: %s", error);
628 }
629
630 muser->deliver_ctx = NULL;
631
632 *error_code_r = error_code;
633 *error_r = error;
634 return ret;
635 }
636
mail_deliver_hook_set(deliver_mail_func_t * new_hook)637 deliver_mail_func_t *mail_deliver_hook_set(deliver_mail_func_t *new_hook)
638 {
639 deliver_mail_func_t *old_hook = deliver_mail;
640
641 deliver_mail = new_hook;
642 return old_hook;
643 }
644
mail_deliver_save_finish(struct mail_save_context * ctx)645 static int mail_deliver_save_finish(struct mail_save_context *ctx)
646 {
647 struct mailbox *box = ctx->transaction->box;
648 struct mail_deliver_mailbox *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box);
649 struct mail_deliver_user *muser =
650 MAIL_DELIVER_USER_CONTEXT(box->storage->user);
651 struct mail_deliver_transaction *dt =
652 MAIL_DELIVER_STORAGE_CONTEXT(ctx->transaction);
653
654 if (mbox->module_ctx.super.save_finish(ctx) < 0)
655 return -1;
656
657 /* initialize most of the fields from dest_mail */
658 mail_deliver_fields_update(&dt->deliver_fields,
659 muser->deliver_ctx->pool,
660 ctx->dest_mail);
661 return 0;
662 }
663
mail_deliver_copy(struct mail_save_context * ctx,struct mail * mail)664 static int mail_deliver_copy(struct mail_save_context *ctx, struct mail *mail)
665 {
666 struct mailbox *box = ctx->transaction->box;
667 struct mail_deliver_mailbox *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box);
668 struct mail_deliver_user *muser =
669 MAIL_DELIVER_USER_CONTEXT(box->storage->user);
670 struct mail_deliver_transaction *dt =
671 MAIL_DELIVER_STORAGE_CONTEXT(ctx->transaction);
672
673 if (mbox->module_ctx.super.copy(ctx, mail) < 0)
674 return -1;
675
676 /* initialize most of the fields from dest_mail */
677 mail_deliver_fields_update(&dt->deliver_fields,
678 muser->deliver_ctx->pool,
679 ctx->dest_mail);
680 return 0;
681 }
682
683 static void
mail_deliver_fields_update_post_commit(struct mailbox * orig_box,uint32_t uid)684 mail_deliver_fields_update_post_commit(struct mailbox *orig_box, uint32_t uid)
685 {
686 struct mail_deliver_user *muser =
687 MAIL_DELIVER_USER_CONTEXT(orig_box->storage->user);
688 struct mailbox *box;
689 struct mailbox_transaction_context *t;
690 struct mail *mail;
691 const char *storage_id;
692
693 if (!muser->want_storage_id)
694 return;
695
696 /* getting storage_id requires a whole new mailbox view that is
697 synced, so it'll contain the newly written mail. this is racy, so
698 it's possible another process has already deleted the mail. */
699 box = mailbox_alloc(orig_box->list, orig_box->vname, 0);
700 mailbox_set_reason(box, "lib-lda storage-id");
701
702 mail = mail_deliver_open_mail(box, uid, MAIL_FETCH_STORAGE_ID, &t);
703 if (mail != NULL) {
704 if (mail_get_special(mail, MAIL_FETCH_STORAGE_ID, &storage_id) < 0 ||
705 storage_id[0] == '\0')
706 storage_id = NULL;
707 muser->deliver_ctx->fields.storage_id =
708 p_strdup(muser->deliver_ctx->pool, storage_id);
709 mail_free(&mail);
710 (void)mailbox_transaction_commit(&t);
711 } else {
712 muser->deliver_ctx->fields.storage_id = NULL;
713 }
714 mailbox_free(&box);
715 }
716
717 static struct mailbox_transaction_context *
mail_deliver_transaction_begin(struct mailbox * box,enum mailbox_transaction_flags flags,const char * reason)718 mail_deliver_transaction_begin(struct mailbox *box,
719 enum mailbox_transaction_flags flags,
720 const char *reason)
721 {
722 struct mail_deliver_mailbox *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box);
723 struct mail_deliver_user *muser =
724 MAIL_DELIVER_USER_CONTEXT(box->storage->user);
725 struct mailbox_transaction_context *t;
726 struct mail_deliver_transaction *dt;
727
728 i_assert(muser->deliver_ctx != NULL);
729
730 t = mbox->module_ctx.super.transaction_begin(box, flags, reason);
731 dt = p_new(muser->deliver_ctx->pool, struct mail_deliver_transaction, 1);
732
733 MODULE_CONTEXT_SET(t, mail_deliver_storage_module, dt);
734 return t;
735 }
736
737 static int
mail_deliver_transaction_commit(struct mailbox_transaction_context * ctx,struct mail_transaction_commit_changes * changes_r)738 mail_deliver_transaction_commit(struct mailbox_transaction_context *ctx,
739 struct mail_transaction_commit_changes *changes_r)
740 {
741 struct mailbox *box = ctx->box;
742 struct mail_deliver_mailbox *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box);
743 struct mail_deliver_transaction *dt = MAIL_DELIVER_STORAGE_CONTEXT(ctx);
744 struct mail_deliver_user *muser =
745 MAIL_DELIVER_USER_CONTEXT(box->storage->user);
746
747 i_assert(muser->deliver_ctx != NULL);
748
749 /* sieve creates multiple transactions, saves the mails and
750 then commits all of them at the end. we'll need to keep
751 switching the deliver_ctx->fields for each commit.
752
753 we also want to do this only for commits generated by sieve.
754 other plugins or storage backends may be creating transactions as
755 well, which we need to ignore. */
756 if ((box->flags & MAILBOX_FLAG_POST_SESSION) != 0) {
757 muser->deliver_ctx->fields = dt->deliver_fields;
758 mail_deliver_update_event(muser->deliver_ctx);
759 }
760
761 if (mbox->module_ctx.super.transaction_commit(ctx, changes_r) < 0)
762 return -1;
763
764 if (array_count(&changes_r->saved_uids) > 0) {
765 const struct seq_range *range =
766 array_front(&changes_r->saved_uids);
767
768 mail_deliver_fields_update_post_commit(box, range->seq1);
769 }
770 return 0;
771 }
772
mail_deliver_mail_user_created(struct mail_user * user)773 static void mail_deliver_mail_user_created(struct mail_user *user)
774 {
775 struct mail_deliver_user *muser;
776
777 muser = p_new(user->pool, struct mail_deliver_user, 1);
778 MODULE_CONTEXT_SET(user, mail_deliver_user_module, muser);
779 }
780
mail_deliver_mailbox_allocated(struct mailbox * box)781 static void mail_deliver_mailbox_allocated(struct mailbox *box)
782 {
783 struct mailbox_vfuncs *v = box->vlast;
784 struct mail_deliver_mailbox *mbox;
785 struct mail_deliver_user *muser =
786 MAIL_DELIVER_USER_CONTEXT(box->storage->user);
787
788 /* we are doing something other than lda/lmtp delivery
789 and should not be involved */
790 if (muser->deliver_ctx == NULL)
791 return;
792
793 if ((box->flags & MAILBOX_FLAG_POST_SESSION) != 0)
794 mailbox_set_reason(box, "lib-lda delivery");
795
796 mbox = p_new(box->pool, struct mail_deliver_mailbox, 1);
797 mbox->module_ctx.super = *v;
798 box->vlast = &mbox->module_ctx.super;
799 v->save_finish = mail_deliver_save_finish;
800 v->copy = mail_deliver_copy;
801 v->transaction_begin = mail_deliver_transaction_begin;
802 v->transaction_commit = mail_deliver_transaction_commit;
803
804 MODULE_CONTEXT_SET(box, mail_deliver_storage_module, mbox);
805 }
806
807 static struct mail_storage_hooks mail_deliver_hooks = {
808 .mail_user_created = mail_deliver_mail_user_created,
809 .mailbox_allocated = mail_deliver_mailbox_allocated
810 };
811
mail_deliver_hooks_init(void)812 void mail_deliver_hooks_init(void)
813 {
814 mail_storage_hooks_add_internal(&mail_deliver_hooks);
815 }
816