Ejemplo n.º 1
0
Archivo: mail.c Proyecto: zatsepin/core
int mail_set_attachment_keywords(struct mail *mail)
{
	int ret;
	const struct mail_storage_settings *mail_set =
		mail_storage_get_settings(mailbox_get_storage(mail->box));

	const char *const keyword_has_attachment[] = {
		MAIL_KEYWORD_HAS_ATTACHMENT,
		NULL,
	};
	const char *const keyword_has_no_attachment[] = {
		MAIL_KEYWORD_HAS_NO_ATTACHMENT,
		NULL
	};
	struct message_part_attachment_settings set = {
		.content_type_filter =
			mail_set->parsed_mail_attachment_content_type_filter,
		.exclude_inlined =
			mail_set->parsed_mail_attachment_exclude_inlined,
	};
	struct mail_keywords *kw_has = NULL, *kw_has_not = NULL;

	/* walk all parts and see if there is an attachment */
	struct message_part *parts;
	if (mail_get_parts(mail, &parts) < 0) {
		mail_set_critical(mail, "Failed to add attachment keywords: "
				  "mail_get_parts() failed: %s",
				  mail_storage_get_last_internal_error(mail->box->storage, NULL));
		ret = -1;
	} else if (parts->data == NULL &&
		   mail_parse_parts(mail, &parts) < 0) {
		ret = -1;
	} else if (mailbox_keywords_create(mail->box, keyword_has_attachment, &kw_has) < 0 ||
		   mailbox_keywords_create(mail->box, keyword_has_no_attachment, &kw_has_not) < 0) {
		mail_set_critical(mail, "Failed to add attachment keywords: "
				  "mailbox_keywords_create(%s) failed: %s",
				  mailbox_get_vname(mail->box),
				  mail_storage_get_last_internal_error(mail->box->storage, NULL));
		ret = -1;
	} else {
		bool has_attachment = mail_message_has_attachment(parts, &set);

		/* make sure only one of the keywords gets set */
		mail_update_keywords(mail, MODIFY_REMOVE, has_attachment ? kw_has_not : kw_has);
		mail_update_keywords(mail, MODIFY_ADD, has_attachment ? kw_has : kw_has_not);
		ret = has_attachment ? 1 : 0;
	}

	if (kw_has != NULL)
		mailbox_keywords_unref(&kw_has);
	if (kw_has_not != NULL)
		mailbox_keywords_unref(&kw_has_not);

	return ret;
}
static int
cmd_flags_run_box(struct flags_cmd_context *ctx,
		  const struct mailbox_info *info)
{
	struct doveadm_mail_iter *iter;
	struct mailbox *box;
	struct mail *mail;
	struct mail_keywords *kw = NULL;

	if (doveadm_mail_iter_init(&ctx->ctx, info, ctx->ctx.search_args,
				   0, NULL, &iter) < 0)
		return -1;
	box = doveadm_mail_iter_get_mailbox(iter);

	if (ctx->keywords != NULL) {
		if (mailbox_keywords_create(box, ctx->keywords, &kw) < 0) {
			i_error("Invalid keywords: %s",
				mailbox_get_last_error(box, NULL));
			(void)doveadm_mail_iter_deinit(&iter);
			ctx->ctx.exit_code = DOVEADM_EX_NOTPOSSIBLE;
			return -1;
		}
	}

	while (doveadm_mail_iter_next(iter, &mail)) {
		mail_update_flags(mail, ctx->modify_type, ctx->flags);
		if (kw != NULL)
			mail_update_keywords(mail, ctx->modify_type, kw);
	}
	if (kw != NULL)
		mailbox_keywords_unref(&kw);
	return doveadm_mail_iter_deinit(&iter);
}
Ejemplo n.º 3
0
static bool
store_parse_args(struct imap_store_context *ctx, const struct imap_arg *args)
{
	struct client_command_context *cmd = ctx->cmd;
	const struct imap_arg *list_args;
	const char *type;
	const char *const *keywords_list = NULL;

	ctx->max_modseq = (uint64_t)-1;
	if (imap_arg_get_list(args, &list_args)) {
		if (!store_parse_modifiers(ctx, list_args))
			return FALSE;
		args++;
	}

	if (!imap_arg_get_astring(args, &type) ||
	    !get_modify_type(ctx, type)) {
		client_send_command_error(cmd, "Invalid arguments.");
		return FALSE;
	}
	args++;

	if (imap_arg_get_list(args, &list_args)) {
		if (!client_parse_mail_flags(cmd, list_args,
					     &ctx->flags, &keywords_list))
			return FALSE;
	} else {
		if (!client_parse_mail_flags(cmd, args,
					     &ctx->flags, &keywords_list))
			return FALSE;
	}

	if (keywords_list != NULL || ctx->modify_type == MODIFY_REPLACE) {
		if (mailbox_keywords_create(cmd->client->mailbox, keywords_list,
					    &ctx->keywords) < 0) {
			/* invalid keywords */
			client_send_box_error(cmd, cmd->client->mailbox);
			return FALSE;
		}
	}
	return TRUE;
}
Ejemplo n.º 4
0
static int
cmd_append_handle_args(struct client_command_context *cmd,
		       const struct imap_arg *args, bool *nonsync_r)
{
	struct client *client = cmd->client;
	struct cmd_append_context *ctx = cmd->context;
	const struct imap_arg *flags_list;
	const struct imap_arg *cat_list = NULL;
	enum mail_flags flags;
	const char *const *keywords_list;
	struct mail_keywords *keywords;
	struct istream *input;
	const char *internal_date_str;
	time_t internal_date;
	int ret, timezone_offset;
	bool valid;

	/* [<flags>] */
	if (!imap_arg_get_list(args, &flags_list))
		flags_list = NULL;
	else
		args++;

	/* [<internal date>] */
	if (args->type != IMAP_ARG_STRING)
		internal_date_str = NULL;
	else {
		internal_date_str = imap_arg_as_astring(args);
		args++;
	}

	/* <message literal> | CATENATE (..) */
	valid = FALSE;
	*nonsync_r = FALSE;
	ctx->catenate = FALSE;
	if (imap_arg_get_literal_size(args, &ctx->literal_size)) {
		*nonsync_r = args->type == IMAP_ARG_LITERAL_SIZE_NONSYNC;
		ctx->binary_input = args->literal8;
		valid = TRUE;
	} else if (!imap_arg_atom_equals(args, "CATENATE")) {
		/* invalid */
	} else if (!imap_arg_get_list(++args, &cat_list)) {
		/* invalid */
	} else {
		valid = TRUE;
		ctx->catenate = TRUE;
		/* We'll do BINARY conversion only if the CATENATE's first
		   part is a literal8. If it doesn't and a literal8 is seen
		   later we'll abort the append with UNKNOWN-CTE. */
		ctx->binary_input = imap_arg_atom_equals(&cat_list[0], "TEXT") &&
			cat_list[1].literal8;

	}
	if (!IMAP_ARG_IS_EOL(&args[1]))
		valid = FALSE;
	if (!valid) {
		client->input_skip_line = TRUE;
		if (!ctx->failed)
			client_send_command_error(cmd, "Invalid arguments.");
		return -1;
	}

	if (flags_list == NULL || ctx->failed) {
		flags = 0;
		keywords = NULL;
	} else {
		if (!client_parse_mail_flags(cmd, flags_list,
					     &flags, &keywords_list))
			return -1;
		if (keywords_list == NULL)
			keywords = NULL;
		else if (mailbox_keywords_create(ctx->box, keywords_list,
						 &keywords) < 0) {
			/* invalid keywords - delay failure */
			client_send_box_error(cmd, ctx->box);
			ctx->failed = TRUE;
			keywords = NULL;
		}
	}

	if (internal_date_str == NULL || ctx->failed) {
		/* no time given, default to now. */
		internal_date = (time_t)-1;
		timezone_offset = 0;
	} else if (!imap_parse_datetime(internal_date_str,
					&internal_date, &timezone_offset)) {
		client_send_command_error(cmd, "Invalid internal date.");
		if (keywords != NULL)
			mailbox_keywords_unref(&keywords);
		return -1;
	}

	if (internal_date != (time_t)-1 &&
	    internal_date > ioloop_time + INTERNALDATE_MAX_FUTURE_SECS) {
		/* the client specified a time in the future, set it to now. */
		internal_date = (time_t)-1;
		timezone_offset = 0;
	}

	if (cat_list != NULL) {
		ctx->cat_msg_size = 0;
		ctx->input = i_stream_create_chain(&ctx->catchain);
	} else {
		if (ctx->literal_size == 0) {
			/* no message data, abort */
			if (!ctx->failed) {
				client_send_tagline(cmd,
					"NO Can't save a zero byte message.");
				ctx->failed = TRUE;
			}
			if (!*nonsync_r) {
				if (keywords != NULL)
					mailbox_keywords_unref(&keywords);
				return -1;
			}
			/* {0+} used. although there isn't any point in using
			   MULTIAPPEND here and adding more messages, it is
			   technically valid so we'll continue parsing.. */
		}
		ctx->litinput = i_stream_create_limit(client->input, ctx->literal_size);
		ctx->input = ctx->litinput;
		i_stream_ref(ctx->input);
	}
	if (ctx->binary_input) {
		input = i_stream_create_binary_converter(ctx->input);
		i_stream_unref(&ctx->input);
		ctx->input = input;
	}

	if (!ctx->failed) {
		/* save the mail */
		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);
		if (mailbox_save_begin(&ctx->save_ctx, ctx->input) < 0) {
			/* save initialization failed */
			client_send_box_error(cmd, ctx->box);
			ctx->failed = TRUE;
		}
	}
	if (keywords != NULL)
		mailbox_keywords_unref(&keywords);
	ctx->count++;

	if (cat_list == NULL) {
		/* normal APPEND */
		return 1;
	} else if (cat_list->type == IMAP_ARG_EOL) {
		/* zero parts */
		if (!ctx->failed)
			client_send_command_error(cmd, "Empty CATENATE list.");
		client->input_skip_line = TRUE;
		return -1;
	} else if ((ret = cmd_append_catenate(cmd, cat_list, nonsync_r)) < 0) {
		/* invalid parameters, abort immediately */
		return -1;
	} else if (ret == 0) {
		/* CATENATE consisted only of URLs */
		return 0;
	} else {
		/* TEXT part found from CATENATE */
		return 1;
	}
}