static int
cmd_import_box(struct import_cmd_context *ctx, struct mail_user *dest_user,
	       const struct mailbox_info *info,
	       struct mail_search_args *search_args)
{
	struct doveadm_mail_iter *iter;
	struct mailbox_transaction_context *trans;
	struct mailbox *box;
	struct mail *mail;
	int ret = 0;

	if (doveadm_mail_iter_init(info, search_args, &trans, &iter) < 0)
		return -1;

	mail = mail_alloc(trans, 0, NULL);
	if (doveadm_mail_iter_next(iter, mail)) {
		/* at least one mail matches in this mailbox */
		if (dest_mailbox_open_or_create(ctx, dest_user, info->name,
						&box) == 0) {
			if (cmd_import_box_contents(iter, mail, box) < 0)
				ret = -1;
			mailbox_free(&box);
		}
	}
	mail_free(&mail);
	if (doveadm_mail_iter_deinit_sync(&iter) < 0)
		ret = -1;
	return ret;
}
Example #2
0
void mail_raw_close(struct mail_raw **mailr)
{
	mail_free(&(*mailr)->mail);
	mailbox_transaction_rollback(&(*mailr)->trans);
	mailbox_free(&(*mailr)->box);

	i_free(*mailr);
	*mailr = NULL;
}
Example #3
0
File: mail.c Project: avkrotov/fdm
void
mail_destroy(struct mail *m)
{
	mail_free(m);
	if (m->base != NULL) {
		SHM_DEREGISTER(&m->shm);
		shm_destroy(&m->shm);
	}
}
Example #4
0
File: mail.c Project: avkrotov/fdm
void
mail_close(struct mail *m)
{
	mail_free(m);
	if (m->base != NULL) {
		SHM_DEREGISTER(&m->shm);
		shm_close(&m->shm);
	}
}
Example #5
0
/******************************************************************
 Read window dispose
*******************************************************************/
void read_window_dispose(GtkObject *object, gpointer user_data)
{
	struct Read_Data *data = (struct Read_Data*)user_data;

	if (data->folder_path) free(data->folder_path);
	mail_free(data->mail);

	if (data->num < MAX_READ_OPEN) read_open[data->num] = NULL;
	free(data);
	gtk_widget_hide_all(GTK_WIDGET(object));
}
Example #6
0
static void
zlib_mailbox_transaction_rollback(struct mailbox_transaction_context *t)
{
	union mailbox_module_context *zbox = ZLIB_CONTEXT(t->box);
	struct zlib_transaction_context *zt = ZLIB_CONTEXT(t);

	if (zt->tmp_mail != NULL)
		mail_free(&zt->tmp_mail);

	zbox->super.transaction_rollback(t);
	i_free(zt);
}
Example #7
0
static int fetch_and_copy(struct client *client,
			  struct mailbox_transaction_context *t,
			  struct mail_search_args *search_args,
			  const char **src_uidset_r,
			  unsigned int *copy_count_r)
{
	struct mail_search_context *search_ctx;
        struct mailbox_transaction_context *src_trans;
	struct mail_save_context *save_ctx;
	struct mail *mail;
	unsigned int copy_count = 0;
	struct msgset_generator_context srcset_ctx;
	string_t *src_uidset;
	int ret;

	src_uidset = t_str_new(256);
	msgset_generator_init(&srcset_ctx, src_uidset);

	src_trans = mailbox_transaction_begin(client->mailbox, 0);
	search_ctx = mailbox_search_init(src_trans, search_args, NULL);

	mail = mail_alloc(src_trans, 0, NULL);
	ret = 1;
	while (mailbox_search_next(search_ctx, mail) && ret > 0) {
		if (mail->expunged) {
			ret = 0;
			break;
		}

		if ((++copy_count % COPY_CHECK_INTERVAL) == 0)
			client_send_sendalive_if_needed(client);

		save_ctx = mailbox_save_alloc(t);
		mailbox_save_copy_flags(save_ctx, mail);

		if (mailbox_copy(&save_ctx, mail) < 0)
			ret = mail->expunged ? 0 : -1;

		msgset_generator_next(&srcset_ctx, mail->uid);
	}
	mail_free(&mail);
	msgset_generator_finish(&srcset_ctx);

	if (mailbox_search_deinit(&search_ctx) < 0)
		ret = -1;

	if (mailbox_transaction_commit(&src_trans) < 0)
		ret = -1;

	*src_uidset_r = str_c(src_uidset);
	*copy_count_r = copy_count;
	return ret;
}
Example #8
0
void index_sort_program_deinit(struct mail_search_sort_program **_program)
{
	struct mail_search_sort_program *program = *_program;

	*_program = NULL;

	if (program->context != NULL)
		index_sort_list_finish(program);
	mail_free(&program->temp_mail);
	array_free(&program->seqs);
	i_free(program);
}
Example #9
0
static void
antispam_mailbox_transaction_rollback(struct mailbox_transaction_context *ctx)
{
	struct antispam_mailbox *asbox = ANTISPAM_CONTEXT(ctx->box);
	struct antispam_internal_context *ast = ANTISPAM_CONTEXT(ctx);

	if (ast->mail)
		mail_free(&ast->mail);

	asbox->module_ctx.super.transaction_rollback(ctx);

	antispam_transaction_rollback(&ast->backendctx);
}
Example #10
0
static int
antispam_mailbox_transaction_commit(struct mailbox_transaction_context *ctx,
				    uint32_t *uid_validity_r,
				    uint32_t *first_saved_uid_r,
				    uint32_t *last_saved_uid_r)
{
	struct antispam_mailbox *asbox = ANTISPAM_CONTEXT(ctx->box);
	struct antispam_internal_context *ast = ANTISPAM_CONTEXT(ctx);

	if (antispam_transaction_commit(ctx, &ast->backendctx) < 0) {
		if (ast->mail)
			mail_free(&ast->mail);

		asbox->module_ctx.super.transaction_rollback(ctx);
		return -1;
	}

	if (ast->mail)
		mail_free(&ast->mail);

	return asbox->module_ctx.super.transaction_commit(ctx, uid_validity_r,
					       first_saved_uid_r,
					       last_saved_uid_r);
}
Example #11
0
/******************************************************************
 This close and disposed the window (note: this must not be called
 within a normal callback hook (because the object is disposed in
 this function)!
*******************************************************************/
static void read_window_close(struct Read_Data **pdata)
{
	struct Read_Data *data = *pdata;
	set(data->wnd,MUIA_Window_Open,FALSE);
	DoMethod(App,OM_REMMEMBER,data->wnd);
	MUI_DisposeObject(data->wnd);

	if (data->attachment_html_menu) MUI_DisposeObject(data->attachment_html_menu);
	if (data->attachment_standard_menu) MUI_DisposeObject(data->attachment_standard_menu);

	if (data->file_req) MUI_FreeAslRequest(data->file_req);
	mail_free(data->mail);
	if (data->num < MAX_READ_OPEN) read_open[data->num] = 0;
	free(data);
}
Example #12
0
static int
zlib_mailbox_transaction_commit(struct mailbox_transaction_context *t,
				struct mail_transaction_commit_changes *changes_r)
{
	union mailbox_module_context *zbox = ZLIB_CONTEXT(t->box);
	struct zlib_transaction_context *zt = ZLIB_CONTEXT(t);
	int ret;

