Example #1
0
int mail_save_copy_default_metadata(struct mail_save_context *ctx,
				    struct mail *mail)
{
	const char *from_envelope, *guid;
	time_t received_date;

	if (ctx->data.received_date == (time_t)-1) {
		if (mail_get_received_date(mail, &received_date) < 0) {
			mail_copy_set_failed(ctx, mail, "received-date");
			return -1;
		}
		mailbox_save_set_received_date(ctx, received_date, 0);
	}
	if (ctx->data.from_envelope == NULL) {
		if (mail_get_special(mail, MAIL_FETCH_FROM_ENVELOPE,
				     &from_envelope) < 0) {
			mail_copy_set_failed(ctx, mail, "from-envelope");
			return -1;
		}
		if (*from_envelope != '\0')
			mailbox_save_set_from_envelope(ctx, from_envelope);
	}
	if (ctx->data.guid == NULL) {
		if (mail_get_special(mail, MAIL_FETCH_GUID, &guid) < 0) {
			mail_copy_set_failed(ctx, mail, "guid");
			return -1;
		}
		if (*guid != '\0')
			mailbox_save_set_guid(ctx, guid);
	}
	return 0;
}
static int
cmd_deduplicate_box(struct doveadm_mail_cmd_context *_ctx,
		    const struct mailbox_info *info,
		    struct mail_search_args *search_args)
{
	struct deduplicate_cmd_context *ctx =
		(struct deduplicate_cmd_context *)_ctx;
	struct doveadm_mail_iter *iter;
	struct mailbox *box;
	struct mail *mail;
	enum mail_error error;
	pool_t pool;
	HASH_TABLE(const char *, struct uidlist *) hash;
	const char *key, *errstr;
	struct uidlist *value;
	int ret = 0;

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

