Пример #1
0
static int imapc_mail_get_guid(struct mail *_mail, const char **value_r)
{
	struct index_mail *imail = (struct index_mail *)_mail;
	struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
	const enum index_cache_field cache_idx =
		imail->ibox->cache_fields[MAIL_CACHE_GUID].idx;

	if (imapc_mail_get_cached_guid(_mail)) {
		*value_r = imail->data.guid;
		return 0;
	}

	/* GUID not in cache, fetch it */
	if (mbox->guid_fetch_field_name != NULL) {
		if (imapc_mail_fetch(_mail, MAIL_FETCH_GUID, NULL) < 0)
			return -1;
		if (imail->data.guid == NULL) {
			(void)imapc_mail_failed(_mail, mbox->guid_fetch_field_name);
			return -1;
		}
	} else {
		/* use hash of message headers as the GUID */
		if (imapc_mail_get_hdr_hash(imail) < 0)
			return -1;
	}

	index_mail_cache_add_idx(imail, cache_idx,
				 imail->data.guid, strlen(imail->data.guid)+1);
	*value_r = imail->data.guid;
	return 0;
}
Пример #2
0
static int
imapc_mail_get_header_stream(struct mail *_mail,
			     struct mailbox_header_lookup_ctx *headers,
			     struct istream **stream_r)
{
	struct imapc_mail *mail = (struct imapc_mail *)_mail;
	struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
	enum mail_lookup_abort old_abort = _mail->lookup_abort;
	int ret;

	if (mail->imail.data.access_part != 0 ||
	    !IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_FETCH_HEADERS)) {
		/* we're going to be reading the header/body anyway */
		return index_mail_get_header_stream(_mail, headers, stream_r);
	}

	/* see if the wanted headers are already in cache */
	_mail->lookup_abort = MAIL_LOOKUP_ABORT_READ_MAIL;
	ret = index_mail_get_header_stream(_mail, headers, stream_r);
	_mail->lookup_abort = old_abort;
	if (ret == 0)
		return 0;

	/* fetch only the wanted headers */
	if (imapc_mail_fetch(_mail, 0, headers->name) < 0)
		return -1;
	/* the headers should cached now. */
	return index_mail_get_header_stream(_mail, headers, stream_r);
}
Пример #3
0
static int imapc_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
{
	struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
	struct index_mail *mail = (struct index_mail *)_mail;
	struct index_mail_data *data = &mail->data;
	struct istream *input;
	uoff_t old_offset;
	int ret;

	if (data->physical_size == (uoff_t)-1) {
		(void)index_mail_get_physical_size(_mail, size_r);
		if (data->physical_size != (uoff_t)-1) {
			*size_r = data->physical_size;
			return 0;
		}
	}

	if (IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_RFC822_SIZE) &&
	    data->stream == NULL) {
		/* trust RFC822.SIZE to be correct */
		if (imapc_mail_fetch(_mail, MAIL_FETCH_PHYSICAL_SIZE) < 0)
			return -1;
		if (data->physical_size == (uoff_t)-1) {
			if (imapc_mail_failed(_mail, "RFC822.SIZE") < 0)
				return -1;
			/* assume that the server never returns RFC822.SIZE
			   for this mail (see BODY[] failure handling) */
			data->physical_size = 0;
		}
		*size_r = data->physical_size;
		return 0;
	}

	old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
	if (mail_get_stream(_mail, NULL, NULL, &input) < 0)
		return -1;
	i_stream_seek(data->stream, old_offset);

	ret = i_stream_get_size(data->stream, TRUE,
				&data->physical_size);
	if (ret <= 0) {
		i_assert(ret != 0);
		mail_storage_set_critical(_mail->box->storage,
					  "imapc: stat(%s) failed: %m",
					  i_stream_get_name(data->stream));
		return -1;
	}
	*size_r = data->physical_size;
	return 0;
}
Пример #4
0
static int
imapc_mail_get_stream(struct mail *_mail, bool get_body,
		      struct message_size *hdr_size,
		      struct message_size *body_size, struct istream **stream_r)
{
	struct imapc_mail *mail = (struct imapc_mail *)_mail;
	struct index_mail_data *data = &mail->imail.data;
	enum mail_fetch_field fetch_field;

	if (get_body && !mail->body_fetched &&
	    mail->imail.data.stream != NULL) {
		/* we've fetched the header, but we need the body now too */
		index_mail_close_streams(&mail->imail);
	}