	if (zt->tmp_mail != NULL)
		mail_free(&zt->tmp_mail);

	ret = zbox->super.transaction_commit(t, changes_r);
	i_free(zt);
	return ret;
}
Example #13
0
int index_sort_program_deinit(struct mail_search_sort_program **_program)
{
	struct mail_search_sort_program *program = *_program;

	*_program = NULL;

	if (program->context != NULL)
		index_sort_list_finish(program);
	mail_free(&program->temp_mail);
	array_free(&program->seqs);

	int ret = program->failed ? -1 : 0;
	i_free(program);
	return ret;
}
Example #14
0
static void virtual_mail_free(struct mail *mail)
{
	struct virtual_mail *vmail = (struct virtual_mail *)mail;
	struct mail **mails;
	unsigned int i, count;

	mails = array_get_modifiable(&vmail->backend_mails, &count);
	for (i = 0; i < count; i++)
		mail_free(&mails[i]);
	array_free(&vmail->backend_mails);

	if (vmail->wanted_headers != NULL)
		mailbox_header_lookup_unref(&vmail->wanted_headers);

	pool_unref(&vmail->imail.data_pool);
	pool_unref(&vmail->imail.mail.pool);
}
Example #15
0
void imap_msgpart_url_free(struct imap_msgpart_url **_mpurl)
{
	struct imap_msgpart_url *mpurl = *_mpurl;

	*_mpurl = NULL;

	if (mpurl->result.input != NULL)
		i_stream_unref(&mpurl->result.input);
	if (mpurl->part != NULL)
		imap_msgpart_free(&mpurl->part);
	if (mpurl->mail != NULL)
		mail_free(&mpurl->mail);
	if (mpurl->trans != NULL)
		mailbox_transaction_rollback(&mpurl->trans);
	if (mpurl->box != NULL && mpurl->box != mpurl->selected_box)
		mailbox_free(&mpurl->box);	
	if (mpurl->section != NULL)
		i_free(mpurl->section);
	i_free(mpurl->mailbox);
	i_free(mpurl);
}
Example #16
0
static int
index_mailbox_get_first_save_date(struct mailbox *box,
				  struct mailbox_metadata *metadata_r)
{
	const struct mail_index_header *hdr;
	struct mailbox_transaction_context *t;
	struct mail *mail;
	uint32_t seq;
	int ret = -1;