	pool = pool_alloconly_create("deduplicate", 10240);
	hash_table_create(&hash, pool, 0, str_hash, strcmp);
	while (doveadm_mail_iter_next(iter, &mail)) {
		if (ctx->by_msgid) {
			if (mail_get_first_header(mail, "Message-ID", &key) < 0) {
				errstr = mailbox_get_last_error(mail->box, &error);
				if (error == MAIL_ERROR_NOTFOUND)
					continue;
				i_error("Couldn't lookup Message-ID: for UID=%u: %s",
					mail->uid, errstr);
				doveadm_mail_failed_error(_ctx, error);
				ret = -1;
				break;
			}
		} else {
			if (mail_get_special(mail, MAIL_FETCH_GUID, &key) < 0) {
				errstr = mailbox_get_last_error(mail->box, &error);
				if (error == MAIL_ERROR_NOTFOUND)
					continue;
				i_error("Couldn't lookup GUID: for UID=%u: %s",
					mail->uid, errstr);
				doveadm_mail_failed_error(_ctx, error);
				ret = -1;
				break;
			}
		}
		if (key != NULL && *key != '\0') {
			value = p_new(pool, struct uidlist, 1);
			value->uid = mail->uid;
			value->next = hash_table_lookup(hash, key);

			if (value->next == NULL) {
				key = p_strdup(pool, key);
				hash_table_insert(hash, key, value);
			} else {
				hash_table_update(hash, key, value);
			}
		}
	}
static int
exporter_get_guids(struct dsync_mailbox_exporter *exporter,
                   struct mail *mail, const char **guid_r,
                   const char **hdr_hash_r)
{
    *guid_r = "";
    *hdr_hash_r = NULL;

    /* always try to get GUID, even if we're also getting header hash */
    if (mail_get_special(mail, MAIL_FETCH_GUID, guid_r) < 0)
        return dsync_mail_error(exporter, mail, "GUID");

    if (!exporter->mails_have_guids) {
        /* get header hash also */
        if (dsync_mail_get_hdr_hash(mail, hdr_hash_r) < 0)
            return dsync_mail_error(exporter, mail, "hdr-stream");
        return 1;
    } else if (**guid_r == '\0') {
        exporter->error = "Backend doesn't support GUIDs, "
                          "sync with header hashes instead";
        return -1;
    } else {
        /* GUIDs are required, we don't need header hash */
        return 1;
    }
}
Example #4
0
static float index_sort_get_relevancy(struct mail *mail)
{
	const char *str;

	if (mail_get_special(mail, MAIL_FETCH_SEARCH_RELEVANCY, &str) < 0)
		return 0;
	else
		return strtod(str, NULL);
}
Example #5
0
static float index_sort_get_score(struct mail *mail)
{
	const char *str;

	if (mail_get_special(mail, MAIL_FETCH_SEARCH_SCORE, &str) < 0)
		return 0;
	else
		return strtod(str, NULL);
}
Example #6
0
static uoff_t index_sort_get_pop3_order(struct mail *mail)
{
	const char *str;
	uoff_t size;

	if (mail_get_special(mail, MAIL_FETCH_POP3_ORDER, &str) < 0 ||
	    str_to_uoff(str, &size) < 0)
		return (uint32_t)-1;
	else
		return size;
}
Example #7
0
static int index_sort_get_relevancy(struct mail *mail, float *result_r)
{
	const char *str;

	if (mail_get_special(mail, MAIL_FETCH_SEARCH_RELEVANCY, &str) < 0) {
		*result_r = 0;
		return -1;
	}
	*result_r = strtod(str, NULL);
	return 0;
}
Example #8
0
static int index_sort_get_pop3_order(struct mail *mail, uoff_t *size_r)
{
	const char *str;

	if (mail_get_special(mail, MAIL_FETCH_POP3_ORDER, &str) < 0) {
		*size_r = (uint32_t)-1;
		return -1;
	}

	if (str_to_uoff(str, size_r) < 0)
		*size_r = (uint32_t)-1;
	return 0;
}
Example #9
0
int dsync_mail_fill(struct mail *mail, struct dsync_mail *dmail_r,
		    const char **error_field_r)
{
	const char *guid, *str;

	memset(dmail_r, 0, sizeof(*dmail_r));

	if (mail_get_special(mail, MAIL_FETCH_GUID, &guid) < 0) {
		*error_field_r = "GUID";
		return -1;
	}
	dmail_r->guid = guid;
	dmail_r->uid = mail->uid;

	dmail_r->input_mail = mail;
	dmail_r->input_mail_uid = mail->uid;
	if (mail_get_stream(mail, NULL, NULL, &dmail_r->input) < 0) {
		*error_field_r = "body";
		return -1;
	}

	if (mail_get_special(mail, MAIL_FETCH_UIDL_BACKEND, &dmail_r->pop3_uidl) < 0) {
		*error_field_r = "pop3-uidl";
		return -1;
	}
	if (mail_get_special(mail, MAIL_FETCH_POP3_ORDER, &str) < 0) {
		*error_field_r = "pop3-order";
		return -1;
	}
	if (*str != '\0') {
		if (str_to_uint(str, &dmail_r->pop3_order) < 0)
			i_unreached();
	}
	if (mail_get_received_date(mail, &dmail_r->received_date) < 0) {
		*error_field_r = "received-date";
		return -1;
	}
	return 0;
}
Example #10
0
/* Returns >0 = matched, 0 = not matched, -1 = unknown */
static int search_arg_match_mailbox(struct index_search_context *ctx,
				    struct mail_search_arg *arg)
{
	const char *str;