	if (data->stream == NULL) {
		if (!data->initialized) {
			/* coming here from mail_set_seq() */
			mail_set_aborted(_mail);
			return -1;
		}
		fetch_field = get_body ||
			(data->access_part & READ_BODY) != 0 ?
			MAIL_FETCH_STREAM_BODY : MAIL_FETCH_STREAM_HEADER;
		if (imapc_mail_fetch(_mail, fetch_field) < 0)
			return -1;

		if (data->stream == NULL) {
			if (imapc_mail_failed(_mail, "BODY[]") < 0)
				return -1;
			i_assert(data->stream == NULL);

			/* this could be either a temporary server bug, or the
			   server may permanently just not return anything for
			   this mail. the latter happens at least with Exchange
			   when trying to fetch calendar "mails", so we'll just
			   return them as empty mails instead of disconnecting
			   the client. */
			mail->body_fetched = TRUE;
			data->stream = i_stream_create_from_data(&uchar_nul, 0);
			imapc_mail_init_stream(mail, TRUE);
		}
	}

	return index_mail_init_stream(&mail->imail, hdr_size, body_size,
				      stream_r);
}
Пример #5
0
static int
imapc_mail_get_stream(struct mail *_mail, bool get_body,
		      struct message_size *hdr_size,
		      struct message_size *body_size, struct istream **stream_r)
{
	struct imapc_mail *mail = (struct imapc_mail *)_mail;
	struct index_mail_data *data = &mail->imail.data;
	enum mail_fetch_field fetch_field;

	if (get_body && !mail->body_fetched &&
	    mail->imail.data.stream != NULL) {
		/* we've fetched the header, but we need the body now too */
		index_mail_close_streams(&mail->imail);
	}

	if (data->stream == NULL) {
		if (!data->initialized) {
			/* coming here from mail_set_seq() */
			mail_set_aborted(_mail);
			return -1;
		}
		fetch_field = get_body ||
			(data->access_part & READ_BODY) != 0 ?
			MAIL_FETCH_STREAM_BODY : MAIL_FETCH_STREAM_HEADER;
		if (imapc_mail_fetch(_mail, fetch_field, NULL) < 0)
			return -1;

		if (data->stream == NULL) {
			if (imapc_mail_failed(_mail, "BODY[]"))
				return -1;
			i_assert(data->stream == NULL);

			/* return the broken email as empty */
			mail->body_fetched = TRUE;
			data->stream = i_stream_create_from_data(NULL, 0);
			imapc_mail_init_stream(mail);
		}
	}

	return index_mail_init_stream(&mail->imail, hdr_size, body_size,
				      stream_r);
}
Пример #6
0
static int imapc_mail_get_received_date(struct mail *_mail, time_t *date_r)
{
	struct index_mail *mail = (struct index_mail *)_mail;
	struct index_mail_data *data = &mail->data;

	if (index_mail_get_received_date(_mail, date_r) == 0)
		return 0;

	if (data->received_date == (time_t)-1) {
		if (imapc_mail_fetch(_mail, MAIL_FETCH_RECEIVED_DATE) < 0)
			return -1;
		if (data->received_date == (time_t)-1) {
			if (imapc_mail_failed(_mail, "INTERNALDATE") < 0)
				return -1;
			/* assume that the server never returns INTERNALDATE
			   for this mail (see BODY[] failure handling) */
			data->received_date = 0;
		}
	}
	*date_r = data->received_date;
	return 0;
}
Пример #7
0
static int imapc_mail_get_guid(struct mail *_mail, const char **value_r)
{
	struct index_mail *imail = (struct index_mail *)_mail;
	struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
	const enum index_cache_field cache_idx =
		imail->ibox->cache_fields[MAIL_CACHE_GUID].idx;
	string_t *str;

	if (imail->data.guid != NULL) {
		*value_r = imail->data.guid;
		return 0;
	}

	str = str_new(imail->mail.data_pool, 64);
	if (mail_cache_lookup_field(_mail->transaction->cache_view,
				    str, imail->mail.mail.seq, cache_idx) > 0) {
		*value_r = str_c(str);
		return 0;
	}

	/* GUID not in cache, fetch it */
	if (mbox->guid_fetch_field_name != NULL) {
		if (imapc_mail_fetch(_mail, MAIL_FETCH_GUID) < 0)
			return -1;
		if (imail->data.guid == NULL) {
			(void)imapc_mail_failed(_mail, mbox->guid_fetch_field_name);
			return -1;
		}
	} else {
		/* use hash of message headers as the GUID */
		if (imapc_mail_get_hdr_hash(imail) < 0)
			return -1;
	}

	index_mail_cache_add_idx(imail, cache_idx,
				 imail->data.guid, strlen(imail->data.guid)+1);
	*value_r = imail->data.guid;
	return 0;
}