	hdr = mail_index_get_header(box->view);
	if (hdr->messages_count == 0) {
		metadata_r->first_save_date = (time_t)-1;
		return 0;
	}

	t = mailbox_transaction_begin(box, 0, __func__);
	mail = mail_alloc(t, 0, NULL);
	for (seq = 1; seq <= hdr->messages_count; seq++) {
		mail_set_seq(mail, seq);
		if (mail_get_save_date(mail, &metadata_r->first_save_date) == 0) {
			ret = 0;
			break;
		}
		if (mailbox_get_last_mail_error(box) != MAIL_ERROR_EXPUNGED) {
			/* failed */
			break;
		}
	}
	mail_free(&mail);
	(void)mailbox_transaction_commit(&t);
	if (seq > hdr->messages_count) {
		/* all messages were expunged after all */
		metadata_r->first_save_date = (time_t)-1;
		return 0;
	}
	return ret;
}
Example #17
0
int imap_msgpart_url_open_mail(struct imap_msgpart_url *mpurl,
			       struct mail **mail_r, const char **error_r)
{
	struct mailbox_transaction_context *t;
	struct mailbox *box;
	enum mail_error error_code;
	struct mail *mail;
	int ret;

	if (mpurl->mail != NULL) {
		*mail_r = mpurl->mail;
		return 1;
	}

	/* open mailbox if it is not yet open */
	if ((ret = imap_msgpart_url_open_mailbox(mpurl, &box, &error_code,
						 error_r)) <= 0)
		return ret;

	/* start transaction */
	t = mailbox_transaction_begin(box, 0);
	mail = mail_alloc(t, MAIL_FETCH_MESSAGE_PARTS |
			  MAIL_FETCH_IMAP_BODYSTRUCTURE, NULL);

	/* find the message */
	if (!mail_set_uid(mail, mpurl->uid)) {
		*error_r = "Message not found";
		mail_free(&mail);
		mailbox_transaction_rollback(&t);	
		return 0;
	}

	mpurl->trans = t;
	mpurl->mail = mail;
	*mail_r = mail;
	return 1;
}
Example #18
0
static int
antispam_copy(struct mailbox_transaction_context *t, struct mail *mail,
              enum mail_flags flags, struct mail_keywords *keywords,
              struct mail *dest_mail)
{
    struct antispam_mailbox *asbox = ANTISPAM_CONTEXT(t->box);
    struct antispam_transaction_context *ast =
        ANTISPAM_CONTEXT(t);
    struct mail *copy_dest_mail;
    int ret;
    bool src_trash, dst_trash;

    if (dest_mail != NULL)
        copy_dest_mail = dest_mail;
    else
        copy_dest_mail = mail_alloc(t, MAIL_FETCH_PHYSICAL_SIZE, NULL);

    i_assert(mail->box);

    asbox->save_hack = FALSE;
    asbox->movetype = MMT_UNINTERESTING;

    if (mailbox_is_unsure(t->box)) {
        mail_storage_set_error(t->box->storage,
                               "Cannot copy to unsure folder");
        return -1;
    }

    src_trash = mailbox_is_trash(mail->box);
    dst_trash = mailbox_is_trash(t->box);

    debug_verbose("mail copy: from trash: %d, to trash: %d\n",
                  src_trash, dst_trash);

    if (!src_trash && !dst_trash) {
        bool src_spam = mailbox_is_spam(mail->box);
        bool dst_spam = mailbox_is_spam(t->box);
        bool src_unsu = mailbox_is_unsure(mail->box);

        debug_verbose("mail copy: src spam: %d, dst spam: %d,"
                      " src unsure: %d\n",
                      src_spam, dst_spam, src_unsu);

        if ((src_spam || src_unsu) && !dst_spam)
            asbox->movetype = MMT_TO_CLEAN;
        else if ((!src_spam || src_unsu) && dst_spam)
            asbox->movetype = MMT_TO_SPAM;
    }