	switch (arg->type) {
	case SEARCH_MAILBOX:
		if (mail_get_special(ctx->mail, MAIL_FETCH_MAILBOX_NAME,
				     &str) < 0)
			return -1;

		if (strcasecmp(str, "INBOX") == 0)
			return strcasecmp(arg->value.str, "INBOX") == 0;
		return strcmp(str, arg->value.str) == 0;
	case SEARCH_MAILBOX_GLOB:
		if (mail_get_special(ctx->mail, MAIL_FETCH_MAILBOX_NAME,
				     &str) < 0)
			return -1;
		return imap_match(arg->value.mailbox_glob, str) == IMAP_MATCH_YES;
	default:
		return -1;
	}
}
Example #11
0
static int
virtual_mail_get_special(struct mail *mail, enum mail_fetch_field field,
			 const char **value_r)
{
	struct virtual_mail *vmail = (struct virtual_mail *)mail;
	struct mailbox *box = vmail->backend_mail->box;

	if (virtual_mail_handle_lost(vmail) < 0)
		return -1;
	if (mail_get_special(vmail->backend_mail, field, value_r) < 0) {
		virtual_box_copy_error(mail->box, box);
		return -1;
	}
	return 0;
}
Example #12
0
File: mail.c Project: zatsepin/core
static int mail_parse_parts(struct mail *mail, struct message_part **parts_r)
{
	const char *structure, *error;
	struct mail_private *pmail = (struct mail_private*)mail;

	/* need to get bodystructure first */
	if (mail_get_special(mail, MAIL_FETCH_IMAP_BODYSTRUCTURE, &structure) < 0)
		return -1;
	if (imap_bodystructure_parse_full(structure, pmail->data_pool, parts_r,
					  &error) < 0) {
		mail_set_critical(mail, "imap_bodystructure_parse() failed: %s",
				  error);
		return -1;
	}
	return 0;
}
Example #13
0
static int
maildir_copy_hardlink(struct mail_save_context *ctx, struct mail *mail)
{
	struct maildir_mailbox *dest_mbox =
		(struct maildir_mailbox *)ctx->transaction->box;
	struct maildir_mailbox *src_mbox;
	struct maildir_filename *mf;
	struct hardlink_ctx do_ctx;
	const char *path, *guid, *dest_fname;
	uoff_t vsize, size;
	enum mail_lookup_abort old_abort;

	if (strcmp(mail->box->storage->name, MAILDIR_STORAGE_NAME) == 0)
		src_mbox = (struct maildir_mailbox *)mail->box;
	else if (strcmp(mail->box->storage->name, "raw") == 0) {
		/* lda uses raw format */
		src_mbox = NULL;
	} else {
		/* Can't hard link files from the source storage */
		return 0;
	}

	/* hard link to tmp/ with a newly generated filename and later when we
	   have uidlist locked, move it to new/cur. */
	dest_fname = maildir_filename_generate();
	memset(&do_ctx, 0, sizeof(do_ctx));
	do_ctx.dest_path =
		t_strdup_printf("%s/tmp/%s", mailbox_get_path(&dest_mbox->box),
				dest_fname);
	if (src_mbox != NULL) {
		/* maildir */
		if (maildir_file_do(src_mbox, mail->uid,
				    do_hardlink, &do_ctx) < 0)
			return -1;
	} else {
		/* raw / lda */
		if (mail_get_special(mail, MAIL_FETCH_UIDL_FILE_NAME,
				     &path) < 0 || *path == '\0')
			return 0;
		if (do_hardlink(dest_mbox, path, &do_ctx) < 0)
			return -1;
	}

	if (!do_ctx.success) {
		/* couldn't copy with hardlinking, fallback to copying */
		return 0;
	}

	/* hardlinked to tmp/, treat as normal copied mail */
	mf = maildir_save_add(ctx, dest_fname, mail);
	if (mail_get_special(mail, MAIL_FETCH_GUID, &guid) == 0) {
		if (*guid != '\0')
			maildir_save_set_dest_basename(ctx, mf, guid);
	}

	/* remember size/vsize if possible */
	old_abort = mail->lookup_abort;
	mail->lookup_abort = MAIL_LOOKUP_ABORT_READ_MAIL;
	if (mail_get_physical_size(mail, &size) < 0)
		size = (uoff_t)-1;
	if (mail_get_virtual_size(mail, &vsize) < 0)
		vsize = (uoff_t)-1;
	maildir_save_set_sizes(mf, size, vsize);
	mail->lookup_abort = old_abort;
	return 1;
}
Example #14
0
static int pop3_map_read(struct mail_storage *storage)
{
	struct pop3_migration_mail_storage *mstorage =
		POP3_MIGRATION_CONTEXT(storage);
	struct mailbox *pop3_box = mstorage->pop3_box;
	struct mailbox_transaction_context *t;
	struct mail_search_args *search_args;
	struct mail_search_context *ctx;
	struct mail *mail;
	struct pop3_uidl_map *map;
	const char *uidl;
	uoff_t size;
	int ret = 0;

	if (array_is_created(&mstorage->pop3_uidl_map)) {
		/* already read these, just reset the imap_uids */
		array_foreach_modifiable(&mstorage->pop3_uidl_map, map)
			map->imap_uid = 0;
		return 0;
	}
	i_array_init(&mstorage->pop3_uidl_map, 128);

	if (mailbox_sync(pop3_box, 0) < 0) {
		i_error("pop3_migration: Couldn't sync mailbox %s: %s",
			pop3_box->vname, mailbox_get_last_error(pop3_box, NULL));
		return -1;
	}

	t = mailbox_transaction_begin(pop3_box, 0);
	search_args = mail_search_build_init();
	mail_search_build_add_all(search_args);
	ctx = mailbox_search_init(t, search_args, NULL,
				  MAIL_FETCH_VIRTUAL_SIZE, NULL);
	mail_search_args_unref(&search_args);

	while (mailbox_search_next(ctx, &mail)) {
		if (mail_get_virtual_size(mail, &size) < 0) {
			i_error("pop3_migration: Failed to get size for msg %u: %s",
				mail->seq,
				mailbox_get_last_error(pop3_box, NULL));
			ret = -1;
			break;
		}
		if (mail_get_special(mail, MAIL_FETCH_UIDL_BACKEND, &uidl) < 0) {
			i_error("pop3_migration: Failed to get UIDL for msg %u: %s",
				mail->seq,
				mailbox_get_last_error(pop3_box, NULL));
			ret = -1;
			break;
		}
		if (*uidl == '\0') {
			i_warning("pop3_migration: UIDL for msg %u is empty",
				  mail->seq);
			continue;
		}

		map = array_append_space(&mstorage->pop3_uidl_map);
		map->pop3_seq = mail->seq;
		map->pop3_uidl = p_strdup(storage->pool, uidl);
		map->size = size;
	}

	if (mailbox_search_deinit(&ctx) < 0)
		ret = -1;
	(void)mailbox_transaction_commit(&t);
	return ret;
}
Example #15
0
/* Returns >0 = matched, 0 = not matched, -1 = unknown */
static int search_arg_match_cached(struct index_search_context *ctx,
				   struct mail_search_arg *arg)
{
	const char *str;
	struct tm *tm;
	uoff_t virtual_size;
	time_t date;
	int tz_offset;
	bool have_tz_offset;

