25
26
MAIL_LOG_FIELD_BOX = 0x02,
26
27
MAIL_LOG_FIELD_MSGID = 0x04,
27
28
MAIL_LOG_FIELD_PSIZE = 0x08,
28
MAIL_LOG_FIELD_VSIZE = 0x10
29
MAIL_LOG_FIELD_VSIZE = 0x10,
30
MAIL_LOG_FIELD_FLAGS = 0x20,
31
MAIL_LOG_FIELD_FROM = 0x40,
32
MAIL_LOG_FIELD_SUBJECT = 0x80
30
34
#define MAIL_LOG_DEFAULT_FIELDS \
31
35
(MAIL_LOG_FIELD_UID | MAIL_LOG_FIELD_BOX | \
38
42
MAIL_LOG_EVENT_COPY = 0x08,
39
43
MAIL_LOG_EVENT_MAILBOX_DELETE = 0x10,
40
44
MAIL_LOG_EVENT_MAILBOX_RENAME = 0x20,
42
MAIL_LOG_EVENT_MASK_ALL = 0x1f
45
MAIL_LOG_EVENT_FLAG_CHANGE = 0x40,
46
MAIL_LOG_EVENT_APPEND = 0x80
44
#define MAIL_LOG_DEFAULT_EVENTS MAIL_LOG_EVENT_MASK_ALL
48
#define MAIL_LOG_DEFAULT_EVENTS \
49
(MAIL_LOG_EVENT_DELETE | MAIL_LOG_EVENT_UNDELETE | \
50
MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY | \
51
MAIL_LOG_EVENT_MAILBOX_DELETE | MAIL_LOG_EVENT_MAILBOX_RENAME)
46
53
static const char *field_names[] = {
272
static void mail_log_add_hdr(struct mail *mail, string_t *str,
273
const char *name, const char *header)
277
if (mail_get_first_header(mail, header, &value) <= 0)
279
str_printfa(str, "%s=%s, ", name, str_sanitize(value, HEADER_LOG_LEN));
258
282
static void mail_log_action(struct mailbox_transaction_context *dest_trans,
259
283
struct mail *mail, enum mail_log_event event,
260
284
const char *data)
262
286
struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(dest_trans);
268
290
if ((mail_log_set.events & event) == 0)
272
pool = pool_alloconly_create("mail log transaction", 1024);
273
lt = p_new(pool, struct mail_log_transaction_context, 1);
275
MODULE_CONTEXT_SET(dest_trans, mail_log_storage_module, lt);
279
295
if (mail_log_set.group_events) {
284
300
str = t_str_new(128);
285
301
str_printfa(str, "%s: ", mail_log_event_get_name(event));
287
if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0)
303
if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0 && mail->uid != 0)
288
304
str_printfa(str, "uid=%u, ", mail->uid);
290
306
if ((mail_log_set.fields & MAIL_LOG_FIELD_BOX) != 0)
291
307
mail_log_append_mailbox_name(str, mail->box);
308
if ((mail_log_set.fields & MAIL_LOG_FIELD_FLAGS) != 0) {
309
str_printfa(str, "flags=(");
310
imap_write_flags(str, mail_get_flags(mail),
311
mail_get_keywords(mail));
312
str_append(str, "), ");
293
314
if (event == MAIL_LOG_EVENT_COPY)
294
315
str_printfa(str, "dest=%s, ", data);
296
if ((mail_log_set.fields & MAIL_LOG_FIELD_MSGID) != 0) {
297
if (mail_get_first_header(mail, "Message-ID", &msgid) <= 0)
299
str_printfa(str, "msgid=%s, ",
300
str_sanitize(msgid, MSGID_LOG_LEN));
317
if ((mail_log_set.fields & MAIL_LOG_FIELD_MSGID) != 0)
318
mail_log_add_hdr(mail, str, "msgid", "Message-ID");
319
if ((mail_log_set.fields & MAIL_LOG_FIELD_FROM) != 0)
320
mail_log_add_hdr(mail, str, "from", "From");
321
if ((mail_log_set.fields & MAIL_LOG_FIELD_SUBJECT) != 0)
322
mail_log_add_hdr(mail, str, "subject", "Subject");
303
324
if ((mail_log_set.fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
304
325
(event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
350
371
new_flags = flags;
353
if (((old_flags ^ new_flags) & MAIL_DELETED) == 0)
375
if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) T_BEGIN {
357
376
mail_log_action(_mail->transaction, _mail,
358
377
(new_flags & MAIL_DELETED) != 0 ?
359
378
MAIL_LOG_EVENT_DELETE :
360
379
MAIL_LOG_EVENT_UNDELETE, NULL);
382
if ((old_flags & ~MAIL_DELETED) != (new_flags & ~MAIL_DELETED)) {
383
mail_log_action(_mail->transaction, _mail,
384
MAIL_LOG_EVENT_FLAG_CHANGE, NULL);
389
mail_log_mail_update_keywords(struct mail *_mail, enum modify_type modify_type,
390
struct mail_keywords *keywords)
392
struct mail_private *mail = (struct mail_private *)_mail;
393
union mail_module_context *lmail = MAIL_LOG_MAIL_CONTEXT(mail);
394
const char *const *old_keywords, *const *new_keywords;
397
old_keywords = mail_get_keywords(_mail);
398
lmail->super.update_keywords(_mail, modify_type, keywords);
399
new_keywords = mail_get_keywords(_mail);
401
for (i = 0; old_keywords[i] != NULL && new_keywords[i] != NULL; i++) {
402
if (strcmp(old_keywords[i], new_keywords[i]) != 0)
406
if (old_keywords[i] != NULL || new_keywords[i] != NULL) {
407
mail_log_action(_mail->transaction, _mail,
408
MAIL_LOG_EVENT_FLAG_CHANGE, NULL);
364
412
static struct mail *
378
426
lmail->super = mail->v;
380
428
mail->v.update_flags = mail_log_mail_update_flags;
429
mail->v.update_keywords = mail_log_mail_update_keywords;
381
430
mail->v.expunge = mail_log_mail_expunge;
382
431
MODULE_CONTEXT_SET_SELF(mail, mail_log_mail_module, lmail);
387
mail_log_copy(struct mailbox_transaction_context *t, struct mail *mail,
388
enum mail_flags flags, struct mail_keywords *keywords,
389
struct mail *dest_mail)
436
mail_log_copy(struct mail_save_context *ctx, struct mail *mail)
391
union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
438
union mailbox_module_context *lbox =
439
MAIL_LOG_CONTEXT(ctx->transaction->box);
392
440
const char *name;
394
if (lbox->super.copy(t, mail, flags, keywords, dest_mail) < 0)
442
if (lbox->super.copy(ctx, mail) < 0)
398
name = str_sanitize(mailbox_get_name(t->box),
446
name = str_sanitize(mailbox_get_name(ctx->transaction->box),
399
447
MAILBOX_NAME_LOG_LEN);
400
mail_log_action(t, mail, MAIL_LOG_EVENT_COPY, name);
448
mail_log_action(ctx->transaction, mail,
449
MAIL_LOG_EVENT_COPY, name);
455
mail_log_save_begin(struct mail_save_context *ctx, struct istream *input)
457
struct mail_log_transaction_context *lt =
458
MAIL_LOG_CONTEXT(ctx->transaction);
459
union mailbox_module_context *lbox =
460
MAIL_LOG_CONTEXT(ctx->transaction->box);
462
if (ctx->dest_mail == NULL) {
463
if (lt->tmp_mail == NULL)
464
lt->tmp_mail = mail_alloc(ctx->transaction, 0, NULL);
465
ctx->dest_mail = lt->tmp_mail;
468
return lbox->super.save_begin(ctx, input);
471
static int mail_log_save_finish(struct mail_save_context *ctx)
473
union mailbox_module_context *lbox =
474
MAIL_LOG_CONTEXT(ctx->transaction->box);
476
if (lbox->super.save_finish(ctx) < 0)
480
mail_log_action(ctx->transaction, ctx->dest_mail,
481
MAIL_LOG_EVENT_APPEND, NULL);
486
static struct mailbox_transaction_context *
487
mail_log_transaction_begin(struct mailbox *box,
488
enum mailbox_transaction_flags flags)
490
union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(box);
491
struct mailbox_transaction_context *t;
492
struct mail_log_transaction_context *lt;
495
t = lbox->super.transaction_begin(box, flags);
497
pool = pool_alloconly_create("mail log transaction", 1024);
498
lt = p_new(pool, struct mail_log_transaction_context, 1);
500
MODULE_CONTEXT_SET(t, mail_log_storage_module, lt);
411
510
struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(t);
412
511
union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
415
if (lt->changes > 0 && mail_log_set.group_events)
416
mail_log_group_changes(t->box, lt);
417
pool_unref(<->pool);
513
if (lt->changes > 0 && mail_log_set.group_events)
514
mail_log_group_changes(t->box, lt);
515
if (lt->tmp_mail != NULL)
516
mail_free(<->tmp_mail);
517
pool_unref(<->pool);
420
519
return lbox->super.transaction_commit(t, uid_validity_r,
421
520
first_saved_uid_r,
428
527
struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(t);
429
528
union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
432
if (lt->changes > 0 && !mail_log_set.group_events) {
433
i_info("Transaction rolled back: "
434
"Ignore last %u changes", lt->changes);
436
pool_unref(<->pool);
530
if (lt->changes > 0 && !mail_log_set.group_events) {
531
i_info("Transaction rolled back: "
532
"Ignore last %u changes", lt->changes);
534
if (lt->tmp_mail != NULL)
535
mail_free(<->tmp_mail);
536
pool_unref(<->pool);
439
538
lbox->super.transaction_rollback(t);
457
556
box->v.mail_alloc = mail_log_mail_alloc;
458
557
box->v.copy = mail_log_copy;
558
box->v.save_begin = mail_log_save_begin;
559
box->v.save_finish = mail_log_save_finish;
560
box->v.transaction_begin = mail_log_transaction_begin;
459
561
box->v.transaction_commit = mail_log_transaction_commit;
460
562
box->v.transaction_rollback = mail_log_transaction_rollback;
461
563
MODULE_CONTEXT_SET_SELF(box, mail_log_storage_module, lbox);