changeset 6280:eb7c9d8ece54 HEAD

mail_*() APIs changed to return int and return the actual data as pointer. Changed some code to do error handling a bit better.
author Timo Sirainen <tss@iki.fi>
date Sun, 12 Aug 2007 19:40:54 +0300
parents f52e7d1402b5
children ffe50f268e4e
files src/deliver/deliver.c src/deliver/mail-send.c src/imap/imap-fetch-body.c src/imap/imap-fetch.c src/imap/imap-thread.c src/lib-storage/index/cydir/cydir-mail.c src/lib-storage/index/dbox/dbox-mail.c src/lib-storage/index/index-mail-headers.c src/lib-storage/index/index-mail.c src/lib-storage/index/index-mail.h src/lib-storage/index/index-search.c src/lib-storage/index/index-sort.c src/lib-storage/index/maildir/maildir-mail.c src/lib-storage/index/maildir/maildir-save.c src/lib-storage/index/mbox/mbox-mail.c src/lib-storage/mail-copy.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.h src/lib-storage/mail.c src/plugins/expire/expire-plugin.c src/plugins/expire/expire-tool.c src/plugins/fts/fts-storage.c src/plugins/mail-log/mail-log-plugin.c src/plugins/quota/quota-count.c src/plugins/quota/quota-storage.c src/plugins/quota/quota.c src/plugins/trash/trash-plugin.c src/pop3/client.c src/pop3/commands.c
diffstat 29 files changed, 660 insertions(+), 595 deletions(-) [+]
line wrap: on
line diff
--- a/src/deliver/deliver.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/deliver/deliver.c	Sun Aug 12 19:40:54 2007 +0300
@@ -152,8 +152,10 @@
 	else
 		ret = mailbox_transaction_commit(&t, 0);
 
-	msgid = mail_get_first_header(mail, "Message-ID");
-	msgid = msgid == NULL ? "" : str_sanitize(msgid, 80);
+	if (mail_get_first_header(mail, "Message-ID", &msgid) <= 0)
+		msgid = "";
+	else
+		msgid = str_sanitize(msgid, 80);
 	mailbox_name = str_sanitize(mailbox_get_name(box), 80);
 
 	if (ret == 0) {
@@ -175,11 +177,11 @@
 	struct message_address *addr;
 	const char *str;
 
-	str = mail_get_first_header(mail, "Return-Path");
-	addr = str == NULL ? NULL :
-		message_address_parse(pool_datastack_create(),
-				      (const unsigned char *)str,
-				      strlen(str), 1, FALSE);
+	if (mail_get_first_header(mail, "Return-Path", &str) <= 0)
+		return NULL;
+	addr = message_address_parse(pool_datastack_create(),
+				     (const unsigned char *)str,
+				     strlen(str), 1, FALSE);
 	return addr == NULL || addr->mailbox == NULL || addr->domain == NULL ||
 		*addr->mailbox == '\0' || *addr->domain == '\0' ?
 		NULL : t_strconcat(addr->mailbox, "@", addr->domain, NULL);
@@ -799,9 +801,9 @@
 			return EX_TEMPFAIL;
 		}
 
-		msgid = mail_get_first_header(mail, "Message-ID");
-		i_info("msgid=%s: Rejected: %s",
-		       msgid == NULL ? "" : str_sanitize(msgid, 80),
+		if (mail_get_first_header(mail, "Message-ID", &msgid) <= 0)
+			msgid = "";
+		i_info("msgid=%s: Rejected: %s", str_sanitize(msgid, 80),
 		       str_sanitize(error_string, 512));
 
 		/* we'll have to reply with permanent failure */
--- a/src/deliver/mail-send.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/deliver/mail-send.c	Sun Aug 12 19:40:54 2007 +0300
@@ -31,13 +31,16 @@
 		{ '\0', NULL }
 	};
 	struct var_expand_table *tab;
+	const char *subject;
 
 	tab = t_malloc(sizeof(static_tab));
 	memcpy(tab, static_tab, sizeof(static_tab));
 
 	tab[0].value = "\r\n";
 	tab[1].value = reason;
-	tab[2].value = str_sanitize(mail_get_first_header(mail, "Subject"), 80);
+	if (mail_get_first_header(mail, "Subject", &subject) <= 0)
+		subject = "";
+	tab[2].value = str_sanitize(subject, 80);
 	tab[3].value = recipient;
 
 	return tab;
@@ -57,7 +60,8 @@
     size_t size;
     int ret;
 
-    orig_msgid = mail_get_first_header(mail, "Message-ID");
+    if (mail_get_first_header(mail, "Message-ID", &orig_msgid) < 0)
+	    orig_msgid = NULL;
     return_addr = deliver_get_return_address(mail);
     if (return_addr == NULL) {
 	    i_info("msgid=%s: Return-Path missing, rejection reason: %s",
@@ -102,9 +106,8 @@
 	    boundary);
     fprintf(f, "Reporting-UA: %s; Dovecot Mail Delivery Agent\r\n",
 	    deliver_set->hostname);
-    str = mail_get_first_header(mail, "Original-Recipient");
-    if (str != NULL)
-	fprintf(f, "Original-Recipient: rfc822; %s\r\n", str);
+    if (mail_get_first_header(mail, "Original-Recipient", &str) > 0)
+	    fprintf(f, "Original-Recipient: rfc822; %s\r\n", str);
     fprintf(f, "Final-Recipient: rfc822; %s\r\n", recipient);
 
     if (orig_msgid != NULL)
@@ -116,8 +119,7 @@
     /* original message's headers */
     fprintf(f, "--%s\r\nContent-Type: message/rfc822\r\n\r\n", boundary);
 
-    input = mail_get_stream(mail, &hdr_size, NULL);
-    if (input != NULL) {
+    if (mail_get_stream(mail, &hdr_size, NULL, &input) == 0) {
 	    /* Note: If you add more headers, they need to be sorted.
 	       We'll drop Content-Type because we're not including the message
 	       body, and having a multipart Content-Type may confuse some
@@ -155,16 +157,16 @@
     struct smtp_client *smtp_client;
     FILE *f;
     const unsigned char *data;
+    const char *return_path;
     size_t size;
     int ret;
 
-    input = mail_get_stream(mail, NULL, NULL);
-    if (input == NULL)
+    if (mail_get_stream(mail, NULL, NULL, &input) < 0)
 	    return -1;
 
-    smtp_client = smtp_client_open(forwardto,
-				   mail_get_first_header(mail, "Return-Path"),
-				   &f);
+    if (mail_get_first_header(mail, "Return-Path", &return_path) <= 0)
+	    return_path = "";
+    smtp_client = smtp_client_open(forwardto, return_path, &f);
 
     input = i_stream_create_header_filter(input, HEADER_FILTER_EXCLUDE |
                                           HEADER_FILTER_NO_CR, hide_headers,
--- a/src/imap/imap-fetch-body.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/imap/imap-fetch-body.c	Sun Aug 12 19:40:54 2007 +0300
@@ -325,10 +325,9 @@
 	const struct message_size *fetch_size;
 	struct message_size hdr_size, body_size;
 
-	ctx->cur_input =
-		mail_get_stream(mail, &hdr_size,
-				body->section[0] == 'H' ? NULL : &body_size);
-	if (ctx->cur_input == NULL)
+	if (mail_get_stream(mail, &hdr_size,
+			    body->section[0] == 'H' ? NULL : &body_size,
+			    &ctx->cur_input) < 0)
 		return -1;
 
 	i_stream_ref(ctx->cur_input);
@@ -416,8 +415,7 @@
 fetch_body_header_partial(struct imap_fetch_context *ctx, struct mail *mail,
 			  const struct imap_fetch_body_data *body)
 {
-	ctx->cur_input = mail_get_stream(mail, NULL, NULL);
-	if (ctx->cur_input == NULL)
+	if (mail_get_stream(mail, NULL, NULL, &ctx->cur_input) < 0)
 		return -1;
 
 	i_stream_ref(ctx->cur_input);
@@ -439,8 +437,7 @@
 		return 0;
 	}
 
-	ctx->cur_input = mail_get_header_stream(mail, body->header_ctx);
-	if (ctx->cur_input == NULL)
+	if (mail_get_header_stream(mail, body->header_ctx, &ctx->cur_input) < 0)
 		return -1;
 
 	i_stream_ref(ctx->cur_input);
@@ -466,8 +463,7 @@
 	const char *path;
 	unsigned int num;
 
-	part = mail_get_parts(mail);
-	if (part == NULL)
+	if (mail_get_parts(mail, &part) < 0)
 		return -1;
 
 	path = body->section;
@@ -527,8 +523,7 @@
 		return 1;
 	}
 
-	ctx->cur_input = mail_get_stream(mail, NULL, NULL);
-	if (ctx->cur_input == NULL)
+	if (mail_get_stream(mail, NULL, NULL, &ctx->cur_input) < 0)
 		return -1;
 
 	i_stream_ref(ctx->cur_input);
@@ -861,8 +856,7 @@
 {
 	uoff_t size;
 
-	size = mail_get_virtual_size(mail);
-	if (size == (uoff_t)-1)
+	if (mail_get_virtual_size(mail, &size) < 0)
 		return -1;
 
 	str_printfa(ctx->cur_str, "RFC822.SIZE %"PRIuUOFF_T" ", size);
@@ -875,8 +869,7 @@
 	struct message_size hdr_size, body_size;
 	const char *str;
 
-	ctx->cur_input = mail_get_stream(mail, &hdr_size, &body_size);
-	if (ctx->cur_input == NULL)
+	if (mail_get_stream(mail, &hdr_size, &body_size, &ctx->cur_input) < 0)
 		return -1;
 
 	i_stream_ref(ctx->cur_input);
@@ -904,8 +897,7 @@
 	struct message_size hdr_size;
 	const char *str;
 
-	ctx->cur_input = mail_get_stream(mail, &hdr_size, NULL);
-	if (ctx->cur_input == NULL)
+	if (mail_get_stream(mail, &hdr_size, NULL, &ctx->cur_input) < 0)
 		return -1;
 
 	i_stream_ref(ctx->cur_input);
@@ -929,8 +921,7 @@
 	struct message_size hdr_size, body_size;
 	const char *str;
 
-	ctx->cur_input = mail_get_stream(mail, &hdr_size, &body_size);
-	if (ctx->cur_input == NULL)
+	if (mail_get_stream(mail, &hdr_size, &body_size, &ctx->cur_input) < 0)
 		return -1;
 
 	i_stream_ref(ctx->cur_input);
--- a/src/imap/imap-fetch.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/imap/imap-fetch.c	Sun Aug 12 19:40:54 2007 +0300
@@ -403,8 +403,7 @@
 {
 	const char *body;
 
-	body = mail_get_special(mail, MAIL_FETCH_IMAP_BODY);
-	if (body == NULL)
+	if (mail_get_special(mail, MAIL_FETCH_IMAP_BODY, &body) < 0)
 		return -1;
 
 	if (ctx->first)
@@ -438,8 +437,8 @@
 {
 	const char *bodystructure;
 
-	bodystructure = mail_get_special(mail, MAIL_FETCH_IMAP_BODYSTRUCTURE);
-	if (bodystructure == NULL)
+	if (mail_get_special(mail, MAIL_FETCH_IMAP_BODYSTRUCTURE,
+			     &bodystructure) < 0)
 		return -1;
 
 	if (ctx->first)
@@ -473,8 +472,7 @@
 {
 	const char *envelope;
 
-	envelope = mail_get_special(mail, MAIL_FETCH_IMAP_ENVELOPE);
-	if (envelope == NULL)
+	if (mail_get_special(mail, MAIL_FETCH_IMAP_ENVELOPE, &envelope) < 0)
 		return -1;
 
 	if (ctx->first)
@@ -538,14 +536,13 @@
 static int fetch_internaldate(struct imap_fetch_context *ctx, struct mail *mail,
 			      void *context __attr_unused__)
 {
-	time_t time;
+	time_t date;
 
-	time = mail_get_received_date(mail);
-	if (time == (time_t)-1)
+	if (mail_get_received_date(mail, &date) < 0)
 		return -1;
 
 	str_printfa(ctx->cur_str, "INTERNALDATE \"%s\" ",
-		    imap_to_datetime(time));
+		    imap_to_datetime(date));
 	return 1;
 }
 
--- a/src/imap/imap-thread.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/imap/imap-thread.c	Sun Aug 12 19:40:54 2007 +0300
@@ -446,19 +446,24 @@
 
 	t_push();
 
-	sent_date = mail_get_date(mail, NULL);
-	if (sent_date == (time_t)-1)
+	if (mail_get_date(mail, &sent_date, NULL) < 0)
 		sent_date = 0;
 
-	message_id = mail_get_first_header(mail, "message-id");
+	if (mail_get_first_header(mail, "message-id", &message_id) < 0)
+		message_id = NULL;
 	node = update_message(ctx, get_msgid(&message_id), sent_date,
 			      ctx->id_is_uid ? mail->uid : mail->seq);
 
 	/* link references */
-	references = mail_get_first_header(mail, "references");
+	if (mail_get_first_header(mail, "references", &references) < 0)
+		references = NULL;
+
 	if (!link_references(ctx, node, references)) {
-		in_reply_to = mail_get_first_header(mail, "in-reply-to");
-		refid = in_reply_to == NULL ? NULL : get_msgid(&in_reply_to);
+		if (mail_get_first_header(mail, "in-reply-to",
+					  &in_reply_to) <= 0)
+			refid = NULL;
+		else
+			refid = get_msgid(&in_reply_to);
 
 		if (refid != NULL)
 			link_node(ctx, refid, node, TRUE);
@@ -694,8 +699,9 @@
 		if (seq != 0) {
 			mail_set_seq(ctx->mail, seq);
 			t_push();
-                        subject = mail_get_first_header(ctx->mail, "subject");
-			add_base_subject(ctx, subject, node);
+			if (mail_get_first_header(ctx->mail, "subject",
+						  &subject) > 0)
+				add_base_subject(ctx, subject, node);
 			t_pop();
 		}
 	}
--- a/src/lib-storage/index/cydir/cydir-mail.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/index/cydir/cydir-mail.c	Sun Aug 12 19:40:54 2007 +0300
@@ -35,66 +35,69 @@
 	return 0;
 }
 
-static time_t cydir_mail_get_received_date(struct mail *_mail)
+static int cydir_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;
 	struct stat st;
 	uint32_t t;
 
-	(void)index_mail_get_received_date(_mail);
-	if (data->received_date != (time_t)-1)
-		return data->received_date;
+	(void)index_mail_get_received_date(_mail, date_r);
+	if (*date_r != (time_t)-1)
+		return 0;
 
 	if (cydir_mail_stat(_mail, &st) < 0)
-		return (time_t)-1;
+		return -1;
 
 	data->received_date = t = st.st_mtime;
 	index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, &t, sizeof(t));
-	return data->received_date;
+	*date_r = data->received_date;
+	return 0;
 }
 