    if (asbox->super.copy(t, mail, flags, keywords, copy_dest_mail) < 0)
        return -1;

    /*
     * If copying used saving internally, we already have treated the mail
     */
    if (asbox->save_hack || asbox->movetype == MMT_UNINTERESTING)
        ret = 0;
    else
        ret = backend->handle_mail(t, ast, copy_dest_mail,
                                   move_to_class(asbox->movetype));

    /*
     * Both save_hack and movetype are only valid within a copy operation,
     * i.e. they are now invalid. Because, in theory, another operation
     * could be done after mailbox_open(), we need to reset the movetype
     * variable here. save_hack doesn't need to be reset because it is
     * only ever set within the save function and tested within this copy
     * function after being reset at the beginning of the copy, movetype
     * however is tested within the save_finish() function and a subsequent
     * save to the mailbox should not invoke the backend.
     */
    asbox->movetype = MMT_APPEND;

    if (copy_dest_mail != dest_mail)
        mail_free(&copy_dest_mail);
    return ret;
}
Example #19
0
static int antispam_save_finish(struct mail_save_context *ctx,
                                struct mail *dest_mail)
{
    struct antispam_mailbox *asbox =
        ANTISPAM_CONTEXT(ctx->transaction->box);
    struct antispam_transaction_context *ast =
        ANTISPAM_CONTEXT(ctx->transaction);
    struct mail *save_dest_mail;
    int ret;

    if (dest_mail != NULL)
        save_dest_mail = dest_mail;
    else
        save_dest_mail = mail_alloc(ctx->transaction,
                                    MAIL_FETCH_PHYSICAL_SIZE, NULL);

    if (asbox->super.save_finish(ctx, save_dest_mail) < 0)
        return -1;

    asbox->save_hack = TRUE;

    ret = 0;

    switch (asbox->movetype) {
    case MMT_UNINTERESTING:
        break;
    case MMT_APPEND:
        /* Disallow APPENDs to UNSURE folders. */
        if (mailbox_is_unsure(save_dest_mail->box)) {
            ret = -1;
            mail_storage_set_error(save_dest_mail->box->storage,
                                   "Cannot APPEND to an UNSURE folder.");
            break;
        } else if (mailbox_is_spam(save_dest_mail->box)) {
            /*
             * The client is APPENDing a message to a SPAM folder
             * so we try to train the backend on it. For most of
             * the backends, that can only succeed if the message
             * contains appropriate information.
             *
             * This happens especially when offlineimap is used and
             * the user moved a message to the SPAM folder while
             * offline---offlineimap cannot reproduce the COPY but
             * rather APPENDs the moved message on the next sync.
             *
             * This could be a bad if the spam headers were not
             * generated on our server, but since the user can
             * always APPEND to another folder and then COPY to a
             * SPAM folder backends need to be prepared for cases
             * like this anyway. With dspam, for example, the worst
             * that can happen is that the APPEND fails with a
             * training error from dspam.
             *
             * Unfortunately, we cannot handle the cases where
             *  (1) the user moved a message from one folder that
             *      contains SPAM to another folder containing SPAM
             *  (2) the user moved a message out of the SPAM folder
             *  (3) the user recovered a message from trash
             *
             * Because of these limitations, this behaviour needs
             * to be enabled with an option.
             */
            if (!antispam_can_append_to_spam) {
                ret = -1;
                mail_storage_set_error(
                    save_dest_mail->box->storage,
                    "Cannot APPEND to a SPAM folder.");
                break;
            }
            asbox->movetype = MMT_TO_SPAM;
            /* fall through to default case to invoke backend */
        } else {
            /* neither UNSURE nor SPAM, regular folder */
            break;
        }
    /* fall through */
    default:
        ret = backend->handle_mail(ctx->transaction, ast, save_dest_mail,
                                   move_to_class(asbox->movetype));
    }

    if (save_dest_mail != dest_mail)
        mail_free(&save_dest_mail);
    return ret;
}
Example #20
0
static void
index_storage_virtual_size_add_new(struct mailbox *box,
				   struct index_vsize_header *vsize_hdr)
{
	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
	const struct mail_index_header *hdr;
	struct mailbox_transaction_context *trans;
	struct mail_search_context *search_ctx;
	struct mail_search_args *search_args;
	struct mail *mail;
	uint32_t seq1, seq2;
	uoff_t vsize;
	int ret = 0;

