}
if (t->save_ctx != NULL) {
+ mailbox_save_context_deinit(t->save_ctx);
if (ret < 0) {
t->box->v.transaction_save_rollback(t->save_ctx);
t->save_ctx = NULL;
}
}
- if (t->save_ctx != NULL)
+ if (t->save_ctx != NULL) {
+ i_assert(t->save_ctx->dest_mail == NULL);
t->box->v.transaction_save_commit_post(t->save_ctx, result_r);
+ }
if (pvt_sync_ctx != NULL) {
if (index_mailbox_sync_pvt_newmails(pvt_sync_ctx, t) < 0) {
struct mailbox_transaction_context *t =
MAIL_STORAGE_CONTEXT(index_trans);
- if (t->save_ctx != NULL)
+ if (t->save_ctx != NULL) {
+ mailbox_save_context_deinit(t->save_ctx);
t->box->v.transaction_save_rollback(t->save_ctx);
+ }
i_assert(t->mail_ref_count == 0);
t->super.rollback(index_trans);
/* mail is being copied or moved. However, this is set also with
mailbox_save_using_mail() and then saving==TRUE. */
unsigned int copying_or_moving:1;
+ /* dest_mail was set via mailbox_save_set_dest_mail() */
+ unsigned int dest_mail_external:1;
};
struct mailbox_sync_context {
enum mail_index_open_flags
mail_storage_settings_to_index_flags(const struct mail_storage_settings *set);
+void mailbox_save_context_deinit(struct mail_save_context *ctx);
#endif
return t->box;
}
+static void mailbox_save_dest_mail_close(struct mail_save_context *ctx)
+{
+ struct mail_private *mail = (struct mail_private *)ctx->dest_mail;
+
+ mail->v.close(&mail->mail);
+}
+
struct mail_save_context *
mailbox_save_alloc(struct mailbox_transaction_context *t)
{
ctx->unfinished = TRUE;
ctx->data.received_date = (time_t)-1;
ctx->data.save_date = (time_t)-1;
+
+ /* Always have a dest_mail available. A lot of plugins make use
+ of this. */
+ if (ctx->dest_mail == NULL)
+ ctx->dest_mail = mail_alloc(t, 0, NULL);
+ else {
+ /* make sure the mail isn't used before mail_set_seq_saving() */
+ mailbox_save_dest_mail_close(ctx);
+ }
return ctx;
}
+void mailbox_save_context_deinit(struct mail_save_context *ctx)
+{
+ i_assert(ctx->dest_mail != NULL);
+
+ if (!ctx->dest_mail_external)
+ mail_free(&ctx->dest_mail);
+ else
+ ctx->dest_mail = NULL;
+}
+
void mailbox_save_set_flags(struct mail_save_context *ctx,
enum mail_flags flags,
struct mail_keywords *keywords)
void mailbox_save_set_dest_mail(struct mail_save_context *ctx,
struct mail *mail)
{
+ i_assert(mail != NULL);
+
+ if (!ctx->dest_mail_external)
+ mail_free(&ctx->dest_mail);
ctx->dest_mail = mail;
+ ctx->dest_mail_external = TRUE;
}
int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input)
{
struct mail_save_context *ctx = *_ctx;
struct mail_keywords *keywords = ctx->data.keywords;
- struct mail_private *mail;
*_ctx = NULL;
T_BEGIN {
} T_END;
if (keywords != NULL && !ctx->finishing)
mailbox_keywords_unref(&keywords);
- if (ctx->dest_mail != NULL) {
- /* the dest_mail is no longer valid. if we're still saving
- more mails, the mail sequence may get reused. make sure
- the mail gets reset in between */
- mail = (struct mail_private *)ctx->dest_mail;
- mail->v.close(&mail->mail);
- }
+
+ /* the dest_mail is no longer valid. if we're still saving
+ more mails, the mail sequence may get reused. make sure
+ the mail gets reset in between */
+ mailbox_save_dest_mail_close(ctx);
+
mailbox_save_context_reset(ctx, FALSE);
}