-static time_t cydir_mail_get_save_date(struct mail *_mail)
+static int cydir_mail_get_save_date(struct mail *_mail, time_t *date_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	struct stat st;
 	uint32_t t;
 
-	(void)index_mail_get_save_date(_mail);
-	if (data->save_date != (time_t)-1)
-		return data->save_date;
+	(void)index_mail_get_save_date(_mail, date_r);
+	if (*date_r != (time_t)-1)
+		return 0;
 
 	if (cydir_mail_stat(_mail, &st) < 0)
 		return (time_t)-1;
 
 	data->save_date = t = st.st_ctime;
 	index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE, &t, sizeof(t));
-	return data->save_date;
+	*date_r = data->save_date;
+	return 0;
 }
 
-static uoff_t cydir_mail_get_physical_size(struct mail *_mail)
+static int cydir_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	struct stat st;
 
-	(void)index_mail_get_physical_size(_mail);
-	if (data->physical_size != (uoff_t)-1)
-		return data->physical_size;
+	(void)index_mail_get_physical_size(_mail, size_r);
+	if (*size_r != (uoff_t)-1)
+		return 0;
 
 	if (cydir_mail_stat(_mail, &st) < 0)
-		return (uoff_t)-1;
+		return -1;
 
 	data->physical_size = data->virtual_size = st.st_size;
 	index_mail_cache_add(mail, MAIL_CACHE_PHYSICAL_FULL_SIZE,
 			     &data->physical_size, sizeof(data->physical_size));
-	return data->physical_size;
+	*size_r = data->physical_size;
+	return 0;
 }
 
-static struct istream *
+static int
 cydir_mail_get_stream(struct mail *_mail, struct message_size *hdr_size,
-		      struct message_size *body_size)
+		      struct message_size *body_size, struct istream **stream_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	const char *path;
@@ -110,13 +113,13 @@
 				mail_storage_set_critical(_mail->box->storage,
 					"open(%s) failed: %m", path);
 			}
-			return NULL;
+			return -1;
 		}
 		mail->data.stream =
 			i_stream_create_fd(fd, MAIL_READ_BLOCK_SIZE, TRUE);
 	}
 
-	return index_mail_init_stream(mail, hdr_size, body_size);
+	return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
 }
 
 struct mail_vfuncs cydir_mail_vfuncs = {
--- a/src/lib-storage/index/dbox/dbox-mail.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-mail.c	Sun Aug 12 19:40:54 2007 +0300
@@ -144,16 +144,16 @@
 	return -1;
 }
 
-static time_t dbox_mail_get_received_date(struct mail *_mail)
+static int dbox_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;
 	uoff_t offset;
 	uint32_t t;
 
-	(void)index_mail_get_received_date(_mail);
-	if (data->received_date != (time_t)-1)
-		return data->received_date;
+	(void)index_mail_get_received_date(_mail, date_r);
+	if (*date_r != (time_t)-1)
+		return 0;
 
 	if (dbox_mail_open(mail, &offset) <= 0)
 		return (time_t)-1;
@@ -165,21 +165,22 @@
 
 	t = data->received_date;
 	index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, &t, sizeof(t));
-	return data->received_date;
+	*date_r = data->received_date;
+	return 0;
 }
 
-static time_t dbox_mail_get_save_date(struct mail *_mail)
+static int dbox_mail_get_save_date(struct mail *_mail, time_t *date_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	uoff_t offset;
 
-	(void)index_mail_get_save_date(_mail);
-	if (data->save_date != (time_t)-1)
-		return data->save_date;
+	(void)index_mail_get_save_date(_mail, date_r);
+	if (*date_r != (time_t)-1)
+		return 0;
 
 	if (dbox_mail_open(mail, &offset) <= 0)
-		return (time_t)-1;
+		return -1;
 	if (data->save_date == (time_t)-1) {
 		/* it's broken and conflicts with our "not found"
 		   return value. change it. */
@@ -188,32 +189,34 @@
 
 	index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE,
 			     &data->save_date, sizeof(data->save_date));
-	return data->save_date;
+	*date_r = data->save_date;
+	return 0;
 }
 
-static uoff_t dbox_mail_get_physical_size(struct mail *_mail)
+static int dbox_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	uoff_t offset;
 
-	(void)index_mail_get_physical_size(_mail);
-	if (data->physical_size != (uoff_t)-1)
-		return data->physical_size;
+	(void)index_mail_get_physical_size(_mail, size_r);
+	if (*size_r != (uoff_t)-1)
+		return 0;
 
 	if (dbox_mail_open(mail, &offset) <= 0)
-		return (uoff_t)-1;
+		return -1;
 
 	index_mail_cache_add(mail, MAIL_CACHE_PHYSICAL_FULL_SIZE,
 			     &data->physical_size, sizeof(data->physical_size));
-	return data->physical_size;
+	*size_r = data->physical_size;
+	return 0;
 
 }
 
-static struct istream *
-dbox_mail_get_stream(struct mail *_mail,
-		     struct message_size *hdr_size,
-		     struct message_size *body_size)
+static int dbox_mail_get_stream(struct mail *_mail,
+				struct message_size *hdr_size,
+				struct message_size *body_size,
+				struct istream **stream_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct dbox_mailbox *mbox = (struct dbox_mailbox *)mail->ibox;
@@ -221,7 +224,7 @@
 
 	if (mail->data.stream == NULL) {
 		if (dbox_mail_open(mail, &offset) <= 0)
-			return NULL;
+			return -1;
 
 		offset += mbox->file->mail_header_size;
 		mail->data.stream =
@@ -229,7 +232,7 @@
 					      mbox->file->seeked_mail_size);
 	}
 
-	return index_mail_init_stream(mail, hdr_size, body_size);
+	return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
 }
 
 struct mail_vfuncs dbox_mail_vfuncs = {
--- a/src/lib-storage/index/index-mail-headers.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/index/index-mail-headers.c	Sun Aug 12 19:40:54 2007 +0300
@@ -387,11 +387,12 @@
 			     struct mailbox_header_lookup_ctx *headers)
 {
 	struct index_mail_data *data = &mail->data;
+	struct istream *input;
 	uoff_t old_offset;
 
 	old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
 
-	if (mail_get_stream(&mail->mail.mail, NULL, NULL) == NULL)
+	if (mail_get_stream(&mail->mail.mail, NULL, NULL, &input) < 0)
 		return -1;
 
 	index_mail_parse_header_init(mail, headers);
@@ -427,7 +428,7 @@
 		index_mail_parse_finish_imap_envelope(mail);
 }
 
-void index_mail_headers_get_envelope(struct index_mail *mail)
+int index_mail_headers_get_envelope(struct index_mail *mail)
 {
 	struct mailbox_header_lookup_ctx *header_ctx;
 	struct istream *stream;
@@ -439,7 +440,9 @@
 	mail->data.save_envelope = TRUE;
 	header_ctx = mailbox_header_lookup_init(&mail->ibox->box,
 						imap_envelope_headers);
-	stream = mail_get_header_stream(&mail->mail.mail, header_ctx);
+	if (mail_get_header_stream(&mail->mail.mail, header_ctx, &stream) < 0)
+		return -1;
+
 	if (mail->data.envelope == NULL && stream != NULL) {
 		/* we got the headers from cache - parse them to get the
 		   envelope */
@@ -451,6 +454,7 @@
 
 	if (mail->data.stream != NULL)
 		i_stream_seek(mail->data.stream, old_offset);
+	return 0;
 }
 
 static size_t get_header_size(buffer_t *buffer, size_t pos)
@@ -548,8 +552,9 @@
 	return array_idx(&header_values, 0);
 }
 
-static const char *const *
-index_mail_get_raw_headers(struct index_mail *mail, const char *field)
+static int
+index_mail_get_raw_headers(struct index_mail *mail, const char *field,
+			   const char *const **value_r)
 {
 	const char *headers[2], *value;
 	struct mailbox_header_lookup_ctx *headers_ctx;
@@ -569,34 +574,32 @@
 				      mail->data.seq, &field_idx, 1) <= 0) {
 		/* not in cache / error - first see if it's already parsed */
 		p_free(mail->data_pool, dest);
-		if (mail->header_seq == mail->data.seq) {
-			ret = index_mail_header_is_parsed(mail, field_idx);
-			if (ret != -1) {
-				return ret == 0 ? NULL :
-					index_mail_get_parsed_header(mail,
-								     field_idx);
-			}
+		if (mail->header_seq != mail->data.seq) {
+			/* parse */
+			headers[0] = field; headers[1] = NULL;
+			headers_ctx = mailbox_header_lookup_init(
+						&mail->ibox->box, headers);
+			ret = index_mail_parse_headers(mail, headers_ctx);
+			mailbox_header_lookup_deinit(&headers_ctx);
+			if (ret < 0)
+				return -1;
 		}
 
-		/* parse */
-		headers[0] = field; headers[1] = NULL;
-		headers_ctx = mailbox_header_lookup_init(&mail->ibox->box,
-							 headers);
-		ret = index_mail_parse_headers(mail, headers_ctx);
-		mailbox_header_lookup_deinit(&headers_ctx);
-		if (ret < 0)
-			return NULL;
-
-		ret = index_mail_header_is_parsed(mail, field_idx);
-		i_assert(ret != -1);
-		return ret == 0 ? NULL :
-			index_mail_get_parsed_header(mail, field_idx);
+		if ((ret = index_mail_header_is_parsed(mail, field_idx)) <= 0) {
+			/* not found */
+			i_assert(ret != -1);
+			*value_r = p_new(mail->data_pool, const char *, 1);
+			return 0;
+		}
+		*value_r = index_mail_get_parsed_header(mail, field_idx);
+		return 0;
 	}
 	data = buffer_get_modifiable_data(dest, &len);
 
 	if (len == 0) {
 		/* cached as non-existing. */
-		return p_new(mail->data_pool, const char *, 1);
+		*value_r = p_new(mail->data_pool, const char *, 1);
+		return 0;
 	}
 
 	p_array_init(&header_values, mail->data_pool, 4);
@@ -618,7 +621,8 @@
 
 	value = NULL;
 	array_append(&header_values, &value, sizeof(value));
-	return array_idx(&header_values, 0);
+	*value_r = array_idx(&header_values, 0);
+	return 0;
 }
 
 static const char *const *