	hdr = mail_index_get_header(box->view);
	if (vsize_hdr->highest_uid == 0)
		seq2 = 0;
	else if (!mail_index_lookup_seq_range(box->view, 1,
					      vsize_hdr->highest_uid,
					      &seq1, &seq2))
		seq2 = 0;

	if (vsize_hdr->message_count != seq2) {
		if (vsize_hdr->message_count < seq2) {
			mail_storage_set_critical(box->storage,
				"vsize-hdr has invalid message-count (%u < %u)",
				vsize_hdr->message_count, seq2);
		} else {
			/* some messages have been expunged, rescan */
		}
		memset(vsize_hdr, 0, sizeof(*vsize_hdr));
		seq2 = 0;
	}

	search_args = mail_search_build_init();
	mail_search_build_add_seqset(search_args, seq2 + 1,
				     hdr->messages_count);

	trans = mailbox_transaction_begin(box, 0);
	search_ctx = mailbox_search_init(trans, search_args, NULL);
	mail = mail_alloc(trans, MAIL_FETCH_VIRTUAL_SIZE, NULL);
	while (mailbox_search_next(search_ctx, mail)) {
		if (mail_get_virtual_size(mail, &vsize) < 0) {
			if (mail->expunged)
				continue;
			ret = -1;
			break;
		}
		vsize_hdr->vsize += vsize;
		vsize_hdr->highest_uid = mail->uid;
		vsize_hdr->message_count++;
	}
	mail_free(&mail);
	if (mailbox_search_deinit(&search_ctx) < 0)
		ret = -1;

	if (ret == 0) {
		/* success, cache all */
		vsize_hdr->highest_uid = hdr->next_uid - 1;
	} else {
		/* search failed, cache only up to highest seen uid */
	}
	mail_index_update_header_ext(trans->itrans, ibox->vsize_hdr_ext_id,
				     0, vsize_hdr, sizeof(*vsize_hdr));
	(void)mailbox_transaction_commit(&trans);

}
Example #21
0
static int snarf(struct mailbox *srcbox, struct mailbox *destbox)
{
	struct mail_search_args *search_args;
	struct mail_search_context *search_ctx;
        struct mailbox_transaction_context *src_trans, *dest_trans;
	struct mail_save_context *save_ctx;
	struct mail *mail;
	enum mail_error error;
	int ret;

	/* make sure the destination mailbox has been opened */
	if (mailbox_open(destbox) < 0)
		return -1;

	if (mailbox_sync(srcbox, MAILBOX_SYNC_FLAG_FULL_READ) < 0)
		return -1;

	src_trans = mailbox_transaction_begin(srcbox, 0);
	dest_trans = mailbox_transaction_begin(destbox,
					MAILBOX_TRANSACTION_FLAG_EXTERNAL);

	search_args = mail_search_build_init();
	mail_search_build_add_all(search_args);
	search_ctx = mailbox_search_init(src_trans, search_args, NULL);
	mail_search_args_unref(&search_args);

	ret = 0;
	mail = mail_alloc(src_trans, MAIL_FETCH_STREAM_HEADER |
			  MAIL_FETCH_STREAM_BODY, NULL);
	while (mailbox_search_next(search_ctx, mail)) {
		if (mail->expunged)
			continue;

		save_ctx = mailbox_save_alloc(dest_trans);
		if (mailbox_copy(&save_ctx, mail) < 0 && !mail->expunged) {
			(void)mail_storage_get_last_error(destbox->storage,
							  &error);
			/* if we failed because of out of disk space, just
			   move those messages we managed to move so far. */
			if (error != MAIL_ERROR_NOSPACE)
				ret = -1;
			break;
		}
		mail_expunge(mail);
	}
	mail_free(&mail);

	if (mailbox_search_deinit(&search_ctx) < 0)
		ret = -1;

	/* commit the copied messages to the destination mailbox. if we crash
	   between that and between expunging the messages from the source
	   mailbox, we're left with duplicates. */
	if (ret < 0)
		mailbox_transaction_rollback(&dest_trans);
	else if (mailbox_transaction_commit(&dest_trans) < 0)
		ret = -1;

	if (ret < 0)
		mailbox_transaction_rollback(&src_trans);
	else {
		if (mailbox_transaction_commit(&src_trans) < 0)
			ret = -1;
	}
	if (ret == 0) {
		if (mailbox_sync(srcbox, 0) < 0)
			ret = -1;
	}
	return ret;
}