	switch (arg->type) {
	/* internal dates */
	case SEARCH_BEFORE:
	case SEARCH_ON:
	case SEARCH_SINCE:
		have_tz_offset = FALSE; tz_offset = 0; date = (time_t)-1;
		switch (arg->value.date_type) {
		case MAIL_SEARCH_DATE_TYPE_SENT:
			if (mail_get_date(ctx->mail, &date, &tz_offset) < 0)
				return -1;
			have_tz_offset = TRUE;
			break;
		case MAIL_SEARCH_DATE_TYPE_RECEIVED:
			if (mail_get_received_date(ctx->mail, &date) < 0)
				return -1;
			break;
		case MAIL_SEARCH_DATE_TYPE_SAVED:
			if (mail_get_save_date(ctx->mail, &date) < 0)
				return -1;
			break;
		}

		if ((arg->value.search_flags &
		     MAIL_SEARCH_ARG_FLAG_USE_TZ) == 0) {
			if (!have_tz_offset) {
				tm = localtime(&date);
				tz_offset = utc_offset(tm, date);
			}
			date += tz_offset * 60;
		}

		switch (arg->type) {
		case SEARCH_BEFORE:
			return date < arg->value.time;
		case SEARCH_ON:
			return date >= arg->value.time &&
				date < arg->value.time + 3600*24;
		case SEARCH_SINCE:
			return date >= arg->value.time;
		default:
			/* unreachable */
			break;
		}

	/* sizes */
	case SEARCH_SMALLER:
	case SEARCH_LARGER:
		if (mail_get_virtual_size(ctx->mail, &virtual_size) < 0)
			return -1;

		if (arg->type == SEARCH_SMALLER)
			return virtual_size < arg->value.size;
		else
			return virtual_size > arg->value.size;

	case SEARCH_GUID:
		if (mail_get_special(ctx->mail, MAIL_FETCH_GUID, &str) < 0)
			return -1;
		return strcmp(str, arg->value.str) == 0;
	default:
		return -1;
	}
}