@@ -651,32 +655,32 @@
 	return decoded_list;
 }
 
-const char *const *index_mail_get_headers(struct mail *_mail, const char *field,
-					  bool decode_to_utf8)
+int index_mail_get_headers(struct mail *_mail, const char *field,
+			   bool decode_to_utf8, const char *const **value_r)
+{
+	struct index_mail *mail = (struct index_mail *)_mail;
+
+	if (index_mail_get_raw_headers(mail, field, value_r) < 0)
+		return -1;
+	if (!decode_to_utf8 || **value_r == NULL)
+		return 0;
+
+	*value_r = index_mail_headers_decode(mail, *value_r, (unsigned int)-1);
+	return 0;
+}
+
+int index_mail_get_first_header(struct mail *_mail, const char *field,
+				bool decode_to_utf8, const char **value_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	const char *const *list;
 
-	list = index_mail_get_raw_headers(mail, field);
-	if (!decode_to_utf8 || list == NULL || *list == NULL)
-		return list;
-
-	return index_mail_headers_decode(mail, list, (unsigned int)-1);
-}
-
-const char *index_mail_get_first_header(struct mail *_mail, const char *field,
-					bool decode_to_utf8)
-{
-	struct index_mail *mail = (struct index_mail *)_mail;
-	const char *const *list;
-
-	list = index_mail_get_raw_headers(mail, field);
-	if (list == NULL || *list == NULL)
-		return NULL;
-
-	if (decode_to_utf8)
+	if (index_mail_get_raw_headers(mail, field, &list) < 0)
+		return -1;
+	if (decode_to_utf8 && list[0] != NULL)
 		list = index_mail_headers_decode(mail, list, 1);
-	return list[0];
+	*value_r = list[0];
+	return list[0] != NULL ? 1 : 0;
 }
 
 static void header_cache_callback(struct message_header_line *hdr,
@@ -688,19 +692,20 @@
 	index_mail_parse_header(NULL, hdr, mail);
 }
 
-struct istream *
-index_mail_get_header_stream(struct mail *_mail,
-			     struct mailbox_header_lookup_ctx *_headers)
+int index_mail_get_header_stream(struct mail *_mail,
+				 struct mailbox_header_lookup_ctx *_headers,
+				 struct istream **stream_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_header_lookup_ctx *headers =
 		(struct index_header_lookup_ctx *)_headers;
+	struct istream *input;
 	string_t *dest;
 
 	if (mail->data.save_bodystructure_header) {
 		/* we have to parse the header. */
 		if (index_mail_parse_headers(mail, _headers) < 0)
-			return NULL;
+			return -1;
 	}
 
 	dest = str_new(mail->data_pool, 256);
@@ -712,13 +717,14 @@
 		mail->data.filter_stream =
 			i_stream_create_from_data(str_data(dest),
 						  str_len(dest));
-		return mail->data.filter_stream;
+		*stream_r = mail->data.filter_stream;
+		return 0;
 	}
 	/* not in cache / error */
 	p_free(mail->data_pool, dest);
 
-	if (mail_get_stream(&mail->mail.mail, NULL, NULL) == NULL)
-		return NULL;
+	if (mail_get_stream(&mail->mail.mail, NULL, NULL, &input) < 0)
+		return -1;
 
 	if (mail->data.filter_stream != NULL)
 		i_stream_destroy(&mail->data.filter_stream);
@@ -730,7 +736,8 @@
 					      HEADER_FILTER_HIDE_BODY,
 					      headers->name, headers->count,
 					      header_cache_callback, mail);
-	return mail->data.filter_stream;
+	*stream_r = mail->data.filter_stream;
+	return 0;
 }
 
 struct mailbox_header_lookup_ctx *
--- a/src/lib-storage/index/index-mail.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/index/index-mail.c	Sun Aug 12 19:40:54 2007 +0300
@@ -34,8 +34,8 @@
 	{ "mime.parts", 0, MAIL_CACHE_FIELD_VARIABLE_SIZE, 0, 0 }
 };
 
-static void index_mail_parse_body(struct index_mail *mail,
-				  enum index_cache_field field);
+static int index_mail_parse_body(struct index_mail *mail,
+				 enum index_cache_field field);
 
 static bool get_cached_parts(struct index_mail *mail)
 {
@@ -98,22 +98,17 @@
 	return ret;
 }
 
