This allows adding more parameters easily in future.
--HG--
branch : HEAD
/* save the mail */
ctx->input = i_stream_create_limit(client->input, ctx->msg_size);
- ret = mailbox_save_init(ctx->t, flags, keywords,
- internal_date, timezone_offset, NULL,
- ctx->input, FALSE, &ctx->save_ctx);
+ ctx->save_ctx = mailbox_save_alloc(ctx->t);
+ mailbox_save_set_flags(ctx->save_ctx, flags, keywords);
+ mailbox_save_set_received_date(ctx->save_ctx,
+ internal_date, timezone_offset);
+ ret = mailbox_save_begin(&ctx->save_ctx, ctx->input);
if (keywords != NULL)
mailbox_keywords_free(ctx->box, &keywords);
uint32_t seq;
struct istream *input;
struct ostream *output;
- struct mail *mail, *cur_dest_mail;
- time_t cur_received_date;
+ struct mail *mail;
int fd;
unsigned int failed:1;
return t_strdup_printf("%s/%s.%u", dir, ctx->tmp_basename, num);
}
-int cydir_save_init(struct mailbox_transaction_context *_t,
- enum mail_flags flags, struct mail_keywords *keywords,
- time_t received_date, int timezone_offset ATTR_UNUSED,
- const char *from_envelope ATTR_UNUSED,
- struct istream *input, struct mail **dest_mail,
- struct mail_save_context **ctx_r)
+struct mail_save_context *
+cydir_save_alloc(struct mailbox_transaction_context *_t)
{
struct cydir_transaction_context *t =
(struct cydir_transaction_context *)_t;
struct cydir_mailbox *mbox = (struct cydir_mailbox *)t->ictx.ibox;
struct cydir_save_context *ctx = t->save_ctx;
- enum mail_flags save_flags;
- struct istream *crlf_input;
i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
- if (ctx == NULL) {
- ctx = t->save_ctx = i_new(struct cydir_save_context, 1);
- ctx->ctx.transaction = &t->ictx.mailbox_ctx;
- ctx->mbox = mbox;
- ctx->trans = t->ictx.trans;
- ctx->tmp_basename = cydir_generate_tmp_filename();
- }
+ if (t->save_ctx != NULL)
+ return &t->save_ctx->ctx;
+
+ ctx = t->save_ctx = i_new(struct cydir_save_context, 1);
+ ctx->ctx.transaction = &t->ictx.mailbox_ctx;
+ ctx->mbox = mbox;
+ ctx->trans = t->ictx.trans;
+ ctx->tmp_basename = cydir_generate_tmp_filename();
+ return &ctx->ctx;
+}
+
+int cydir_save_begin(struct mail_save_context *_ctx, struct istream *input)
+{
+ struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx;
+ struct mailbox_transaction_context *trans = _ctx->transaction;
+ enum mail_flags save_flags;
+ struct istream *crlf_input;
T_BEGIN {
const char *path;
o_stream_create_fd_file(ctx->fd, 0, FALSE);
o_stream_cork(ctx->output);
} else {
- mail_storage_set_critical(_t->box->storage,
+ mail_storage_set_critical(trans->box->storage,
"open(%s) failed: %m", path);
ctx->failed = TRUE;
}
return -1;
/* add to index */
- save_flags = flags & ~MAIL_RECENT;
+ save_flags = _ctx->flags & ~MAIL_RECENT;
mail_index_append(ctx->trans, 0, &ctx->seq);
mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE,
save_flags);
- if (keywords != NULL) {
+ if (_ctx->keywords != NULL) {
mail_index_update_keywords(ctx->trans, ctx->seq,
- MODIFY_REPLACE, keywords);
+ MODIFY_REPLACE, _ctx->keywords);
}
- if (*dest_mail == NULL) {
+ if (_ctx->dest_mail == NULL) {
if (ctx->mail == NULL)
- ctx->mail = mail_alloc(_t, 0, NULL);
- *dest_mail = ctx->mail;
+ ctx->mail = mail_alloc(trans, 0, NULL);
+ _ctx->dest_mail = ctx->mail;
}
- mail_set_seq(*dest_mail, ctx->seq);
+ mail_set_seq(_ctx->dest_mail, ctx->seq);
crlf_input = i_stream_create_crlf(input);
- ctx->input = index_mail_cache_parse_init(*dest_mail, crlf_input);
+ ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input);
i_stream_unref(&crlf_input);
-
- ctx->cur_dest_mail = *dest_mail;
- ctx->cur_received_date = received_date;
-
- *ctx_r = &ctx->ctx;
return ctx->failed ? -1 : 0;
}
ctx->failed = TRUE;
return -1;
}
- index_mail_cache_parse_continue(ctx->cur_dest_mail);
+ index_mail_cache_parse_continue(_ctx->dest_mail);
/* both tee input readers may consume data from our primary
input stream. we'll have to make sure we don't return with
}
}
- if (ctx->cur_received_date == (time_t)-1) {
+ if (_ctx->received_date == (time_t)-1) {
if (fstat(ctx->fd, &st) == 0)
- ctx->cur_received_date = st.st_mtime;
+ _ctx->received_date = st.st_mtime;
else {
mail_storage_set_critical(storage,
"fstat(%s) failed: %m", path);
struct utimbuf ut;
ut.actime = ioloop_time;
- ut.modtime = ctx->cur_received_date;
+ ut.modtime = _ctx->received_date;
if (utime(path, &ut) < 0) {
mail_storage_set_critical(storage,
"utime(%s) failed: %m", path);
}
}
- index_mail_cache_parse_deinit(ctx->cur_dest_mail,
- ctx->cur_received_date, !ctx->failed);
+ index_mail_cache_parse_deinit(_ctx->dest_mail,
+ _ctx->received_date, !ctx->failed);
i_stream_unref(&ctx->input);
return ctx->failed ? -1 : 0;
index_storage_search_deinit,
index_storage_search_next_nonblock,
index_storage_search_next_update_seq,
- cydir_save_init,
+ cydir_save_alloc,
+ cydir_save_begin,
cydir_save_continue,
cydir_save_finish,
cydir_save_cancel,
void cydir_transaction_class_init(void);
void cydir_transaction_class_deinit(void);
-int cydir_save_init(struct mailbox_transaction_context *_t,
- enum mail_flags flags, struct mail_keywords *keywords,
- time_t received_date, int timezone_offset,
- const char *from_envelope, struct istream *input,
- struct mail **dest_mail, struct mail_save_context **ctx_r);
+struct mail_save_context *
+cydir_save_alloc(struct mailbox_transaction_context *_t);
+int cydir_save_begin(struct mail_save_context *ctx, struct istream *input);
int cydir_save_continue(struct mail_save_context *ctx);
int cydir_save_finish(struct mail_save_context *ctx);
void cydir_save_cancel(struct mail_save_context *ctx);
/* updated for each appended mail: */
uint32_t seq;
struct istream *input;
- struct mail *mail, *cur_dest_mail;
- time_t cur_received_date;
- enum mail_flags cur_flags;
+ struct mail *mail;
string_t *cur_keywords;
struct dbox_file *cur_file;
keywords);
}
-int dbox_save_init(struct mailbox_transaction_context *_t,
- enum mail_flags flags, struct mail_keywords *keywords,
- time_t received_date, int timezone_offset ATTR_UNUSED,
- const char *from_envelope ATTR_UNUSED,
- struct istream *input, struct mail **dest_mail,
- struct mail_save_context **ctx_r)
+struct mail_save_context *
+dbox_save_alloc(struct mailbox_transaction_context *_t)
{
struct dbox_transaction_context *t =
(struct dbox_transaction_context *)_t;
struct dbox_mailbox *mbox = (struct dbox_mailbox *)t->ictx.ibox;
- struct dbox_save_context *ctx = t->save_ctx;
+ struct dbox_save_context *ctx;
+
+ i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
+
+ if (t->save_ctx != NULL)
+ return &t->save_ctx->ctx;
+
+ ctx = t->save_ctx = i_new(struct dbox_save_context, 1);
+ ctx->ctx.transaction = &t->ictx.mailbox_ctx;
+ ctx->mbox = mbox;
+ ctx->trans = t->ictx.trans;
+ ctx->append_ctx = dbox_index_append_begin(mbox->dbox_index);
+ i_array_init(&ctx->mails, 32);
+ return &ctx->ctx;
+}
+
+int dbox_save_begin(struct mail_save_context *_ctx, struct istream *input)
+{
+ struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
struct dbox_message_header dbox_msg_hdr;
struct dbox_save_mail *save_mail;
struct istream *crlf_input;
const struct stat *st;
uoff_t mail_size;
- i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
-
- if (ctx == NULL) {
- ctx = t->save_ctx = i_new(struct dbox_save_context, 1);
- ctx->ctx.transaction = &t->ictx.mailbox_ctx;
- ctx->mbox = mbox;
- ctx->trans = t->ictx.trans;
- ctx->append_ctx = dbox_index_append_begin(mbox->dbox_index);
- i_array_init(&ctx->mails, 32);
- }
-
/* get the size of the mail to be saved, if possible */
st = i_stream_stat(input, TRUE);
mail_size = st == NULL || st->st_size == -1 ? 0 : st->st_size;
}
/* add to index */
- save_flags = flags & ~MAIL_RECENT;
+ save_flags = _ctx->flags & ~MAIL_RECENT;
mail_index_append(ctx->trans, 0, &ctx->seq);
mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE,
save_flags);
- if (keywords != NULL) {
+ if (_ctx->keywords != NULL) {
mail_index_update_keywords(ctx->trans, ctx->seq,
- MODIFY_REPLACE, keywords);
+ MODIFY_REPLACE, _ctx->keywords);
}
- if (*dest_mail == NULL) {
+ if (_ctx->dest_mail == NULL) {
if (ctx->mail == NULL)
- ctx->mail = mail_alloc(_t, 0, NULL);
- *dest_mail = ctx->mail;
+ ctx->mail = mail_alloc(_ctx->transaction, 0, NULL);
+ _ctx->dest_mail = ctx->mail;
}
- mail_set_seq(*dest_mail, ctx->seq);
-
- ctx->cur_dest_mail = *dest_mail;
+ mail_set_seq(_ctx->dest_mail, ctx->seq);
crlf_input = i_stream_create_lf(input);
- ctx->input = index_mail_cache_parse_init(*dest_mail, crlf_input);
+ ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input);
i_stream_unref(&crlf_input);
save_mail = array_append_space(&ctx->mails);
o_stream_cork(ctx->cur_output);
if (o_stream_send(ctx->cur_output, &dbox_msg_hdr,
sizeof(dbox_msg_hdr)) < 0) {
- mail_storage_set_critical(_t->box->storage,
+ mail_storage_set_critical(_ctx->transaction->box->storage,
"o_stream_send(%s) failed: %m",
dbox_file_get_path(ctx->cur_file));
ctx->failed = TRUE;
}
- ctx->cur_received_date = received_date != (time_t)-1 ?
- received_date : ioloop_time;
- ctx->cur_flags = flags;
- dbox_save_keywords(ctx, keywords);
-
- *ctx_r = &ctx->ctx;
+ if (_ctx->received_date == (time_t)-1)
+ _ctx->received_date = ioloop_time;
+ dbox_save_keywords(ctx, _ctx->keywords);
return ctx->failed ? -1 : 0;
}
ctx->failed = TRUE;
return -1;
}
- index_mail_cache_parse_continue(ctx->cur_dest_mail);
+ index_mail_cache_parse_continue(_ctx->dest_mail);
/* both tee input readers may consume data from our primary
input stream. we'll have to make sure we don't return with
str = t_str_new(256);
/* write first fields that don't change */
str_printfa(str, "%c%lx\n", DBOX_METADATA_RECEIVED_TIME,
- (unsigned long)ctx->cur_received_date);
+ (unsigned long)ctx->ctx.received_date);
str_printfa(str, "%c%lx\n", DBOX_METADATA_SAVE_TIME,
(unsigned long)ioloop_time);
- if (mail_get_virtual_size(ctx->cur_dest_mail, &vsize) < 0)
+ if (mail_get_virtual_size(ctx->ctx.dest_mail, &vsize) < 0)
i_unreached();
str_printfa(str, "%c%llx\n", DBOX_METADATA_VIRTUAL_SIZE,
(unsigned long long)vsize);
/* flags */
str_append_c(str, DBOX_METADATA_FLAGS);
- dbox_mail_metadata_flags_append(str, ctx->cur_flags);
+ dbox_mail_metadata_flags_append(str, ctx->ctx.flags);
str_append_c(str, '\n');
/* keywords */
if (ctx->cur_output == NULL)
return -1;
- index_mail_cache_parse_deinit(ctx->cur_dest_mail,
- ctx->cur_received_date, !ctx->failed);
+ index_mail_cache_parse_deinit(_ctx->dest_mail,
+ _ctx->received_date, !ctx->failed);
if (!ctx->failed) T_BEGIN {
const char *cur_path;
index_storage_search_deinit,
index_storage_search_next_nonblock,
index_storage_search_next_update_seq,
- dbox_save_init,
+ dbox_save_alloc,
+ dbox_save_begin,
dbox_save_continue,
dbox_save_finish,
dbox_save_cancel,
enum mail_fetch_field wanted_fields,
struct mailbox_header_lookup_ctx *wanted_headers);
-int dbox_save_init(struct mailbox_transaction_context *_t,
- enum mail_flags flags, struct mail_keywords *keywords,
- time_t received_date, int timezone_offset,
- const char *from_envelope, struct istream *input,
- struct mail **dest_mail, struct mail_save_context **ctx_r);
+struct mail_save_context *
+dbox_save_alloc(struct mailbox_transaction_context *_t);
+int dbox_save_begin(struct mail_save_context *ctx, struct istream *input);
int dbox_save_continue(struct mail_save_context *ctx);
int dbox_save_finish(struct mail_save_context *ctx);
void dbox_save_cancel(struct mail_save_context *ctx);
struct istream *input;
struct ostream *output;
int fd;
- time_t received_date;
uint32_t first_seq, seq;
unsigned int want_mails:1;
return fd;
}
-int maildir_save_init(struct mailbox_transaction_context *_t,
- enum mail_flags flags, struct mail_keywords *keywords,
- time_t received_date, int timezone_offset ATTR_UNUSED,
- const char *from_envelope ATTR_UNUSED,
- struct istream *input, struct mail **dest_mail,
- struct mail_save_context **ctx_r)
+struct mail_save_context *
+maildir_save_alloc(struct mailbox_transaction_context *_t)
{
struct maildir_transaction_context *t =
(struct maildir_transaction_context *)_t;
- struct maildir_save_context *ctx;
- struct maildir_mailbox *mbox = (struct maildir_mailbox *)t->ictx.ibox;
i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
if (t->save_ctx == NULL)
t->save_ctx = maildir_save_transaction_init(t);
- ctx = t->save_ctx;
+ return &t->save_ctx->ctx;
+}
+
+int maildir_save_begin(struct mail_save_context *_ctx, struct istream *input)
+{
+ struct maildir_transaction_context *t =
+ (struct maildir_transaction_context *)_ctx->transaction;
+ struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx;
- flags &= ~MAIL_RECENT;
- if (mbox->ibox.keep_recent)
- flags |= MAIL_RECENT;
+ _ctx->flags &= ~MAIL_RECENT;
+ if (ctx->mbox->ibox.keep_recent)
+ _ctx->flags |= MAIL_RECENT;
T_BEGIN {
/* create a new file in tmp/ directory */
const char *fname;
- ctx->fd = maildir_create_tmp(mbox, ctx->tmpdir, &fname);
+ ctx->fd = maildir_create_tmp(ctx->mbox, ctx->tmpdir, &fname);
if (ctx->fd == -1)
ctx->failed = TRUE;
else {
- ctx->received_date = received_date;
ctx->input = (ctx->mbox->storage->storage.flags &
MAIL_STORAGE_FLAG_SAVE_CRLF) != 0 ?
i_stream_create_crlf(input) :
i_stream_create_lf(input);
- maildir_save_add(t, fname, flags, keywords, *dest_mail);
+ maildir_save_add(t, fname, _ctx->flags, _ctx->keywords,
+ _ctx->dest_mail);
}
} T_END;
- if (ctx->failed)
- return -1;
- ctx->output = o_stream_create_fd_file(ctx->fd, 0, FALSE);
- o_stream_cork(ctx->output);
-
- *ctx_r = &ctx->ctx;
+ if (!ctx->failed) {
+ ctx->output = o_stream_create_fd_file(ctx->fd, 0, FALSE);
+ o_stream_cork(ctx->output);
+ }
return ctx->failed ? -1 : 0;
}
ctx->failed = TRUE;
}
- if (ctx->received_date != (time_t)-1) {
+ if (ctx->ctx.received_date != (time_t)-1) {
/* set the received_date by modifying mtime */
buf.actime = ioloop_time;
- buf.modtime = ctx->received_date;
+ buf.modtime = ctx->ctx.received_date;
if (utime(path, &buf) < 0) {
ctx->failed = TRUE;
}
} else if (ctx->fd != -1) {
if (fstat(ctx->fd, &st) == 0)
- ctx->received_date = st.st_mtime;
+ ctx->ctx.received_date = st.st_mtime;
else {
ctx->failed = TRUE;
mail_storage_set_critical(storage,
} else {
/* hardlinked */
if (stat(path, &st) == 0)
- ctx->received_date = st.st_mtime;
+ ctx->ctx.received_date = st.st_mtime;
else {
ctx->failed = TRUE;
mail_storage_set_critical(storage,
if (ctx->cur_dest_mail != NULL) {
index_mail_cache_parse_deinit(ctx->cur_dest_mail,
- ctx->received_date, !ctx->failed);
+ ctx->ctx.received_date,
+ !ctx->failed);
}
i_stream_unref(&ctx->input);
index_storage_search_deinit,
index_storage_search_next_nonblock,
index_storage_search_next_update_seq,
- maildir_save_init,
+ maildir_save_alloc,
+ maildir_save_begin,
maildir_save_continue,
maildir_save_finish,
maildir_save_cancel,
void maildir_transaction_class_init(void);
void maildir_transaction_class_deinit(void);
-int maildir_save_init(struct mailbox_transaction_context *_t,
- enum mail_flags flags, struct mail_keywords *keywords,
- time_t received_date, int timezone_offset,
- const char *from_envelope, struct istream *input,
- struct mail **dest_mail,
- struct mail_save_context **ctx_r);
+struct mail_save_context *
+maildir_save_alloc(struct mailbox_transaction_context *_t);
+int maildir_save_begin(struct mail_save_context *ctx, struct istream *input);
int maildir_save_continue(struct mail_save_context *ctx);
int maildir_save_finish(struct mail_save_context *ctx);
void maildir_save_cancel(struct mail_save_context *ctx);
struct mail *mail;
uoff_t append_offset, mail_offset;
time_t orig_atime;
- time_t received_date;
string_t *headers;
size_t space_end_idx;
return ret;
}
-int mbox_save_init(struct mailbox_transaction_context *_t,
- enum mail_flags flags, struct mail_keywords *keywords,
- time_t received_date, int timezone_offset ATTR_UNUSED,
- const char *from_envelope, struct istream *input,
- struct mail **dest_mail, struct mail_save_context **ctx_r)
+struct mail_save_context *
+mbox_save_alloc(struct mailbox_transaction_context *_t)
{
struct mbox_transaction_context *t =
(struct mbox_transaction_context *)_t;
struct mbox_mailbox *mbox = (struct mbox_mailbox *)t->ictx.ibox;
- struct mbox_save_context *ctx = t->save_ctx;
- enum mail_flags save_flags;
- uint64_t offset;
+ struct mbox_save_context *ctx;
i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
+ if (t->save_ctx != NULL)
+ return &t->save_ctx->ctx;
+
+ ctx = t->save_ctx = i_new(struct mbox_save_context, 1);
+ ctx->ctx.transaction = &t->ictx.mailbox_ctx;
+ ctx->mbox = mbox;
+ ctx->trans = t->ictx.trans;
+ ctx->append_offset = (uoff_t)-1;
+ ctx->headers = str_new(default_pool, 512);
+ ctx->mail_offset = (uoff_t)-1;
+ return &ctx->ctx;
+}
+
+int mbox_save_begin(struct mail_save_context *_ctx, struct istream *input)
+{
+ struct mbox_save_context *ctx = (struct mbox_save_context *)_ctx;
+ struct mbox_transaction_context *t =
+ (struct mbox_transaction_context *)_ctx->transaction;
+ enum mail_flags save_flags;
+ uint64_t offset;
+
/* FIXME: we could write timezone_offset to From-line.. */
- if (received_date == (time_t)-1)
- received_date = ioloop_time;
-
- if (ctx == NULL) {
- ctx = t->save_ctx = i_new(struct mbox_save_context, 1);
- ctx->ctx.transaction = &t->ictx.mailbox_ctx;
- ctx->mbox = mbox;
- ctx->trans = t->ictx.trans;
- ctx->append_offset = (uoff_t)-1;
- ctx->headers = str_new(default_pool, 512);
- ctx->mail_offset = (uoff_t)-1;
- }
+ if (_ctx->received_date == (time_t)-1)
+ _ctx->received_date = ioloop_time;
ctx->failed = FALSE;
ctx->seq = 0;
- if (mbox_save_init_file(ctx, t, *dest_mail != NULL) < 0) {
+ if (mbox_save_init_file(ctx, t, _ctx->dest_mail != NULL) < 0) {
ctx->failed = TRUE;
return -1;
}
- save_flags = (flags & ~MAIL_RECENT) | MAIL_RECENT;
+ save_flags = (_ctx->flags & ~MAIL_RECENT) | MAIL_RECENT;
str_truncate(ctx->headers, 0);
if (ctx->synced) {
if (ctx->mbox->mbox_save_md5)
mail_index_append(ctx->trans, ctx->next_uid, &ctx->seq);
mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE,
save_flags & ~MAIL_RECENT);
- if (keywords != NULL) {
+ if (_ctx->keywords != NULL) {
mail_index_update_keywords(ctx->trans, ctx->seq,
- MODIFY_REPLACE, keywords);
+ MODIFY_REPLACE,
+ _ctx->keywords);
}
offset = ctx->output->offset == 0 ? 0 :
ctx->output->offset - 1;
mail_index_update_ext(ctx->trans, ctx->seq,
- mbox->mbox_ext_idx, &offset, NULL);
+ ctx->mbox->mbox_ext_idx, &offset, NULL);
ctx->next_uid++;
/* parse and cache the mail headers as we read it */
- if (*dest_mail == NULL) {
- if (ctx->mail == NULL)
- ctx->mail = mail_alloc(_t, 0, NULL);
- *dest_mail = ctx->mail;
+ if (_ctx->dest_mail == NULL) {
+ if (ctx->mail == NULL) {
+ ctx->mail = mail_alloc(_ctx->transaction,
+ 0, NULL);
+ }
+ _ctx->dest_mail = ctx->mail;
}
- mail_set_seq(*dest_mail, ctx->seq);
+ mail_set_seq(_ctx->dest_mail, ctx->seq);
}
mbox_save_append_flag_headers(ctx->headers, save_flags);
- mbox_save_append_keyword_headers(ctx, keywords);
+ mbox_save_append_keyword_headers(ctx, _ctx->keywords);
str_append_c(ctx->headers, '\n');
- i_assert(mbox->mbox_lock_type == F_WRLCK);
+ i_assert(ctx->mbox->mbox_lock_type == F_WRLCK);
ctx->mail_offset = ctx->output->offset;
ctx->eoh_offset = (uoff_t)-1;
ctx->last_char = '\n';
- ctx->received_date = received_date;
- if (write_from_line(ctx, received_date, from_envelope) < 0)
+ if (write_from_line(ctx, _ctx->received_date, _ctx->from_envelope) < 0)
ctx->failed = TRUE;
else
ctx->input = mbox_save_get_input_stream(ctx, input);
-
- *ctx_r = &ctx->ctx;
return ctx->failed ? -1 : 0;
}
}
if (ctx->mail != NULL) {
- index_mail_cache_parse_deinit(ctx->mail, ctx->received_date,
+ index_mail_cache_parse_deinit(ctx->mail, ctx->ctx.received_date,
!ctx->failed);
}
if (ctx->input != NULL)
index_storage_search_deinit,
index_storage_search_next_nonblock,
index_storage_search_next_update_seq,
- mbox_save_init,
+ mbox_save_alloc,
+ mbox_save_begin,
mbox_save_continue,
mbox_save_finish,
mbox_save_cancel,
struct mailbox_sync_context *
mbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags);
-int mbox_save_init(struct mailbox_transaction_context *_t,
- enum mail_flags flags, struct mail_keywords *keywords,
- time_t received_date, int timezone_offset,
- const char *from_envelope, struct istream *input,
- struct mail **dest_mail, struct mail_save_context **ctx_r);
+struct mail_save_context *
+mbox_save_alloc(struct mailbox_transaction_context *_t);
+int mbox_save_begin(struct mail_save_context *ctx, struct istream *input);
int mbox_save_continue(struct mail_save_context *ctx);
int mbox_save_finish(struct mail_save_context *ctx);
void mbox_save_cancel(struct mail_save_context *ctx);
NULL,
NULL,
NULL,
+ NULL,
mail_storage_copy,
index_storage_is_inconsistent
}
if (*from_envelope == '\0')
from_envelope = NULL;
- if (mailbox_save_init(t, flags, keywords, received_date,
- 0, from_envelope, input, dest_mail, &ctx) < 0)
+ ctx = mailbox_save_alloc(t);
+ mailbox_save_set_flags(ctx, flags, keywords);
+ mailbox_save_set_received_date(ctx, received_date, 0);
+ mailbox_save_set_from_envelope(ctx, from_envelope);
+ mailbox_save_set_dest_mail(ctx, dest_mail);
+
+ if (mailbox_save_begin(&ctx, input) < 0)
return -1;
do {
/* Internal search function which updates ctx->seq */
int (*search_next_update_seq)(struct mail_search_context *ctx);
- int (*save_init)(struct mailbox_transaction_context *t,
- enum mail_flags flags,
- struct mail_keywords *keywords,
- time_t received_date, int timezone_offset,
- const char *from_envelope, struct istream *input,
- struct mail **dest_mail,
- struct mail_save_context **ctx_r);
+ struct mail_save_context *
+ (*save_alloc)(struct mailbox_transaction_context *t);
+ int (*save_begin)(struct mail_save_context *ctx, struct istream *input);
int (*save_continue)(struct mail_save_context *ctx);
int (*save_finish)(struct mail_save_context *ctx);
void (*save_cancel)(struct mail_save_context *ctx);
struct mail_save_context {
struct mailbox_transaction_context *transaction;
struct mail *dest_mail;
+
+ enum mail_flags flags;
+ struct mail_keywords *keywords;
+
+ time_t received_date;
+ int received_tz_offset;
+
+ char *from_envelope;
};
struct mailbox_sync_context {
return t->box;
}
-int mailbox_save_init(struct mailbox_transaction_context *t,
- enum mail_flags flags, struct mail_keywords *keywords,
- time_t received_date, int timezone_offset,
- const char *from_envelope, struct istream *input,
- struct mail *dest_mail, struct mail_save_context **ctx_r)
-{
- if (t->box->v.save_init == NULL) {
- mail_storage_set_error(t->box->storage, MAIL_ERROR_NOTPOSSIBLE,
+struct mail_save_context *
+mailbox_save_alloc(struct mailbox_transaction_context *t)
+{
+ struct mail_save_context *ctx;
+
+ ctx = t->box->v.save_alloc(t);
+ ctx->received_date = (time_t)-1;
+ return ctx;
+}
+
+void mailbox_save_set_flags(struct mail_save_context *ctx,
+ enum mail_flags flags,
+ struct mail_keywords *keywords)
+{
+ ctx->flags = flags;
+ ctx->keywords = keywords;
+}
+
+void mailbox_save_set_received_date(struct mail_save_context *ctx,
+ time_t received_date, int timezone_offset)
+{
+ ctx->received_date = received_date;
+ ctx->received_tz_offset = timezone_offset;
+}
+
+void mailbox_save_set_from_envelope(struct mail_save_context *ctx,
+ const char *envelope)
+{
+ i_free(ctx->from_envelope);
+ ctx->from_envelope = i_strdup(envelope);
+}
+
+void mailbox_save_set_dest_mail(struct mail_save_context *ctx,
+ struct mail *mail)
+{
+ ctx->dest_mail = mail;
+}
+
+int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input)
+{
+ struct mailbox *box = (*ctx)->transaction->box;
+ int ret;
+
+ if (box->v.save_begin == NULL) {
+ mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
"Saving messages not supported");
- return -1;
+ ret = -1;
+ } else {
+ ret = box->v.save_begin(*ctx, input);
}
- if (t->box->v.save_init(t, flags, keywords,
- received_date, timezone_offset,
- from_envelope, input, &dest_mail, ctx_r) < 0)
- return -1;
- (*ctx_r)->dest_mail = dest_mail;
+ if (ret < 0) {
+ mailbox_save_cancel(ctx);
+ return -1;
+ }
return 0;
}
struct mail_save_context *ctx = *_ctx;
*_ctx = NULL;
+ i_free(ctx->from_envelope);
return ctx->transaction->box->v.save_finish(ctx);
}
struct mail_save_context *ctx = *_ctx;
*_ctx = NULL;
+ i_free(ctx->from_envelope);
ctx->transaction->box->v.save_cancel(ctx);
}
ARRAY_TYPE(seq_range) *removed_uids,
ARRAY_TYPE(seq_range) *added_uids);
-/* Save a mail into mailbox. timezone_offset specifies the timezone in
- minutes in which received_date was originally given with. To use
- current time, set received_date to (time_t)-1.
-
- If dest_mail is set, the saved message can be accessed using it. Note that
+/* Initialize saving a new mail. You must not try to save more than one mail
+ at a time. */
+struct mail_save_context *
+mailbox_save_alloc(struct mailbox_transaction_context *t);
+/* Set the flags and keywords. Nothing is set by default. */
+void mailbox_save_set_flags(struct mail_save_context *ctx,
+ enum mail_flags flags,
+ struct mail_keywords *keywords);
+/* If received date isn't specified the current time is used. timezone_offset
+ specifies the preferred timezone in minutes, but it may be ignored if
+ backend doesn't support storing it. */
+void mailbox_save_set_received_date(struct mail_save_context *ctx,
+ time_t received_date, int timezone_offset);
+/* Set the envelope sender. This is currently used only with mbox files to
+ specify the address in From_-line. */
+void mailbox_save_set_from_envelope(struct mail_save_context *ctx,
+ const char *envelope);
+/* If dest_mail is set, the saved message can be accessed using it. Note that
setting it may require mailbox syncing, so don't set it unless you need
it. Also you shouldn't try to access it before mailbox_save_finish() is
- called.
-
- The given input stream is never read in these functions, only the data
- inside it is used. So you should call i_stream_read() yourself and then
- call mailbox_save_continue() whenever more data is read.
-*/
-int mailbox_save_init(struct mailbox_transaction_context *t,
- enum mail_flags flags, struct mail_keywords *keywords,
- time_t received_date, int timezone_offset,
- const char *from_envelope, struct istream *input,
- struct mail *dest_mail, struct mail_save_context **ctx_r);
+ called. */
+void mailbox_save_set_dest_mail(struct mail_save_context *ctx,
+ struct mail *mail);
+/* Begin saving the message. All mail_save_set_*() calls must have been called
+ before this function. If the save initialization fails, the context is freed
+ and -1 is returned. After beginning the save you should keep calling
+ i_stream_read() and calling mailbox_save_continue() as long as there's
+ more input. */
+int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input);
int mailbox_save_continue(struct mail_save_context *ctx);
int mailbox_save_finish(struct mail_save_context **ctx);
void mailbox_save_cancel(struct mail_save_context **ctx);
}
static int
-acl_save_init(struct mailbox_transaction_context *t,
- enum mail_flags flags, struct mail_keywords *keywords,
- time_t received_date, int timezone_offset,
- const char *from_envelope, struct istream *input,
- struct mail **dest_mail, struct mail_save_context **ctx_r)
+acl_save_begin(struct mail_save_context *ctx, struct istream *input)
{
- struct acl_mailbox *abox = ACL_CONTEXT(t->box);
+ struct mailbox *box = ctx->transaction->box;
+ struct acl_mailbox *abox = ACL_CONTEXT(box);
- if (mailbox_acl_right_lookup(t->box, ACL_STORAGE_RIGHT_INSERT) <= 0)
+ if (mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_INSERT) <= 0)
return -1;
- if (acl_save_get_flags(t->box, &flags, &keywords) < 0)
+ if (acl_save_get_flags(box, &ctx->flags, &ctx->keywords) < 0)
return -1;
- return abox->module_ctx.super.
- save_init(t, flags, keywords, received_date,
- timezone_offset, from_envelope,
- input, dest_mail, ctx_r);
+ return abox->module_ctx.super.save_begin(ctx, input);
}
static int
box->v.allow_new_keywords = acl_allow_new_keywords;
box->v.close = acl_mailbox_close;
box->v.mail_alloc = acl_mail_alloc;
- box->v.save_init = acl_save_init;
+ box->v.save_begin = acl_save_begin;
box->v.keywords_create = acl_keywords_create;
box->v.copy = acl_copy;
box->v.transaction_commit = acl_transaction_commit;
}
static int
-quota_save_init(struct mailbox_transaction_context *t,
- enum mail_flags flags, struct mail_keywords *keywords,
- time_t received_date, int timezone_offset,
- const char *from_envelope, struct istream *input,
- struct mail **dest_mail, struct mail_save_context **ctx_r)
+quota_save_begin(struct mail_save_context *ctx, struct istream *input)
{
+ struct mailbox_transaction_context *t = ctx->transaction;
struct quota_transaction_context *qt = QUOTA_CONTEXT(t);
struct quota_mailbox *qbox = QUOTA_CONTEXT(t->box);
const struct stat *st;
}
}
- if (*dest_mail == NULL) {
+ if (ctx->dest_mail == NULL) {
/* we always want to know the mail size */
if (qt->tmp_mail == NULL) {
qt->tmp_mail = mail_alloc(t, MAIL_FETCH_PHYSICAL_SIZE,
NULL);
}
- *dest_mail = qt->tmp_mail;
+ ctx->dest_mail = qt->tmp_mail;
}
- return qbox->module_ctx.super.
- save_init(t, flags, keywords, received_date,
- timezone_offset, from_envelope,
- input, dest_mail, ctx_r);
+ return qbox->module_ctx.super.save_begin(ctx, input);
}
static int quota_save_finish(struct mail_save_context *ctx)
box->v.transaction_commit = quota_mailbox_transaction_commit;
box->v.transaction_rollback = quota_mailbox_transaction_rollback;
box->v.mail_alloc = quota_mail_alloc;
- box->v.save_init = quota_save_init;
+ box->v.save_begin = quota_save_begin;
box->v.save_finish = quota_save_finish;
box->v.copy = quota_copy;
box->v.sync_notify = quota_mailbox_sync_notify;
return ret;
}
-static int
-virtual_save_init(struct mailbox_transaction_context *_t,
- enum mail_flags flags ATTR_UNUSED,
- struct mail_keywords *keywords ATTR_UNUSED,
- time_t received_date ATTR_UNUSED,
- int timezone_offset ATTR_UNUSED,
- const char *from_envelope ATTR_UNUSED,
- struct istream *input ATTR_UNUSED,
- struct mail **dest_mail ATTR_UNUSED,
- struct mail_save_context **ctx_r)
-{
- mail_storage_set_error(_t->box->storage, MAIL_ERROR_NOTPOSSIBLE,
- "Can't save to virtual mailboxes");
- *ctx_r = NULL;
- return -1;
-}
-
static void virtual_class_init(void)
{
virtual_transaction_class_init();
index_storage_search_deinit,
index_storage_search_next_nonblock,
index_storage_search_next_update_seq,
- virtual_save_init,
+ NULL,
+ NULL,
NULL,
NULL,
NULL,