-uoff_t index_mail_get_cached_uoff_t(struct index_mail *mail,
-				    enum index_cache_field field)
+bool index_mail_get_cached_uoff_t(struct index_mail *mail,
+				  enum index_cache_field field, uoff_t *size_r)
 {
-	uoff_t uoff;
-
-	if (!index_mail_get_fixed_field(mail,
-					mail->ibox->cache_fields[field].idx,
-					&uoff, sizeof(uoff)))
-		uoff = (uoff_t)-1;
-
-	return uoff;
+	return index_mail_get_fixed_field(mail,
+					  mail->ibox->cache_fields[field].idx,
+					  size_r, sizeof(*size_r));
 }
 
 enum mail_flags index_mail_get_flags(struct mail *_mail)
 {
-	struct index_mail *mail = (struct index_mail *) _mail;
+	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
 	if (index_mailbox_is_recent(mail->ibox, _mail->uid))
@@ -125,7 +120,7 @@
 const char *const *index_mail_get_keywords(struct mail *_mail)
 {
 	static const char *const no_keywords[] = { NULL };
-	struct index_mail *mail = (struct index_mail *) _mail;
+	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	ARRAY_TYPE(keyword_indexes) keyword_indexes_arr;
 	const char *const *names;
@@ -163,77 +158,79 @@
 	return array_idx(&data->keywords, 0);
 }
 
-const struct message_part *index_mail_get_parts(struct mail *_mail)
+int index_mail_get_parts(struct mail *_mail,
+			 const struct message_part **parts_r)
 {
-	struct index_mail *mail = (struct index_mail *) _mail;
+	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
-	if (data->parts != NULL)
-		return data->parts;
-
-	if (get_cached_parts(mail))
-		return data->parts;
+	if (data->parts != NULL || get_cached_parts(mail)) {
+		*parts_r = data->parts;
+		return 0;
+	}
 
 	if (data->parser_ctx == NULL) {
 		if (index_mail_parse_headers(mail, NULL) < 0)
-			return NULL;
+			return -1;
 	}
 
 	data->save_message_parts = TRUE;
-	index_mail_parse_body(mail, 0);
+	if (index_mail_parse_body(mail, 0) < 0)
+		return -1;
 
-	return data->parts;
+	*parts_r = data->parts;
+	return 0;
 }
 
-time_t index_mail_get_received_date(struct mail *_mail)
+int index_mail_get_received_date(struct mail *_mail, time_t *date_r)
 {
-	struct index_mail *mail = (struct index_mail *) _mail;
+	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
 	if (data->received_date == (time_t)-1) {
 		uint32_t t;
 
-		if (!index_mail_get_fixed_field(mail, MAIL_CACHE_RECEIVED_DATE,
+		if (index_mail_get_fixed_field(mail, MAIL_CACHE_RECEIVED_DATE,
 						&t, sizeof(t)))
-			return (time_t)-1;
-
-		data->received_date = t;
+			data->received_date = t;
 	}
 
-	return data->received_date;
+	*date_r = data->received_date;
+	return 0;
 }
 
-time_t index_mail_get_save_date(struct mail *_mail)
+int index_mail_get_save_date(struct mail *_mail, time_t *date_r)
 {
-	struct index_mail *mail = (struct index_mail *) _mail;
+	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
 	if (data->save_date == (time_t)-1) {
 		uint32_t t;
 
-		if (!index_mail_get_fixed_field(mail, MAIL_CACHE_SAVE_DATE,
-						&t, sizeof(t)))
-			return (time_t)-1;
-
-		data->save_date = t;
+		if (index_mail_get_fixed_field(mail, MAIL_CACHE_SAVE_DATE,
+					       &t, sizeof(t)))
+			data->save_date = t;
 	}
 
-	return data->save_date;
+	*date_r = data->save_date;
+	return 0;
 }
 
-static void index_mail_cache_sent_date(struct index_mail *mail)
+static int index_mail_cache_sent_date(struct index_mail *mail)
 {
 	struct index_mail_data *data = &mail->data;
 	const char *str;
 	time_t t;
-	int tz;
+	int ret, tz;
 
 	if (data->sent_date.time != (uint32_t)-1)
-		return;
+		return 0;
 
-	str = mail_get_first_header(&mail->mail.mail, "Date");
-	if (str == NULL || !message_date_parse((const unsigned char *)str,
-					       strlen(str), &t, &tz)) {
+	if ((ret = mail_get_first_header(&mail->mail.mail, "Date", &str)) <= 0)
+		return ret;
+
+	if (!message_date_parse((const unsigned char *)str,
+				strlen(str), &t, &tz)) {
 		/* 0 = not found / invalid */
 		t = 0;
 		tz = 0;
@@ -242,27 +239,29 @@
 	data->sent_date.timezone = tz;
 	index_mail_cache_add(mail, MAIL_CACHE_SENT_DATE,
 			     &data->sent_date, sizeof(data->sent_date));
+	return 0;
 }
 
-time_t index_mail_get_date(struct mail *_mail, int *timezone)
+int index_mail_get_date(struct mail *_mail, time_t *date_r, int *timezone_r)
 {
-	struct index_mail *mail = (struct index_mail *) _mail;
+	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
 	if (data->sent_date.time != (uint32_t)-1) {
-		if (timezone != NULL)
-			*timezone = data->sent_date.timezone;
-		return data->sent_date.time;
+		*date_r = data->sent_date.time;
+		return 0;
 	}
 
 	(void)index_mail_get_fixed_field(mail, MAIL_CACHE_SENT_DATE,
 					 &data->sent_date,
 					 sizeof(data->sent_date));
 
-	index_mail_cache_sent_date(mail);
-	if (timezone != NULL)
-		*timezone = data->sent_date.timezone;
-	return data->sent_date.time;
+	if (index_mail_cache_sent_date(mail) < 0)
+		return -1;
+
+	*timezone_r = data->sent_date.timezone;
+	*date_r = data->sent_date.time;
+	return 0;
 }
 
 static bool get_cached_msgpart_sizes(struct index_mail *mail)
@@ -286,58 +285,56 @@
 	return data->parts != NULL;
 }
 
-uoff_t index_mail_get_cached_virtual_size(struct index_mail *mail)
+bool index_mail_get_cached_virtual_size(struct index_mail *mail, uoff_t *size_r)
 {
-	uoff_t size;
-
-	if (mail->data.virtual_size != (uoff_t)-1)
-		return mail->data.virtual_size;
-
-	size = index_mail_get_cached_uoff_t(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE);
-	if (size != (uoff_t)-1)
-		mail->data.virtual_size = size;
-	else
-		(void)get_cached_msgpart_sizes(mail);
-	return mail->data.virtual_size;
+	if (mail->data.virtual_size == (uoff_t)-1) {
+		if (!index_mail_get_cached_uoff_t(mail,
+						  MAIL_CACHE_VIRTUAL_FULL_SIZE,
+						  &mail->data.virtual_size)) {
+			if (!get_cached_msgpart_sizes(mail))
+				return FALSE;
+		}
+	}
+	*size_r = mail->data.virtual_size;
+	return TRUE;
 }
 
-uoff_t index_mail_get_virtual_size(struct mail *_mail)
+int index_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r)
 {
-	struct index_mail *mail = (struct index_mail *) _mail;
+	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	struct message_size hdr_size, body_size;
+	struct istream *input;
 	uoff_t old_offset;
 
-	if (index_mail_get_cached_virtual_size(mail) != (uoff_t)-1)
-		return data->virtual_size;
+	if (index_mail_get_cached_virtual_size(mail, size_r))
+		return 0;
 
 	old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
-	if (mail_get_stream(_mail, &hdr_size, &body_size) == NULL)
-		return (uoff_t)-1;
+	if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
+		return -1;
 	i_stream_seek(data->stream, old_offset);
 
 	i_assert(data->virtual_size != (uoff_t)-1);
 	index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE,
 			     &data->virtual_size, sizeof(data->virtual_size));
-	return data->virtual_size;
+	*size_r = data->virtual_size;
+	return 0;
 }
 
-uoff_t index_mail_get_physical_size(struct mail *_mail)
+int index_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
 {
-	struct index_mail *mail = (struct index_mail *) _mail;
+	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
-	uoff_t size;
 
-	if (data->physical_size != (uoff_t)-1)
-		return data->physical_size;
-
-	size = index_mail_get_cached_uoff_t(mail,
-					    MAIL_CACHE_PHYSICAL_FULL_SIZE);
-	if (size != (uoff_t)-1)
-		data->physical_size = size;
-	else
-		(void)get_cached_msgpart_sizes(mail);
-	return data->physical_size;
+	if (data->physical_size == (uoff_t)-1) {
+		if (!index_mail_get_cached_uoff_t(mail,
+						  MAIL_CACHE_PHYSICAL_FULL_SIZE,
+						  &data->physical_size))
+			(void)get_cached_msgpart_sizes(mail);
+	}
+	*size_r = data->physical_size;
+	return 0;
 }
 
 void index_mail_cache_add(struct index_mail *mail, enum index_cache_field field,
@@ -606,11 +603,23 @@
 	index_mail_body_parsed_cache_sizes(mail);
 }
 
-static void index_mail_parse_body(struct index_mail *mail,
-				  enum index_cache_field field)
+static int index_mail_stream_check_failure(struct index_mail *mail)
+{
+	if (mail->data.stream->stream_errno == 0)
+		return 0;
+
+	errno = mail->data.stream->stream_errno;
+	mail_storage_set_critical(mail->mail.mail.box->storage,
+		"read(mail, uid=%u) failed: %m", mail->mail.mail.uid);
+	return -1;
+}
+
+static int index_mail_parse_body(struct index_mail *mail,
+				 enum index_cache_field field)
 {
 	struct index_mail_data *data = &mail->data;
 	uoff_t old_offset;
+	int ret;
 
 	i_assert(data->parser_ctx != NULL);
 
@@ -630,16 +639,19 @@
 		message_parser_parse_body(data->parser_ctx,
 			null_message_part_header_callback, NULL);
 	}
+	ret = index_mail_stream_check_failure(mail);
 	index_mail_parse_body_finish(mail, field, FALSE);
 
 	i_stream_seek(data->stream, old_offset);
+	return ret;
 }
 
-struct istream *index_mail_init_stream(struct index_mail *_mail,
-				       struct message_size *hdr_size,
-				       struct message_size *body_size)
+int index_mail_init_stream(struct index_mail *_mail,
+			   struct message_size *hdr_size,
+			   struct message_size *body_size,
+			   struct istream **stream_r)
 {
-	struct index_mail *mail = (struct index_mail *) _mail;
+	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
 	if (hdr_size != NULL || body_size != NULL)
@@ -651,7 +663,7 @@
 			if ((data->access_part & PARSE_HDR) != 0) {
 				(void)get_cached_parts(mail);
 				if (index_mail_parse_headers(mail, NULL) < 0)
-					return NULL;
+					return -1;
 			} else {
 				message_get_header_size(data->stream,
 							&data->hdr_size, NULL);
@@ -666,9 +678,10 @@
 	if (body_size != NULL) {
 		i_stream_seek(data->stream, data->hdr_size.physical_size);
 		if (!data->body_size_set) {
-			if ((data->access_part & PARSE_BODY) != 0)
-				index_mail_parse_body(mail, 0);
-			else {
+			if ((data->access_part & PARSE_BODY) != 0) {
+				if (index_mail_parse_body(mail, 0) < 0)
+					return -1;
+			} else {
 				message_get_body_size(data->stream,
 						      &data->body_size, NULL);
 				data->body_size_set = TRUE;
@@ -686,11 +699,12 @@
 	}
 
 	i_stream_seek(data->stream, 0);
-	return data->stream;
+	*stream_r = data->stream;
+	return 0;
 }
 
-static void index_mail_parse_bodystructure(struct index_mail *mail,
-					   enum index_cache_field field)
+static int index_mail_parse_bodystructure(struct index_mail *mail,
+					  enum index_cache_field field)
 {
 	struct index_mail_data *data = &mail->data;
 
@@ -698,7 +712,7 @@
 		/* we have everything parsed already, but just not written to
 		   a string */
 		index_mail_body_parsed_cache_bodystructure(mail, field);
-		return;
+		return 0;
 	}
 
 	if (data->save_bodystructure_header ||
@@ -708,10 +722,10 @@
 		data->save_bodystructure_body = TRUE;
 		(void)get_cached_parts(mail);
 		if (index_mail_parse_headers(mail, NULL) < 0)
-			return;
+			return -1;
 	}
 
-	index_mail_parse_body(mail, field);
+	return index_mail_parse_body(mail, field);
 }
 
 static void
@@ -725,10 +739,10 @@
 		str_append(str, " NIL NIL NIL");
 }
 
-const char *index_mail_get_special(struct mail *_mail,
-				   enum mail_fetch_field field)
+int index_mail_get_special(struct mail *_mail,
+			   enum mail_fetch_field field, const char **value_r)
 {
-	struct index_mail *mail = (struct index_mail *) _mail;
+	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	struct mail_cache_field *cache_fields = mail->ibox->cache_fields;
 	string_t *str;
@@ -740,8 +754,11 @@
                         cache_fields[MAIL_CACHE_IMAP_BODY].idx;
 		unsigned int bodystructure_cache_field =
                         cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx;
-		if (data->body != NULL)
-			return data->body;
+
+		if (data->body != NULL) {
+			*value_r = data->body;
+			return 0;
+		}
 
 		/* 1) use plain-7bit-ascii flag if it exists
 		   2) get BODY if it exists
@@ -754,82 +771,90 @@
 		     MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) != 0 &&
 		    get_cached_parts(mail)) {
 			index_mail_get_plain_bodystructure(mail, str, FALSE);
-			return str_c(str);
-		}
-
-		if (mail_cache_lookup_field(mail->trans->cache_view, str,
-				mail->data.seq, body_cache_field) > 0) {
+			data->body = str_c(str);
+		} else if (mail_cache_lookup_field(mail->trans->cache_view, str,
+					mail->data.seq, body_cache_field) > 0)
 			data->body = str_c(str);
-			return data->body;
-		}
-		if (mail_cache_lookup_field(mail->trans->cache_view, str,
-					    mail->data.seq,
-					    bodystructure_cache_field) > 0) {
+		else if (mail_cache_lookup_field(mail->trans->cache_view, str,
+					mail->data.seq,
+					bodystructure_cache_field) > 0) {
 			data->bodystructure =
 				p_strdup(mail->data_pool, str_c(str));
 			str_truncate(str, 0);
 
 			if (imap_body_parse_from_bodystructure(
-						data->bodystructure, str)) {
+						data->bodystructure, str))
 				data->body = str_c(str);
-				return data->body;
+			else {
+				/* broken, continue.. */
+				mail_cache_set_corrupted(mail->ibox->cache,
+					"Corrupted BODYSTRUCTURE for mail %u",
+					mail->mail.mail.uid);
+				data->bodystructure = NULL;
 			}
+		}
 
-			/* broken, continue.. */
-			mail_cache_set_corrupted(mail->ibox->cache,
-				"Corrupted BODYSTRUCTURE for mail %u",
-				mail->mail.mail.uid);
-			data->bodystructure = NULL;
+		if (data->body == NULL) {
+			str_free(&str);
+			if (index_mail_parse_bodystructure(mail,
+						MAIL_CACHE_IMAP_BODY) < 0)
+				return -1;
 		}
-		str_free(&str);
-
-		index_mail_parse_bodystructure(mail, MAIL_CACHE_IMAP_BODY);
-		return data->body;
+		*value_r = data->body;
+		return 0;
 	}
 	case MAIL_FETCH_IMAP_BODYSTRUCTURE: {
 		unsigned int bodystructure_cache_field =
                         cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx;
 
-		if (data->bodystructure != NULL)
-			return data->bodystructure;
+		if (data->bodystructure != NULL) {
+			*value_r = data->bodystructure;
+			return 0;
+		}
 
 		str = str_new(mail->data_pool, 128);
 		if ((mail->data.cache_flags &
 		     MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) != 0 &&
 		    get_cached_parts(mail)) {
 			index_mail_get_plain_bodystructure(mail, str, TRUE);
-			return str_c(str);
-		}
-
-		if (mail_cache_lookup_field(mail->trans->cache_view, str,
-					    mail->data.seq,
-					    bodystructure_cache_field) > 0) {
+			data->bodystructure = str_c(str);
+		} else if (mail_cache_lookup_field(mail->trans->cache_view, str,
+					mail->data.seq,
+					bodystructure_cache_field) > 0) {
 			data->bodystructure = str_c(str);
-			return data->bodystructure;
+		} else {
+			str_free(&str);
+			if (index_mail_parse_bodystructure(mail,
+					MAIL_CACHE_IMAP_BODYSTRUCTURE) < 0)
+				return -1;
 		}
-		str_free(&str);
-
-		index_mail_parse_bodystructure(mail,
-					       MAIL_CACHE_IMAP_BODYSTRUCTURE);
-		return data->bodystructure;
+		*value_r = data->bodystructure;
+		return 0;
 	}
 	case MAIL_FETCH_IMAP_ENVELOPE:
-		if (data->envelope == NULL)
-			index_mail_headers_get_envelope(mail);
-		return data->envelope;
+		if (data->envelope == NULL) {
+			if (index_mail_headers_get_envelope(mail) < 0)
+				return -1;
+		}
+		*value_r = data->envelope;
+		return 0;
 	case MAIL_FETCH_FROM_ENVELOPE:
 	case MAIL_FETCH_UIDL_FILE_NAME:
-		return NULL;
+		*value_r = "";
+		return 0;
 	case MAIL_FETCH_HEADER_MD5:
 		mail_index_lookup_ext(mail->trans->trans_view, data->seq,
 				      mail->ibox->md5hdr_ext_idx,
 				      &ext_data, NULL);
-		if (ext_data == NULL)
-			return NULL;
-		return binary_to_hex(ext_data, 16);
+		if (ext_data == NULL) {
+			*value_r = "";
+			return 0;
+		}
+		*value_r = binary_to_hex(ext_data, 16);
+		return 0;
 	default:
 		i_unreached();
-		return NULL;
+		return -1;
 	}
 }
 
@@ -930,6 +955,7 @@
 	struct mail_cache_field *cache_fields = mail->ibox->cache_fields;
         struct mail_cache_view *cache_view = mail->trans->cache_view;
 	const struct mail_index_record *rec;
+	struct istream *input;
 
 	if (data->seq == seq)
 		return;
@@ -1031,7 +1057,7 @@
 		if ((mail->wanted_fields & MAIL_FETCH_STREAM_BODY) != 0)
 			data->access_part |= READ_BODY;
 
-		(void)mail_get_stream(_mail, NULL, NULL);
+		(void)mail_get_stream(_mail, NULL, NULL, &input);
 	}
 }
 
@@ -1121,7 +1147,7 @@
 	cache_field = mail->ibox->cache_fields[MAIL_CACHE_SENT_DATE].idx;
 	if (mail_cache_field_want_add(mail->trans->cache_trans,
 				      mail->data.seq, cache_field))
-		index_mail_cache_sent_date(mail);
+		(void)index_mail_cache_sent_date(mail);
 }
 
 void index_mail_cache_parse_deinit(struct mail *_mail, time_t received_date)
--- a/src/lib-storage/index/index-mail.h	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/index/index-mail.h	Sun Aug 12 19:40:54 2007 +0300
@@ -143,30 +143,31 @@
 			     struct index_mail *mail);
 int index_mail_parse_headers(struct index_mail *mail,
 			     struct mailbox_header_lookup_ctx *headers);
-void index_mail_headers_get_envelope(struct index_mail *mail);
+int index_mail_headers_get_envelope(struct index_mail *mail);
 
-const char *index_mail_get_first_header(struct mail *_mail, const char *field,
-					bool decode_to_utf8);
-const char *const *
-index_mail_get_headers(struct mail *_mail, const char *field,
-		       bool decode_to_utf8);
-struct istream *
-index_mail_get_header_stream(struct mail *_mail,
-			     struct mailbox_header_lookup_ctx *headers);
+int index_mail_get_first_header(struct mail *_mail, const char *field,
+				bool decode_to_utf8, const char **value_r);
+int index_mail_get_headers(struct mail *_mail, const char *field,
+			   bool decode_to_utf8, const char *const **value_r);
+int index_mail_get_header_stream(struct mail *_mail,
+				 struct mailbox_header_lookup_ctx *headers,
+				 struct istream **stream_r);
 
 enum mail_flags index_mail_get_flags(struct mail *_mail);
 const char *const *index_mail_get_keywords(struct mail *_mail);
-const struct message_part *index_mail_get_parts(struct mail *_mail);
-time_t index_mail_get_received_date(struct mail *_mail);
-time_t index_mail_get_save_date(struct mail *_mail);
-time_t index_mail_get_date(struct mail *_mail, int *timezone);
-uoff_t index_mail_get_virtual_size(struct mail *mail);
-uoff_t index_mail_get_physical_size(struct mail *mail);
-struct istream *index_mail_init_stream(struct index_mail *mail,
-				       struct message_size *hdr_size,
-				       struct message_size *body_size);
-const char *index_mail_get_special(struct mail *_mail,
-				   enum mail_fetch_field field);
+int index_mail_get_parts(struct mail *_mail,
+			 const struct message_part **parts_r);
+int index_mail_get_received_date(struct mail *_mail, time_t *date_r);
+int index_mail_get_save_date(struct mail *_mail, time_t *date_r);
+int index_mail_get_date(struct mail *_mail, time_t *date_r, int *timezone_r);
+int index_mail_get_virtual_size(struct mail *mail, uoff_t *size_r);
+int index_mail_get_physical_size(struct mail *mail, uoff_t *size_r);
+int index_mail_init_stream(struct index_mail *mail,
+			   struct message_size *hdr_size,
+			   struct message_size *body_size,
+			   struct istream **stream_r);
+int index_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
+			   const char **value_r);
 
 void index_mail_update_flags(struct mail *mail, enum modify_type modify_type,
 			     enum mail_flags flags);
@@ -174,9 +175,10 @@
 				struct mail_keywords *keywords);
 void index_mail_expunge(struct mail *mail);
 
-uoff_t index_mail_get_cached_uoff_t(struct index_mail *mail,
-				    enum index_cache_field field);
-uoff_t index_mail_get_cached_virtual_size(struct index_mail *mail);
+bool index_mail_get_cached_uoff_t(struct index_mail *mail,
+				  enum index_cache_field field, uoff_t *size_r);
+bool index_mail_get_cached_virtual_size(struct index_mail *mail,
+					uoff_t *size_r);
 
 void index_mail_cache_add(struct index_mail *mail, enum index_cache_field field,
 			  const void *data, size_t data_size);
--- a/src/lib-storage/index/index-search.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/index/index-search.c	Sun Aug 12 19:40:54 2007 +0300
@@ -187,8 +187,7 @@
 	case SEARCH_BEFORE:
 	case SEARCH_ON:
 	case SEARCH_SINCE:
-		date = mail_get_received_date(ctx->mail);
-		if (date == (time_t)-1)
+		if (mail_get_received_date(ctx->mail, &date) < 0)
 			return -1;
 
 		switch (arg->type) {
@@ -210,8 +209,7 @@
 	case SEARCH_SENTSINCE:
 		/* NOTE: RFC-3501 specifies that timezone is ignored
 		   in searches. date is returned as UTC, so change it. */
-		date = mail_get_date(ctx->mail, &timezone_offset);
-		if (date == (time_t)-1)
+		if (mail_get_date(ctx->mail, &date, &timezone_offset) < 0)
 			return -1;
 		date += timezone_offset * 60;
 
@@ -231,8 +229,7 @@
 	/* sizes */
 	case SEARCH_SMALLER:
 	case SEARCH_LARGER:
-		virtual_size = mail_get_virtual_size(ctx->mail);
-		if (virtual_size == (uoff_t)-1)
+		if (mail_get_virtual_size(ctx->mail, &virtual_size) < 0)
 			return -1;
 
 		search_size = str_to_uoff_t(arg->value.str);
@@ -513,8 +510,7 @@
 
 		if (headers == NULL) {
 			headers_ctx = NULL;
-			input = mail_get_stream(ctx->mail, NULL, NULL);
-			if (input == NULL)
+			if (mail_get_stream(ctx->mail, NULL, NULL, &input) < 0)
 				return FALSE;
 		} else {
 			/* FIXME: do this once in init */
@@ -522,8 +518,8 @@
 			headers_ctx =
 				mailbox_header_lookup_init(&ctx->ibox->box,
 							   headers);
-			input = mail_get_header_stream(ctx->mail, headers_ctx);
-			if (input == NULL) {
+			if (mail_get_header_stream(ctx->mail, headers_ctx,
+						   &input) < 0) {
 				mailbox_header_lookup_deinit(&headers_ctx);
 				return FALSE;
 			}
@@ -545,8 +541,7 @@
 	} else {
 		struct message_size hdr_size;
 
-		input = mail_get_stream(ctx->mail, &hdr_size, NULL);
-		if (input == NULL)
+		if (mail_get_stream(ctx->mail, &hdr_size, NULL, &input) < 0)
 			return FALSE;
 
 		i_stream_seek(input, hdr_size.physical_size);
@@ -558,7 +553,7 @@
 		memset(&body_ctx, 0, sizeof(body_ctx));
 		body_ctx.index_ctx = ctx;
 		body_ctx.input = input;
-		body_ctx.part = mail_get_parts(ctx->mail);
+		(void)mail_get_parts(ctx->mail, &body_ctx.part);
 
 		mail_search_args_foreach(args, search_body, &body_ctx);
 	}
--- a/src/lib-storage/index/index-sort.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/index/index-sort.c	Sun Aug 12 19:40:54 2007 +0300
@@ -158,8 +158,7 @@
 	struct message_address *addr;
 	const char *str;
 
-	str = mail_get_first_header_utf8(mail, header);
-	if (str == NULL)
+	if (mail_get_first_header_utf8(mail, header, &str) <= 0)
 		return "";
 
 	addr = message_address_parse(pool_datastack_create(),
@@ -177,10 +176,10 @@
 	mail_set_seq(mail, seq);
 	switch (sort_type & MAIL_SORT_MASK) {
 	case MAIL_SORT_SUBJECT:
-		str = mail_get_first_header(mail, "Subject");
-		return str == NULL ? "" :
-			imap_get_base_subject_cased(pool_datastack_create(),
-						    str, NULL);
+		if (mail_get_first_header(mail, "Subject", &str) <= 0)
+			return "";
+		return imap_get_base_subject_cased(pool_datastack_create(),
+						   str, NULL);
 	case MAIL_SORT_CC:
 		str = get_first_mailbox(mail, "Cc");
 		break;
@@ -230,13 +229,13 @@
 			time1 = ctx->cache_time;
 		else {
 			mail_set_seq(ctx->mail, n1->seq);
-			time1 = mail_get_received_date(ctx->mail);
-			if (time1 == (time_t)-1) time1 = 0;
+			if (mail_get_received_date(ctx->mail, &time1) < 0)
+				time1 = 0;
 		}
 
 		mail_set_seq(ctx->mail, n2->seq);
-		time2 = mail_get_received_date(ctx->mail);
-		if (time2 == (time_t)-1) time2 = 0;
+		if (mail_get_received_date(ctx->mail, &time2) < 0)
+			time2 = 0;
 
 		ret = time1 < time2 ? -1 :
 			(time1 > time2 ? 1 : 0);
@@ -246,13 +245,13 @@
 			time1 = ctx->cache_time;
 		else {
 			mail_set_seq(ctx->mail, n1->seq);
-			time1 = mail_get_date(ctx->mail, NULL);
-			if (time1 == (time_t)-1) time1 = 0;
+			if (mail_get_date(ctx->mail, &time1, NULL) < 0)
+				time1 = 0;
 		}
 
 		mail_set_seq(ctx->mail, n2->seq);
-		time2 = mail_get_date(ctx->mail, NULL);
-		if (time2 == (time_t)-1) time2 = 0;
+		if (mail_get_date(ctx->mail, &time2, NULL) < 0)
+			time2 = 0;
 
 		ret = time1 < time2 ? -1 :
 			(time1 > time2 ? 1 : 0);
@@ -262,13 +261,13 @@
 			size1 = ctx->cache_size;
 		else {
 			mail_set_seq(ctx->mail, n1->seq);
-			size1 = mail_get_virtual_size(ctx->mail);
-			if (size1 == (uoff_t)-1) size1 = 0;
+			if (mail_get_virtual_size(ctx->mail, &size1) < 0)
+				size1 = 0;
 		}
 
 		mail_set_seq(ctx->mail, n2->seq);
-		size2 = mail_get_virtual_size(ctx->mail);
-		if (size2 == (uoff_t)-1) size2 = 0;
+		if (mail_get_virtual_size(ctx->mail, &size2) < 0)
+			size2 = 0;
 
 		ret = size1 < size2 ? -1 :
 			(size1 > size2 ? 1 : 0);
@@ -469,24 +468,25 @@
 {
 	time_t time;
 
-	time = mail_get_received_date(mail);
-	return time == (time_t)-1 ? 0 : time;
+	if (mail_get_received_date(mail, &time) < 0)
+		return 0;
+	return time;
 }
 
 static uint32_t get_sort_id_date(struct mail *mail)
 {
 	time_t time;
 
-	time = mail_get_date(mail, NULL);
-	return time == (time_t)-1 ? 0 : time;
+	if (mail_get_date(mail, &time, NULL) < 0)
+		return 0;
+	return time;
 }
 
 static uint32_t get_sort_id_size(struct mail *mail)
 {
 	uoff_t size;
 
-	size = mail_get_virtual_size(mail);
-	if (size == (uoff_t)-1)
+	if (mail_get_virtual_size(mail, &size) < 0)
 		return 0;
 
 	/* FIXME: elsewhere we support 64bit message sizes, but here
@@ -494,7 +494,7 @@
 	   to support 64bit here currently, so until such messages
 	   actually start showing up somewhere, 32bit is enough */
 	i_assert(size <= (uint32_t)-1);
-	return size == size;
+	return size;
 }
 
 static void index_sort_preset_sort_ids(struct mail_search_sort_program *program,
--- a/src/lib-storage/index/maildir/maildir-mail.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-mail.c	Sun Aug 12 19:40:54 2007 +0300
@@ -74,7 +74,9 @@
 
 	if (data->access_part != 0 && data->stream == NULL) {
 		/* we're going to open the mail anyway */
-		(void)mail_get_stream(mail, NULL, NULL);
+		struct istream *input;
+
+		(void)mail_get_stream(mail, NULL, NULL, &input);
 	}
 
 	if (data->stream != NULL) {
@@ -95,46 +97,49 @@
 		}
 	} else {
 		path = maildir_save_file_get_path(mail->transaction, mail->seq);
-		if (do_stat(mbox, path, st) <= 0)
+		if (stat(path, st) < 0) {
+			mail_storage_set_critical(mail->box->storage,
+						  "stat(%s) failed: %m", path);
 			return -1;
+		}
 	}
 	return 0;
 }
 
-static time_t maildir_mail_get_received_date(struct mail *_mail)
+static int maildir_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;
 	struct stat st;
 	uint32_t t;
 
-	(void)index_mail_get_received_date(_mail);
-	if (data->received_date != (time_t)-1)
-		return data->received_date;
+	(void)index_mail_get_received_date(_mail, date_r);
+	if (*date_r != (time_t)-1)
+		return 0;
 
 	if (maildir_mail_stat(_mail, &st) < 0)
-		return (time_t)-1;
+		return -1;
 
-	data->received_date = t = st.st_mtime;
+	*date_r = data->received_date = t = st.st_mtime;
 	index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, &t, sizeof(t));
-	return data->received_date;
+	return 0;
 }
 
-static time_t maildir_mail_get_save_date(struct mail *_mail)
+static int maildir_mail_get_save_date(struct mail *_mail, time_t *date_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	struct stat st;
 	uint32_t t;
 
-	(void)index_mail_get_save_date(_mail);
-	if (data->save_date != (time_t)-1)
-		return data->save_date;
+	(void)index_mail_get_save_date(_mail, date_r);
+	if (*date_r != (time_t)-1)
+		return 0;
 
 	if (maildir_mail_stat(_mail, &st) < 0)
-		return (time_t)-1;
+		return -1;
 
-	data->save_date = t = st.st_ctime;
+	*date_r = data->save_date = t = st.st_ctime;
 	index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE, &t, sizeof(t));
 	return data->save_date;
 }
@@ -210,22 +215,23 @@
 	return mail->pop3_state;
 }
 
-static uoff_t maildir_mail_get_virtual_size(struct mail *_mail)
+static int maildir_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
 	struct index_mail_data *data = &mail->data;
 	struct message_size hdr_size, body_size;
+	struct istream *input;
 	const char *path, *fname, *value;
-	uoff_t old_offset;
+	uoff_t old_offset, size;
 	int pop3_state;
 
-	if (index_mail_get_cached_virtual_size(mail) != (uoff_t)-1)
-		return data->virtual_size;
+	if (index_mail_get_cached_virtual_size(mail, size_r))
+		return 0;
 
 	if (_mail->uid != 0) {
 		if (!maildir_mail_get_fname(mbox, _mail, &fname))
-			return (uoff_t)-1;
+			return -1;
 	} else {
 		path = maildir_save_file_get_path(_mail->transaction,
 						  _mail->seq);
@@ -235,8 +241,10 @@
 
 	/* size can be included in filename */
 	if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
-				      &data->virtual_size))
-		return data->virtual_size;
+				      &data->virtual_size)) {
+		*size_r = data->virtual_size;
+		return 0;
+	}
 
 	/* size can be included in uidlist entry */
 	if (_mail->uid != 0) {
@@ -245,16 +253,18 @@
 		if (value != NULL) {
 			char *p;
 
-			data->virtual_size = strtoull(value, &p, 10);
-			if (*p == '\0')
-				return data->virtual_size;
+			size = strtoull(value, &p, 10);
+			if (*p == '\0') {
+				data->virtual_size = *size_r = size;
+				return 0;
+			}
 		}
 	}
 
 	/* fallback to reading the file */
 	old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
-	if (mail_get_stream(_mail, &hdr_size, &body_size) == NULL)
-		return (uoff_t)-1;
+	if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
+		return -1;
 	i_stream_seek(data->stream, old_offset);
 	i_assert(data->virtual_size != (uoff_t)-1);
 
@@ -272,11 +282,13 @@
 					MAILDIR_UIDLIST_REC_EXT_VSIZE,
 					dec2str(data->virtual_size));
 	}
-	return data->virtual_size;
+	*size_r = data->virtual_size;
+	return 0;
 }
 
-static const char *
-maildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field)
+static int
+maildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
+			 const char **value_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
@@ -285,7 +297,7 @@
 	if (field == MAIL_FETCH_UIDL_FILE_NAME) {
 		if (_mail->uid != 0) {
 			if (!maildir_mail_get_fname(mbox, _mail, &fname))
-				return NULL;
+				return -1;
 		} else {
 			path = maildir_save_file_get_path(_mail->transaction,
 							  _mail->seq);
@@ -293,13 +305,14 @@
 			fname = fname != NULL ? fname + 1 : path;
 		}
 		end = strchr(fname, MAILDIR_INFO_SEP);
-		return end == NULL ? fname : t_strdup_until(fname, end);
+		*value_r = end == NULL ? fname : t_strdup_until(fname, end);
+		return 0;
 	}
 
-	return index_mail_get_special(_mail, field);
+	return index_mail_get_special(_mail, field, value_r);
 }
 							
-static uoff_t maildir_mail_get_physical_size(struct mail *_mail)
+static int maildir_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
@@ -309,13 +322,13 @@
 	uoff_t size;
 	int ret;
 
-	size = index_mail_get_physical_size(_mail);
-	if (size != (uoff_t)-1)
-		return size;
+	(void)index_mail_get_physical_size(_mail, size_r);
+	if (*size_r != (uoff_t)-1)
+		return 0;
 
 	if (_mail->uid != 0) {
 		if (!maildir_mail_get_fname(mbox, _mail, &fname))
-			return (uoff_t)-1;
+			return -1;
 		path = NULL;
 	} else {
 		path = maildir_save_file_get_path(_mail->transaction,
@@ -331,12 +344,15 @@
 			if (ret <= 0) {
 				if (ret == 0)
 					mail_set_expunged(_mail);
-				return (uoff_t)-1;
+				return -1;
 			}
 		} else {
 			/* saved mail which hasn't been committed yet */
-			if (do_stat(mbox, path, &st) <= 0)
-				return (uoff_t)-1;
+			if (stat(path, &st) < 0) {
+				mail_storage_set_critical(_mail->box->storage,
+					"stat(%s) failed: %m", path);
+				return -1;
+			}
 		}
 		size = st.st_size;
 	}
@@ -344,12 +360,14 @@
 	index_mail_cache_add(mail, MAIL_CACHE_PHYSICAL_FULL_SIZE,
 			     &size, sizeof(size));
 	data->physical_size = size;
-	return size;
+	*size_r = size;
+	return 0;
 }
 
-static struct istream *maildir_mail_get_stream(struct mail *_mail,
-					       struct message_size *hdr_size,
-					       struct message_size *body_size)
+static int maildir_mail_get_stream(struct mail *_mail,
+				   struct message_size *hdr_size,
+				   struct message_size *body_size,
+				   struct istream **stream_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
@@ -361,11 +379,11 @@
 		if (data->stream == NULL) {
 			if (deleted)
 				mail_set_expunged(_mail);
-			return NULL;
+			return -1;
 		}
 	}
 
-	return index_mail_init_stream(mail, hdr_size, body_size);
+	return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
 }
 
 struct mail_vfuncs maildir_mail_vfuncs = {
--- a/src/lib-storage/index/maildir/maildir-save.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-save.c	Sun Aug 12 19:40:54 2007 +0300
@@ -484,8 +484,10 @@
 
 	/* remember the size in case we want to add it to filename */
 	ctx->file_last->size = ctx->output->offset;
-	ctx->file_last->vsize = ctx->cur_dest_mail == NULL ? (uoff_t)-1 :
-		mail_get_virtual_size(ctx->cur_dest_mail);
+	if (ctx->cur_dest_mail == NULL ||
+	    mail_get_virtual_size(ctx->cur_dest_mail,
+				  &ctx->file_last->vsize) < 0)
+		ctx->file_last->vsize = (uoff_t)-1;
 
 	output_errno = ctx->output->stream_errno;
 	o_stream_destroy(&ctx->output);
--- a/src/lib-storage/index/mbox/mbox-mail.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-mail.c	Sun Aug 12 19:40:54 2007 +0300
@@ -91,19 +91,19 @@
 	return 0;
 }
 
-static time_t mbox_mail_get_received_date(struct mail *_mail)
+static int mbox_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;
 	struct mbox_mailbox *mbox = (struct mbox_mailbox *)mail->ibox;
 	uint32_t t;
 
-	(void)index_mail_get_received_date(_mail);
-	if (data->received_date != (time_t)-1)
-		return data->received_date;
+	(void)index_mail_get_received_date(_mail, date_r);
+	if (*date_r != (time_t)-1)
+		return 0;
 
 	if (mbox_mail_seek(mail) < 0)
-		return (time_t)-1;
+		return -1;
 	data->received_date =
 		istream_raw_mbox_get_received_time(mbox->mbox_stream);
 	if (data->received_date == (time_t)-1) {
@@ -114,17 +114,18 @@
 
 	t = data->received_date;
 	index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, &t, sizeof(t));
-	return data->received_date;
+	*date_r = data->received_date;
+	return 0;
 }
 
-static time_t mbox_mail_get_save_date(struct mail *_mail)
+static int mbox_mail_get_save_date(struct mail *_mail, time_t *date_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 
-	(void)index_mail_get_save_date(_mail);
-	if (data->save_date != (time_t)-1)
-		return data->save_date;
+	(void)index_mail_get_save_date(_mail, date_r);
+	if (*date_r != (time_t)-1)
+		return 0;
 
 	/* no way to know this. save the current time into cache and use
 	   that from now on. this works only as long as the index files
@@ -132,27 +133,30 @@
 	data->save_date = ioloop_time;
 	index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE,
 			     &data->save_date, sizeof(data->save_date));
-	return data->save_date;
+	*date_r = data->save_date;
+	return 0;
 }
 
-static const char *
-mbox_mail_get_special(struct mail *_mail, enum mail_fetch_field field)
+static int
+mbox_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
+		      const char **value_r)
 {
 #define EMPTY_MD5_SUM "00000000000000000000000000000000"
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct mbox_mailbox *mbox = (struct mbox_mailbox *)mail->ibox;
-	const char *value;
 
 	switch (field) {
 	case MAIL_FETCH_FROM_ENVELOPE:
 		if (mbox_mail_seek(mail) < 0)
-			return NULL;
+			return -1;
 
-		return istream_raw_mbox_get_sender(mbox->mbox_stream);
+		*value_r = istream_raw_mbox_get_sender(mbox->mbox_stream);
+		return 0;
 	case MAIL_FETCH_HEADER_MD5:
-		value = index_mail_get_special(_mail, field);
-		if (value != NULL && strcmp(value, EMPTY_MD5_SUM) != 0)
-			return value;
+		if (index_mail_get_special(_mail, field, value_r) < 0)
+			return -1;
+		if (**value_r != '\0' && strcmp(*value_r, EMPTY_MD5_SUM) != 0)
+			return 0;
 
 		/* i guess in theory the EMPTY_MD5_SUM is valid and can happen,
 		   but it's almost guaranteed that it means the MD5 sum is
@@ -160,16 +164,16 @@
 		mbox->mbox_save_md5 = TRUE;
                 mbox_prepare_resync(mail);
 		if (mbox_sync(mbox, MBOX_SYNC_FORCE_SYNC) < 0)
-			return NULL;
+			return -1;
 		break;
 	default:
 		break;
 	}
 
-	return index_mail_get_special(_mail, field);
+	return index_mail_get_special(_mail, field, value_r);
 }
 
-static uoff_t mbox_mail_get_physical_size(struct mail *_mail)
+static int mbox_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
@@ -178,24 +182,28 @@
 	uoff_t hdr_offset, body_offset, body_size;
 
 	if (mbox_mail_seek(mail) < 0)
-		return (uoff_t)-1;
+		return -1;
 
 	/* our header size varies, so don't do any caching */
 	stream = mbox->mbox_stream;
 	hdr_offset = istream_raw_mbox_get_header_offset(stream);
 	body_offset = istream_raw_mbox_get_body_offset(stream);
-	if (body_offset == (uoff_t)-1)
-		return (uoff_t)-1;
+	if (body_offset == (uoff_t)-1) {
+		mail_storage_set_critical(_mail->box->storage,
+					  "Couldn't get mbox size");
+		return -1;
+	}
 	body_size = istream_raw_mbox_get_body_size(stream, (uoff_t)-1);
 
 	data->physical_size = (body_offset - hdr_offset) + body_size;
-	return data->physical_size;
-
+	*size_r = data->physical_size;
+	return 0;
 }
 
-static struct istream *mbox_mail_get_stream(struct mail *_mail,
-					    struct message_size *hdr_size,
-					    struct message_size *body_size)
+static int mbox_mail_get_stream(struct mail *_mail,
+				struct message_size *hdr_size,
+				struct message_size *body_size,
+				struct istream **stream_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
@@ -205,7 +213,7 @@
 
 	if (data->stream == NULL) {
 		if (mbox_mail_seek(mail) < 0)
-			return NULL;
+			return -1;
 
 		raw_stream = mbox->mbox_stream;
 		offset = istream_raw_mbox_get_header_offset(raw_stream);
@@ -219,7 +227,7 @@
 		i_stream_unref(&raw_stream);
 	}
 
-	return index_mail_init_stream(mail, hdr_size, body_size);
+	return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
 }
 
 struct mail_vfuncs mbox_mail_vfuncs = {
--- a/src/lib-storage/mail-copy.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/mail-copy.c	Sun Aug 12 19:40:54 2007 +0300
@@ -12,15 +12,20 @@
 	struct mail_save_context *ctx;
 	struct istream *input;
 	const char *from_envelope;
+	time_t received_date;
 
-	input = mail_get_stream(mail, NULL, NULL);
-	if (input == NULL)
+	if (mail_get_stream(mail, NULL, NULL, &input) < 0)
+		return -1;
+	if (mail_get_received_date(mail, &received_date) < 0)
+		return -1;
+	if (mail_get_special(mail, MAIL_FETCH_FROM_ENVELOPE,
+			     &from_envelope) < 0)
 		return -1;
 
-	from_envelope = mail_get_special(mail, MAIL_FETCH_FROM_ENVELOPE);
+	if (*from_envelope == '\0')
+		from_envelope = NULL;
 
-	if (mailbox_save_init(t, flags, keywords,
-			      mail_get_received_date(mail),
+	if (mailbox_save_init(t, flags, keywords, received_date,
 			      0, from_envelope, input, dest_mail, &ctx) < 0)
 		return -1;
 
--- a/src/lib-storage/mail-storage-private.h	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/mail-storage-private.h	Sun Aug 12 19:40:54 2007 +0300
@@ -201,27 +201,28 @@
 
 	enum mail_flags (*get_flags)(struct mail *mail);
 	const char *const *(*get_keywords)(struct mail *mail);
-	const struct message_part *(*get_parts)(struct mail *mail);
 
-	time_t (*get_date)(struct mail *mail, int *timezone);
-	time_t (*get_received_date)(struct mail *mail);
-	time_t (*get_save_date)(struct mail *mail);
-	uoff_t (*get_virtual_size)(struct mail *mail);
-	uoff_t (*get_physical_size)(struct mail *mail);
+	int (*get_parts)(struct mail *mail,
+			 const struct message_part **parts_r);
+	int (*get_date)(struct mail *mail, time_t *date_r, int *timezone_r);
+	int (*get_received_date)(struct mail *mail, time_t *date_r);
+	int (*get_save_date)(struct mail *mail, time_t *date_r);
+	int (*get_virtual_size)(struct mail *mail, uoff_t *size_r);
+	int (*get_physical_size)(struct mail *mail, uoff_t *size_r);
 
-	const char *(*get_first_header)(struct mail *mail, const char *field,
-					bool decode_to_utf8);
-	const char *const *(*get_headers)(struct mail *mail, const char *field,
-					  bool decode_to_utf8);
-	struct istream *
-		(*get_header_stream)(struct mail *mail,
-				     struct mailbox_header_lookup_ctx *headers);
-	struct istream *(*get_stream)(struct mail *mail,
-				      struct message_size *hdr_size,
-				      struct message_size *body_size);
+	int (*get_first_header)(struct mail *mail, const char *field,
+				bool decode_to_utf8, const char **value_r);
+	int (*get_headers)(struct mail *mail, const char *field,
+			   bool decode_to_utf8, const char *const **value_r);
+	int (*get_header_stream)(struct mail *mail,
+				 struct mailbox_header_lookup_ctx *headers,
+				 struct istream **stream_r);
+	int (*get_stream)(struct mail *mail, struct message_size *hdr_size,
+			  struct message_size *body_size,
+			  struct istream **stream_r);
 
-	const char *(*get_special)(struct mail *mail,
-				   enum mail_fetch_field field);
+	int (*get_special)(struct mail *mail, enum mail_fetch_field field,
+			   const char **value_r);
 
 	void (*update_flags)(struct mail *mail, enum modify_type modify_type,
 			     enum mail_flags flags);
--- a/src/lib-storage/mail-storage.h	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/mail-storage.h	Sun Aug 12 19:40:54 2007 +0300
@@ -143,6 +143,7 @@
 	MAILBOX_SYNC_TYPE_KEYWORDS	= 0x04
 };
 
+struct message_part;
 struct mail_namespace;
 struct mail_storage;
 struct mail_search_arg;
@@ -390,13 +391,6 @@
    do forced CLOSE. */
 bool mailbox_is_inconsistent(struct mailbox *box);
 
-/* Returns message's flags */
-enum mail_flags mail_get_flags(struct mail *mail);
-/* Returns message's keywords */
-const char *const *mail_get_keywords(struct mail *mail);
-/* Returns message's MIME parts */
-const struct message_part *mail_get_parts(struct mail *mail);
-
 struct mail *mail_alloc(struct mailbox_transaction_context *t,
 			enum mail_fetch_field wanted_fields,
 			struct mailbox_header_lookup_ctx *wanted_headers);
@@ -406,44 +400,54 @@
    mail_*() functions shouldn't be called if FALSE is returned. */
 bool mail_set_uid(struct mail *mail, uint32_t uid);
 
-/* Get the Date-header of the mail. Timezone is in minutes.
-   Returns (time_t)-1 if error occurred, 0 if field wasn't found or
-   couldn't be parsed. */
-time_t mail_get_date(struct mail *mail, int *timezone);
-/* Get the time when the mail was received (IMAP INTERNALDATE).
-   Returns (time_t)-1 if error occurred. */
-time_t mail_get_received_date(struct mail *mail);
+/* Returns message's flags */
+enum mail_flags mail_get_flags(struct mail *mail);
+/* Returns message's keywords */
+const char *const *mail_get_keywords(struct mail *mail);
+
+/* Returns message's MIME parts */
+int mail_get_parts(struct mail *mail, const struct message_part **parts_r);
+
+/* Get the Date-header of the mail. Timezone is in minutes. date=0 if it
+   wasn't found or it was invalid. */
+int mail_get_date(struct mail *mail, time_t *date_r, int *timezone_r);
+/* Get the time when the mail was received (IMAP INTERNALDATE). */
+int mail_get_received_date(struct mail *mail, time_t *date_r);
 /* Get the time when the mail was saved into this mailbox. This time may not
-   always be entirely reliable. Returns (time_t)-1 if error occurred. */
-time_t mail_get_save_date(struct mail *mail);
+   always be entirely reliable. */
+int mail_get_save_date(struct mail *mail, time_t *date_r);
 
 /* Get the space used by the mail as seen by the reader. Linefeeds are always
-   counted as being CR+LF. Returns (uoff_t)-1 if error occurred */
-uoff_t mail_get_virtual_size(struct mail *mail);
-/* Get the space used by the mail in disk.
-   Returns (uoff_t)-1 if error occurred */
-uoff_t mail_get_physical_size(struct mail *mail);
+   counted as being CR+LF. */
+int mail_get_virtual_size(struct mail *mail, uoff_t *size_r);
+/* Get the space used by the mail in disk. */
+int mail_get_physical_size(struct mail *mail, uoff_t *size_r);
 
-/* Get value for single header field */
-const char *mail_get_first_header(struct mail *mail, const char *field);
+/* Get value for single header field, or NULL if header wasn't found.
+   Returns 1 if header was found, 0 if not, -1 if error. */
+int mail_get_first_header(struct mail *mail, const char *field,
+			  const char **value_r);
 /* Like mail_get_first_header(), but decode MIME encoded words to UTF-8 */
-const char *mail_get_first_header_utf8(struct mail *mail, const char *field);
+int mail_get_first_header_utf8(struct mail *mail, const char *field,
+			       const char **value_r);
 /* Return a NULL-terminated list of values for each found field. */
-const char *const *mail_get_headers(struct mail *mail, const char *field);
+int mail_get_headers(struct mail *mail, const char *field,
+		     const char *const **value_r);
 /* Like mail_get_headers(), but decode MIME encoded words to UTF-8 */
-const char *const *mail_get_headers_utf8(struct mail *mail, const char *field);
+int mail_get_headers_utf8(struct mail *mail, const char *field,
+			  const char *const **value_r);
 /* Returns stream containing specified headers. */
-struct istream *
-mail_get_header_stream(struct mail *mail,
-		       struct mailbox_header_lookup_ctx *headers);
+int mail_get_header_stream(struct mail *mail,
+			   struct mailbox_header_lookup_ctx *headers,
+			   struct istream **stream_r);
 /* Returns input stream pointing to beginning of message header.
    hdr_size and body_size are updated unless they're NULL. */
-struct istream *mail_get_stream(struct mail *mail,
-				struct message_size *hdr_size,
-				struct message_size *body_size);
+int mail_get_stream(struct mail *mail, struct message_size *hdr_size,
+		    struct message_size *body_size, struct istream **stream_r);
 
 /* Get any of the "special" fields. */
-const char *mail_get_special(struct mail *mail, enum mail_fetch_field field);
+int mail_get_special(struct mail *mail, enum mail_fetch_field field,
+		     const char **value_r);
 
 /* Update message flags. */
 void mail_update_flags(struct mail *mail, enum modify_type modify_type,
--- a/src/lib-storage/mail.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/lib-storage/mail.c	Sun Aug 12 19:40:54 2007 +0300
@@ -47,99 +47,107 @@
 	return p->v.get_keywords(mail);
 }
 
-const struct message_part *mail_get_parts(struct mail *mail)
+int mail_get_parts(struct mail *mail, const struct message_part **parts_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.get_parts(mail);
+	return p->v.get_parts(mail, parts_r);
 }
 
-time_t mail_get_received_date(struct mail *mail)
+int mail_get_date(struct mail *mail, time_t *date_r, int *timezone_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
+	int tz;
 
-	return p->v.get_received_date(mail);
+	if (timezone_r == NULL)
+		timezone_r = &tz;
+
+	return p->v.get_date(mail, date_r, timezone_r);
 }
 
-time_t mail_get_save_date(struct mail *mail)
+int mail_get_received_date(struct mail *mail, time_t *date_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.get_save_date(mail);
+	return p->v.get_received_date(mail, date_r);
 }
 
-time_t mail_get_date(struct mail *mail, int *timezone)
+int mail_get_save_date(struct mail *mail, time_t *date_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.get_date(mail, timezone);
+	return p->v.get_save_date(mail, date_r);
 }
 
-uoff_t mail_get_virtual_size(struct mail *mail)
+int mail_get_virtual_size(struct mail *mail, uoff_t *size_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.get_virtual_size(mail);
+	return p->v.get_virtual_size(mail, size_r);
 }
 
-uoff_t mail_get_physical_size(struct mail *mail)
+int mail_get_physical_size(struct mail *mail, uoff_t *size_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.get_physical_size(mail);
+	return p->v.get_physical_size(mail, size_r);
 }
 
-const char *mail_get_first_header(struct mail *mail, const char *field)
+int mail_get_first_header(struct mail *mail, const char *field,
+			  const char **value_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.get_first_header(mail, field, FALSE);
+	return p->v.get_first_header(mail, field, FALSE, value_r);
 }
 
-const char *mail_get_first_header_utf8(struct mail *mail, const char *field)
+int mail_get_first_header_utf8(struct mail *mail, const char *field,
+			       const char **value_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.get_first_header(mail, field, TRUE);
+	return p->v.get_first_header(mail, field, TRUE, value_r);
 }
 
-const char *const *mail_get_headers(struct mail *mail, const char *field)
+int mail_get_headers(struct mail *mail, const char *field,
+		     const char *const **value_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.get_headers(mail, field, FALSE);
+	return p->v.get_headers(mail, field, FALSE, value_r);
 }
 
-const char *const *mail_get_headers_utf8(struct mail *mail, const char *field)
+int mail_get_headers_utf8(struct mail *mail, const char *field,
+			  const char *const **value_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.get_headers(mail, field, TRUE);
+	return p->v.get_headers(mail, field, TRUE, value_r);
 }
 
-struct istream *
-mail_get_header_stream(struct mail *mail,
-		       struct mailbox_header_lookup_ctx *headers)
+int mail_get_header_stream(struct mail *mail,
+			   struct mailbox_header_lookup_ctx *headers,
+			   struct istream **stream_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.get_header_stream(mail, headers);
+	return p->v.get_header_stream(mail, headers, stream_r);
 }
 
-struct istream *mail_get_stream(struct mail *mail,
-				struct message_size *hdr_size,
-				struct message_size *body_size)
+int mail_get_stream(struct mail *mail, struct message_size *hdr_size,
+		    struct message_size *body_size, struct istream **stream_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.get_stream(mail, hdr_size, body_size);
+	return p->v.get_stream(mail, hdr_size, body_size, stream_r);
 }
 
-const char *mail_get_special(struct mail *mail, enum mail_fetch_field field)
+int mail_get_special(struct mail *mail, enum mail_fetch_field field,
+		     const char **value_r)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.get_special(mail, field);
+	return p->v.get_special(mail, field, value_r);
 }
 
 void mail_update_flags(struct mail *mail, enum modify_type modify_type,
--- a/src/plugins/expire/expire-plugin.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/plugins/expire/expire-plugin.c	Sun Aug 12 19:40:54 2007 +0300
@@ -78,8 +78,7 @@
 	for (seq = 2; seq <= hdr->messages_count; seq++) {
 		if (!mail_index_is_expunged(view, seq)) {
 			mail_set_seq(xt->mail, seq);
-			*stamp_r = mail_get_save_date(xt->mail);
-			if (*stamp_r != (time_t)-1)
+			if (mail_get_save_date(xt->mail, stamp_r) == 0)
 				return;
 		}
 	}
--- a/src/plugins/expire/expire-tool.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/plugins/expire/expire-tool.c	Sun Aug 12 19:40:54 2007 +0300
@@ -91,8 +91,7 @@
 
 	now = time(NULL);
 	while ((ret = mailbox_search_next(search_ctx, mail)) > 0) {
-		save_time = mail_get_save_date(mail);
-		if (save_time == (time_t)-1) {
+		if (mail_get_save_date(mail, &save_time) < 0) {
 			/* maybe just got expunged. anyway try again later. */
 			ret = -1;
 			break;
--- a/src/plugins/fts/fts-storage.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/plugins/fts/fts-storage.c	Sun Aug 12 19:40:54 2007 +0300
@@ -163,8 +163,7 @@
 
 	ctx->uid = ctx->mail->uid;
 
-	input = mail_get_stream(ctx->mail, NULL, NULL);
-	if (input == NULL)
+	if (mail_get_stream(ctx->mail, NULL, NULL, &input) < 0)
 		return -1;
 
 	prev_part = skip_part = NULL;
--- a/src/plugins/mail-log/mail-log-plugin.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/plugins/mail-log/mail-log-plugin.c	Sun Aug 12 19:40:54 2007 +0300
@@ -174,15 +174,13 @@
 
 	if ((mail_log_set.fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
 	    (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
-		size = mail_get_physical_size(mail);
-		if (size != (uoff_t)-1)
+		if (mail_get_physical_size(mail, &size) == 0)
 			group->psize_total += size;
 	}
 
 	if ((mail_log_set.fields & MAIL_LOG_FIELD_VSIZE) != 0 &&
 	    (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
-		size = mail_get_virtual_size(mail);
-		if (size != (uoff_t)-1)
+		if (mail_get_virtual_size(mail, &size) == 0)
 			group->vsize_total += size;
 	}
 }
@@ -297,21 +295,20 @@
 		str_printfa(str, "dest=%s, ", data);
 
 	if ((mail_log_set.fields & MAIL_LOG_FIELD_MSGID) != 0) {
-		msgid = mail_get_first_header(mail, "Message-ID");
-		str_printfa(str, "msgid=%s, ", msgid == NULL ? "(null)" :
+		if (mail_get_first_header(mail, "Message-ID", &msgid) <= 0)
+			msgid = "(null";
+		str_printfa(str, "msgid=%s, ",
 			    str_sanitize(msgid, MSGID_LOG_LEN));
 	}
 
 	if ((mail_log_set.fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
 	    (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
-		size = mail_get_physical_size(mail);
-		if (size != (uoff_t)-1)
+		if (mail_get_physical_size(mail, &size) == 0)
 			str_printfa(str, "size=%"PRIuUOFF_T", ", size);
 	}
 	if ((mail_log_set.fields & MAIL_LOG_FIELD_VSIZE) != 0 &&
 	    (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
-		size = mail_get_virtual_size(mail);
-		if (size != (uoff_t)-1)
+		if (mail_get_virtual_size(mail, &size) == 0)
 			str_printfa(str, "vsize=%"PRIuUOFF_T", ", size);
 	}
 	str_truncate(str, str_len(str)-2);
--- a/src/plugins/quota/quota-count.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/plugins/quota/quota-count.c	Sun Aug 12 19:40:54 2007 +0300
@@ -29,8 +29,7 @@
 	ctx = mailbox_search_init(trans, NULL, &search_arg, NULL);
 	mail = mail_alloc(trans, MAIL_FETCH_PHYSICAL_SIZE, NULL);
 	while (mailbox_search_next(ctx, mail) > 0) {
-		size = mail_get_physical_size(mail);
-		if (size != (uoff_t)-1)
+		if (mail_get_physical_size(mail, &size) == 0)
 			*bytes_r += size;
 		*count_r += 1;
 	}
--- a/src/plugins/quota/quota-storage.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/plugins/quota/quota-storage.c	Sun Aug 12 19:40:54 2007 +0300
@@ -53,8 +53,7 @@
 	   the mail at the same time. In here we'll just save the message's
 	   physical size and do the quota freeing later when the message was
 	   known to be expunged. */
-	size = mail_get_physical_size(_mail);
-	if (size != (uoff_t)-1) {
+	if (mail_get_physical_size(_mail, &size) == 0) {
 		if (!array_is_created(&qbox->expunge_uids)) {
 			i_array_init(&qbox->expunge_uids, 64);
 			i_array_init(&qbox->expunge_sizes, 64);
@@ -318,12 +317,8 @@
 			mail_alloc(qbox->expunge_trans,
 				   MAIL_FETCH_PHYSICAL_SIZE, NULL);
 	}
-	if (!mail_set_uid(qbox->expunge_qt->tmp_mail, uid))
-		size = (uoff_t)-1;
-	else
-		size = mail_get_physical_size(qbox->expunge_qt->tmp_mail);
-
-	if (size != (uoff_t)-1)
+	if (mail_set_uid(qbox->expunge_qt->tmp_mail, uid) &&
+	    mail_get_physical_size(qbox->expunge_qt->tmp_mail, &size) == 0)
 		quota_free_bytes(qbox->expunge_qt, size);
 	else {
 		/* there's no way to get the size. recalculate the quota. */
--- a/src/plugins/quota/quota.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/plugins/quota/quota.c	Sun Aug 12 19:40:54 2007 +0300
@@ -696,9 +696,13 @@
 int quota_try_alloc(struct quota_transaction_context *ctx,
 		    struct mail *mail, bool *too_large_r)
 {
+	uoff_t size;
 	int ret;
 
-	ret = quota_test_alloc(ctx, mail_get_physical_size(mail), too_large_r);
+	if (mail_get_physical_size(mail, &size) < 0)
+		return -1;
+
+	ret = quota_test_alloc(ctx, size, too_large_r);
 	if (ret <= 0)
 		return ret;
 
@@ -754,8 +758,7 @@
 {
 	uoff_t size;
 
-	size = mail_get_physical_size(mail);
-	if (size != (uoff_t)-1)
+	if (mail_get_physical_size(mail, &size) == 0)
 		ctx->bytes_used += size;
 
 	ctx->count_used++;
@@ -765,8 +768,7 @@
 {
 	uoff_t size;
 
-	size = mail_get_physical_size(mail);
-	if (size == (uoff_t)-1)
+	if (mail_get_physical_size(mail, &size) < 0)
 		quota_recalculate(ctx);
 	else
 		quota_free_bytes(ctx, size);
--- a/src/plugins/trash/trash-plugin.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/plugins/trash/trash-plugin.c	Sun Aug 12 19:40:54 2007 +0300
@@ -91,7 +91,8 @@
 		trash->mail_set = TRUE;
 	}
 
-	*received_time_r = mail_get_received_date(trash->mail);
+	if (mail_get_received_date(trash->mail, received_time_r) < 0)
+		return -1;
 	return 1;
 }
 
@@ -145,8 +146,8 @@
 		}
 
 		if (oldest_idx < count) {
-			size = mail_get_physical_size(trashes[oldest_idx].mail);
-			if (size == (uoff_t)-1) {
+			if (mail_get_physical_size(trashes[oldest_idx].mail,
+						   &size) < 0) {
 				/* maybe expunged already? */
 				trashes[oldest_idx].mail_set = FALSE;
 				continue;
--- a/src/pop3/client.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/pop3/client.c	Sun Aug 12 19:40:54 2007 +0300
@@ -57,6 +57,7 @@
         struct mailbox_status status;
 	struct mail *mail;
 	buffer_t *message_sizes_buf;
+	uoff_t size;
 	int i;
 	bool failed;
 
@@ -82,9 +83,7 @@
 		failed = FALSE;
 		mail = mail_alloc(t, MAIL_FETCH_VIRTUAL_SIZE, NULL);
 		while (mailbox_search_next(ctx, mail) > 0) {
-			uoff_t size = mail_get_virtual_size(mail);
-
-			if (size == (uoff_t)-1) {
+			if (mail_get_virtual_size(mail, &size) < 0) {
 				failed = TRUE;
 				break;
 			}
--- a/src/pop3/commands.c	Sun Aug 12 18:16:40 2007 +0300
+++ b/src/pop3/commands.c	Sun Aug 12 19:40:54 2007 +0300
@@ -379,12 +379,8 @@
 	ctx->mail = mail_alloc(client->trans, MAIL_FETCH_STREAM_HEADER |
 			       MAIL_FETCH_STREAM_BODY, NULL);
 
-	if (mailbox_search_next(ctx->search_ctx, ctx->mail) <= 0)
-		ctx->stream = NULL;
-	else
-		ctx->stream = mail_get_stream(ctx->mail, NULL, NULL);
-
-	if (ctx->stream == NULL) {
+	if (mailbox_search_next(ctx->search_ctx, ctx->mail) <= 0 ||
+	    mail_get_stream(ctx->mail, NULL, NULL, &ctx->stream) < 0) {
 		client_send_line(client, "-ERR Message not found.");
 		fetch_deinit(ctx);
 		return;
@@ -542,18 +538,18 @@
 		if ((uidl_keymask & UIDL_UID) != 0)
 			tab[1].value = dec2str(ctx->mail->uid);
 		if ((uidl_keymask & UIDL_MD5) != 0) {
-			tab[2].value = mail_get_special(ctx->mail,
-							MAIL_FETCH_HEADER_MD5);
-			if (tab[2].value == NULL) {
+			if (mail_get_special(ctx->mail, MAIL_FETCH_HEADER_MD5,
+					     &tab[2].value) < 0 ||
+			    *tab[2].value == '\0') {
 				/* broken */
 				i_fatal("UIDL: Header MD5 not found");
 			}
 		}
 		if ((uidl_keymask & UIDL_FILE_NAME) != 0) {
-			tab[3].value =
-				mail_get_special(ctx->mail,
-						 MAIL_FETCH_UIDL_FILE_NAME);
-			if (tab[3].value == NULL) {
+			if (mail_get_special(ctx->mail,
+					     MAIL_FETCH_UIDL_FILE_NAME,
+					     &tab[3].value) < 0 ||
+			    *tab[3].value == '\0') {
 				/* broken */
 				i_fatal("UIDL: File name not found");
 			}
@@ -563,12 +559,11 @@
 		str_printfa(str, ctx->message == 0 ? "%u " : "+OK %u ",
 			    ctx->mail->seq);
 
-		uidl = !reuse_xuidl ? NULL :
-			mail_get_first_header(ctx->mail, "X-UIDL");
-		if (uidl == NULL)
+		if (reuse_xuidl &&
+		    mail_get_first_header(ctx->mail, "X-UIDL", &uidl) > 0)
+			str_append(str, uidl);
+		else
 			var_expand(str, uidl_format, tab);
-		else
-			str_append(str, uidl);
 		ret = client_send_line(client, "%s", str_c(str));
 		t_pop();