[evolution-data-server/camel-gobject: 44/67] Add GError to the stream API and watch the pretty ripples.



commit 63ffa6aee509e8cca146d5385af30b80161a215e
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sun Nov 29 17:08:38 2009 -0500

    Add GError to the stream API and watch the pretty ripples.

 camel/camel-block-file.c                           |   42 +-
 camel/camel-block-file.h                           |   43 +-
 camel/camel-cipher-context.c                       |   12 +-
 camel/camel-cipher-context.h                       |    2 +-
 camel/camel-data-cache.c                           |    6 +-
 camel/camel-data-wrapper.c                         |  279 +++---
 camel/camel-data-wrapper.h                         |   80 +-
 camel/camel-file-utils.c                           |   77 ++-
 camel/camel-file-utils.h                           |    8 +-
 camel/camel-filter-driver.c                        |   20 +-
 camel/camel-filter-search.c                        |    5 +-
 camel/camel-folder-search.c                        |    4 +-
 camel/camel-folder-summary.c                       |    5 +-
 camel/camel-gpg-context.c                          |   97 +-
 camel/camel-http-stream.c                          |  482 +++++-----
 camel/camel-http-stream.h                          |   32 +-
 camel/camel-index-control.c                        |   35 +-
 camel/camel-index.c                                |   20 +-
 camel/camel-index.h                                |   98 ++-
 camel/camel-mime-filter-save.c                     |    2 +-
 camel/camel-mime-message.c                         |  420 ++++----
 camel/camel-mime-parser.c                          |   21 +-
 camel/camel-mime-parser.h                          |    2 +-
 camel/camel-mime-part-utils.c                      |   38 +-
 camel/camel-mime-part-utils.h                      |    5 +-
 camel/camel-mime-part.c                            | 1074 ++++++++++----------
 camel/camel-mime-part.h                            |    7 +-
 camel/camel-multipart-signed.c                     |  568 ++++++-----
 camel/camel-multipart.c                            |  541 +++++-----
 camel/camel-partition-table.c                      |  148 ++-
 camel/camel-partition-table.h                      |   62 +-
 camel/camel-search-private.c                       |    4 +-
 camel/camel-seekable-stream.c                      |   22 +-
 camel/camel-seekable-stream.h                      |   32 +-
 camel/camel-seekable-substream.c                   |   46 +-
 camel/camel-smime-context.c                        |   48 +-
 camel/camel-stream-buffer.c                        |   52 +-
 camel/camel-stream-buffer.h                        |    6 +-
 camel/camel-stream-filter.c                        |   34 +-
 camel/camel-stream-fs.c                            |   79 ++-
 camel/camel-stream-fs.h                            |    6 +-
 camel/camel-stream-mem.c                           |    9 +-
 camel/camel-stream-null.c                          |    6 +-
 camel/camel-stream-process.c                       |   24 +-
 camel/camel-stream-vfs.c                           |   15 +-
 camel/camel-stream.c                               |   81 +-
 camel/camel-stream.h                               |   65 +-
 camel/camel-tcp-stream-raw.c                       |   28 +-
 camel/camel-tcp-stream-ssl.c                       |   56 +-
 camel/camel-tcp-stream.c                           |    6 +-
 camel/camel-tcp-stream.h                           |   46 +-
 camel/camel-text-index.c                           |  194 +++--
 camel/camel-text-index.h                           |   22 +-
 camel/camel-uid-cache.c                            |    6 +-
 camel/providers/groupwise/camel-groupwise-folder.c |   16 +-
 .../providers/groupwise/camel-groupwise-journal.c  |   13 +-
 camel/providers/groupwise/camel-groupwise-utils.c  |   18 +-
 camel/providers/imap/camel-imap-command.c          |   53 +-
 camel/providers/imap/camel-imap-folder.c           |   29 +-
 camel/providers/imap/camel-imap-message-cache.c    |   55 +-
 camel/providers/imap/camel-imap-search.c           |   12 +-
 camel/providers/imap/camel-imap-store.c            |   27 +-
 camel/providers/imap/camel-imap-wrapper.c          |  103 +-
 camel/providers/local/camel-local-folder.c         |    4 +-
 camel/providers/local/camel-local-summary.c        |   26 +-
 camel/providers/local/camel-maildir-folder.c       |   34 +-
 camel/providers/local/camel-mbox-folder.c          |   55 +-
 camel/providers/local/camel-mh-folder.c            |   28 +-
 camel/providers/local/camel-mh-store.c             |   27 +-
 camel/providers/nntp/camel-nntp-folder.c           |   58 +-
 camel/providers/nntp/camel-nntp-store.c            |   80 +-
 camel/providers/nntp/camel-nntp-stream.c           |   69 +-
 camel/providers/nntp/camel-nntp-stream.h           |   27 +-
 camel/providers/nntp/camel-nntp-summary.c          |   20 +-
 camel/providers/pop3/camel-pop3-engine.c           |    4 +-
 camel/providers/pop3/camel-pop3-folder.c           |   36 +-
 camel/providers/pop3/camel-pop3-store.c            |   38 +-
 camel/providers/pop3/camel-pop3-stream.c           |   22 +-
 .../providers/sendmail/camel-sendmail-transport.c  |   12 +-
 camel/providers/smtp/camel-smtp-transport.c        |  340 ++-----
 .../libedata-cal/tmpl/e-data-cal-common.sgml       |    1 +
 81 files changed, 3306 insertions(+), 3023 deletions(-)
---
diff --git a/camel/camel-block-file.c b/camel/camel-block-file.c
index d940e9f..e4b162d 100644
--- a/camel/camel-block-file.c
+++ b/camel/camel-block-file.c
@@ -32,7 +32,9 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <gio/gio.h>
 #include <glib/gstdio.h>
+#include <glib/gi18n-lib.h>
 
 #include "camel-block-file.h"
 #include "camel-file-utils.h"
@@ -363,6 +365,7 @@ camel_cache_remove(c, key);
  * @path:
  * @:
  * @block_size:
+ * @error: return location for a #GError, or %NULL
  *
  * Allocate a new block file, stored at @path.  @version contains an 8 character
  * version string which must match the head of the file, or the file will be
@@ -372,7 +375,12 @@ camel_cache_remove(c, key);
  *
  * Return value: The new block file, or NULL if it could not be created.
  **/
-CamelBlockFile *camel_block_file_new(const gchar *path, gint flags, const gchar version[8], gsize block_size)
+CamelBlockFile *
+camel_block_file_new (const gchar *path,
+                      gint flags,
+                      const gchar version[8],
+                      gsize block_size,
+                      GError **error)
 {
 	CamelBlockFileClass *class;
 	CamelBlockFile *bs;
@@ -382,7 +390,7 @@ CamelBlockFile *camel_block_file_new(const gchar *path, gint flags, const gchar
 	bs->path = g_strdup(path);
 	bs->flags = flags;
 
-	bs->root_block = camel_block_file_get_block(bs, 0);
+	bs->root_block = camel_block_file_get_block (bs, 0, error);
 	if (bs->root_block == NULL) {
 		g_object_unref (bs);
 		return NULL;
@@ -475,25 +483,28 @@ camel_block_file_delete(CamelBlockFile *bs)
 /**
  * camel_block_file_new_block:
  * @bs:
+ * @error: return location for a #GError, or %NULL
  *
  * Allocate a new block, return a pointer to it.  Old blocks
  * may be flushed to disk during this call.
  *
  * Return value: The block, or NULL if an error occured.
  **/
-CamelBlock *camel_block_file_new_block(CamelBlockFile *bs)
+CamelBlock *
+camel_block_file_new_block (CamelBlockFile *bs,
+                            GError **error)
 {
 	CamelBlock *bl;
 
 	CAMEL_BLOCK_FILE_LOCK(bs, root_lock);
 
 	if (bs->root->free) {
-		bl = camel_block_file_get_block(bs, bs->root->free);
+		bl = camel_block_file_get_block (bs, bs->root->free, error);
 		if (bl == NULL)
 			goto fail;
 		bs->root->free = ((camel_block_t *)bl->data)[0];
 	} else {
-		bl = camel_block_file_get_block(bs, bs->root->last);
+		bl = camel_block_file_get_block(bs, bs->root->last, error);
 		if (bl == NULL)
 			goto fail;
 		bs->root->last += CAMEL_BLOCK_SIZE;
@@ -513,14 +524,18 @@ fail:
  * camel_block_file_free_block:
  * @bs:
  * @id:
+ * @error: return location for a #GError, or %NULL
  *
  *
  **/
-gint camel_block_file_free_block(CamelBlockFile *bs, camel_block_t id)
+gint
+camel_block_file_free_block (CamelBlockFile *bs,
+                             camel_block_t id,
+                             GError **error)
 {
 	CamelBlock *bl;
 
-	bl = camel_block_file_get_block(bs, id);
+	bl = camel_block_file_get_block (bs, id, error);
 	if (bl == NULL)
 		return -1;
 
@@ -541,13 +556,17 @@ gint camel_block_file_free_block(CamelBlockFile *bs, camel_block_t id)
  * camel_block_file_get_block:
  * @bs:
  * @id:
+ * @error: return location for a #GError, or %NULL
  *
  * Retreive a block @id.
  *
  * Return value: The block, or NULL if blockid is invalid or a file error
  * occured.
  **/
-CamelBlock *camel_block_file_get_block(CamelBlockFile *bs, camel_block_t id)
+CamelBlock *
+camel_block_file_get_block (CamelBlockFile *bs,
+                            camel_block_t id,
+                            GError **error)
 {
 	CamelBlock *bl, *flush, *prev;
 
@@ -556,7 +575,10 @@ CamelBlock *camel_block_file_get_block(CamelBlockFile *bs, camel_block_t id)
 	if ((bs->root == NULL && id != 0)
 	    || (bs->root != NULL && (id > bs->root->last || id == 0))
 	    || (id % bs->block_size) != 0) {
-		errno = EINVAL;
+		g_set_error (
+			error, G_IO_ERROR,
+			G_IO_ERROR_INVALID_ARGUMENT,
+			_("Invalid block file"));
 		return NULL;
 	}
 
@@ -576,7 +598,7 @@ CamelBlock *camel_block_file_get_block(CamelBlockFile *bs, camel_block_t id)
 		bl = g_malloc0(sizeof(*bl));
 		bl->id = id;
 		if (lseek(bs->fd, id, SEEK_SET) == -1 ||
-		    camel_read (bs->fd, (gchar *) bl->data, CAMEL_BLOCK_SIZE) == -1) {
+		    camel_read (bs->fd, (gchar *) bl->data, CAMEL_BLOCK_SIZE, error) == -1) {
 			block_file_unuse(bs);
 			CAMEL_BLOCK_FILE_UNLOCK(bs, cache_lock);
 			g_free(bl);
diff --git a/camel/camel-block-file.h b/camel/camel-block-file.h
index 209be9a..da2b980 100644
--- a/camel/camel-block-file.h
+++ b/camel/camel-block-file.h
@@ -138,21 +138,34 @@ struct _CamelBlockFileClass {
 	gint (*init_root)(CamelBlockFile *);
 };
 
-GType camel_block_file_get_type(void);
-
-CamelBlockFile *camel_block_file_new(const gchar *path, gint flags, const gchar version[8], gsize block_size);
-gint camel_block_file_rename(CamelBlockFile *bs, const gchar *path);
-gint camel_block_file_delete(CamelBlockFile *kf);
-
-CamelBlock *camel_block_file_new_block(CamelBlockFile *bs);
-gint camel_block_file_free_block(CamelBlockFile *bs, camel_block_t id);
-CamelBlock *camel_block_file_get_block(CamelBlockFile *bs, camel_block_t id);
-void camel_block_file_detach_block(CamelBlockFile *bs, CamelBlock *bl);
-void camel_block_file_attach_block(CamelBlockFile *bs, CamelBlock *bl);
-void camel_block_file_touch_block(CamelBlockFile *bs, CamelBlock *bl);
-void camel_block_file_unref_block(CamelBlockFile *bs, CamelBlock *bl);
-gint camel_block_file_sync_block(CamelBlockFile *bs, CamelBlock *bl);
-gint camel_block_file_sync(CamelBlockFile *bs);
+GType		camel_block_file_get_type	(void);
+CamelBlockFile *camel_block_file_new		(const gchar *path,
+						 gint flags,
+						 const gchar version[8],
+						 gsize block_size,
+						 GError **error);
+gint		camel_block_file_rename		(CamelBlockFile *bs,
+						 const gchar *path);
+gint		camel_block_file_delete		(CamelBlockFile *kf);
+CamelBlock *	camel_block_file_new_block	(CamelBlockFile *bs,
+						 GError **error);
+gint		camel_block_file_free_block	(CamelBlockFile *bs,
+						 camel_block_t id,
+						 GError **error);
+CamelBlock *	camel_block_file_get_block	(CamelBlockFile *bs,
+						 camel_block_t id,
+						 GError **error);
+void		camel_block_file_detach_block	(CamelBlockFile *bs,
+						 CamelBlock *bl);
+void		camel_block_file_attach_block	(CamelBlockFile *bs,
+						 CamelBlock *bl);
+void		camel_block_file_touch_block	(CamelBlockFile *bs,
+						 CamelBlock *bl);
+void		camel_block_file_unref_block	(CamelBlockFile *bs,
+						 CamelBlock *bl);
+gint		camel_block_file_sync_block	(CamelBlockFile *bs,
+						 CamelBlock *bl);
+gint		camel_block_file_sync		(CamelBlockFile *bs);
 
 /* ********************************************************************** */
 
diff --git a/camel/camel-cipher-context.c b/camel/camel-cipher-context.c
index ce4265f..c1648d1 100644
--- a/camel/camel-cipher-context.c
+++ b/camel/camel-cipher-context.c
@@ -827,6 +827,7 @@ cc_prepare_sign (CamelMimePart *part)
  * @part: Part to write.
  * @flags: flags for the canonicalisation filter (CamelMimeFilterCanon)
  * @ostream: stream to write canonicalised output to.
+ * @error: return location for a #GError, or %NULL
  *
  * Writes a part to a stream in a canonicalised format, suitable for signing/encrypting.
  *
@@ -835,7 +836,10 @@ cc_prepare_sign (CamelMimePart *part)
  * Return value: -1 on error;
  **/
 gint
-camel_cipher_canonical_to_stream (CamelMimePart *part, guint32 flags, CamelStream *ostream)
+camel_cipher_canonical_to_stream (CamelMimePart *part,
+                                  guint32 flags,
+                                  CamelStream *ostream,
+                                  GError **error)
 {
 	CamelStream *filter;
 	CamelMimeFilter *canon;
@@ -849,12 +853,12 @@ camel_cipher_canonical_to_stream (CamelMimePart *part, guint32 flags, CamelStrea
 	camel_stream_filter_add (CAMEL_STREAM_FILTER (filter), canon);
 	g_object_unref (canon);
 
-	if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)part, filter) != -1
-	    && camel_stream_flush (filter) != -1)
+	if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)part, filter, error) != -1
+	    && camel_stream_flush (filter, error) != -1)
 		res = 0;
 
 	g_object_unref (filter);
-	camel_stream_reset (ostream);
+	camel_stream_reset (ostream, NULL);
 
 	return res;
 }
diff --git a/camel/camel-cipher-context.h b/camel/camel-cipher-context.h
index 4679f79..9c3fd34 100644
--- a/camel/camel-cipher-context.h
+++ b/camel/camel-cipher-context.h
@@ -218,7 +218,7 @@ void		     camel_cipher_validity_envelope(CamelCipherValidity *parent, CamelCiph
 void                 camel_cipher_validity_free (CamelCipherValidity *validity);
 
 /* utility functions */
-gint		     camel_cipher_canonical_to_stream(CamelMimePart *part, guint32 flags, CamelStream *ostream);
+gint		     camel_cipher_canonical_to_stream(CamelMimePart *part, guint32 flags, CamelStream *ostream, GError **error);
 
 G_END_DECLS
 
diff --git a/camel/camel-data-cache.c b/camel/camel-data-cache.c
index f7dbcf2..82756be 100644
--- a/camel/camel-data-cache.c
+++ b/camel/camel-data-cache.c
@@ -390,7 +390,8 @@ camel_data_cache_add (CamelDataCache *cdc,
 		}
 	} while (stream != NULL);
 
-	stream = camel_stream_fs_new_with_name(real, O_RDWR|O_CREAT|O_TRUNC, 0600);
+	stream = camel_stream_fs_new_with_name (
+		real, O_RDWR|O_CREAT|O_TRUNC, 0600, error);
 	if (stream)
 		camel_object_bag_add(cdc->priv->busy_bag, real, stream);
 	else
@@ -427,7 +428,8 @@ camel_data_cache_get (CamelDataCache *cdc,
 	real = data_cache_path(cdc, FALSE, path, key);
 	stream = camel_object_bag_reserve(cdc->priv->busy_bag, real);
 	if (!stream) {
-		stream = camel_stream_fs_new_with_name(real, O_RDWR, 0600);
+		stream = camel_stream_fs_new_with_name (
+			real, O_RDWR, 0600, error);
 		if (stream)
 			camel_object_bag_add(cdc->priv->busy_bag, real, stream);
 		else
diff --git a/camel/camel-data-wrapper.c b/camel/camel-data-wrapper.c
index 3da4195..e377513 100644
--- a/camel/camel-data-wrapper.c
+++ b/camel/camel-data-wrapper.c
@@ -41,15 +41,6 @@
 
 static gpointer parent_class;
 
-static gint construct_from_stream(CamelDataWrapper *, CamelStream *);
-static gssize write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
-static gssize decode_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
-static void set_mime_type (CamelDataWrapper *data_wrapper, const gchar *mime_type);
-static gchar *get_mime_type (CamelDataWrapper *data_wrapper);
-static CamelContentType *get_mime_type_field (CamelDataWrapper *data_wrapper);
-static void set_mime_type_field (CamelDataWrapper *data_wrapper, CamelContentType *mime_type);
-static gboolean is_offline (CamelDataWrapper *data_wrapper);
-
 static void
 data_wrapper_dispose (GObject *object)
 {
@@ -80,6 +71,129 @@ data_wrapper_finalize (GObject *object)
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static gssize
+data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper,
+                              CamelStream *stream,
+                              GError **error)
+{
+	gssize ret;
+
+	if (data_wrapper->stream == NULL) {
+		return -1;
+	}
+
+	CAMEL_DATA_WRAPPER_LOCK (data_wrapper, stream_lock);
+	if (camel_stream_reset (data_wrapper->stream, error) == -1) {
+		CAMEL_DATA_WRAPPER_UNLOCK (data_wrapper, stream_lock);
+		return -1;
+	}
+
+	ret = camel_stream_write_to_stream (
+		data_wrapper->stream, stream, error);
+
+	CAMEL_DATA_WRAPPER_UNLOCK (data_wrapper, stream_lock);
+
+	return ret;
+}
+
+static gssize
+data_wrapper_decode_to_stream (CamelDataWrapper *data_wrapper,
+                               CamelStream *stream,
+                               GError **error)
+{
+	CamelMimeFilter *filter;
+	CamelStream *fstream;
+	gssize ret;
+
+	fstream = camel_stream_filter_new (stream);
+
+	switch (data_wrapper->encoding) {
+	case CAMEL_TRANSFER_ENCODING_BASE64:
+		filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_BASE64_DEC);
+		camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
+		g_object_unref (filter);
+		break;
+	case CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE:
+		filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_QP_DEC);
+		camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
+		g_object_unref (filter);
+		break;
+	case CAMEL_TRANSFER_ENCODING_UUENCODE:
+		filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_UU_DEC);
+		camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
+		g_object_unref (filter);
+		break;
+	default:
+		break;
+	}
+
+	if (camel_content_type_is (data_wrapper->mime_type, "text", "*")) {
+		filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE,
+						     CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
+		camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
+		g_object_unref (filter);
+	}
+
+	ret = camel_data_wrapper_write_to_stream (
+		data_wrapper, fstream, error);
+
+	camel_stream_flush (fstream, NULL);
+	g_object_unref (fstream);
+
+	return ret;
+}
+
+static void
+data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper,
+                            const gchar *mime_type)
+{
+	if (data_wrapper->mime_type)
+		camel_content_type_unref (data_wrapper->mime_type);
+	data_wrapper->mime_type = camel_content_type_decode (mime_type);
+}
+
+static gchar *
+data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper)
+{
+	return camel_content_type_simple (data_wrapper->mime_type);
+}
+
+static CamelContentType *
+data_wrapper_get_mime_type_field (CamelDataWrapper *data_wrapper)
+{
+	return data_wrapper->mime_type;
+}
+
+static void
+data_wrapper_set_mime_type_field (CamelDataWrapper *data_wrapper,
+                                  CamelContentType *mime_type)
+{
+	if (mime_type)
+		camel_content_type_ref (mime_type);
+	if (data_wrapper->mime_type)
+		camel_content_type_unref (data_wrapper->mime_type);
+	data_wrapper->mime_type = mime_type;
+}
+
+static gint
+data_wrapper_construct_from_stream (CamelDataWrapper *data_wrapper,
+                                    CamelStream *stream,
+                                    GError **error)
+{
+	if (data_wrapper->stream)
+		g_object_unref (data_wrapper->stream);
+
+	data_wrapper->stream = stream;
+	g_object_ref (stream);
+	return 0;
+}
+
+static gboolean
+data_wrapper_is_offline (CamelDataWrapper *data_wrapper)
+{
+	return data_wrapper->offline;
+}
+
 static void
 data_wrapper_class_init (CamelDataWrapperClass *class)
 {
@@ -92,14 +206,14 @@ data_wrapper_class_init (CamelDataWrapperClass *class)
 	object_class->dispose = data_wrapper_dispose;
 	object_class->finalize = data_wrapper_finalize;
 
-	class->write_to_stream = write_to_stream;
-	class->decode_to_stream = decode_to_stream;
-	class->set_mime_type = set_mime_type;
-	class->get_mime_type = get_mime_type;
-	class->get_mime_type_field = get_mime_type_field;
-	class->set_mime_type_field = set_mime_type_field;
-	class->construct_from_stream = construct_from_stream;
-	class->is_offline = is_offline;
+	class->write_to_stream = data_wrapper_write_to_stream;
+	class->decode_to_stream = data_wrapper_decode_to_stream;
+	class->set_mime_type = data_wrapper_set_mime_type;
+	class->get_mime_type = data_wrapper_get_mime_type;
+	class->get_mime_type_field = data_wrapper_get_mime_type_field;
+	class->set_mime_type_field = data_wrapper_set_mime_type_field;
+	class->construct_from_stream = data_wrapper_construct_from_stream;
+	class->is_offline = data_wrapper_is_offline;
 }
 
 static void
@@ -146,32 +260,11 @@ camel_data_wrapper_new (void)
 	return g_object_new (CAMEL_TYPE_DATA_WRAPPER, NULL);
 }
 
-static gssize
-write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
-{
-	gssize ret;
-
-	if (data_wrapper->stream == NULL) {
-		return -1;
-	}
-
-	CAMEL_DATA_WRAPPER_LOCK (data_wrapper, stream_lock);
-	if (camel_stream_reset (data_wrapper->stream) == -1) {
-		CAMEL_DATA_WRAPPER_UNLOCK (data_wrapper, stream_lock);
-		return -1;
-	}
-
-	ret = camel_stream_write_to_stream (data_wrapper->stream, stream);
-
-	CAMEL_DATA_WRAPPER_UNLOCK (data_wrapper, stream_lock);
-
-	return ret;
-}
-
 /**
  * camel_data_wrapper_write_to_stream:
  * @data_wrapper: a #CamelDataWrapper object
  * @stream: a #CamelStream for output
+ * @error: return location for a #GError, or %NULL
  *
  * Writes the content of @data_wrapper to @stream in a machine-independent
  * format appropriate for the data. It should be possible to construct an
@@ -182,7 +275,8 @@ write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
  **/
 gssize
 camel_data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper,
-                                    CamelStream *stream)
+                                    CamelStream *stream,
+                                    GError **error)
 {
 	CamelDataWrapperClass *class;
 
@@ -192,56 +286,14 @@ camel_data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper,
 	class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
 	g_return_val_if_fail (class->write_to_stream != NULL, -1);
 
-	return class->write_to_stream (data_wrapper, stream);
-}
-
-static gssize
-decode_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
-{
-	CamelMimeFilter *filter;
-	CamelStream *fstream;
-	gssize ret;
-
-	fstream = camel_stream_filter_new (stream);
-
-	switch (data_wrapper->encoding) {
-	case CAMEL_TRANSFER_ENCODING_BASE64:
-		filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_BASE64_DEC);
-		camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
-		g_object_unref (filter);
-		break;
-	case CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE:
-		filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_QP_DEC);
-		camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
-		g_object_unref (filter);
-		break;
-	case CAMEL_TRANSFER_ENCODING_UUENCODE:
-		filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_UU_DEC);
-		camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
-		g_object_unref (filter);
-		break;
-	default:
-		break;
-	}
-
-	if (camel_content_type_is (data_wrapper->mime_type, "text", "*")) {
-		filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE,
-						     CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
-		camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
-		g_object_unref (filter);
-	}
-
-	ret = camel_data_wrapper_write_to_stream (data_wrapper, fstream);
-	camel_stream_flush (fstream);
-	g_object_unref (fstream);
-
-	return ret;
+	return class->write_to_stream (data_wrapper, stream, error);
 }
 
 /**
  * camel_data_wrapper_decode_to_stream:
  * @data_wrapper: a #CamelDataWrapper object
  * @stream: a #CamelStream for decoded data to be written to
+ * @error: return location for a #GError, or %NULL
  *
  * Writes the decoded data content to @stream.
  *
@@ -249,7 +301,8 @@ decode_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
  **/
 gssize
 camel_data_wrapper_decode_to_stream (CamelDataWrapper *data_wrapper,
-                                     CamelStream *stream)
+                                     CamelStream *stream,
+                                     GError **error)
 {
 	CamelDataWrapperClass *class;
 
@@ -259,24 +312,14 @@ camel_data_wrapper_decode_to_stream (CamelDataWrapper *data_wrapper,
 	class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
 	g_return_val_if_fail (class->decode_to_stream != NULL, -1);
 
-	return class->decode_to_stream (data_wrapper, stream);
-}
-
-static gint
-construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
-{
-	if (data_wrapper->stream)
-		g_object_unref (data_wrapper->stream);
-
-	data_wrapper->stream = stream;
-	g_object_ref (stream);
-	return 0;
+	return class->decode_to_stream (data_wrapper, stream, error);
 }
 
 /**
  * camel_data_wrapper_construct_from_stream:
  * @data_wrapper: a #CamelDataWrapper object
  * @stream: an input #CamelStream
+ * @error: return location for a #GError, or %NULL
  *
  * Constructs the content of @data_wrapper from the supplied @stream.
  *
@@ -284,7 +327,8 @@ construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
  **/
 gint
 camel_data_wrapper_construct_from_stream (CamelDataWrapper *data_wrapper,
-                                          CamelStream *stream)
+                                          CamelStream *stream,
+                                          GError **error)
 {
 	CamelDataWrapperClass *class;
 
@@ -294,15 +338,7 @@ camel_data_wrapper_construct_from_stream (CamelDataWrapper *data_wrapper,
 	class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
 	g_return_val_if_fail (class->construct_from_stream != NULL, -1);
 
-	return class->construct_from_stream (data_wrapper, stream);
-}
-
-static void
-set_mime_type (CamelDataWrapper *data_wrapper, const gchar *mime_type)
-{
-	if (data_wrapper->mime_type)
-		camel_content_type_unref (data_wrapper->mime_type);
-	data_wrapper->mime_type = camel_content_type_decode (mime_type);
+	return class->construct_from_stream (data_wrapper, stream, error);
 }
 
 /**
@@ -333,12 +369,6 @@ camel_data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper,
 	class->set_mime_type (data_wrapper, mime_type);
 }
 
-static gchar *
-get_mime_type (CamelDataWrapper *data_wrapper)
-{
-	return camel_content_type_simple (data_wrapper->mime_type);
-}
-
 /**
  * camel_data_wrapper_get_mime_type:
  * @data_wrapper: a #CamelDataWrapper object
@@ -358,12 +388,6 @@ camel_data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper)
 	return class->get_mime_type (data_wrapper);
 }
 
-static CamelContentType *
-get_mime_type_field (CamelDataWrapper *data_wrapper)
-{
-	return data_wrapper->mime_type;
-}
-
 /**
  * camel_data_wrapper_get_mime_type_field:
  * @data_wrapper: a #CamelDataWrapper object
@@ -383,17 +407,6 @@ camel_data_wrapper_get_mime_type_field (CamelDataWrapper *data_wrapper)
 	return class->get_mime_type_field (data_wrapper);
 }
 
-static void
-set_mime_type_field (CamelDataWrapper *data_wrapper,
-		     CamelContentType *mime_type)
-{
-	if (mime_type)
-		camel_content_type_ref (mime_type);
-	if (data_wrapper->mime_type)
-		camel_content_type_unref (data_wrapper->mime_type);
-	data_wrapper->mime_type = mime_type;
-}
-
 /**
  * camel_data_wrapper_set_mime_type_field:
  * @data_wrapper: a #CamelDataWrapper object
@@ -417,12 +430,6 @@ camel_data_wrapper_set_mime_type_field (CamelDataWrapper *data_wrapper,
 	class->set_mime_type_field (data_wrapper, mime_type);
 }
 
-static gboolean
-is_offline (CamelDataWrapper *data_wrapper)
-{
-	return data_wrapper->offline;
-}
-
 /**
  * camel_data_wrapper_is_offline:
  * @data_wrapper: a #CamelDataWrapper object
diff --git a/camel/camel-data-wrapper.h b/camel/camel-data-wrapper.h
index 5ed47eb..013ade4 100644
--- a/camel/camel-data-wrapper.h
+++ b/camel/camel-data-wrapper.h
@@ -75,46 +75,50 @@ struct _CamelDataWrapper {
 struct _CamelDataWrapperClass {
 	CamelObjectClass parent_class;
 
-	/* Virtual methods */
-	void                (*set_mime_type)          (CamelDataWrapper *data_wrapper,
-						       const gchar *mime_type);
-	gchar *              (*get_mime_type)          (CamelDataWrapper *data_wrapper);
-	CamelContentType *  (*get_mime_type_field)    (CamelDataWrapper *data_wrapper);
-	void                (*set_mime_type_field)    (CamelDataWrapper *data_wrapper,
-						       CamelContentType *mime_type_field);
-
-	gssize             (*write_to_stream)        (CamelDataWrapper *data_wrapper,
-						       CamelStream *stream);
-
-	gssize             (*decode_to_stream)       (CamelDataWrapper *data_wrapper,
-						       CamelStream *stream);
-
-	gint                 (*construct_from_stream)  (CamelDataWrapper *data_wrapper,
-						       CamelStream *);
-
-	gboolean            (*is_offline)             (CamelDataWrapper *data_wrapper);
+	void		(*set_mime_type)	(CamelDataWrapper *data_wrapper,
+						 const gchar *mime_type);
+	gchar *		(*get_mime_type)	(CamelDataWrapper *data_wrapper);
+	CamelContentType *
+			(*get_mime_type_field)	(CamelDataWrapper *data_wrapper);
+	void		(*set_mime_type_field)	(CamelDataWrapper *data_wrapper,
+						 CamelContentType *mime_type_field);
+	gssize		(*write_to_stream)	(CamelDataWrapper *data_wrapper,
+						 CamelStream *stream,
+						 GError **error);
+	gssize		(*decode_to_stream)	(CamelDataWrapper *data_wrapper,
+						 CamelStream *stream,
+						 GError **error);
+	gint		(*construct_from_stream)(CamelDataWrapper *data_wrapper,
+						 CamelStream *stream,
+						 GError **error);
+	gboolean	(*is_offline)		(CamelDataWrapper *data_wrapper);
 };
 
-GType camel_data_wrapper_get_type (void);
-
-/* public methods */
-CamelDataWrapper *camel_data_wrapper_new(void);
-gssize           camel_data_wrapper_write_to_stream        (CamelDataWrapper *data_wrapper,
-							     CamelStream *stream);
-gssize           camel_data_wrapper_decode_to_stream       (CamelDataWrapper *data_wrapper,
-							     CamelStream *stream);
-
-void              camel_data_wrapper_set_mime_type          (CamelDataWrapper *data_wrapper,
-							     const gchar *mime_type);
-gchar             *camel_data_wrapper_get_mime_type          (CamelDataWrapper *data_wrapper);
-CamelContentType *camel_data_wrapper_get_mime_type_field    (CamelDataWrapper *data_wrapper);
-void              camel_data_wrapper_set_mime_type_field    (CamelDataWrapper *data_wrapper,
-							     CamelContentType *mime_type);
-
-gint               camel_data_wrapper_construct_from_stream  (CamelDataWrapper *data_wrapper,
-							     CamelStream *stream);
-
-gboolean          camel_data_wrapper_is_offline             (CamelDataWrapper *data_wrapper);
+GType		camel_data_wrapper_get_type	(void);
+CamelDataWrapper *
+		camel_data_wrapper_new		(void);
+gssize		camel_data_wrapper_write_to_stream
+						(CamelDataWrapper *data_wrapper,
+						 CamelStream *stream,
+						 GError **error);
+gssize		camel_data_wrapper_decode_to_stream
+						(CamelDataWrapper *data_wrapper,
+						 CamelStream *stream,
+						 GError **error);
+void		camel_data_wrapper_set_mime_type(CamelDataWrapper *data_wrapper,
+						 const gchar *mime_type);
+gchar *		camel_data_wrapper_get_mime_type(CamelDataWrapper *data_wrapper);
+CamelContentType *
+		camel_data_wrapper_get_mime_type_field
+						(CamelDataWrapper *data_wrapper);
+void		camel_data_wrapper_set_mime_type_field
+						(CamelDataWrapper *data_wrapper,
+						 CamelContentType *mime_type);
+gint		camel_data_wrapper_construct_from_stream
+						(CamelDataWrapper *data_wrapper,
+						 CamelStream *stream,
+						 GError **error);
+gboolean	camel_data_wrapper_is_offline	(CamelDataWrapper *data_wrapper);
 
 G_END_DECLS
 
diff --git a/camel/camel-file-utils.c b/camel/camel-file-utils.c
index f266e0f..9f77c25 100644
--- a/camel/camel-file-utils.c
+++ b/camel/camel-file-utils.c
@@ -38,6 +38,9 @@
 #define EWOULDBLOCK EAGAIN
 #endif
 
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+
 #include <libedataserver/e-data-server-util.h>
 
 #include "camel-file-utils.h"
@@ -402,6 +405,7 @@ camel_file_util_safe_filename (const gchar *name)
  * @fd: file descriptor
  * @buf: buffer to fill
  * @n: number of bytes to read into @buf
+ * @error: return location for a #GError, or %NULL
  *
  * Cancellable libc read() replacement.
  *
@@ -412,12 +416,19 @@ camel_file_util_safe_filename (const gchar *name)
  * be set appropriately.
  **/
 gssize
-camel_read (gint fd, gchar *buf, gsize n)
+camel_read (gint fd,
+            gchar *buf,
+            gsize n,
+            GError **error)
 {
 	gssize nread;
 	gint cancel_fd;
 
 	if (camel_operation_cancel_check (NULL)) {
+		g_set_error (
+			error, G_IO_ERROR,
+			G_IO_ERROR_CANCELLED,
+			_("Cancelled read"));
 		errno = EINTR;
 		return -1;
 	}
@@ -471,6 +482,14 @@ camel_read (gint fd, gchar *buf, gsize n)
 #endif
 	}
 
+	if (errno != 0) {
+		g_set_error (
+			error, G_IO_ERROR,
+			g_io_error_from_errno (errno),
+			"%s", g_strerror (errno));
+		return -1;
+	}
+
 	return nread;
 }
 
@@ -479,6 +498,7 @@ camel_read (gint fd, gchar *buf, gsize n)
  * @fd: file descriptor
  * @buf: buffer to write
  * @n: number of bytes of @buf to write
+ * @error: return location for a #GError, or %NULL
  *
  * Cancellable libc write() replacement.
  *
@@ -489,12 +509,19 @@ camel_read (gint fd, gchar *buf, gsize n)
  * be set appropriately.
  **/
 gssize
-camel_write (gint fd, const gchar *buf, gsize n)
+camel_write (gint fd,
+             const gchar *buf,
+             gsize n,
+             GError **error)
 {
 	gssize w, written = 0;
 	gint cancel_fd;
 
 	if (camel_operation_cancel_check (NULL)) {
+		g_set_error (
+			error, G_IO_ERROR,
+			G_IO_ERROR_CANCELLED,
+			_("Cancelled write"));
 		errno = EINTR;
 		return -1;
 	}
@@ -559,8 +586,13 @@ camel_write (gint fd, const gchar *buf, gsize n)
 #endif
 	}
 
-	if (w == -1)
+	if (errno != 0) {
+		g_set_error (
+			error, G_IO_ERROR,
+			g_io_error_from_errno (errno),
+			"%s", g_strerror (errno));
 		return -1;
+	}
 
 	return written;
 }
@@ -570,6 +602,7 @@ camel_write (gint fd, const gchar *buf, gsize n)
  * @fd: a socket
  * @buf: buffer to fill
  * @n: number of bytes to read into @buf
+ * @error: return location for a #GError, or %NULL
  *
  * Cancellable read() replacement for sockets. Code that intends to be
  * portable to Win32 should call this function only on sockets
@@ -580,15 +613,22 @@ camel_write (gint fd, const gchar *buf, gsize n)
  * camel_read_socket() will retry the read until it gets something.
  **/
 gssize
-camel_read_socket (gint fd, gchar *buf, gsize n)
+camel_read_socket (gint fd,
+                   gchar *buf,
+                   gsize n,
+                   GError **error)
 {
 #ifndef G_OS_WIN32
-	return camel_read (fd, buf, n);
+	return camel_read (fd, buf, n, error);
 #else
 	gssize nread;
 	gint cancel_fd;
 
 	if (camel_operation_cancel_check (NULL)) {
+		g_set_error (
+			error, G_IO_ERROR,
+			G_IO_ERROR_CANCELLED,
+			_("Cancelled read"));
 		errno = EINTR;
 		return -1;
 	}
@@ -632,6 +672,14 @@ camel_read_socket (gint fd, gchar *buf, gsize n)
 		;
 	}
 
+	if (errno != 0) {
+		g_set_error (
+			error, G_IO_ERROR,
+			g_io_error_from_errno (errno),
+			"%s", g_strerror (errno));
+		return -1;
+	}
+
 	return nread;
 #endif
 }
@@ -641,6 +689,7 @@ camel_read_socket (gint fd, gchar *buf, gsize n)
  * @fd: file descriptor
  * @buf: buffer to write
  * @n: number of bytes of @buf to write
+ * @error: return location for a #GError, or %NULL
  *
  * Cancellable write() replacement for sockets. Code that intends to
  * be portable to Win32 should call this function only on sockets
@@ -650,15 +699,22 @@ camel_read_socket (gint fd, gchar *buf, gsize n)
  * be set appropriately.
  **/
 gssize
-camel_write_socket (gint fd, const gchar *buf, gsize n)
+camel_write_socket (gint fd,
+                    const gchar *buf,
+                    gsize n,
+                    GError **error)
 {
 #ifndef G_OS_WIN32
-	return camel_write (fd, buf, n);
+	return camel_write (fd, buf, n, error);
 #else
 	gssize w, written = 0;
 	gint cancel_fd;
 
 	if (camel_operation_cancel_check (NULL)) {
+		g_set_error (
+			error, G_IO_ERROR,
+			G_IO_ERROR_CANCELLED,
+			_("Cancelled read"));
 		errno = EINTR;
 		return -1;
 	}
@@ -711,8 +767,13 @@ camel_write_socket (gint fd, const gchar *buf, gsize n)
 		ioctlsocket (fd, FIONBIO, &arg);
 	}
 
-	if (w == -1)
+	if (errno != 0) {
+		g_set_error (
+			error, G_IO_ERROR,
+			g_io_error_from_errno (errno),
+			"%s", g_strerror (errno));
 		return -1;
+	}
 
 	return written;
 #endif
diff --git a/camel/camel-file-utils.h b/camel/camel-file-utils.h
index 7f031d9..8e5c3ed 100644
--- a/camel/camel-file-utils.h
+++ b/camel/camel-file-utils.h
@@ -66,11 +66,11 @@ gchar *camel_file_util_safe_filename (const gchar *name);
  * camel_read_socket() and camel_write_socket(). These are cancellable
  * also on Win32.
  */
-gssize camel_read (gint fd, gchar *buf, gsize n);
-gssize camel_write (gint fd, const gchar *buf, gsize n);
+gssize camel_read (gint fd, gchar *buf, gsize n, GError **error);
+gssize camel_write (gint fd, const gchar *buf, gsize n, GError **error);
 
-gssize camel_read_socket (gint fd, gchar *buf, gsize n);
-gssize camel_write_socket (gint fd, const gchar *buf, gsize n);
+gssize camel_read_socket (gint fd, gchar *buf, gsize n, GError **error);
+gssize camel_write_socket (gint fd, const gchar *buf, gsize n, GError **error);
 
 gchar *camel_file_util_savename(const gchar *filename);
 
diff --git a/camel/camel-filter-driver.c b/camel/camel-filter-driver.c
index a2fc9a9..6ddb363 100644
--- a/camel/camel-filter-driver.c
+++ b/camel/camel-filter-driver.c
@@ -834,13 +834,13 @@ pipe_to_system (struct _ESExp *f, gint argc, struct _ESExpResult **argv, CamelFi
 	g_ptr_array_free (args, TRUE);
 
 	stream = camel_stream_fs_new_with_fd (pipe_to_child);
-	if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (p->message), stream) == -1) {
+	if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (p->message), stream, NULL) == -1) {
 		g_object_unref (stream);
 		close (pipe_from_child);
 		goto wait;
 	}
 
-	if (camel_stream_flush (stream) == -1) {
+	if (camel_stream_flush (stream, NULL) == -1) {
 		g_object_unref (stream);
 		close (pipe_from_child);
 		goto wait;
@@ -850,22 +850,22 @@ pipe_to_system (struct _ESExp *f, gint argc, struct _ESExpResult **argv, CamelFi
 
 	stream = camel_stream_fs_new_with_fd (pipe_from_child);
 	mem = camel_stream_mem_new ();
-	if (camel_stream_write_to_stream (stream, mem) == -1) {
+	if (camel_stream_write_to_stream (stream, mem, NULL) == -1) {
 		g_object_unref (stream);
 		g_object_unref (mem);
 		goto wait;
 	}
 
 	g_object_unref (stream);
-	camel_stream_reset (mem);
+	camel_stream_reset (mem, NULL);
 
 	parser = camel_mime_parser_new ();
-	camel_mime_parser_init_with_stream (parser, mem);
+	camel_mime_parser_init_with_stream (parser, mem, NULL);
 	camel_mime_parser_scan_from (parser, FALSE);
 	g_object_unref (mem);
 
 	message = camel_mime_message_new ();
-	if (camel_mime_part_construct_from_parser ((CamelMimePart *) message, parser) == -1) {
+	if (camel_mime_part_construct_from_parser ((CamelMimePart *) message, parser, NULL) == -1) {
 		g_set_error (
 			&p->error, CAMEL_ERROR, CAMEL_ERROR_SYSTEM,
 			_("Invalid message stream received from %s: %s"),
@@ -1290,13 +1290,7 @@ camel_filter_driver_filter_mbox (CamelFilterDriver *driver,
 		message = camel_mime_message_new ();
 		mime_part = CAMEL_MIME_PART (message);
 
-		if (camel_mime_part_construct_from_parser (mime_part, mp) == -1) {
-			g_set_error (
-				error, CAMEL_ERROR,
-				(errno == EINTR) ?
-				CAMEL_ERROR_USER_CANCEL :
-				CAMEL_ERROR_SYSTEM,
-				_("Cannot open message"));
+		if (camel_mime_part_construct_from_parser (mime_part, mp, error) == -1) {
 			report_status (driver, CAMEL_FILTER_STATUS_END, 100, _("Failed on message %d"), i);
 			g_object_unref (message);
 			goto fail;
diff --git a/camel/camel-filter-search.c b/camel/camel-filter-search.c
index 5eeea2a..a0ce715 100644
--- a/camel/camel-filter-search.c
+++ b/camel/camel-filter-search.c
@@ -614,8 +614,9 @@ run_command (struct _ESExp *f, gint argc, struct _ESExpResult **argv, FilterMess
 	message = camel_filter_search_get_message (fms, f);
 
 	stream = camel_stream_fs_new_with_fd (pipe_to_child);
-	camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), stream);
-	camel_stream_flush (stream);
+	camel_data_wrapper_write_to_stream (
+		CAMEL_DATA_WRAPPER (message), stream, NULL);
+	camel_stream_flush (stream, NULL);
 	g_object_unref (stream);
 
 	context = g_main_context_new ();
diff --git a/camel/camel-folder-search.c b/camel/camel-folder-search.c
index 128a4cd..7febee4 100644
--- a/camel/camel-folder-search.c
+++ b/camel/camel-folder-search.c
@@ -1484,8 +1484,8 @@ match_words_1message (CamelDataWrapper *object, struct _camel_search_words *word
 		stream = camel_stream_mem_new_with_byte_array (byte_array);
 
 		/* FIXME: The match should be part of a stream op */
-		camel_data_wrapper_decode_to_stream (containee, stream);
-		camel_stream_write (stream, "", 1);
+		camel_data_wrapper_decode_to_stream (containee, stream, NULL);
+		camel_stream_write (stream, "", 1, NULL);
 		for (i=0;i<words->len;i++) {
 			/* FIXME: This is horridly slow, and should use a real search algorithm */
 			if (camel_ustrstrcase((const gchar *) byte_array->data, words->words[i]->word) != NULL) {
diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c
index 5c7fd29..17ebd64 100644
--- a/camel/camel-folder-summary.c
+++ b/camel/camel-folder-summary.c
@@ -4384,8 +4384,9 @@ summary_build_content_info_message(CamelFolderSummary *s, CamelMessageInfo *msgi
 			CAMEL_STREAM_FILTER (p->filter_stream),
 			p->filter_index);
 
-		camel_data_wrapper_decode_to_stream(containee, p->filter_stream);
-		camel_stream_flush(p->filter_stream);
+		camel_data_wrapper_decode_to_stream (
+			containee, p->filter_stream, NULL);
+		camel_stream_flush(p->filter_stream, NULL);
 
 		camel_stream_filter_remove (
 			CAMEL_STREAM_FILTER (p->filter_stream), idx_id);
diff --git a/camel/camel-gpg-context.c b/camel/camel-gpg-context.c
index 28f404f..ce2d747 100644
--- a/camel/camel-gpg-context.c
+++ b/camel/camel-gpg-context.c
@@ -368,7 +368,7 @@ gpg_ctx_get_diagnostics (struct _GpgCtx *gpg)
 {
 	if (!gpg->diagflushed) {
 		gpg->diagflushed = TRUE;
-		camel_stream_flush (gpg->diagnostics);
+		camel_stream_flush (gpg->diagnostics, NULL);
 		if (gpg->diagbuf->len == 0)
 			return NULL;
 
@@ -1115,7 +1115,8 @@ gpg_ctx_op_step (struct _GpgCtx *gpg,
 			goto exception;
 
 		if (nread > 0) {
-			gsize written = camel_stream_write (gpg->ostream, buffer, (gsize) nread);
+			gsize written = camel_stream_write (
+				gpg->ostream, buffer, (gsize) nread, NULL);
 			if (written != nread)
 				goto exception;
 		} else {
@@ -1136,7 +1137,7 @@ gpg_ctx_op_step (struct _GpgCtx *gpg,
 			goto exception;
 
 		if (nread > 0) {
-			camel_stream_write (gpg->diagnostics, buffer, nread);
+			camel_stream_write (gpg->diagnostics, buffer, nread, NULL);
 		} else {
 			gpg->seen_eof2 = TRUE;
 		}
@@ -1177,7 +1178,8 @@ gpg_ctx_op_step (struct _GpgCtx *gpg,
 		d(printf ("writing to gpg's stdin...\n"));
 
 		/* write our stream to gpg's stdin */
-		nread = camel_stream_read (gpg->istream, buffer, sizeof (buffer));
+		nread = camel_stream_read (
+			gpg->istream, buffer, sizeof (buffer), error);
 		if (nread > 0) {
 			gssize w, nwritten = 0;
 
@@ -1315,13 +1317,13 @@ gpg_sign (CamelCipherContext *context,
 
 	/* FIXME: stream this, we stream output at least */
 	istream = camel_stream_mem_new();
-	if (camel_cipher_canonical_to_stream(ipart, CAMEL_MIME_FILTER_CANON_STRIP|CAMEL_MIME_FILTER_CANON_CRLF|CAMEL_MIME_FILTER_CANON_FROM,
-					     istream) == -1) {
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Could not generate signing data: %s"),
-			g_strerror (errno));
+	if (camel_cipher_canonical_to_stream(
+		ipart, CAMEL_MIME_FILTER_CANON_STRIP |
+		CAMEL_MIME_FILTER_CANON_CRLF |
+		CAMEL_MIME_FILTER_CANON_FROM,
+		istream, error) == -1) {
+		g_prefix_error (
+			error, _("Could not generate signing data: "));
 		goto fail;
 	}
 
@@ -1380,8 +1382,8 @@ gpg_sign (CamelCipherContext *context,
 	res = 0;
 
 	dw = camel_data_wrapper_new();
-	camel_stream_reset(ostream);
-	camel_data_wrapper_construct_from_stream(dw, ostream);
+	camel_stream_reset(ostream, NULL);
+	camel_data_wrapper_construct_from_stream(dw, ostream, NULL);
 
 	sigpart = camel_mime_part_new();
 	ct = camel_content_type_new("application", "pgp-signature");
@@ -1404,7 +1406,7 @@ gpg_sign (CamelCipherContext *context,
 
 	mps->signature = sigpart;
 	mps->contentraw = istream;
-	camel_stream_reset(istream);
+	camel_stream_reset(istream, NULL);
 	g_object_ref (istream);
 
 	camel_medium_set_content ((CamelMedium *)opart, (CamelDataWrapper *)mps);
@@ -1418,7 +1420,8 @@ fail:
 }
 
 static gchar *
-swrite (CamelMimePart *sigpart)
+swrite (CamelMimePart *sigpart,
+        GError **error)
 {
 	CamelStream *ostream;
 	gchar *template;
@@ -1433,11 +1436,12 @@ swrite (CamelMimePart *sigpart)
 	/* TODO: This should probably just write the decoded message content out, not the part + headers */
 
 	ostream = camel_stream_fs_new_with_fd (fd);
-	ret = camel_data_wrapper_write_to_stream((CamelDataWrapper *)sigpart, ostream);
+	ret = camel_data_wrapper_write_to_stream (
+		CAMEL_DATA_WRAPPER (sigpart), ostream, error);
 	if (ret != -1) {
-		ret = camel_stream_flush (ostream);
+		ret = camel_stream_flush (ostream, error);
 		if (ret != -1)
-			ret = camel_stream_close (ostream);
+			ret = camel_stream_close (ostream, error);
 	}
 
 	g_object_unref (ostream);
@@ -1510,8 +1514,8 @@ gpg_verify (CamelCipherContext *context,
 		CamelDataWrapper *content;
 		content = camel_medium_get_content ((CamelMedium *) ipart);
 		istream = camel_stream_mem_new();
-		camel_data_wrapper_decode_to_stream (content, istream);
-		camel_stream_reset(istream);
+		camel_data_wrapper_decode_to_stream (content, istream, NULL);
+		camel_stream_reset(istream, NULL);
 		sigpart = NULL;
 	} else {
 		/* Invalid Mimetype */
@@ -1554,18 +1558,15 @@ gpg_verify (CamelCipherContext *context,
 #endif
 
 	if (sigpart) {
-		sigfile = swrite (sigpart);
+		sigfile = swrite (sigpart, error);
 		if (sigfile == NULL) {
-			g_set_error (
-				error, CAMEL_ERROR, CAMEL_ERROR_SYSTEM,
-				_("Cannot verify message signature: "
-				  "could not create temp file: %s"),
-				g_strerror (errno));
+			g_prefix_error (
+				error, _("Cannot verify message signature: "));
 			goto exception;
 		}
 	}
 
-	camel_stream_reset(istream);
+	camel_stream_reset (istream, NULL);
 	canon_stream = camel_stream_mem_new ();
 
 	/* strip trailing white-spaces */
@@ -1574,12 +1575,12 @@ gpg_verify (CamelCipherContext *context,
 	camel_stream_filter_add (CAMEL_STREAM_FILTER (filter), canon);
 	g_object_unref (canon);
 
-	camel_stream_write_to_stream (istream, filter);
+	camel_stream_write_to_stream (istream, filter, NULL);
 
 	g_object_unref (filter);
-	camel_stream_reset (istream);
+	camel_stream_reset (istream, NULL);
 
-	camel_stream_reset (canon_stream);
+	camel_stream_reset (canon_stream, NULL);
 
 	gpg = gpg_ctx_new (context);
 	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_VERIFY);
@@ -1675,11 +1676,10 @@ gpg_encrypt (CamelCipherContext *context,
 
 	ostream = camel_stream_mem_new();
 	istream = camel_stream_mem_new();
-	if (camel_cipher_canonical_to_stream(ipart, CAMEL_MIME_FILTER_CANON_CRLF, istream) == -1) {
-		g_set_error (
-			error, CAMEL_ERROR, CAMEL_ERROR_SYSTEM,
-			_("Could not generate encrypting data: %s"),
-			g_strerror (errno));
+	if (camel_cipher_canonical_to_stream (
+		ipart, CAMEL_MIME_FILTER_CANON_CRLF, istream, error) == -1) {
+		g_prefix_error (
+			error, _("Could not generate encrypting data: "));
 		goto fail1;
 	}
 
@@ -1722,7 +1722,7 @@ gpg_encrypt (CamelCipherContext *context,
 	res = 0;
 
 	dw = camel_data_wrapper_new();
-	camel_data_wrapper_construct_from_stream(dw, ostream);
+	camel_data_wrapper_construct_from_stream (dw, ostream, NULL);
 
 	encpart = camel_mime_part_new();
 	ct = camel_content_type_new("application", "octet-stream");
@@ -1736,13 +1736,13 @@ gpg_encrypt (CamelCipherContext *context,
 	camel_mime_part_set_description(encpart, _("This is a digitally encrypted message part"));
 
 	vstream = camel_stream_mem_new();
-	camel_stream_write(vstream, "Version: 1\n", strlen("Version: 1\n"));
-	camel_stream_reset(vstream);
+	camel_stream_write (vstream, "Version: 1\n", strlen("Version: 1\n"), NULL);
+	camel_stream_reset (vstream, NULL);
 
 	verpart = camel_mime_part_new();
 	dw = camel_data_wrapper_new();
 	camel_data_wrapper_set_mime_type(dw, class->encrypt_protocol);
-	camel_data_wrapper_construct_from_stream(dw, vstream);
+	camel_data_wrapper_construct_from_stream (dw, vstream, NULL);
 	g_object_unref (vstream);
 	camel_medium_set_content ((CamelMedium *)verpart, dw);
 	g_object_unref (dw);
@@ -1827,8 +1827,8 @@ gpg_decrypt (CamelCipherContext *context,
 	}
 
 	istream = camel_stream_mem_new();
-	camel_data_wrapper_decode_to_stream (content, istream);
-	camel_stream_reset(istream);
+	camel_data_wrapper_decode_to_stream (content, istream, NULL);
+	camel_stream_reset (istream, NULL);
 
 	ostream = camel_stream_mem_new();
 	camel_stream_mem_set_secure((CamelStreamMem *)ostream);
@@ -1861,20 +1861,21 @@ gpg_decrypt (CamelCipherContext *context,
 		goto fail;
 	}
 
-	camel_stream_reset(ostream);
+	camel_stream_reset (ostream, NULL);
 	if (camel_content_type_is(ct, "multipart", "encrypted")) {
 		CamelDataWrapper *dw;
 		CamelStream *null = camel_stream_null_new ();
 
 		/* Multipart encrypted - parse a full mime part */
-		rv = camel_data_wrapper_construct_from_stream ((CamelDataWrapper *)opart, ostream);
+		rv = camel_data_wrapper_construct_from_stream (
+			CAMEL_DATA_WRAPPER (opart), ostream, error);
 
 		dw = camel_medium_get_content ((CamelMedium *)opart);
-		if (!camel_data_wrapper_decode_to_stream (dw, null)) {
+		if (!camel_data_wrapper_decode_to_stream (dw, null, NULL)) {
 			/* nothing had been decoded from the stream, it doesn't
 			   contain any header, like Content-Type or such, thus
 			   write it as a message body */
-			rv = camel_data_wrapper_construct_from_stream (dw, ostream);
+			rv = camel_data_wrapper_construct_from_stream (dw, ostream, error);
 		}
 
 		g_object_unref (null);
@@ -1882,7 +1883,7 @@ gpg_decrypt (CamelCipherContext *context,
 		/* Inline signed - raw data (may not be a mime part) */
 		CamelDataWrapper *dw;
 		dw = camel_data_wrapper_new ();
-		rv = camel_data_wrapper_construct_from_stream(dw, ostream);
+		rv = camel_data_wrapper_construct_from_stream (dw, ostream, error);
 		camel_data_wrapper_set_mime_type(dw, "application/octet-stream");
 		camel_medium_set_content ((CamelMedium *)opart, dw);
 		g_object_unref (dw);
@@ -1909,10 +1910,6 @@ gpg_decrypt (CamelCipherContext *context,
 				valid->sign.status = CAMEL_CIPHER_VALIDITY_SIGN_BAD;
 			}
 		}
-	} else {
-		g_set_error (
-			error, CAMEL_ERROR, CAMEL_ERROR_SYSTEM,
-			_("Unable to parse message content"));
 	}
 
  fail:
diff --git a/camel/camel-http-stream.c b/camel/camel-http-stream.c
index 493c434..0f3138d 100644
--- a/camel/camel-http-stream.c
+++ b/camel/camel-http-stream.c
@@ -30,6 +30,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+
 #include "camel-http-stream.h"
 #include "camel-mime-utils.h"
 #include "camel-net-utils.h"
@@ -42,150 +45,18 @@
 #include "camel-tcp-stream-ssl.h"
 #endif
 
+#define SSL_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3)
+
 #define d(x)
 
 static gpointer parent_class;
 
-static gssize stream_read (CamelStream *stream, gchar *buffer, gsize n);
-static gssize stream_write (CamelStream *stream, const gchar *buffer, gsize n);
-static gint stream_flush  (CamelStream *stream);
-static gint stream_close  (CamelStream *stream);
-static gint stream_reset  (CamelStream *stream);
-
-static void
-http_stream_dispose (GObject *object)
-{
-	CamelHttpStream *http = CAMEL_HTTP_STREAM (object);
-
-	if (http->parser != NULL) {
-		g_object_unref (http->parser);
-		http->parser = NULL;
-	}
-
-	if (http->content_type != NULL) {
-		camel_content_type_unref (http->content_type);
-		http->content_type = NULL;
-	}
-
-	if (http->session != NULL) {
-		g_object_unref (http->session);
-		http->session = NULL;
-	}
-
-	if (http->raw != NULL) {
-		g_object_unref (http->raw);
-		http->raw = NULL;
-	}
-
-	if (http->read != NULL) {
-		g_object_unref (http->read);
-		http->read = NULL;
-	}
-
-	/* Chain up to parent's dispose() method. */
-	G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-http_stream_finalize (GObject *object)
-{
-	CamelHttpStream *http = CAMEL_HTTP_STREAM (object);
-
-	camel_header_raw_clear (http->raw_headers);
-	g_queue_free (http->raw_headers);
-
-	if (http->url != NULL)
-		camel_url_free (http->url);
-
-	if (http->proxy)
-		camel_url_free (http->proxy);
-
-	g_free (http->authrealm);
-	g_free (http->authpass);
-
-	/* Chain up to parent's finalize() method. */
-	G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-http_stream_class_init (CamelHttpStreamClass *class)
-{
-	GObjectClass *object_class;
-	CamelStreamClass *stream_class;
-
-	parent_class = g_type_class_peek_parent (class);
-
-	object_class = G_OBJECT_CLASS (class);
-	object_class->dispose = http_stream_dispose;
-	object_class->finalize = http_stream_finalize;
-
-	stream_class = CAMEL_STREAM_CLASS (class);
-	stream_class->read = stream_read;
-	stream_class->write = stream_write;
-	stream_class->flush = stream_flush;
-	stream_class->close = stream_close;
-	stream_class->reset = stream_reset;
-}
-
-static void
-http_stream_init (CamelHttpStream *http)
-{
-	http->raw_headers = g_queue_new ();
-}
-
-GType
-camel_http_stream_get_type (void)
-{
-	static GType type = G_TYPE_INVALID;
-
-	if (G_UNLIKELY (type == G_TYPE_INVALID))
-		type = g_type_register_static_simple (
-			CAMEL_TYPE_STREAM,
-			"CamelHttpStream",
-			sizeof (CamelHttpStreamClass),
-			(GClassInitFunc) http_stream_class_init,
-			sizeof (CamelHttpStream),
-			(GInstanceInitFunc) http_stream_init,
-			0);
-
-	return type;
-}
-
-/**
- * camel_http_stream_new:
- * @method: HTTP method
- * @session: active session
- * @url: URL to act upon
- *
- * Return value: a http stream
- **/
-CamelStream *
-camel_http_stream_new (CamelHttpMethod method, struct _CamelSession *session, CamelURL *url)
-{
-	CamelHttpStream *stream;
-	gchar *str;
-
-	g_return_val_if_fail(CAMEL_IS_SESSION(session), NULL);
-	g_return_val_if_fail(url != NULL, NULL);
-
-	stream = g_object_new (CAMEL_TYPE_HTTP_STREAM, NULL);
-
-	stream->method = method;
-	stream->session = session;
-	g_object_ref (session);
-
-	str = camel_url_to_string (url, 0);
-	stream->url = camel_url_new (str, NULL);
-	g_free (str);
-
-	return (CamelStream *)stream;
-}
-
-#define SSL_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3)
-
 static CamelStream *
-http_connect (CamelHttpStream *http, CamelURL *url)
+http_connect (CamelHttpStream *http,
+              CamelURL *url,
+              GError **error)
 {
+	CamelTcpStream *tcp_stream;
 	CamelStream *stream = NULL;
 	struct addrinfo *ai, hints = { 0 };
 	gint errsave;
@@ -220,7 +91,9 @@ http_connect (CamelHttpStream *http, CamelURL *url)
 		return NULL;
 	}
 
-	if (camel_tcp_stream_connect (CAMEL_TCP_STREAM (stream), ai) == -1) {
+	tcp_stream = CAMEL_TCP_STREAM (stream);
+
+	if (camel_tcp_stream_connect (tcp_stream, ai, error) == -1) {
 		errsave = errno;
 		g_object_unref (stream);
 		camel_freeaddrinfo(ai);
@@ -237,7 +110,7 @@ http_connect (CamelHttpStream *http, CamelURL *url)
 }
 
 static void
-http_disconnect(CamelHttpStream *http)
+http_disconnect (CamelHttpStream *http)
 {
 	if (http->raw) {
 		g_object_unref (http->raw);
@@ -255,41 +128,80 @@ http_disconnect(CamelHttpStream *http)
 	}
 }
 
-static const gchar *
-http_next_token (const guchar *in)
+static gint
+http_method_invoke (CamelHttpStream *http,
+                    GError **error)
 {
-	const guchar *inptr = in;
+	const gchar *method = NULL, *use_url;
+	gchar *url;
 
-	while (*inptr && !isspace ((gint) *inptr))
-		inptr++;
+	switch (http->method) {
+	case CAMEL_HTTP_METHOD_GET:
+		method = "GET";
+		break;
+	case CAMEL_HTTP_METHOD_HEAD:
+		method = "HEAD";
+		break;
+	default:
+		g_assert_not_reached ();
+	}
 
-	while (*inptr && isspace ((gint) *inptr))
-		inptr++;
+	url = camel_url_to_string (http->url, 0);
 
-	return (const gchar *) inptr;
-}
+	if (http->proxy) {
+		use_url = url;
+	} else if (http->url->host && *http->url->host) {
+		use_url = strstr (url, http->url->host) + strlen (http->url->host);
+	} else {
+		use_url = http->url->path;
+	}
 
-static gint
-http_get_statuscode (CamelHttpStream *http)
-{
-	const gchar *token;
-	gchar buffer[4096];
+	d(printf("HTTP Stream Sending: %s %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\n",
+		 method,
+		 use_url,
+		 http->user_agent ? http->user_agent : "CamelHttpStream/1.0",
+		 http->url->host));
+	if (camel_stream_printf (
+		http->raw, error,
+		"%s %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\n",
+		method, use_url, http->user_agent ? http->user_agent :
+		"CamelHttpStream/1.0", http->url->host) == -1) {
+		http_disconnect(http);
+		g_free (url);
+		return -1;
+	}
+	g_free (url);
+
+	if (http->authrealm) {
+		d(printf("HTTP Stream Sending: WWW-Authenticate: %s\n", http->authrealm));
+	}
 
-	if (camel_stream_buffer_gets ((CamelStreamBuffer *)http->read, buffer, sizeof (buffer)) <= 0)
+	if (http->authrealm && camel_stream_printf (
+		http->raw, error, "WWW-Authenticate: %s\r\n",
+		http->authrealm) == -1) {
+		http_disconnect(http);
 		return -1;
+	}
 
-	d(printf("HTTP Status: %s\n", buffer));
+	if (http->authpass && http->proxy) {
+		d(printf("HTTP Stream Sending: Proxy-Aurhorization: Basic %s\n", http->authpass));
+	}
 
-	/* parse the HTTP status code */
-	if (!g_ascii_strncasecmp (buffer, "HTTP/", 5)) {
-		token = http_next_token ((const guchar *) buffer);
-		http->statuscode = camel_header_decode_int (&token);
-		return http->statuscode;
+	if (http->authpass && http->proxy && camel_stream_printf (
+		http->raw, error, "Proxy-Authorization: Basic %s\r\n",
+		http->authpass) == -1) {
+		http_disconnect(http);
+		return -1;
 	}
 
-	http_disconnect(http);
+	/* end the headers */
+	if (camel_stream_write (http->raw, "\r\n", 2, error) == -1 ||
+		camel_stream_flush (http->raw, error) == -1) {
+		http_disconnect(http);
+		return -1;
+	}
 
-	return -1;
+	return 0;
 }
 
 static gint
@@ -306,7 +218,7 @@ http_get_headers (CamelHttpStream *http)
 		g_object_unref (http->parser);
 
 	http->parser = camel_mime_parser_new ();
-	camel_mime_parser_init_with_stream (http->parser, http->read);
+	camel_mime_parser_init_with_stream (http->parser, http->read, NULL);
 
 	switch (camel_mime_parser_step (http->parser, &buf, &len)) {
 	case CAMEL_MIME_PARSER_STATE_MESSAGE:
@@ -361,79 +273,106 @@ http_get_headers (CamelHttpStream *http)
 	return -1;
 }
 
-static gint
-http_method_invoke (CamelHttpStream *http)
+static const gchar *
+http_next_token (const guchar *in)
 {
-	const gchar *method = NULL, *use_url;
-	gchar *url;
+	const guchar *inptr = in;
 
-	switch (http->method) {
-	case CAMEL_HTTP_METHOD_GET:
-		method = "GET";
-		break;
-	case CAMEL_HTTP_METHOD_HEAD:
-		method = "HEAD";
-		break;
-	default:
-		g_assert_not_reached ();
-	}
+	while (*inptr && !isspace ((gint) *inptr))
+		inptr++;
 
-	url = camel_url_to_string (http->url, 0);
+	while (*inptr && isspace ((gint) *inptr))
+		inptr++;
 
-	if (http->proxy) {
-		use_url = url;
-	} else if (http->url->host && *http->url->host) {
-		use_url = strstr (url, http->url->host) + strlen (http->url->host);
-	} else {
-		use_url = http->url->path;
-	}
+	return (const gchar *) inptr;
+}
 
-	d(printf("HTTP Stream Sending: %s %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\n",
-		 method,
-		 use_url,
-		 http->user_agent ? http->user_agent : "CamelHttpStream/1.0",
-		 http->url->host));
-	if (camel_stream_printf (http->raw, "%s %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\n",
-				 method,
-				 use_url,
-				 http->user_agent ? http->user_agent : "CamelHttpStream/1.0",
-				 http->url->host) == -1) {
-		http_disconnect(http);
-		g_free (url);
+static gint
+http_get_statuscode (CamelHttpStream *http,
+                     GError **error)
+{
+	const gchar *token;
+	gchar buffer[4096];
+
+	if (camel_stream_buffer_gets (
+		CAMEL_STREAM_BUFFER (http->read),
+		buffer, sizeof (buffer), error) <= 0)
 		return -1;
+
+	d(printf("HTTP Status: %s\n", buffer));
+
+	/* parse the HTTP status code */
+	if (!g_ascii_strncasecmp (buffer, "HTTP/", 5)) {
+		token = http_next_token ((const guchar *) buffer);
+		http->statuscode = camel_header_decode_int (&token);
+		return http->statuscode;
 	}
-	g_free (url);
 
-	if (http->authrealm) {
-		d(printf("HTTP Stream Sending: WWW-Authenticate: %s\n", http->authrealm));
+	http_disconnect(http);
+
+	return -1;
+}
+
+static void
+http_stream_dispose (GObject *object)
+{
+	CamelHttpStream *http = CAMEL_HTTP_STREAM (object);
+
+	if (http->parser != NULL) {
+		g_object_unref (http->parser);
+		http->parser = NULL;
 	}
 
-	if (http->authrealm && camel_stream_printf (http->raw, "WWW-Authenticate: %s\r\n", http->authrealm) == -1) {
-		http_disconnect(http);
-		return -1;
+	if (http->content_type != NULL) {
+		camel_content_type_unref (http->content_type);
+		http->content_type = NULL;
 	}
 
-	if (http->authpass && http->proxy) {
-		d(printf("HTTP Stream Sending: Proxy-Aurhorization: Basic %s\n", http->authpass));
+	if (http->session != NULL) {
+		g_object_unref (http->session);
+		http->session = NULL;
 	}
 
-	if (http->authpass && http->proxy && camel_stream_printf (http->raw, "Proxy-Authorization: Basic %s\r\n",
-								  http->authpass) == -1) {
-		http_disconnect(http);
-		return -1;
+	if (http->raw != NULL) {
+		g_object_unref (http->raw);
+		http->raw = NULL;
 	}
 
-	/* end the headers */
-	if (camel_stream_write (http->raw, "\r\n", 2) == -1 || camel_stream_flush (http->raw) == -1) {
-		http_disconnect(http);
-		return -1;
+	if (http->read != NULL) {
+		g_object_unref (http->read);
+		http->read = NULL;
 	}
 
-	return 0;
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+http_stream_finalize (GObject *object)
+{
+	CamelHttpStream *http = CAMEL_HTTP_STREAM (object);
+
+	camel_header_raw_clear (http->raw_headers);
+	g_queue_free (http->raw_headers);
+
+	if (http->url != NULL)
+		camel_url_free (http->url);
+
+	if (http->proxy)
+		camel_url_free (http->proxy);
+
+	g_free (http->authrealm);
+	g_free (http->authpass);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 static gssize
-stream_read (CamelStream *stream, gchar *buffer, gsize n)
+http_stream_read (CamelStream *stream,
+                  gchar *buffer,
+                  gsize n,
+                  GError **error)
 {
 	CamelHttpStream *http = CAMEL_HTTP_STREAM (stream);
 	const gchar *parser_buf;
@@ -447,15 +386,17 @@ stream_read (CamelStream *stream, gchar *buffer, gsize n)
  redirect:
 
 	if (!http->raw) {
-		if (http_connect (http, http->proxy ? http->proxy : http->url) == NULL)
+		if (http_connect (
+			http, http->proxy ? http->proxy :
+			http->url, error) == NULL)
 			return -1;
 
-		if (http_method_invoke (http) == -1) {
+		if (http_method_invoke (http, error) == -1) {
 			http_disconnect(http);
 			return -1;
 		}
 
-		if (http_get_statuscode (http) == -1) {
+		if (http_get_statuscode (http, error) == -1) {
 			http_disconnect(http);
 			return -1;
 		}
@@ -526,29 +467,38 @@ stream_read (CamelStream *stream, gchar *buffer, gsize n)
 }
 
 static gssize
-stream_write (CamelStream *stream, const gchar *buffer, gsize n)
+http_stream_write (CamelStream *stream,
+                   const gchar *buffer,
+                   gsize n,
+                   GError **error)
 {
+	g_set_error (
+		error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+		_("Cannot write to HTTP streams"));
+
 	return -1;
 }
 
 static gint
-stream_flush (CamelStream *stream)
+http_stream_flush (CamelStream *stream,
+                   GError **error)
 {
 	CamelHttpStream *http = (CamelHttpStream *) stream;
 
 	if (http->raw)
-		return camel_stream_flush (http->raw);
+		return camel_stream_flush (http->raw, error);
 	else
 		return 0;
 }
 
 static gint
-stream_close (CamelStream *stream)
+http_stream_close (CamelStream *stream,
+                   GError **error)
 {
 	CamelHttpStream *http = (CamelHttpStream *) stream;
 
 	if (http->raw) {
-		if (camel_stream_close (http->raw) == -1)
+		if (camel_stream_close (http->raw, error) == -1)
 			return -1;
 
 		http_disconnect(http);
@@ -558,7 +508,8 @@ stream_close (CamelStream *stream)
 }
 
 static gint
-stream_reset (CamelStream *stream)
+http_stream_reset (CamelStream *stream,
+                   GError **error)
 {
 	CamelHttpStream *http = CAMEL_HTTP_STREAM (stream);
 
@@ -568,13 +519,90 @@ stream_reset (CamelStream *stream)
 	return 0;
 }
 
+static void
+http_stream_class_init (CamelHttpStreamClass *class)
+{
+	GObjectClass *object_class;
+	CamelStreamClass *stream_class;
+
+	parent_class = g_type_class_peek_parent (class);
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->dispose = http_stream_dispose;
+	object_class->finalize = http_stream_finalize;
+
+	stream_class = CAMEL_STREAM_CLASS (class);
+	stream_class->read = http_stream_read;
+	stream_class->write = http_stream_write;
+	stream_class->flush = http_stream_flush;
+	stream_class->close = http_stream_close;
+	stream_class->reset = http_stream_reset;
+}
+
+static void
+http_stream_init (CamelHttpStream *http)
+{
+	http->raw_headers = g_queue_new ();
+}
+
+GType
+camel_http_stream_get_type (void)
+{
+	static GType type = G_TYPE_INVALID;
+
+	if (G_UNLIKELY (type == G_TYPE_INVALID))
+		type = g_type_register_static_simple (
+			CAMEL_TYPE_STREAM,
+			"CamelHttpStream",
+			sizeof (CamelHttpStreamClass),
+			(GClassInitFunc) http_stream_class_init,
+			sizeof (CamelHttpStream),
+			(GInstanceInitFunc) http_stream_init,
+			0);
+
+	return type;
+}
+
+/**
+ * camel_http_stream_new:
+ * @method: HTTP method
+ * @session: active session
+ * @url: URL to act upon
+ *
+ * Return value: a http stream
+ **/
+CamelStream *
+camel_http_stream_new (CamelHttpMethod method, struct _CamelSession *session, CamelURL *url)
+{
+	CamelHttpStream *stream;
+	gchar *str;
+
+	g_return_val_if_fail(CAMEL_IS_SESSION(session), NULL);
+	g_return_val_if_fail(url != NULL, NULL);
+
+	stream = g_object_new (CAMEL_TYPE_HTTP_STREAM, NULL);
+
+	stream->method = method;
+	stream->session = session;
+	g_object_ref (session);
+
+	str = camel_url_to_string (url, 0);
+	stream->url = camel_url_new (str, NULL);
+	g_free (str);
+
+	return (CamelStream *)stream;
+}
+
 CamelContentType *
-camel_http_stream_get_content_type (CamelHttpStream *http_stream)
+camel_http_stream_get_content_type (CamelHttpStream *http_stream,
+                                    GError **error)
 {
 	g_return_val_if_fail (CAMEL_IS_HTTP_STREAM (http_stream), NULL);
 
 	if (!http_stream->content_type && !http_stream->raw) {
-		if (stream_read (CAMEL_STREAM (http_stream), NULL, 0) == -1)
+		CamelStream *stream = CAMEL_STREAM (http_stream);
+
+		if (http_stream_read (stream, NULL, 0, error) == -1)
 			return NULL;
 	}
 
diff --git a/camel/camel-http-stream.h b/camel/camel-http-stream.h
index 5458b18..ce892bf 100644
--- a/camel/camel-http-stream.h
+++ b/camel/camel-http-stream.h
@@ -93,22 +93,26 @@ struct _CamelHttpStream {
 
 struct _CamelHttpStreamClass {
 	CamelStreamClass parent_class;
-
-	/* Virtual methods */
 };
 
-GType camel_http_stream_get_type (void);
-
-/* public methods */
-CamelStream *camel_http_stream_new (CamelHttpMethod method, struct _CamelSession *session, CamelURL *url);
-
-void camel_http_stream_set_user_agent (CamelHttpStream *http_stream, const gchar *user_agent);
-
-void camel_http_stream_set_proxy (CamelHttpStream *http_stream, const gchar *proxy_url);
-void camel_http_stream_set_proxy_authrealm (CamelHttpStream *http_stream, const gchar *proxy_authrealm);
-void camel_http_stream_set_proxy_authpass (CamelHttpStream *http_stream, const gchar *proxy_authpass);
-
-CamelContentType *camel_http_stream_get_content_type (CamelHttpStream *http_stream);
+GType		camel_http_stream_get_type	(void);
+CamelStream *	camel_http_stream_new		(CamelHttpMethod method,
+						 struct _CamelSession *session,
+						 CamelURL *url);
+void		camel_http_stream_set_user_agent(CamelHttpStream *http_stream,
+						 const gchar *user_agent);
+void		camel_http_stream_set_proxy	(CamelHttpStream *http_stream,
+						 const gchar *proxy_url);
+void		camel_http_stream_set_proxy_authrealm
+						(CamelHttpStream *http_stream,
+						 const gchar *proxy_authrealm);
+void		camel_http_stream_set_proxy_authpass
+						(CamelHttpStream *http_stream,
+						 const gchar *proxy_authpass);
+CamelContentType *
+		camel_http_stream_get_content_type
+						(CamelHttpStream *http_stream,
+						 GError **error);
 
 G_END_DECLS
 
diff --git a/camel/camel-index-control.c b/camel/camel-index-control.c
index d1f9693..a9c55dd 100644
--- a/camel/camel-index-control.c
+++ b/camel/camel-index-control.c
@@ -37,19 +37,21 @@ do_compress(gint argc, gchar **argv)
 {
 	gint i;
 	CamelIndex *idx;
+	GError *error = NULL;
 
 	for (i=2;i<argc;i++) {
 		printf("Opening index file: %s\n", argv[i]);
-		idx = (CamelIndex *)camel_text_index_new(argv[i], O_RDWR);
+		idx = (CamelIndex *)camel_text_index_new(argv[i], O_RDWR, &error);
 		if (idx) {
 			printf(" Compressing ...\n");
-			if (camel_index_compress(idx) == -1) {
+			if (camel_index_compress (idx, &error) == -1) {
 				g_object_unref (idx);
 				return 1;
 			}
 			g_object_unref (idx);
 		} else {
-			printf(" Failed: %s\n", g_strerror (errno));
+			printf(" Failed: %s\n", error->message);
+			g_error_free (error);
 			return 1;
 		}
 	}
@@ -61,16 +63,18 @@ do_dump(gint argc, gchar **argv)
 {
 	gint i;
 	CamelIndex *idx;
+	GError *error = NULL;
 
 	for (i=2;i<argc;i++) {
 		printf("Opening index file: %s\n", argv[i]);
-		idx = (CamelIndex *)camel_text_index_new(argv[i], O_RDONLY);
+		idx = (CamelIndex *)camel_text_index_new(argv[i], O_RDONLY, &error);
 		if (idx) {
 			printf(" Dumping ...\n");
 			camel_text_index_dump((CamelTextIndex *)idx);
 			g_object_unref (idx);
 		} else {
-			printf(" Failed: %s\n", g_strerror (errno));
+			printf(" Failed: %s\n", error->message);
+			g_error_free (error);
 			return 1;
 		}
 	}
@@ -82,15 +86,17 @@ do_info(gint argc, gchar **argv)
 {
 	gint i;
 	CamelIndex *idx;
+	GError *error = NULL;
 
 	for (i=2;i<argc;i++) {
 		printf("Opening index file: %s\n", argv[i]);
-		idx = (CamelIndex *)camel_text_index_new(argv[i], O_RDONLY);
+		idx = (CamelIndex *)camel_text_index_new(argv[i], O_RDONLY, &error);
 		if (idx) {
 			camel_text_index_info((CamelTextIndex *)idx);
 			g_object_unref (idx);
 		} else {
-			printf(" Failed: %s\n", g_strerror (errno));
+			printf(" Failed: %s\n", error->message);
+			g_error_free (error);
 			return 0;
 		}
 	}
@@ -102,15 +108,17 @@ do_check(gint argc, gchar **argv)
 {
 	gint i;
 	CamelIndex *idx;
+	GError *error = NULL;
 
 	for (i=2;i<argc;i++) {
 		printf("Opening index file: %s\n", argv[i]);
-		idx = (CamelIndex *)camel_text_index_new(argv[i], O_RDONLY);
+		idx = (CamelIndex *)camel_text_index_new(argv[i], O_RDONLY, &error);
 		if (idx) {
 			camel_text_index_validate((CamelTextIndex *)idx);
 			g_object_unref (idx);
 		} else {
-			printf(" Failed: %s\n", g_strerror (errno));
+			printf(" Failed: %s\n", error->message);
+			g_error_free (error);
 			return 0;
 		}
 	}
@@ -167,7 +175,8 @@ do_perf(gint argc, gchar **argv)
 		return 1;
 	}
 
-	idx = (CamelIndex *)camel_text_index_new("/tmp/index", O_TRUNC|O_CREAT|O_RDWR);
+	idx = (CamelIndex *) camel_text_index_new (
+		"/tmp/index", O_TRUNC|O_CREAT|O_RDWR, NULL);
 	if (idx == NULL) {
 		perror("open index");
 		closedir(dir);
@@ -187,8 +196,8 @@ do_perf(gint argc, gchar **argv)
 		camel_mime_filter_index_set_name(
 			CAMEL_MIME_FILTER_INDEX (filter_index), idn);
 		name = g_strdup_printf("%s/%s", path, d->d_name);
-		stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0);
-		camel_stream_write_to_stream(stream, filter);
+		stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0, NULL);
+		camel_stream_write_to_stream(stream, filter, NULL);
 		g_object_unref (stream);
 		g_free(name);
 
@@ -200,7 +209,7 @@ do_perf(gint argc, gchar **argv)
 
 	closedir(dir);
 
-	camel_index_sync(idx);
+	camel_index_sync(idx, NULL);
 	g_object_unref (idx);
 
 	g_object_unref (filter);
diff --git a/camel/camel-index.c b/camel/camel-index.c
index ef4ef8d..dc345c3 100644
--- a/camel/camel-index.c
+++ b/camel/camel-index.c
@@ -30,6 +30,8 @@
 #include <unistd.h>
 #include <sys/stat.h>
 
+#include <glib/gi18n-lib.h>
+
 #include "camel-index.h"
 #include "camel-object.h"
 
@@ -148,7 +150,8 @@ camel_index_set_normalise (CamelIndex *idx, CamelIndexNorm func, gpointer data)
 }
 
 gint
-camel_index_sync (CamelIndex *idx)
+camel_index_sync (CamelIndex *idx,
+                  GError **error)
 {
 	CamelIndexClass *class;
 
@@ -158,15 +161,18 @@ camel_index_sync (CamelIndex *idx)
 	g_return_val_if_fail (class->sync != NULL, -1);
 
 	if ((idx->state & CAMEL_INDEX_DELETED) == 0)
-		return class->sync (idx);
+		return class->sync (idx, error);
 	else {
-		errno = ENOENT;
+		g_set_error (
+			error, CAMEL_ERROR, CAMEL_ERROR_SYSTEM,
+			_("Index has been deleted"));
 		return -1;
 	}
 }
 
 gint
-camel_index_compress (CamelIndex *idx)
+camel_index_compress (CamelIndex *idx,
+                      GError **error)
 {
 	CamelIndexClass *class;
 
@@ -176,9 +182,11 @@ camel_index_compress (CamelIndex *idx)
 	g_return_val_if_fail (class->compress != NULL, -1);
 
 	if ((idx->state & CAMEL_INDEX_DELETED) == 0)
-		return class->compress (idx);
+		return class->compress (idx, error);
 	else {
-		errno = ENOENT;
+		g_set_error (
+			error, CAMEL_ERROR, CAMEL_ERROR_SYSTEM,
+			_("Index has been deleted"));
 		return -1;
 	}
 }
diff --git a/camel/camel-index.h b/camel/camel-index.h
index 69535a9..21e2a68 100644
--- a/camel/camel-index.h
+++ b/camel/camel-index.h
@@ -168,47 +168,73 @@ struct _CamelIndex {
 struct _CamelIndexClass {
 	CamelObjectClass parent_class;
 
-	gint			(*sync)(CamelIndex *idx);
-	gint			(*compress)(CamelIndex *idx);
-	gint			(*delete)(CamelIndex *idx);
-
-	gint			(*rename)(CamelIndex *idx, const gchar *path);
-
-	gint			(*has_name)(CamelIndex *idx, const gchar *name);
-	CamelIndexName *	(*add_name)(CamelIndex *idx, const gchar *name);
-	gint			(*write_name)(CamelIndex *idx, CamelIndexName *idn);
-	CamelIndexCursor *	(*find_name)(CamelIndex *idx, const gchar *name);
-	void			(*delete_name)(CamelIndex *idx, const gchar *name);
-	CamelIndexCursor *	(*find)(CamelIndex *idx, const gchar *word);
-
-	CamelIndexCursor *      (*words)(CamelIndex *idx);
-	CamelIndexCursor *      (*names)(CamelIndex *idx);
+	gint		(*sync)			(CamelIndex *idx,
+						 GError **error);
+	gint		(*compress)		(CamelIndex *idx,
+						 GError **error);
+	gint		(*delete)		(CamelIndex *idx);
+
+	gint		(*rename)		(CamelIndex *idx,
+						 const gchar *path);
+
+	gint		(*has_name)		(CamelIndex *idx,
+						 const gchar *name);
+	CamelIndexName *(*add_name)		(CamelIndex *idx,
+						 const gchar *name);
+	gint		(*write_name)		(CamelIndex *idx,
+						 CamelIndexName *idn);
+	CamelIndexCursor *
+			(*find_name)		(CamelIndex *idx,
+						 const gchar *name);
+	void		(*delete_name)		(CamelIndex *idx,
+						 const gchar *name);
+	CamelIndexCursor *
+			(*find)			(CamelIndex *idx,
+						 const gchar *word);
+	CamelIndexCursor *
+			(*words)		(CamelIndex *idx);
+	CamelIndexCursor *
+			(*names)		(CamelIndex *idx);
 };
 
 /* flags, stored in 'state', set with set_state */
 #define CAMEL_INDEX_DELETED (1<<0)
 
-GType              camel_index_get_type	(void);
-
-CamelIndex        *camel_index_new(const gchar *path, gint flags);
-void               camel_index_construct(CamelIndex *, const gchar *path, gint flags);
-gint               camel_index_rename(CamelIndex *, const gchar *path);
-
-void               camel_index_set_normalise(CamelIndex *idx, CamelIndexNorm func, gpointer data);
-
-gint                camel_index_sync(CamelIndex *idx);
-gint                camel_index_compress(CamelIndex *idx);
-gint                camel_index_delete(CamelIndex *idx);
-
-gint                camel_index_has_name(CamelIndex *idx, const gchar *name);
-CamelIndexName    *camel_index_add_name(CamelIndex *idx, const gchar *name);
-gint                camel_index_write_name(CamelIndex *idx, CamelIndexName *idn);
-CamelIndexCursor  *camel_index_find_name(CamelIndex *idx, const gchar *name);
-void               camel_index_delete_name(CamelIndex *idx, const gchar *name);
-CamelIndexCursor  *camel_index_find(CamelIndex *idx, const gchar *word);
-
-CamelIndexCursor  *camel_index_words(CamelIndex *idx);
-CamelIndexCursor  *camel_index_names(CamelIndex *idx);
+GType		camel_index_get_type	(void);
+CamelIndex *	camel_index_new		(const gchar *path,
+					 gint flags);
+void		camel_index_construct	(CamelIndex *index,
+					 const gchar *path,
+					 gint flags);
+gint		camel_index_rename	(CamelIndex *index,
+					 const gchar *path);
+void		camel_index_set_normalise
+					(CamelIndex *idx,
+					 CamelIndexNorm func,
+					 gpointer data);
+gint		camel_index_sync	(CamelIndex *idx,
+					 GError **error);
+gint		camel_index_compress	(CamelIndex *idx,
+					 GError **error);
+gint		camel_index_delete	(CamelIndex *idx);
+gint		camel_index_has_name	(CamelIndex *idx,
+					 const gchar *name);
+CamelIndexName *camel_index_add_name	(CamelIndex *idx,
+					 const gchar *name);
+gint		camel_index_write_name	(CamelIndex *idx,
+					 CamelIndexName *idn);
+CamelIndexCursor *
+		camel_index_find_name	(CamelIndex *idx,
+					 const gchar *name);
+void		camel_index_delete_name	(CamelIndex *idx,
+					 const gchar *name);
+CamelIndexCursor *
+		camel_index_find	(CamelIndex *idx,
+					 const gchar *word);
+CamelIndexCursor *
+		camel_index_words	(CamelIndex *idx);
+CamelIndexCursor *
+		camel_index_names	(CamelIndex *idx);
 
 G_END_DECLS
 
diff --git a/camel/camel-mime-filter-save.c b/camel/camel-mime-filter-save.c
index fa5aed0..1b98b89 100644
--- a/camel/camel-mime-filter-save.c
+++ b/camel/camel-mime-filter-save.c
@@ -51,7 +51,7 @@ mime_filter_save_filter (CamelMimeFilter *mime_filter,
 	priv = CAMEL_MIME_FILTER_SAVE_GET_PRIVATE (mime_filter);
 
 	if (priv->stream != NULL)
-		camel_stream_write (priv->stream, in, len);
+		camel_stream_write (priv->stream, in, len, NULL);
 
 	*out = (gchar *) in;
 	*outlen = len;
diff --git a/camel/camel-mime-message.c b/camel/camel-mime-message.c
index 71fad18..fb1b2f5 100644
--- a/camel/camel-mime-message.c
+++ b/camel/camel-mime-message.c
@@ -87,12 +87,98 @@ static const gchar *recipient_names[] = {
 static gpointer parent_class;
 static GHashTable *header_name_table;
 
-static gssize write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
-static void add_header (CamelMedium *medium, const gchar *name, gconstpointer value);
-static void set_header (CamelMedium *medium, const gchar *name, gconstpointer value);
-static void remove_header (CamelMedium *medium, const gchar *name);
-static gint construct_from_parser (CamelMimePart *, CamelMimeParser *);
-static void unref_recipient (gpointer key, gpointer value, gpointer user_data);
+/* FIXME: check format of fields. */
+static gboolean
+process_header (CamelMedium *medium,
+                const gchar *name,
+                const gchar *value)
+{
+	CamelHeaderType header_type;
+	CamelMimeMessage *message = CAMEL_MIME_MESSAGE (medium);
+	CamelInternetAddress *addr;
+	const gchar *charset;
+	gchar *unfolded;
+
+	header_type = (CamelHeaderType) g_hash_table_lookup (header_name_table, name);
+	switch (header_type) {
+	case HEADER_FROM:
+		addr = camel_internet_address_new();
+		unfolded = camel_header_unfold (value);
+		if (camel_address_decode ((CamelAddress *) addr, unfolded) <= 0) {
+			g_object_unref (addr);
+		} else {
+			if (message->from)
+				g_object_unref (message->from);
+			message->from = addr;
+		}
+		g_free (unfolded);
+		break;
+	case HEADER_REPLY_TO:
+		addr = camel_internet_address_new();
+		unfolded = camel_header_unfold (value);
+		if (camel_address_decode ((CamelAddress *) addr, unfolded) <= 0) {
+			g_object_unref (addr);
+		} else {
+			if (message->reply_to)
+				g_object_unref (message->reply_to);
+			message->reply_to = addr;
+		}
+		g_free (unfolded);
+		break;
+	case HEADER_SUBJECT:
+		g_free (message->subject);
+		if (((CamelDataWrapper *) message)->mime_type) {
+			charset = camel_content_type_param (((CamelDataWrapper *) message)->mime_type, "charset");
+			charset = camel_iconv_charset_name (charset);
+		} else
+			charset = NULL;
+
+		unfolded = camel_header_unfold (value);
+		message->subject = g_strstrip (camel_header_decode_string (unfolded, charset));
+		g_free (unfolded);
+		break;
+	case HEADER_TO:
+	case HEADER_CC:
+	case HEADER_BCC:
+	case HEADER_RESENT_TO:
+	case HEADER_RESENT_CC:
+	case HEADER_RESENT_BCC:
+		addr = g_hash_table_lookup (message->recipients, name);
+		if (value) {
+			unfolded = camel_header_unfold (value);
+			camel_address_decode (CAMEL_ADDRESS (addr), unfolded);
+			g_free (unfolded);
+		} else {
+			camel_address_remove (CAMEL_ADDRESS (addr), -1);
+		}
+		return FALSE;
+	case HEADER_DATE:
+		if (value) {
+			message->date = camel_header_decode_date (value, &message->date_offset);
+		} else {
+			message->date = CAMEL_MESSAGE_DATE_CURRENT;
+			message->date_offset = 0;
+		}
+		break;
+	case HEADER_MESSAGE_ID:
+		g_free (message->message_id);
+		if (value)
+			message->message_id = camel_header_msgid_decode (value);
+		else
+			message->message_id = NULL;
+		break;
+	default:
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void
+unref_recipient (gpointer key, gpointer value, gpointer user_data)
+{
+	g_object_unref (value);
+}
 
 static void
 mime_message_dispose (GObject *object)
@@ -129,6 +215,124 @@ mime_message_finalize (GObject *object)
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static gssize
+mime_message_write_to_stream (CamelDataWrapper *data_wrapper,
+                              CamelStream *stream,
+                              GError **error)
+{
+	CamelDataWrapperClass *data_wrapper_class;
+	CamelMimeMessage *mm = CAMEL_MIME_MESSAGE (data_wrapper);
+
+	/* force mandatory headers ... */
+	if (mm->from == NULL) {
+		/* FIXME: should we just abort?  Should we make one up? */
+		g_warning ("No from set for message");
+		camel_medium_set_header ((CamelMedium *)mm, "From", "");
+	}
+	if (!camel_medium_get_header ((CamelMedium *)mm, "Date"))
+		camel_mime_message_set_date (mm, CAMEL_MESSAGE_DATE_CURRENT, 0);
+
+	if (mm->subject == NULL)
+		camel_mime_message_set_subject (mm, "No Subject");
+
+	if (mm->message_id == NULL)
+		camel_mime_message_set_message_id (mm, NULL);
+
+	/* FIXME: "To" header needs to be set explicitly as well ... */
+
+	if (!camel_medium_get_header ((CamelMedium *)mm, "Mime-Version"))
+		camel_medium_set_header ((CamelMedium *)mm, "Mime-Version", "1.0");
+
+	/* Chain up to parent's write_to_stream() method. */
+	data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (parent_class);
+	return data_wrapper_class->write_to_stream (data_wrapper, stream, error);
+}
+
+static void
+mime_message_add_header (CamelMedium *medium,
+                         const gchar *name,
+                         gconstpointer value)
+{
+	CamelMediumClass *medium_class;
+
+	medium_class = CAMEL_MEDIUM_CLASS (parent_class);
+
+	/* if we process it, then it must be forced unique as well ... */
+	if (process_header (medium, name, value))
+		medium_class->set_header (medium, name, value);
+	else
+		medium_class->add_header (medium, name, value);
+}
+
+static void
+mime_message_set_header (CamelMedium *medium,
+                         const gchar *name,
+                         gconstpointer value)
+{
+	process_header (medium, name, value);
+
+	/* Chain up to parent's set_header() method. */
+	CAMEL_MEDIUM_CLASS (parent_class)->set_header (medium, name, value);
+}
+
+static void
+mime_message_remove_header (CamelMedium *medium,
+                            const gchar *name)
+{
+	process_header (medium, name, NULL);
+
+	/* Chain up to parent's remove_header() method. */
+	CAMEL_MEDIUM_CLASS (parent_class)->remove_header (medium, name);
+}
+
+static gint
+mime_message_construct_from_parser (CamelMimePart *dw,
+                                    CamelMimeParser *mp,
+                                    GError **error)
+{
+	CamelMimePartClass *mime_part_class;
+	gchar *buf;
+	gsize len;
+	gint state;
+	gint ret;
+	gint err;
+
+	d(printf("constructing mime-message\n"));
+
+	d(printf("mime_message::construct_from_parser()\n"));
+
+	/* let the mime-part construct the guts ... */
+	mime_part_class = CAMEL_MIME_PART_CLASS (parent_class);
+	ret = mime_part_class->construct_from_parser (dw, mp, error);
+
+	if (ret == -1)
+		return -1;
+
+	/* ... then clean up the follow-on state */
+	state = camel_mime_parser_step (mp, &buf, &len);
+	switch (state) {
+	case CAMEL_MIME_PARSER_STATE_EOF:
+	case CAMEL_MIME_PARSER_STATE_FROM_END:
+		/* these doesn't belong to us */
+		camel_mime_parser_unstep (mp);
+	case CAMEL_MIME_PARSER_STATE_MESSAGE_END:
+		break;
+	default:
+		g_error ("Bad parser state: Expecing MESSAGE_END or EOF or EOM, got: %u", camel_mime_parser_state (mp));
+		camel_mime_parser_unstep (mp);
+		return -1;
+	}
+
+	d(printf("mime_message::construct_from_parser() leaving\n"));
+	err = camel_mime_parser_errno(mp);
+	if (err != 0) {
+		errno = err;
+		ret = -1;
+	}
+
+	return ret;
+}
+
 static void
 mime_message_class_init (CamelMimeMessageClass *class)
 {
@@ -145,16 +349,16 @@ mime_message_class_init (CamelMimeMessageClass *class)
 	object_class->finalize = mime_message_finalize;
 
 	data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (class);
-	data_wrapper_class->write_to_stream = write_to_stream;
-	data_wrapper_class->decode_to_stream = write_to_stream;
+	data_wrapper_class->write_to_stream = mime_message_write_to_stream;
+	data_wrapper_class->decode_to_stream = mime_message_write_to_stream;
 
 	medium_class = CAMEL_MEDIUM_CLASS (class);
-	medium_class->add_header = add_header;
-	medium_class->set_header = set_header;
-	medium_class->remove_header = remove_header;
+	medium_class->add_header = mime_message_add_header;
+	medium_class->set_header = mime_message_set_header;
+	medium_class->remove_header = mime_message_remove_header;
 
 	mime_part_class = CAMEL_MIME_PART_CLASS (class);
-	mime_part_class->construct_from_parser = construct_from_parser;
+	mime_part_class->construct_from_parser = mime_message_construct_from_parser;
 
 	header_name_table = g_hash_table_new (
 		camel_strcase_hash, camel_strcase_equal);
@@ -208,12 +412,6 @@ camel_mime_message_get_type (void)
 	return type;
 }
 
-static void
-unref_recipient (gpointer key, gpointer value, gpointer user_data)
-{
-	g_object_unref (value);
-}
-
 /**
  * camel_mime_message_new:
  *
@@ -590,188 +788,6 @@ camel_mime_message_get_source (CamelMimeMessage *mime_message)
 	return src;
 }
 
-/* mime_message */
-static gint
-construct_from_parser (CamelMimePart *dw, CamelMimeParser *mp)
-{
-	gchar *buf;
-	gsize len;
-	gint state;
-	gint ret;
-	gint err;
-
-	d(printf("constructing mime-message\n"));
-
-	d(printf("mime_message::construct_from_parser()\n"));
-
-	/* let the mime-part construct the guts ... */
-	ret = ((CamelMimePartClass *)parent_class)->construct_from_parser(dw, mp);
-
-	if (ret == -1)
-		return -1;
-
-	/* ... then clean up the follow-on state */
-	state = camel_mime_parser_step (mp, &buf, &len);
-	switch (state) {
-	case CAMEL_MIME_PARSER_STATE_EOF:
-	case CAMEL_MIME_PARSER_STATE_FROM_END:
-		/* these doesn't belong to us */
-		camel_mime_parser_unstep (mp);
-	case CAMEL_MIME_PARSER_STATE_MESSAGE_END:
-		break;
-	default:
-		g_error ("Bad parser state: Expecing MESSAGE_END or EOF or EOM, got: %u", camel_mime_parser_state (mp));
-		camel_mime_parser_unstep (mp);
-		return -1;
-	}
-
-	d(printf("mime_message::construct_from_parser() leaving\n"));
-	err = camel_mime_parser_errno(mp);
-	if (err != 0) {
-		errno = err;
-		ret = -1;
-	}
-
-	return ret;
-}
-
-static gssize
-write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
-{
-	CamelMimeMessage *mm = CAMEL_MIME_MESSAGE (data_wrapper);
-
-	/* force mandatory headers ... */
-	if (mm->from == NULL) {
-		/* FIXME: should we just abort?  Should we make one up? */
-		g_warning ("No from set for message");
-		camel_medium_set_header ((CamelMedium *)mm, "From", "");
-	}
-	if (!camel_medium_get_header ((CamelMedium *)mm, "Date"))
-		camel_mime_message_set_date (mm, CAMEL_MESSAGE_DATE_CURRENT, 0);
-
-	if (mm->subject == NULL)
-		camel_mime_message_set_subject (mm, "No Subject");
-
-	if (mm->message_id == NULL)
-		camel_mime_message_set_message_id (mm, NULL);
-
-	/* FIXME: "To" header needs to be set explicitly as well ... */
-
-	if (!camel_medium_get_header ((CamelMedium *)mm, "Mime-Version"))
-		camel_medium_set_header ((CamelMedium *)mm, "Mime-Version", "1.0");
-
-	return CAMEL_DATA_WRAPPER_CLASS (parent_class)->write_to_stream (data_wrapper, stream);
-}
-
-/* FIXME: check format of fields. */
-static gboolean
-process_header (CamelMedium *medium, const gchar *name, const gchar *value)
-{
-	CamelHeaderType header_type;
-	CamelMimeMessage *message = CAMEL_MIME_MESSAGE (medium);
-	CamelInternetAddress *addr;
-	const gchar *charset;
-	gchar *unfolded;
-
-	header_type = (CamelHeaderType) g_hash_table_lookup (header_name_table, name);
-	switch (header_type) {
-	case HEADER_FROM:
-		addr = camel_internet_address_new();
-		unfolded = camel_header_unfold (value);
-		if (camel_address_decode ((CamelAddress *) addr, unfolded) <= 0) {
-			g_object_unref (addr);
-		} else {
-			if (message->from)
-				g_object_unref (message->from);
-			message->from = addr;
-		}
-		g_free (unfolded);
-		break;
-	case HEADER_REPLY_TO:
-		addr = camel_internet_address_new();
-		unfolded = camel_header_unfold (value);
-		if (camel_address_decode ((CamelAddress *) addr, unfolded) <= 0) {
-			g_object_unref (addr);
-		} else {
-			if (message->reply_to)
-				g_object_unref (message->reply_to);
-			message->reply_to = addr;
-		}
-		g_free (unfolded);
-		break;
-	case HEADER_SUBJECT:
-		g_free (message->subject);
-		if (((CamelDataWrapper *) message)->mime_type) {
-			charset = camel_content_type_param (((CamelDataWrapper *) message)->mime_type, "charset");
-			charset = camel_iconv_charset_name (charset);
-		} else
-			charset = NULL;
-
-		unfolded = camel_header_unfold (value);
-		message->subject = g_strstrip (camel_header_decode_string (unfolded, charset));
-		g_free (unfolded);
-		break;
-	case HEADER_TO:
-	case HEADER_CC:
-	case HEADER_BCC:
-	case HEADER_RESENT_TO:
-	case HEADER_RESENT_CC:
-	case HEADER_RESENT_BCC:
-		addr = g_hash_table_lookup (message->recipients, name);
-		if (value) {
-			unfolded = camel_header_unfold (value);
-			camel_address_decode (CAMEL_ADDRESS (addr), unfolded);
-			g_free (unfolded);
-		} else {
-			camel_address_remove (CAMEL_ADDRESS (addr), -1);
-		}
-		return FALSE;
-	case HEADER_DATE:
-		if (value) {
-			message->date = camel_header_decode_date (value, &message->date_offset);
-		} else {
-			message->date = CAMEL_MESSAGE_DATE_CURRENT;
-			message->date_offset = 0;
-		}
-		break;
-	case HEADER_MESSAGE_ID:
-		g_free (message->message_id);
-		if (value)
-			message->message_id = camel_header_msgid_decode (value);
-		else
-			message->message_id = NULL;
-		break;
-	default:
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static void
-set_header (CamelMedium *medium, const gchar *name, gconstpointer value)
-{
-	process_header (medium, name, value);
-	CAMEL_MEDIUM_CLASS (parent_class)->set_header (medium, name, value);
-}
-
-static void
-add_header (CamelMedium *medium, const gchar *name, gconstpointer value)
-{
-	/* if we process it, then it must be forced unique as well ... */
-	if (process_header (medium, name, value))
-		CAMEL_MEDIUM_CLASS (parent_class)->set_header (medium, name, value);
-	else
-		CAMEL_MEDIUM_CLASS (parent_class)->add_header (medium, name, value);
-}
-
-static void
-remove_header (CamelMedium *medium, const gchar *name)
-{
-	process_header (medium, name, NULL);
-	CAMEL_MEDIUM_CLASS (parent_class)->remove_header (medium, name);
-}
-
 typedef gboolean (*CamelPartFunc)(CamelMimeMessage *, CamelMimePart *, gpointer data);
 
 static gboolean
@@ -905,7 +921,7 @@ find_best_encoding (CamelMimePart *part, CamelBestencRequired required, CamelBes
 	bestenc = camel_mime_filter_bestenc_new (flags);
 	idb = camel_stream_filter_add (CAMEL_STREAM_FILTER (filter), bestenc);
 	d(printf("writing to checking stream\n"));
-	camel_data_wrapper_decode_to_stream (content, filter);
+	camel_data_wrapper_decode_to_stream (content, filter, NULL);
 	camel_stream_filter_remove (CAMEL_STREAM_FILTER (filter), idb);
 	if (idc != -1) {
 		camel_stream_filter_remove (CAMEL_STREAM_FILTER (filter), idc);
@@ -948,7 +964,7 @@ find_best_encoding (CamelMimePart *part, CamelBestencRequired required, CamelBes
 				CAMEL_STREAM_FILTER (filter), bestenc);
 
 			/* and write it to the new stream */
-			camel_data_wrapper_write_to_stream (content, filter);
+			camel_data_wrapper_write_to_stream (content, filter, NULL);
 
 			g_object_unref (charenc);
 		}
diff --git a/camel/camel-mime-parser.c b/camel/camel-mime-parser.c
index bc2f2db..757a408 100644
--- a/camel/camel-mime-parser.c
+++ b/camel/camel-mime-parser.c
@@ -139,7 +139,7 @@ struct _header_scan_filter {
 static void folder_scan_step(struct _header_scan_state *s, gchar **databuffer, gsize *datalength);
 static void folder_scan_drop_step(struct _header_scan_state *s);
 static gint folder_scan_init_with_fd(struct _header_scan_state *s, gint fd);
-static gint folder_scan_init_with_stream(struct _header_scan_state *s, CamelStream *stream);
+static gint folder_scan_init_with_stream(struct _header_scan_state *s, CamelStream *stream, GError **error);
 static struct _header_scan_state *folder_scan_init(void);
 static void folder_scan_close(struct _header_scan_state *s);
 static struct _header_scan_stack *folder_scan_content(struct _header_scan_state *s, gint *lastone, gchar **data, gsize *length);
@@ -452,6 +452,7 @@ camel_mime_parser_init_with_fd(CamelMimeParser *m, gint fd)
  * camel_mime_parser_init_with_stream:
  * @m:
  * @stream:
+ * @error: return location for a #GError, or %NULL
  *
  * Initialise the scanner with a source stream.  The scanner's
  * offsets will be relative to the current file position of
@@ -461,11 +462,13 @@ camel_mime_parser_init_with_fd(CamelMimeParser *m, gint fd)
  * Return value: -1 on error.
  **/
 gint
-camel_mime_parser_init_with_stream(CamelMimeParser *m, CamelStream *stream)
+camel_mime_parser_init_with_stream (CamelMimeParser *parser,
+                                    CamelStream *stream,
+                                    GError **error)
 {
-	struct _header_scan_state *s = _PRIVATE(m);
+	struct _header_scan_state *s = _PRIVATE (parser);
 
-	return folder_scan_init_with_stream(s, stream);
+	return folder_scan_init_with_stream (s, stream, error);
 }
 
 /**
@@ -895,7 +898,7 @@ folder_read(struct _header_scan_state *s)
 		memmove(s->inbuf, s->inptr, inoffset);
 	}
 	if (s->stream) {
-		len = camel_stream_read(s->stream, s->inbuf+inoffset, SCAN_BUF-inoffset);
+		len = camel_stream_read(s->stream, s->inbuf+inoffset, SCAN_BUF-inoffset, NULL);
 	} else {
 		len = read(s->fd, s->inbuf+inoffset, SCAN_BUF-inoffset);
 	}
@@ -942,7 +945,9 @@ folder_seek(struct _header_scan_state *s, off_t offset, gint whence)
 		if (CAMEL_IS_SEEKABLE_STREAM(s->stream)) {
 			/* NOTE: assumes whence seekable stream == whence libc, which is probably
 			   the case (or bloody well should've been) */
-			newoffset = camel_seekable_stream_seek((CamelSeekableStream *)s->stream, offset, whence);
+			newoffset = camel_seekable_stream_seek (
+				CAMEL_SEEKABLE_STREAM (s->stream),
+				offset, whence, NULL);
 		} else {
 			newoffset = -1;
 			errno = EINVAL;
@@ -1469,7 +1474,9 @@ folder_scan_init_with_fd(struct _header_scan_state *s, gint fd)
 }
 
 static gint
-folder_scan_init_with_stream(struct _header_scan_state *s, CamelStream *stream)
+folder_scan_init_with_stream (struct _header_scan_state *s,
+                              CamelStream *stream,
+                              GError **error)
 {
 	folder_scan_reset(s);
 	s->stream = stream;
diff --git a/camel/camel-mime-parser.h b/camel/camel-mime-parser.h
index 8f1528a..50e6a71 100644
--- a/camel/camel-mime-parser.h
+++ b/camel/camel-mime-parser.h
@@ -103,7 +103,7 @@ gint		camel_mime_parser_errno (CamelMimeParser *parser);
 
 /* using an fd will be a little faster, but not much (over a simple stream) */
 gint		camel_mime_parser_init_with_fd (CamelMimeParser *m, gint fd);
-gint		camel_mime_parser_init_with_stream (CamelMimeParser *m, CamelStream *stream);
+gint		camel_mime_parser_init_with_stream (CamelMimeParser *m, CamelStream *stream, GError **error);
 
 /* get the stream or fd back of the parser */
 CamelStream    *camel_mime_parser_stream (CamelMimeParser *parser);
diff --git a/camel/camel-mime-part-utils.c b/camel/camel-mime-part-utils.c
index e79c978..6c69fa8 100644
--- a/camel/camel-mime-part-utils.c
+++ b/camel/camel-mime-part-utils.c
@@ -54,13 +54,16 @@
 	       #include <stdio.h>*/
 
 /* simple data wrapper */
-static void
-simple_data_wrapper_construct_from_parser (CamelDataWrapper *dw, CamelMimeParser *mp)
+static gboolean
+simple_data_wrapper_construct_from_parser (CamelDataWrapper *dw,
+                                           CamelMimeParser *mp,
+                                           GError **error)
 {
 	gchar *buf;
 	GByteArray *buffer;
 	CamelStream *mem;
 	gsize len;
+	gint retval;
 
 	d(printf ("simple_data_wrapper_construct_from_parser()\n"));
 
@@ -74,20 +77,24 @@ simple_data_wrapper_construct_from_parser (CamelDataWrapper *dw, CamelMimeParser
 	d(printf("message part kept in memory!\n"));
 
 	mem = camel_stream_mem_new_with_byte_array (buffer);
-	camel_data_wrapper_construct_from_stream (dw, mem);
+	retval = camel_data_wrapper_construct_from_stream (dw, mem, error);
 	g_object_unref (mem);
+
+	return (retval == 0);
 }
 
 /* This replaces the data wrapper repository ... and/or could be replaced by it? */
-void
-camel_mime_part_construct_content_from_parser (CamelMimePart *dw, CamelMimeParser *mp)
+gboolean
+camel_mime_part_construct_content_from_parser (CamelMimePart *dw,
+                                               CamelMimeParser *mp,
+                                               GError **error)
 {
 	CamelDataWrapper *content = NULL;
 	CamelContentType *ct;
 	gchar *encoding;
+	gboolean success = TRUE;
 
-	if (!dw)
-		return;
+	g_return_val_if_fail (CAMEL_IS_MIME_PART (dw), FALSE);
 
 	ct = camel_mime_parser_content_type (mp);
 
@@ -102,13 +109,15 @@ camel_mime_part_construct_content_from_parser (CamelMimePart *dw, CamelMimeParse
 			camel_multipart_construct_from_parser ((CamelMultipart *) content, mp);
 		} else {
 			content = camel_data_wrapper_new ();
-			simple_data_wrapper_construct_from_parser (content, mp);
+			success = simple_data_wrapper_construct_from_parser (
+				content, mp, error);
 		}
 		break;
 	case CAMEL_MIME_PARSER_STATE_MESSAGE:
 		d(printf("Creating message part\n"));
 		content = (CamelDataWrapper *) camel_mime_message_new ();
-		camel_mime_part_construct_from_parser ((CamelMimePart *)content, mp);
+		success = (camel_mime_part_construct_from_parser (
+			(CamelMimePart *)content, mp, error) == 0);
 		break;
 	case CAMEL_MIME_PARSER_STATE_MULTIPART:
 		d(printf("Creating multi-part\n"));
@@ -137,10 +146,13 @@ camel_mime_part_construct_content_from_parser (CamelMimePart *dw, CamelMimeParse
 	}
 
 	g_free (encoding);
+
+	return success;
 }
 
 gboolean
-camel_mime_message_build_preview (CamelMimePart *msg, CamelMessageInfo *info)
+camel_mime_message_build_preview (CamelMimePart *msg,
+                                  CamelMessageInfo *info)
 {
 	CamelDataWrapper *dw;
 	gboolean got_plain = FALSE;
@@ -163,15 +175,15 @@ camel_mime_message_build_preview (CamelMimePart *msg, CamelMessageInfo *info)
 		    !camel_content_type_is (dw->mime_type, "text", "calendar")) {
 		CamelStream *mstream, *bstream;
 		mstream = camel_stream_mem_new();
-		if (camel_data_wrapper_decode_to_stream (dw, mstream) > 0) {
+		if (camel_data_wrapper_decode_to_stream (dw, mstream, NULL) > 0) {
 			gchar *line = NULL;
 			GString *str = g_string_new (NULL);
 
-			camel_stream_reset (mstream);
+			camel_stream_reset (mstream, NULL);
 			bstream = camel_stream_buffer_new (mstream, CAMEL_STREAM_BUFFER_READ|CAMEL_STREAM_BUFFER_BUFFER);
 
 			/* We should fetch just 200 unquoted lines. */
-			while ((line = camel_stream_buffer_read_line((CamelStreamBuffer *)bstream)) && str->len < 200) {
+			while ((line = camel_stream_buffer_read_line((CamelStreamBuffer *)bstream, NULL)) && str->len < 200) {
 				gchar *tmp = line;
 				if (!line)
 					continue;
diff --git a/camel/camel-mime-part-utils.h b/camel/camel-mime-part-utils.h
index 6691c9e..774822d 100644
--- a/camel/camel-mime-part-utils.h
+++ b/camel/camel-mime-part-utils.h
@@ -35,7 +35,10 @@
 
 G_BEGIN_DECLS
 
-void camel_mime_part_construct_content_from_parser(CamelMimePart *, CamelMimeParser *mp);
+gboolean	camel_mime_part_construct_content_from_parser
+						(CamelMimePart *mime_part,
+						 CamelMimeParser *mp,
+						 GError **error);
 gboolean camel_mime_message_build_preview (CamelMimePart *msg, CamelMessageInfo *info);
 
 G_END_DECLS
diff --git a/camel/camel-mime-part.c b/camel/camel-mime-part.c
index a0e0060..2e5ed96 100644
--- a/camel/camel-mime-part.c
+++ b/camel/camel-mime-part.c
@@ -93,29 +93,70 @@ static GHashTable *header_formatted_table;
 
 static gpointer parent_class;
 
-/* from CamelDataWrapper */
-static gssize         write_to_stream                 (CamelDataWrapper *dw, CamelStream *stream);
-static gint	       construct_from_stream	       (CamelDataWrapper *dw, CamelStream *stream);
+static gssize
+write_raw (CamelStream *stream,
+           CamelHeaderRaw *header_raw,
+           GError **error)
+{
+	const gchar *name;
+	const gchar *value;
 
-/* from CamelMedium */
-static void            add_header                      (CamelMedium *medium, const gchar *name, gconstpointer value);
-static void            set_header                      (CamelMedium *medium, const gchar *name, gconstpointer value);
-static void            remove_header                   (CamelMedium *medium, const gchar *name);
-static const void     *get_header                      (CamelMedium *medium, const gchar *name);
-static GArray         *get_headers                     (CamelMedium *medium);
-static void            free_headers                    (CamelMedium *medium, GArray *headers);
+	name = camel_header_raw_get_name (header_raw);
+	value = camel_header_raw_get_value (header_raw);
 
-static void            set_content                     (CamelMedium *medium, CamelDataWrapper *content);
+	return camel_stream_printf (
+		stream, error, "%s%s%s\n", name,
+		isspace(value[0]) ? ":" : ": ", value);
+}
 
-/* from camel mime parser */
-static gint             construct_from_parser           (CamelMimePart *mime_part, CamelMimeParser *mp);
+static gssize
+write_references (CamelStream *stream,
+                  CamelHeaderRaw *raw_header,
+                  GError **error)
+{
+	gssize len, out, total;
+	const gchar *ids, *ide;
+	const gchar *name;
+	const gchar *value;
 
-/* forward references */
-static void set_disposition (CamelMimePart *mime_part, const gchar *disposition);
+	/* this is only approximate, based on the next >, this way it retains any content
+	   from the original which may not be properly formatted, etc.  It also doesn't handle
+	   the case where an individual messageid is too long, however thats a bad mail to
+	   start with ... */
 
-/* format output of headers */
-static gssize write_references(CamelStream *stream, CamelHeaderRaw *raw_header);
-static gssize write_raw(CamelStream *stream, CamelHeaderRaw *raw_header);
+	name = camel_header_raw_get_name (raw_header);
+	value = camel_header_raw_get_value (raw_header);
+
+	len = strlen(name)+1;
+	total = camel_stream_printf (
+		stream, error, "%s%s", name, isspace(value[0])?":":": ");
+	if (total == -1)
+		return -1;
+	while (*value) {
+		ids = value;
+		ide = strchr(ids+1, '>');
+		if (ide)
+			value = ++ide;
+		else
+			ide = value = strlen(ids)+ids;
+
+		if (len>0 && len + (ide - ids) >= CAMEL_FOLD_SIZE) {
+			out = camel_stream_printf (stream, error, "\n\t");
+			if (out == -1)
+				return -1;
+			total += out;
+			len = 0;
+		}
+		out = camel_stream_write (stream, ids, ide-ids, error);
+		if (out == -1)
+			return -1;
+		len += out;
+		total += out;
+	}
+	camel_stream_write (stream, "\n", 1, NULL);
+
+	return total;
+}
 
 /* loads in a hash table the set of header names we */
 /* recognize and associate them with a unique enum  */
@@ -180,6 +221,74 @@ init_header_name_table(void)
 }
 
 static void
+mime_part_set_disposition (CamelMimePart *mime_part,
+                           const gchar *disposition)
+{
+	camel_content_disposition_unref(mime_part->priv->disposition);
+	if (disposition)
+		mime_part->priv->disposition =
+			camel_content_disposition_decode (disposition);
+	else
+		mime_part->priv->disposition = NULL;
+}
+
+static gboolean
+mime_part_process_header (CamelMedium *medium,
+                          const gchar *name,
+                          const gchar *value)
+{
+	CamelMimePart *mime_part = CAMEL_MIME_PART (medium);
+	CamelHeaderType header_type;
+	const gchar *charset;
+	gchar *text;
+
+	/* Try to parse the header pair. If it corresponds to something   */
+	/* known, the job is done in the parsing routine. If not,         */
+	/* we simply add the header in a raw fashion                      */
+
+	header_type = (CamelHeaderType) g_hash_table_lookup (header_name_table, name);
+	switch (header_type) {
+	case HEADER_DESCRIPTION: /* raw header->utf8 conversion */
+		g_free (mime_part->priv->description);
+		if (((CamelDataWrapper *) mime_part)->mime_type) {
+			charset = camel_content_type_param (((CamelDataWrapper *) mime_part)->mime_type, "charset");
+			charset = camel_iconv_charset_name (charset);
+		} else
+			charset = NULL;
+		mime_part->priv->description = g_strstrip (camel_header_decode_string (value, charset));
+		break;
+	case HEADER_DISPOSITION:
+		mime_part_set_disposition (mime_part, value);
+		break;
+	case HEADER_CONTENT_ID:
+		g_free (mime_part->priv->content_id);
+		mime_part->priv->content_id = camel_header_contentid_decode (value);
+		break;
+	case HEADER_ENCODING:
+		text = camel_header_token_decode (value);
+		mime_part->priv->encoding = camel_transfer_encoding_from_string (text);
+		g_free (text);
+		break;
+	case HEADER_CONTENT_MD5:
+		g_free (mime_part->priv->content_md5);
+		mime_part->priv->content_md5 = g_strdup (value);
+		break;
+	case HEADER_CONTENT_LOCATION:
+		g_free (mime_part->priv->content_location);
+		mime_part->priv->content_location = camel_header_location_decode (value);
+		break;
+	case HEADER_CONTENT_TYPE:
+		if (((CamelDataWrapper *) mime_part)->mime_type)
+			camel_content_type_unref (((CamelDataWrapper *) mime_part)->mime_type);
+		((CamelDataWrapper *) mime_part)->mime_type = camel_content_type_decode (value);
+		break;
+	default:
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static void
 mime_part_set_property (GObject *object,
                         guint property_id,
                         const GValue *value,
@@ -284,6 +393,391 @@ mime_part_finalize (GObject *object)
 }
 
 static void
+mime_part_add_header (CamelMedium *medium,
+                      const gchar *name,
+                      gconstpointer value)
+{
+	CamelMimePart *part = CAMEL_MIME_PART (medium);
+	GQueue *header_queue;
+
+	header_queue = camel_mime_part_get_raw_headers (part);
+
+	/* Try to parse the header pair. If it corresponds to something   */
+	/* known, the job is done in the parsing routine. If not,         */
+	/* we simply add the header in a raw fashion                      */
+
+	/* If it was one of the headers we handled, it must be unique, set it instead of add */
+	if (mime_part_process_header (medium, name, value))
+		camel_header_raw_remove (header_queue, name);
+	camel_header_raw_append (header_queue, name, value, -1);
+}
+
+static void
+mime_part_set_header (CamelMedium *medium,
+                      const gchar *name,
+                      gconstpointer value)
+{
+	CamelMimePart *part = CAMEL_MIME_PART (medium);
+	GQueue *header_queue;
+
+	header_queue = camel_mime_part_get_raw_headers (part);
+
+	mime_part_process_header (medium, name, value);
+	camel_header_raw_remove (header_queue, name);
+	camel_header_raw_append (header_queue, name, value, -1);
+}
+
+static void
+mime_part_remove_header (CamelMedium *medium,
+                         const gchar *name)
+{
+	CamelMimePart *part = (CamelMimePart *)medium;
+	GQueue *header_queue;
+
+	header_queue = camel_mime_part_get_raw_headers (part);
+
+	mime_part_process_header (medium, name, NULL);
+	camel_header_raw_remove (header_queue, name);
+}
+
+static gconstpointer
+mime_part_get_header (CamelMedium *medium,
+                      const gchar *name)
+{
+	CamelMimePart *part = (CamelMimePart *)medium;
+	GQueue *header_queue;
+
+	header_queue = camel_mime_part_get_raw_headers (part);
+
+	return camel_header_raw_find (header_queue, name, NULL);
+}
+
+static GArray *
+mime_part_get_headers (CamelMedium *medium)
+{
+	CamelMimePart *part = (CamelMimePart *)medium;
+	GArray *headers;
+	CamelMediumHeader header;
+	GQueue *header_queue;
+	GList *link;
+
+	header_queue = camel_mime_part_get_raw_headers (part);
+	link = g_queue_peek_head_link (header_queue);
+
+	headers = g_array_new (FALSE, FALSE, sizeof (CamelMediumHeader));
+
+	while (link != NULL) {
+		CamelHeaderRaw *raw_header = link->data;
+
+		header.name = camel_header_raw_get_name (raw_header);
+		header.value = camel_header_raw_get_value (raw_header);
+		g_array_append_val (headers, header);
+
+		link = g_list_next (link);
+	}
+
+	return headers;
+}
+
+static void
+mime_part_free_headers (CamelMedium *medium,
+                        GArray *headers)
+{
+	g_array_free (headers, TRUE);
+}
+
+static void
+mime_part_set_content (CamelMedium *medium,
+                       CamelDataWrapper *content)
+{
+	CamelDataWrapper *mime_part = CAMEL_DATA_WRAPPER (medium);
+	CamelMediumClass *medium_class;
+	CamelContentType *content_type;
+
+	/* Chain up to parent's set_content() method. */
+	medium_class = CAMEL_MEDIUM_CLASS (parent_class);
+	medium_class->set_content (medium, content);
+
+	content_type = camel_data_wrapper_get_mime_type_field (content);
+	if (mime_part->mime_type != content_type) {
+		gchar *txt;
+
+		txt = camel_content_type_format (content_type);
+		camel_medium_set_header (medium, "Content-Type", txt);
+		g_free (txt);
+	}
+}
+
+static gssize
+mime_part_write_to_stream (CamelDataWrapper *dw,
+                           CamelStream *stream,
+                           GError **error)
+{
+	CamelMimePart *mp = CAMEL_MIME_PART (dw);
+	CamelMedium *medium = CAMEL_MEDIUM (dw);
+	CamelStream *ostream = stream;
+	CamelDataWrapper *content;
+	GQueue *header_queue;
+	gssize total = 0;
+	gssize count;
+	gint errnosav;
+
+	d(printf("mime_part::write_to_stream\n"));
+
+	/* FIXME: something needs to be done about this ... */
+	/* TODO: content-languages header? */
+
+	header_queue = camel_mime_part_get_raw_headers (mp);
+
+	if (!g_queue_is_empty (header_queue)) {
+		GList *link;
+		gssize (*writefn)(CamelStream *stream, CamelHeaderRaw *);
+
+		link = g_queue_peek_head_link (header_queue);
+
+		/* fold/write the headers.   But dont fold headers that are already formatted
+		   (e.g. ones with parameter-lists, that we know about, and have created) */
+		while (link != NULL) {
+			CamelHeaderRaw *raw_header = link->data;
+			const gchar *name, *value;
+
+			name = camel_header_raw_get_name (raw_header);
+			value = camel_header_raw_get_value (raw_header);
+
+			if (value == NULL) {
+				g_warning("value is NULL here for %s", name);
+				count = 0;
+			} else if ((writefn = g_hash_table_lookup(header_formatted_table, name)) == NULL) {
+				gchar *folded;
+
+				folded = camel_header_fold(value, strlen(name));
+				count = camel_stream_printf (
+					stream, error, "%s%s%s\n", name,
+					isspace (folded[0]) ? ":" : ": ",
+					folded);
+				g_free(folded);
+			} else {
+				count = writefn(stream, raw_header);
+			}
+			if (count == -1)
+				return -1;
+			total += count;
+
+			link = g_list_next (link);
+		}
+	}
+
+	count = camel_stream_write (stream, "\n", 1, error);
+	if (count == -1)
+		return -1;
+	total += count;
+
+	content = camel_medium_get_content (medium);
+	if (content) {
+		CamelMimeFilter *filter = NULL;
+		CamelStream *filter_stream = NULL;
+		CamelMimeFilter *charenc = NULL;
+		const gchar *content_charset = NULL;
+		const gchar *part_charset = NULL;
+		gboolean reencode = FALSE;
+		const gchar *filename;
+
+		if (camel_content_type_is (dw->mime_type, "text", "*")) {
+			content_charset = camel_content_type_param (content->mime_type, "charset");
+			part_charset = camel_content_type_param (dw->mime_type, "charset");
+
+			if (content_charset && part_charset) {
+				content_charset = camel_iconv_charset_name (content_charset);
+				part_charset = camel_iconv_charset_name (part_charset);
+			}
+		}
+
+		if (mp->priv->encoding != content->encoding) {
+			switch (mp->priv->encoding) {
+			case CAMEL_TRANSFER_ENCODING_BASE64:
+				filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_BASE64_ENC);
+				break;
+			case CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE:
+				filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_QP_ENC);
+				break;
+			case CAMEL_TRANSFER_ENCODING_UUENCODE:
+				filename = camel_mime_part_get_filename (mp);
+				count = camel_stream_printf (
+					ostream, error, "begin 644 %s\n",
+					filename ? filename : "untitled");
+				if (count == -1)
+					return -1;
+				total += count;
+				filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_UU_ENC);
+				break;
+			default:
+				/* content is encoded but the part doesn't want to be... */
+				reencode = TRUE;
+				break;
+			}
+		}
+
+		if (content_charset && part_charset && part_charset != content_charset)
+			charenc = camel_mime_filter_charset_new (content_charset, part_charset);
+
+		if (filter || charenc) {
+			filter_stream = camel_stream_filter_new (stream);
+
+			/* if we have a character encoder, add that always */
+			if (charenc) {
+				camel_stream_filter_add (
+					CAMEL_STREAM_FILTER (filter_stream),
+					charenc);
+				g_object_unref (charenc);
+			}
+
+			/* we only re-do crlf on encoded blocks */
+			if (filter && camel_content_type_is (dw->mime_type, "text", "*")) {
+				CamelMimeFilter *crlf = camel_mime_filter_crlf_new(CAMEL_MIME_FILTER_CRLF_ENCODE,
+										   CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
+
+				camel_stream_filter_add (
+					CAMEL_STREAM_FILTER (filter_stream),
+					crlf);
+				g_object_unref (crlf);
+			}
+
+			if (filter) {
+				camel_stream_filter_add (
+					CAMEL_STREAM_FILTER (filter_stream),
+					filter);
+				g_object_unref (filter);
+			}
+
+			stream = filter_stream;
+
+			reencode = TRUE;
+		}
+
+		if (reencode)
+			count = camel_data_wrapper_decode_to_stream (
+				content, stream, error);
+		else
+			count = camel_data_wrapper_write_to_stream (
+				content, stream, error);
+
+		if (filter_stream) {
+			errnosav = errno;
+			camel_stream_flush (stream, NULL);
+			g_object_unref (filter_stream);
+			errno = errnosav;
+		}
+
+		if (count == -1)
+			return -1;
+
+		total += count;
+
+		if (reencode && mp->priv->encoding == CAMEL_TRANSFER_ENCODING_UUENCODE) {
+			count = camel_stream_write (
+				ostream, "end\n", 4, error);
+			if (count == -1)
+				return -1;
+			total += count;
+		}
+	} else {
+		g_warning("No content for medium, nothing to write");
+	}
+
+	return total;
+}
+
+static gint
+mime_part_construct_from_stream (CamelDataWrapper *dw,
+                                 CamelStream *s,
+                                 GError **error)
+{
+	CamelMimeParser *mp;
+	gint ret;
+
+	d(printf("mime_part::construct_from_stream()\n"));
+
+	mp = camel_mime_parser_new();
+	if (camel_mime_parser_init_with_stream (mp, s, error) == -1) {
+		ret = -1;
+	} else {
+		ret = camel_mime_part_construct_from_parser (
+			CAMEL_MIME_PART (dw), mp, error);
+	}
+	g_object_unref (mp);
+	return ret;
+}
+
+static gint
+mime_part_construct_from_parser (CamelMimePart *mime_part,
+                                 CamelMimeParser *mp,
+                                 GError **error)
+{
+	CamelDataWrapper *dw = (CamelDataWrapper *) mime_part;
+	GQueue *header_queue;
+	GList *link;
+	const gchar *content;
+	gchar *buf;
+	gsize len;
+	gint err;
+	gboolean retval = 0;
+
+	d(printf("mime_part::construct_from_parser()\n"));
+
+	switch (camel_mime_parser_step(mp, &buf, &len)) {
+	case CAMEL_MIME_PARSER_STATE_MESSAGE:
+		/* set the default type of a message always */
+		if (dw->mime_type)
+			camel_content_type_unref (dw->mime_type);
+		dw->mime_type = camel_content_type_decode ("message/rfc822");
+	case CAMEL_MIME_PARSER_STATE_HEADER:
+	case CAMEL_MIME_PARSER_STATE_MULTIPART:
+		/* we have the headers, build them into 'us' */
+		header_queue = camel_mime_parser_headers_raw(mp);
+
+		/* if content-type exists, process it first, set for fallback charset in headers */
+		content = camel_header_raw_find(header_queue, "content-type", NULL);
+		if (content)
+			mime_part_process_header (
+				(CamelMedium *)dw, "content-type", content);
+
+		link = g_queue_peek_head_link (header_queue);
+
+		while (link != NULL) {
+			CamelHeaderRaw *raw_header = link->data;
+			const gchar *name;
+			const gchar *value;
+
+			name = camel_header_raw_get_name (raw_header);
+			value = camel_header_raw_get_value (raw_header);
+
+			if (g_ascii_strcasecmp(name, "content-type") == 0
+			    && value != content)
+				camel_medium_add_header((CamelMedium *)dw, "X-Invalid-Content-Type", value);
+			else
+				camel_medium_add_header((CamelMedium *)dw, name, value);
+
+			link = g_list_next (link);
+		}
+
+		retval = camel_mime_part_construct_content_from_parser (
+			mime_part, mp, error);
+		break;
+	default:
+		g_warning("Invalid state encountered???: %u", camel_mime_parser_state(mp));
+	}
+
+	d(printf("mime_part::construct_from_parser() leaving\n"));
+	err = camel_mime_parser_errno(mp);
+	if (err != 0) {
+		errno = err;
+		retval = -1;
+	}
+
+	return retval;
+}
+
+static void
 mime_part_class_init (CamelMimePartClass *class)
 {
 	GObjectClass *object_class;
@@ -299,19 +793,19 @@ mime_part_class_init (CamelMimePartClass *class)
 	object_class->finalize = mime_part_finalize;
 
 	medium_class = CAMEL_MEDIUM_CLASS (class);
-	medium_class->add_header = add_header;
-	medium_class->set_header = set_header;
-	medium_class->get_header = get_header;
-	medium_class->remove_header = remove_header;
-	medium_class->get_headers = get_headers;
-	medium_class->free_headers = free_headers;
-	medium_class->set_content = set_content;
+	medium_class->add_header = mime_part_add_header;
+	medium_class->set_header = mime_part_set_header;
+	medium_class->remove_header = mime_part_remove_header;
+	medium_class->get_header = mime_part_get_header;
+	medium_class->get_headers = mime_part_get_headers;
+	medium_class->free_headers = mime_part_free_headers;
+	medium_class->set_content = mime_part_set_content;
 
 	data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (class);
-	data_wrapper_class->write_to_stream = write_to_stream;
-	data_wrapper_class->construct_from_stream = construct_from_stream;
+	data_wrapper_class->write_to_stream = mime_part_write_to_stream;
+	data_wrapper_class->construct_from_stream = mime_part_construct_from_stream;
 
-	class->construct_from_parser = construct_from_parser;
+	class->construct_from_parser = mime_part_construct_from_parser;
 
 	g_object_class_install_property (
 		object_class,
@@ -391,149 +885,6 @@ camel_mime_part_get_type (void)
 	return type;
 }
 
-/* **** */
-
-static gboolean
-process_header(CamelMedium *medium, const gchar *name, const gchar *value)
-{
-	CamelMimePart *mime_part = CAMEL_MIME_PART (medium);
-	CamelHeaderType header_type;
-	const gchar *charset;
-	gchar *text;
-
-	/* Try to parse the header pair. If it corresponds to something   */
-	/* known, the job is done in the parsing routine. If not,         */
-	/* we simply add the header in a raw fashion                      */
-
-	header_type = (CamelHeaderType) g_hash_table_lookup (header_name_table, name);
-	switch (header_type) {
-	case HEADER_DESCRIPTION: /* raw header->utf8 conversion */
-		g_free (mime_part->priv->description);
-		if (((CamelDataWrapper *) mime_part)->mime_type) {
-			charset = camel_content_type_param (((CamelDataWrapper *) mime_part)->mime_type, "charset");
-			charset = camel_iconv_charset_name (charset);
-		} else
-			charset = NULL;
-		mime_part->priv->description = g_strstrip (camel_header_decode_string (value, charset));
-		break;
-	case HEADER_DISPOSITION:
-		set_disposition (mime_part, value);
-		break;
-	case HEADER_CONTENT_ID:
-		g_free (mime_part->priv->content_id);
-		mime_part->priv->content_id = camel_header_contentid_decode (value);
-		break;
-	case HEADER_ENCODING:
-		text = camel_header_token_decode (value);
-		mime_part->priv->encoding = camel_transfer_encoding_from_string (text);
-		g_free (text);
-		break;
-	case HEADER_CONTENT_MD5:
-		g_free (mime_part->priv->content_md5);
-		mime_part->priv->content_md5 = g_strdup (value);
-		break;
-	case HEADER_CONTENT_LOCATION:
-		g_free (mime_part->priv->content_location);
-		mime_part->priv->content_location = camel_header_location_decode (value);
-		break;
-	case HEADER_CONTENT_TYPE:
-		if (((CamelDataWrapper *) mime_part)->mime_type)
-			camel_content_type_unref (((CamelDataWrapper *) mime_part)->mime_type);
-		((CamelDataWrapper *) mime_part)->mime_type = camel_content_type_decode (value);
-		break;
-	default:
-		return FALSE;
-	}
-	return TRUE;
-}
-
-static void
-set_header (CamelMedium *medium, const gchar *name, gconstpointer value)
-{
-	CamelMimePart *part = CAMEL_MIME_PART (medium);
-	GQueue *header_queue;
-
-	header_queue = camel_mime_part_get_raw_headers (part);
-
-	process_header (medium, name, value);
-	camel_header_raw_remove (header_queue, name);
-	camel_header_raw_append (header_queue, name, value, -1);
-}
-
-static void
-add_header (CamelMedium *medium, const gchar *name, gconstpointer value)
-{
-	CamelMimePart *part = CAMEL_MIME_PART (medium);
-	GQueue *header_queue;
-
-	header_queue = camel_mime_part_get_raw_headers (part);
-
-	/* Try to parse the header pair. If it corresponds to something   */
-	/* known, the job is done in the parsing routine. If not,         */
-	/* we simply add the header in a raw fashion                      */
-
-	/* If it was one of the headers we handled, it must be unique, set it instead of add */
-	if (process_header(medium, name, value))
-		camel_header_raw_remove (header_queue, name);
-	camel_header_raw_append (header_queue, name, value, -1);
-}
-
-static void
-remove_header (CamelMedium *medium, const gchar *name)
-{
-	CamelMimePart *part = (CamelMimePart *)medium;
-	GQueue *header_queue;
-
-	header_queue = camel_mime_part_get_raw_headers (part);
-
-	process_header (medium, name, NULL);
-	camel_header_raw_remove (header_queue, name);
-}
-
-static gconstpointer
-get_header (CamelMedium *medium, const gchar *name)
-{
-	CamelMimePart *part = (CamelMimePart *)medium;
-	GQueue *header_queue;
-
-	header_queue = camel_mime_part_get_raw_headers (part);
-
-	return camel_header_raw_find (header_queue, name, NULL);
-}
-
-static GArray *
-get_headers (CamelMedium *medium)
-{
-	CamelMimePart *part = (CamelMimePart *)medium;
-	GArray *headers;
-	CamelMediumHeader header;
-	GQueue *header_queue;
-	GList *link;
-
-	header_queue = camel_mime_part_get_raw_headers (part);
-	link = g_queue_peek_head_link (header_queue);
-
-	headers = g_array_new (FALSE, FALSE, sizeof (CamelMediumHeader));
-
-	while (link != NULL) {
-		CamelHeaderRaw *raw_header = link->data;
-
-		header.name = camel_header_raw_get_name (raw_header);
-		header.value = camel_header_raw_get_value (raw_header);
-		g_array_append_val (headers, header);
-
-		link = g_list_next (link);
-	}
-
-	return headers;
-}
-
-static void
-free_headers (CamelMedium *medium, GArray *gheaders)
-{
-	g_array_free (gheaders, TRUE);
-}
-
 /* **** Content-Description */
 
 /**
@@ -580,17 +931,6 @@ camel_mime_part_get_description (CamelMimePart *mime_part)
 
 /* **** Content-Disposition */
 
-static void
-set_disposition (CamelMimePart *mime_part, const gchar *disposition)
-{
-	camel_content_disposition_unref(mime_part->priv->disposition);
-	if (disposition)
-		mime_part->priv->disposition =
-			camel_content_disposition_decode (disposition);
-	else
-		mime_part->priv->disposition = NULL;
-}
-
 /**
  * camel_mime_part_set_disposition:
  * @mime_part: a #CamelMimePart object
@@ -611,7 +951,7 @@ camel_mime_part_set_disposition (CamelMimePart *mime_part,
 
 	/* we poke in a new disposition (so we dont lose 'filename', etc) */
 	if (mime_part->priv->disposition == NULL)
-		set_disposition(mime_part, disposition);
+		mime_part_set_disposition (mime_part, disposition);
 
 	if (mime_part->priv->disposition != NULL) {
 		g_free (mime_part->priv->disposition->disposition);
@@ -961,346 +1301,11 @@ camel_mime_part_get_raw_headers (CamelMimePart *mime_part)
 	return mime_part->priv->raw_headers;
 }
 
-static void
-set_content (CamelMedium *medium,
-             CamelDataWrapper *content)
-{
-	CamelDataWrapper *mime_part = CAMEL_DATA_WRAPPER (medium);
-	CamelMediumClass *medium_class;
-	CamelContentType *content_type;
-
-	/* Chain up to parent's set_content() method. */
-	medium_class = CAMEL_MEDIUM_CLASS (parent_class);
-	medium_class->set_content (medium, content);
-
-	content_type = camel_data_wrapper_get_mime_type_field (content);
-	if (mime_part->mime_type != content_type) {
-		gchar *txt;
-
-		txt = camel_content_type_format (content_type);
-		camel_medium_set_header (medium, "Content-Type", txt);
-		g_free (txt);
-	}
-}
-
-/**********************************************************************/
-
-static gssize
-write_references (CamelStream *stream,
-                  CamelHeaderRaw *raw_header)
-{
-	gssize len, out, total;
-	const gchar *ids, *ide;
-	const gchar *name;
-	const gchar *value;
-
-	/* this is only approximate, based on the next >, this way it retains any content
-	   from the original which may not be properly formatted, etc.  It also doesn't handle
-	   the case where an individual messageid is too long, however thats a bad mail to
-	   start with ... */
-
-	name = camel_header_raw_get_name (raw_header);
-	value = camel_header_raw_get_value (raw_header);
-
-	len = strlen(name)+1;
-	total = camel_stream_printf(stream, "%s%s", name, isspace(value[0])?":":": ");
-	if (total == -1)
-		return -1;
-	while (*value) {
-		ids = value;
-		ide = strchr(ids+1, '>');
-		if (ide)
-			value = ++ide;
-		else
-			ide = value = strlen(ids)+ids;
-
-		if (len>0 && len + (ide - ids) >= CAMEL_FOLD_SIZE) {
-			out = camel_stream_printf(stream, "\n\t");
-			if (out == -1)
-				return -1;
-			total += out;
-			len = 0;
-		}
-		out = camel_stream_write(stream, ids, ide-ids);
-		if (out == -1)
-			return -1;
-		len += out;
-		total += out;
-	}
-	camel_stream_write(stream, "\n", 1);
-
-	return total;
-}
-
-#if 0
-/* not needed - yet - handled by default case */
-static gssize
-write_fold(CamelStream *stream, struct _camel_header_raw *h)
-{
-	gchar *val;
-	gint count;
-
-	val = camel_header_fold(h->value, strlen(h->name));
-	count = camel_stream_printf(stream, "%s%s%s\n", h->name, isspace(val[0]) ? ":" : ": ", val);
-	g_free(val);
-
-	return count;
-}
-#endif
-
-static gssize
-write_raw (CamelStream *stream,
-           CamelHeaderRaw *header_raw)
-{
-	const gchar *name;
-	const gchar *value;
-
-	name = camel_header_raw_get_name (header_raw);
-	value = camel_header_raw_get_value (header_raw);
-
-	return camel_stream_printf (
-		stream, "%s%s%s\n", name,
-		isspace(value[0]) ? ":" : ": ", value);
-}
-
-static gssize
-write_to_stream (CamelDataWrapper *dw, CamelStream *stream)
-{
-	CamelMimePart *mp = CAMEL_MIME_PART (dw);
-	CamelMedium *medium = CAMEL_MEDIUM (dw);
-	CamelStream *ostream = stream;
-	CamelDataWrapper *content;
-	GQueue *header_queue;
-	gssize total = 0;
-	gssize count;
-	gint errnosav;
-
-	d(printf("mime_part::write_to_stream\n"));
-
-	/* FIXME: something needs to be done about this ... */
-	/* TODO: content-languages header? */
-
-	header_queue = camel_mime_part_get_raw_headers (mp);
-
-	if (!g_queue_is_empty (header_queue)) {
-		GList *link;
-		gssize (*writefn)(CamelStream *stream, CamelHeaderRaw *);
-
-		link = g_queue_peek_head_link (header_queue);
-
-		/* fold/write the headers.   But dont fold headers that are already formatted
-		   (e.g. ones with parameter-lists, that we know about, and have created) */
-		while (link != NULL) {
-			CamelHeaderRaw *raw_header = link->data;
-			const gchar *name, *value;
-
-			name = camel_header_raw_get_name (raw_header);
-			value = camel_header_raw_get_value (raw_header);
-
-			if (value == NULL) {
-				g_warning("value is NULL here for %s", name);
-				count = 0;
-			} else if ((writefn = g_hash_table_lookup(header_formatted_table, name)) == NULL) {
-				gchar *folded;
-
-				folded = camel_header_fold(value, strlen(name));
-				count = camel_stream_printf(stream, "%s%s%s\n", name, isspace(folded[0]) ? ":" : ": ", folded);
-				g_free(folded);
-			} else {
-				count = writefn(stream, raw_header);
-			}
-			if (count == -1)
-				return -1;
-			total += count;
-
-			link = g_list_next (link);
-		}
-	}
-
-	count = camel_stream_write(stream, "\n", 1);
-	if (count == -1)
-		return -1;
-	total += count;
-
-	content = camel_medium_get_content (medium);
-	if (content) {
-		CamelMimeFilter *filter = NULL;
-		CamelStream *filter_stream = NULL;
-		CamelMimeFilter *charenc = NULL;
-		const gchar *content_charset = NULL;
-		const gchar *part_charset = NULL;
-		gboolean reencode = FALSE;
-		const gchar *filename;
-
-		if (camel_content_type_is (dw->mime_type, "text", "*")) {
-			content_charset = camel_content_type_param (content->mime_type, "charset");
-			part_charset = camel_content_type_param (dw->mime_type, "charset");
-
-			if (content_charset && part_charset) {
-				content_charset = camel_iconv_charset_name (content_charset);
-				part_charset = camel_iconv_charset_name (part_charset);
-			}
-		}
-
-		if (mp->priv->encoding != content->encoding) {
-			switch (mp->priv->encoding) {
-			case CAMEL_TRANSFER_ENCODING_BASE64:
-				filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_BASE64_ENC);
-				break;
-			case CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE:
-				filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_QP_ENC);
-				break;
-			case CAMEL_TRANSFER_ENCODING_UUENCODE:
-				filename = camel_mime_part_get_filename (mp);
-				count = camel_stream_printf (ostream, "begin 644 %s\n", filename ? filename : "untitled");
-				if (count == -1)
-					return -1;
-				total += count;
-				filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_UU_ENC);
-				break;
-			default:
-				/* content is encoded but the part doesn't want to be... */
-				reencode = TRUE;
-				break;
-			}
-		}
-
-		if (content_charset && part_charset && part_charset != content_charset)
-			charenc = camel_mime_filter_charset_new (content_charset, part_charset);
-
-		if (filter || charenc) {
-			filter_stream = camel_stream_filter_new (stream);
-
-			/* if we have a character encoder, add that always */
-			if (charenc) {
-				camel_stream_filter_add (
-					CAMEL_STREAM_FILTER (filter_stream),
-					charenc);
-				g_object_unref (charenc);
-			}
-
-			/* we only re-do crlf on encoded blocks */
-			if (filter && camel_content_type_is (dw->mime_type, "text", "*")) {
-				CamelMimeFilter *crlf = camel_mime_filter_crlf_new(CAMEL_MIME_FILTER_CRLF_ENCODE,
-										   CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
-
-				camel_stream_filter_add (
-					CAMEL_STREAM_FILTER (filter_stream),
-					crlf);
-				g_object_unref (crlf);
-			}
-
-			if (filter) {
-				camel_stream_filter_add (
-					CAMEL_STREAM_FILTER (filter_stream),
-					filter);
-				g_object_unref (filter);
-			}
-
-			stream = filter_stream;
-
-			reencode = TRUE;
-		}
-
-		if (reencode)
-			count = camel_data_wrapper_decode_to_stream (content, stream);
-		else
-			count = camel_data_wrapper_write_to_stream (content, stream);
-
-		if (filter_stream) {
-			errnosav = errno;
-			camel_stream_flush (stream);
-			g_object_unref (filter_stream);
-			errno = errnosav;
-		}
-
-		if (count == -1)
-			return -1;
-
-		total += count;
-
-		if (reencode && mp->priv->encoding == CAMEL_TRANSFER_ENCODING_UUENCODE) {
-			count = camel_stream_write (ostream, "end\n", 4);
-			if (count == -1)
-				return -1;
-			total += count;
-		}
-	} else {
-		g_warning("No content for medium, nothing to write");
-	}
-
-	return total;
-}
-
-/* mime_part */
-static gint
-construct_from_parser (CamelMimePart *mime_part, CamelMimeParser *mp)
-{
-	CamelDataWrapper *dw = (CamelDataWrapper *) mime_part;
-	GQueue *header_queue;
-	GList *link;
-	const gchar *content;
-	gchar *buf;
-	gsize len;
-	gint err;
-
-	d(printf("mime_part::construct_from_parser()\n"));
-
-	switch (camel_mime_parser_step(mp, &buf, &len)) {
-	case CAMEL_MIME_PARSER_STATE_MESSAGE:
-		/* set the default type of a message always */
-		if (dw->mime_type)
-			camel_content_type_unref (dw->mime_type);
-		dw->mime_type = camel_content_type_decode ("message/rfc822");
-	case CAMEL_MIME_PARSER_STATE_HEADER:
-	case CAMEL_MIME_PARSER_STATE_MULTIPART:
-		/* we have the headers, build them into 'us' */
-		header_queue = camel_mime_parser_headers_raw(mp);
-
-		/* if content-type exists, process it first, set for fallback charset in headers */
-		content = camel_header_raw_find(header_queue, "content-type", NULL);
-		if (content)
-			process_header((CamelMedium *)dw, "content-type", content);
-
-		link = g_queue_peek_head_link (header_queue);
-
-		while (link != NULL) {
-			CamelHeaderRaw *raw_header = link->data;
-			const gchar *name;
-			const gchar *value;
-
-			name = camel_header_raw_get_name (raw_header);
-			value = camel_header_raw_get_value (raw_header);
-
-			if (g_ascii_strcasecmp(name, "content-type") == 0
-			    && value != content)
-				camel_medium_add_header((CamelMedium *)dw, "X-Invalid-Content-Type", value);
-			else
-				camel_medium_add_header((CamelMedium *)dw, name, value);
-
-			link = g_list_next (link);
-		}
-
-		camel_mime_part_construct_content_from_parser (mime_part, mp);
-		break;
-	default:
-		g_warning("Invalid state encountered???: %u", camel_mime_parser_state(mp));
-	}
-
-	d(printf("mime_part::construct_from_parser() leaving\n"));
-	err = camel_mime_parser_errno(mp);
-	if (err != 0) {
-		errno = err;
-		return -1;
-	}
-
-	return 0;
-}
-
 /**
  * camel_mime_part_construct_from_parser:
  * @mime_part: a #CamelMimePart object
  * @parser: a #CamelMimeParser object
+ * @error: return location for a #GError, or %NULL
  *
  * Constructs a MIME part from a parser.
  *
@@ -1308,7 +1313,8 @@ construct_from_parser (CamelMimePart *mime_part, CamelMimeParser *mp)
  **/
 gint
 camel_mime_part_construct_from_parser (CamelMimePart *mime_part,
-                                       CamelMimeParser *mp)
+                                       CamelMimeParser *mp,
+                                       GError **error)
 {
 	CamelMimePartClass *class;
 
@@ -1318,31 +1324,9 @@ camel_mime_part_construct_from_parser (CamelMimePart *mime_part,
 	class = CAMEL_MIME_PART_GET_CLASS (mime_part);
 	g_return_val_if_fail (class->construct_from_parser != NULL, -1);
 
-	return class->construct_from_parser (mime_part, mp);
-}
-
-static gint
-construct_from_stream(CamelDataWrapper *dw, CamelStream *s)
-{
-	CamelMimeParser *mp;
-	gint ret;
-
-	d(printf("mime_part::construct_from_stream()\n"));
-
-	mp = camel_mime_parser_new();
-	if (camel_mime_parser_init_with_stream(mp, s) == -1) {
-		g_warning("Cannot create parser for stream");
-		ret = -1;
-	} else {
-		ret = camel_mime_part_construct_from_parser((CamelMimePart *)dw, mp);
-	}
-	g_object_unref (mp);
-	return ret;
+	return class->construct_from_parser (mime_part, mp, error);
 }
 
-/******************************/
-/**  Misc utility functions  **/
-
 /**
  * camel_mime_part_new:
  *
@@ -1382,7 +1366,7 @@ camel_mime_part_set_content (CamelMimePart *mime_part,
 		dw = camel_data_wrapper_new ();
 		camel_data_wrapper_set_mime_type (dw, type);
 		stream = camel_stream_mem_new_with_buffer (data, length);
-		camel_data_wrapper_construct_from_stream (dw, stream);
+		camel_data_wrapper_construct_from_stream (dw, stream, NULL);
 		g_object_unref (stream);
 		camel_medium_set_content (medium, dw);
 		g_object_unref (dw);
@@ -1410,7 +1394,7 @@ camel_mime_part_get_content_size (CamelMimePart *mime_part)
 	dw = camel_medium_get_content (CAMEL_MEDIUM (mime_part));
 
 	null = (CamelStreamNull *) camel_stream_null_new ();
-	camel_data_wrapper_decode_to_stream (dw, (CamelStream *) null);
+	camel_data_wrapper_decode_to_stream (dw, (CamelStream *) null, NULL);
 	size = null->written;
 
 	g_object_unref (null);
diff --git a/camel/camel-mime-part.h b/camel/camel-mime-part.h
index 96a51fd..413dd34 100644
--- a/camel/camel-mime-part.h
+++ b/camel/camel-mime-part.h
@@ -67,8 +67,9 @@ struct _CamelMimePart {
 struct _CamelMimePartClass {
 	CamelMediumClass parent_class;
 
-	/* Virtual methods */
-	gint (*construct_from_parser) (CamelMimePart *, CamelMimeParser *);
+	gint		(*construct_from_parser)(CamelMimePart *mime_part,
+						 CamelMimeParser *parser,
+						 GError **error);
 };
 
 GType camel_mime_part_get_type (void);
@@ -107,7 +108,7 @@ CamelContentType  *camel_mime_part_get_content_type	(CamelMimePart *mime_part);
 GQueue *	camel_mime_part_get_raw_headers	(CamelMimePart *mime_part);
 
 /* construction */
-gint		camel_mime_part_construct_from_parser  (CamelMimePart *mime_part, CamelMimeParser *parser);
+gint		camel_mime_part_construct_from_parser  (CamelMimePart *mime_part, CamelMimeParser *parser, GError **error);
 
 /* utility functions */
 void	camel_mime_part_set_content	       (CamelMimePart *mime_part,
diff --git a/camel/camel-multipart-signed.c b/camel/camel-multipart-signed.c
index 3c3e52c..ab41f83 100644
--- a/camel/camel-multipart-signed.c
+++ b/camel/camel-multipart-signed.c
@@ -50,152 +50,10 @@
 #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))
 	       #include <stdio.h>;*/
 
-static void signed_add_part (CamelMultipart *multipart, CamelMimePart *part);
-static void signed_add_part_at (CamelMultipart *multipart, CamelMimePart *part, guint index);
-static void signed_remove_part (CamelMultipart *multipart, CamelMimePart *part);
-static CamelMimePart *signed_remove_part_at (CamelMultipart *multipart, guint index);
-static CamelMimePart *signed_get_part (CamelMultipart *multipart, guint index);
-static guint signed_get_number (CamelMultipart *multipart);
-
-static gssize write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
-static void set_mime_type_field (CamelDataWrapper *data_wrapper, CamelContentType *mime_type);
-static gint construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
-static gint signed_construct_from_parser (CamelMultipart *multipart, struct _CamelMimeParser *mp);
-
 static gpointer parent_class;
 
-static void
-multipart_signed_dispose (GObject *object)
-{
-	CamelMultipartSigned *multipart;
-
-	multipart = CAMEL_MULTIPART_SIGNED (object);
-
-	if (multipart->signature != NULL) {
-		g_object_unref (multipart->signature);
-		multipart->signature = NULL;
-	}
-
-	if (multipart->content != NULL) {
-		g_object_unref (multipart->content);
-		multipart->content = NULL;
-	}
-
-	if (multipart->contentraw != NULL) {
-		g_object_unref (multipart->contentraw);
-		multipart->contentraw = NULL;
-	}
-
-	/* Chain up to parent's dispose() method. */
-	G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-multipart_signed_finalize (GObject *object)
-{
-	CamelMultipartSigned *multipart;
-
-	multipart = CAMEL_MULTIPART_SIGNED (object);
-
-	g_free (multipart->protocol);
-	g_free (multipart->micalg);
-
-	/* Chain up to parent's finalize() method. */
-	G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-multipart_signed_class_init (CamelMultipartSignedClass *class)
-{
-	GObjectClass *object_class;
-	CamelDataWrapperClass *data_wrapper_class;
-	CamelMultipartClass *multipart_class;
-
-	parent_class = g_type_class_peek_parent (class);
-
-	object_class = G_OBJECT_CLASS (class);
-	object_class->dispose = multipart_signed_dispose;
-	object_class->finalize = multipart_signed_finalize;
-
-	data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (class);
-	data_wrapper_class->construct_from_stream = construct_from_stream;
-	data_wrapper_class->write_to_stream = write_to_stream;
-	data_wrapper_class->decode_to_stream = write_to_stream;
-	data_wrapper_class->set_mime_type_field = set_mime_type_field;
-
-	multipart_class = CAMEL_MULTIPART_CLASS (class);
-	multipart_class->add_part = signed_add_part;
-	multipart_class->add_part_at = signed_add_part_at;
-	multipart_class->remove_part = signed_remove_part;
-	multipart_class->remove_part_at = signed_remove_part_at;
-	multipart_class->get_part = signed_get_part;
-	multipart_class->get_number = signed_get_number;
-	multipart_class->construct_from_parser = signed_construct_from_parser;
-}
-
-static void
-multipart_signed_init (CamelMultipartSigned *multipart)
-{
-	camel_data_wrapper_set_mime_type (
-		CAMEL_DATA_WRAPPER (multipart), "multipart/signed");
-
-	multipart->start1 = -1;
-}
-
-GType
-camel_multipart_signed_get_type (void)
-{
-	static GType type = G_TYPE_INVALID;
-
-	if (G_UNLIKELY (type == G_TYPE_INVALID))
-		type = g_type_register_static_simple (
-			CAMEL_TYPE_MULTIPART,
-			"CamelMultipartSigned",
-			sizeof (CamelMultipartSignedClass),
-			(GClassInitFunc) multipart_signed_class_init,
-			sizeof (CamelMultipartSigned),
-			(GInstanceInitFunc) multipart_signed_init,
-			0);
-
-	return type;
-}
-
-/**
- * camel_multipart_signed_new:
- *
- * Create a new #CamelMultipartSigned object.
- *
- * A MultipartSigned should be used to store and create parts of
- * type "multipart/signed".  This is because multipart/signed is
- * entirely broken-by-design (tm) and uses completely
- * different semantics to other mutlipart types.  It must be treated
- * as opaque data by any transport.  See rfc 3156 for details.
- *
- * There are 3 ways to create the part:
- * Use construct_from_stream.  If this is used, then you must
- * set the mime_type appropriately to match the data uses, so
- * that the multiple parts my be extracted.
- *
- * Use construct_from_parser.  The parser MUST be in the #CAMEL_MIME_PARSER_STATE_HEADER
- * state, and the current content_type MUST be "multipart/signed" with
- * the appropriate boundary and it SHOULD include the appropriate protocol
- * and hash specifiers.
- *
- * Use sign_part.  A signature part will automatically be created
- * and the whole part may be written using write_to_stream to
- * create a 'transport-safe' version (as safe as can be expected with
- * such a broken specification).
- *
- * Returns: a new #CamelMultipartSigned object
- **/
-CamelMultipartSigned *
-camel_multipart_signed_new (void)
-{
-	return g_object_new (CAMEL_TYPE_MULTIPART_SIGNED, NULL);
-}
-
 static gint
-skip_content(CamelMimeParser *cmp)
+multipart_signed_skip_content (CamelMimeParser *cmp)
 {
 	gchar *buf;
 	gsize len;
@@ -210,7 +68,7 @@ skip_content(CamelMimeParser *cmp)
 	case CAMEL_MIME_PARSER_STATE_MESSAGE:
 		/* message body part */
 		(void)camel_mime_parser_step(cmp, &buf, &len);
-		skip_content(cmp);
+		multipart_signed_skip_content (cmp);
 
 		/* clean up followon state if any, see camel-mime-message.c */
 		state = camel_mime_parser_step(cmp, &buf, &len);
@@ -229,7 +87,7 @@ skip_content(CamelMimeParser *cmp)
 	case CAMEL_MIME_PARSER_STATE_MULTIPART:
 		/* embedded multipart */
 		while ((state = camel_mime_parser_step(cmp, &buf, &len)) != CAMEL_MIME_PARSER_STATE_MULTIPART_END)
-			skip_content(cmp);
+			multipart_signed_skip_content (cmp);
 		break;
 	default:
 		g_warning("Invalid state encountered???: %u", camel_mime_parser_state (cmp));
@@ -239,7 +97,7 @@ skip_content(CamelMimeParser *cmp)
 }
 
 static gint
-parse_content(CamelMultipartSigned *mps)
+multipart_signed_parse_content (CamelMultipartSigned *mps)
 {
 	CamelMimeParser *cmp;
 	CamelMultipart *mp = (CamelMultipart *)mps;
@@ -250,24 +108,18 @@ parse_content(CamelMultipartSigned *mps)
 	gint state;
 
 	boundary = camel_multipart_get_boundary(mp);
-	if (boundary == NULL) {
-		g_warning("Trying to get multipart/signed content without setting boundary first");
-		return -1;
-	}
+	g_return_val_if_fail (boundary != NULL, -1);
 
 	stream = ((CamelDataWrapper *)mps)->stream;
-	if (stream == NULL) {
-		g_warning("Trying to parse multipart/signed without constructing first");
-		return -1;
-	}
+	g_return_val_if_fail (stream != NULL, -1);
 
 	/* This is all seriously complex.
 	   This is so we can parse all cases properly, without altering the content.
 	   All we are doing is finding part offsets. */
 
-	camel_stream_reset(stream);
-	cmp = camel_mime_parser_new();
-	camel_mime_parser_init_with_stream(cmp, stream);
+	camel_stream_reset (stream, NULL);
+	cmp = camel_mime_parser_new ();
+	camel_mime_parser_init_with_stream (cmp, stream, NULL);
 	camel_mime_parser_push_state(cmp, CAMEL_MIME_PARSER_STATE_MULTIPART, boundary);
 
 	mps->start1 = -1;
@@ -294,7 +146,7 @@ parse_content(CamelMultipartSigned *mps)
 			break;
 		}
 
-		if (skip_content(cmp) == -1)
+		if (multipart_signed_skip_content (cmp) == -1)
 			break;
 	}
 
@@ -314,13 +166,84 @@ parse_content(CamelMultipartSigned *mps)
 	return 0;
 }
 
-/* we snoop the mime type to get boundary and hash info */
 static void
-set_mime_type_field(CamelDataWrapper *data_wrapper, CamelContentType *mime_type)
+multipart_signed_set_stream (CamelMultipartSigned *mps,
+                             CamelStream *stream)
 {
+	CamelDataWrapper *dw = (CamelDataWrapper *)mps;
+
+	if (dw->stream)
+		g_object_unref (dw->stream);
+	dw->stream = stream;
+
+	mps->start1 = -1;
+	if (mps->content) {
+		g_object_unref (mps->content);
+		mps->content = NULL;
+	}
+	if (mps->contentraw) {
+		g_object_unref (mps->contentraw);
+		mps->contentraw = NULL;
+	}
+	if (mps->signature) {
+		g_object_unref (mps->signature);
+		mps->signature = NULL;
+	}
+}
+
+static void
+multipart_signed_dispose (GObject *object)
+{
+	CamelMultipartSigned *multipart;
+
+	multipart = CAMEL_MULTIPART_SIGNED (object);
+
+	if (multipart->signature != NULL) {
+		g_object_unref (multipart->signature);
+		multipart->signature = NULL;
+	}
+
+	if (multipart->content != NULL) {
+		g_object_unref (multipart->content);
+		multipart->content = NULL;
+	}
+
+	if (multipart->contentraw != NULL) {
+		g_object_unref (multipart->contentraw);
+		multipart->contentraw = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+multipart_signed_finalize (GObject *object)
+{
+	CamelMultipartSigned *multipart;
+
+	multipart = CAMEL_MULTIPART_SIGNED (object);
+
+	g_free (multipart->protocol);
+	g_free (multipart->micalg);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+multipart_signed_set_mime_type_field (CamelDataWrapper *data_wrapper,
+                                      CamelContentType *mime_type)
+{
+	CamelDataWrapperClass *data_wrapper_class;
 	CamelMultipartSigned *mps = (CamelMultipartSigned *)data_wrapper;
 
-	((CamelDataWrapperClass *)parent_class)->set_mime_type_field(data_wrapper, mime_type);
+	/* we snoop the mime type to get boundary and hash info */
+
+	/* Chain up to parent's set_mime_type_field() method. */
+	data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (parent_class);
+	data_wrapper_class->set_mime_type_field(data_wrapper, mime_type);
+
 	if (mime_type) {
 		const gchar *micalg, *protocol;
 
@@ -334,33 +257,140 @@ set_mime_type_field(CamelDataWrapper *data_wrapper, CamelContentType *mime_type)
 	}
 }
 
+static gssize
+multipart_signed_write_to_stream (CamelDataWrapper *data_wrapper,
+                                  CamelStream *stream,
+                                  GError **error)
+{
+	CamelMultipartSigned *mps = (CamelMultipartSigned *)data_wrapper;
+	CamelMultipart *mp = (CamelMultipart *)mps;
+	const gchar *boundary;
+	gssize total = 0;
+	gssize count;
+
+	/* we have 3 basic cases:
+	   1. constructed, we write out the data wrapper stream we got
+	   2. signed content, we create and write out a new stream
+	   3. invalid
+	*/
+
+	/* 1 */
+	/* FIXME: locking? */
+	if (data_wrapper->stream) {
+		camel_stream_reset (data_wrapper->stream, NULL);
+		return camel_stream_write_to_stream (
+			data_wrapper->stream, stream, error);
+	}
+
+	/* 3 */
+	if (mps->signature == NULL || mps->contentraw == NULL)
+		return -1;
+
+	/* 2 */
+	boundary = camel_multipart_get_boundary(mp);
+	if (mp->preface) {
+		count = camel_stream_write_string (
+			stream, mp->preface, error);
+		if (count == -1)
+			return -1;
+		total += count;
+	}
+
+	/* first boundary */
+	count = camel_stream_printf (stream, error, "\n--%s\n", boundary);
+	if (count == -1)
+		return -1;
+	total += count;
+
+	/* output content part */
+	camel_stream_reset (mps->contentraw, NULL);
+	count = camel_stream_write_to_stream (
+		mps->contentraw, stream, error);
+	if (count == -1)
+		return -1;
+	total += count;
+
+	/* boundary */
+	count = camel_stream_printf (stream, error, "\n--%s\n", boundary);
+	if (count == -1)
+		return -1;
+	total += count;
+
+	/* signature */
+	count = camel_data_wrapper_write_to_stream (
+		(CamelDataWrapper *) mps->signature, stream, error);
+	if (count == -1)
+		return -1;
+	total += count;
+
+	/* write the terminating boudary delimiter */
+	count = camel_stream_printf (stream, error, "\n--%s--\n", boundary);
+	if (count == -1)
+		return -1;
+	total += count;
+
+	/* and finally the postface */
+	if (mp->postface) {
+		count = camel_stream_write_string (
+			stream, mp->postface, error);
+		if (count == -1)
+			return -1;
+		total += count;
+	}
+
+	return total;
+}
+
+static gint
+multipart_signed_construct_from_stream (CamelDataWrapper *data_wrapper,
+                                        CamelStream *stream,
+                                        GError **error)
+{
+	CamelMultipartSigned *mps = (CamelMultipartSigned *)data_wrapper;
+	CamelStream *mem = camel_stream_mem_new();
+
+	if (camel_stream_write_to_stream (stream, mem, error) == -1)
+		return -1;
+
+	multipart_signed_set_stream (mps, mem);
+
+	return 0;
+}
+
 static void
-signed_add_part(CamelMultipart *multipart, CamelMimePart *part)
+multipart_signed_add_part (CamelMultipart *multipart,
+                           CamelMimePart *part)
 {
 	g_warning("Cannot add parts to a signed part using add_part");
 }
 
 static void
-signed_add_part_at(CamelMultipart *multipart, CamelMimePart *part, guint index)
+multipart_signed_add_part_at (CamelMultipart *multipart,
+                              CamelMimePart *part,
+                              guint index)
 {
 	g_warning("Cannot add parts to a signed part using add_part_at");
 }
 
 static void
-signed_remove_part(CamelMultipart *multipart, CamelMimePart *part)
+multipart_signed_remove_part (CamelMultipart *multipart,
+                              CamelMimePart *part)
 {
 	g_warning("Cannot remove parts from a signed part using remove_part");
 }
 
 static CamelMimePart *
-signed_remove_part_at (CamelMultipart *multipart, guint index)
+multipart_signed_remove_part_at (CamelMultipart *multipart,
+                                 guint index)
 {
 	g_warning("Cannot remove parts from a signed part using remove_part");
+
 	return NULL;
 }
 
 static CamelMimePart *
-signed_get_part(CamelMultipart *multipart, guint index)
+multipart_signed_get_part (CamelMultipart *multipart,
+                           guint index)
 {
 	CamelMultipartSigned *mps = (CamelMultipartSigned *)multipart;
 	CamelDataWrapper *dw = (CamelDataWrapper *)multipart;
@@ -374,7 +404,7 @@ signed_get_part(CamelMultipart *multipart, guint index)
 			stream = mps->contentraw;
 			g_object_ref (stream);
 		} else if (mps->start1 == -1
-			   && parse_content(mps) == -1
+			   && multipart_signed_parse_content(mps) == -1
 			   && (stream = ((CamelDataWrapper *)mps)->stream) == NULL) {
 			g_warning("Trying to get content on an invalid multipart/signed");
 			return NULL;
@@ -386,25 +416,27 @@ signed_get_part(CamelMultipart *multipart, guint index)
 		} else {
 			stream = camel_seekable_substream_new((CamelSeekableStream *)dw->stream, mps->start1, mps->end1);
 		}
-		camel_stream_reset(stream);
+		camel_stream_reset (stream, NULL);
 		mps->content = camel_mime_part_new();
-		camel_data_wrapper_construct_from_stream((CamelDataWrapper *)mps->content, stream);
+		camel_data_wrapper_construct_from_stream (
+			CAMEL_DATA_WRAPPER (mps->content), stream, NULL);
 		g_object_unref (stream);
 		return mps->content;
 	case CAMEL_MULTIPART_SIGNED_SIGNATURE:
 		if (mps->signature)
 			return mps->signature;
 		if (mps->start1 == -1
-		    && parse_content(mps) == -1) {
+		    && multipart_signed_parse_content(mps) == -1) {
 			g_warning("Trying to get signature on invalid multipart/signed");
 			return NULL;
 		} else if (dw->stream == NULL) {
 			return NULL;
 		}
 		stream = camel_seekable_substream_new((CamelSeekableStream *)dw->stream, mps->start2, mps->end2);
-		camel_stream_reset(stream);
+		camel_stream_reset (stream, NULL);
 		mps->signature = camel_mime_part_new();
-		camel_data_wrapper_construct_from_stream((CamelDataWrapper *)mps->signature, stream);
+		camel_data_wrapper_construct_from_stream (
+			CAMEL_DATA_WRAPPER (mps->signature), stream, NULL);
 		g_object_unref (stream);
 		return mps->signature;
 	default:
@@ -415,7 +447,7 @@ signed_get_part(CamelMultipart *multipart, guint index)
 }
 
 static guint
-signed_get_number(CamelMultipart *multipart)
+multipart_signed_get_number (CamelMultipart *multipart)
 {
 	CamelDataWrapper *dw = (CamelDataWrapper *)multipart;
 	CamelMultipartSigned *mps = (CamelMultipartSigned *)multipart;
@@ -425,7 +457,7 @@ signed_get_number(CamelMultipart *multipart)
 	if ((mps->content || mps->contentraw) && mps->signature)
 		return 2;
 
-	if (mps->start1 == -1 && parse_content(mps) == -1) {
+	if (mps->start1 == -1 && multipart_signed_parse_content(mps) == -1) {
 		if (dw->stream == NULL)
 			return 0;
 		else
@@ -435,46 +467,9 @@ signed_get_number(CamelMultipart *multipart)
 	}
 }
 
-static void
-set_stream(CamelMultipartSigned *mps, CamelStream *stream)
-{
-	CamelDataWrapper *dw = (CamelDataWrapper *)mps;
-
-	if (dw->stream)
-		g_object_unref (dw->stream);
-	dw->stream = stream;
-
-	mps->start1 = -1;
-	if (mps->content) {
-		g_object_unref (mps->content);
-		mps->content = NULL;
-	}
-	if (mps->contentraw) {
-		g_object_unref (mps->contentraw);
-		mps->contentraw = NULL;
-	}
-	if (mps->signature) {
-		g_object_unref (mps->signature);
-		mps->signature = NULL;
-	}
-}
-
 static gint
-construct_from_stream(CamelDataWrapper *data_wrapper, CamelStream *stream)
-{
-	CamelMultipartSigned *mps = (CamelMultipartSigned *)data_wrapper;
-	CamelStream *mem = camel_stream_mem_new();
-
-	if (camel_stream_write_to_stream(stream, mem) == -1)
-		return -1;
-
-	set_stream(mps, mem);
-
-	return 0;
-}
-
-static gint
-signed_construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp)
+multipart_signed_construct_from_parser (CamelMultipart *multipart,
+                                        CamelMimeParser *mp)
 {
 	gint err;
 	CamelContentType *content_type;
@@ -493,9 +488,9 @@ signed_construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser
 
 	stream = camel_stream_mem_new();
 	while (camel_mime_parser_step(mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_BODY_END)
-		camel_stream_write(stream, buf, len);
+		camel_stream_write(stream, buf, len, NULL);
 
-	set_stream(mps, stream);
+	multipart_signed_set_stream (mps, stream);
 
 	err = camel_mime_parser_errno(mp);
 	if (err != 0) {
@@ -505,81 +500,94 @@ signed_construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser
 		return 0;
 }
 
-static gssize
-write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
+static void
+multipart_signed_class_init (CamelMultipartSignedClass *class)
 {
-	CamelMultipartSigned *mps = (CamelMultipartSigned *)data_wrapper;
-	CamelMultipart *mp = (CamelMultipart *)mps;
-	const gchar *boundary;
-	gssize total = 0;
-	gssize count;
-
-	/* we have 3 basic cases:
-	   1. constructed, we write out the data wrapper stream we got
-	   2. signed content, we create and write out a new stream
-	   3. invalid
-	*/
+	GObjectClass *object_class;
+	CamelDataWrapperClass *data_wrapper_class;
+	CamelMultipartClass *multipart_class;
 
-	/* 1 */
-	/* FIXME: locking? */
-	if (data_wrapper->stream) {
-		camel_stream_reset(data_wrapper->stream);
-		return camel_stream_write_to_stream(data_wrapper->stream, stream);
-	}
+	parent_class = g_type_class_peek_parent (class);
 
-	/* 3 */
-	if (mps->signature == NULL || mps->contentraw == NULL)
-		return -1;
+	object_class = G_OBJECT_CLASS (class);
+	object_class->dispose = multipart_signed_dispose;
+	object_class->finalize = multipart_signed_finalize;
 
-	/* 2 */
-	boundary = camel_multipart_get_boundary(mp);
-	if (mp->preface) {
-		count = camel_stream_write_string(stream, mp->preface);
-		if (count == -1)
-			return -1;
-		total += count;
-	}
+	data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (class);
+	data_wrapper_class->set_mime_type_field = multipart_signed_set_mime_type_field;
+	data_wrapper_class->write_to_stream = multipart_signed_write_to_stream;
+	data_wrapper_class->decode_to_stream = multipart_signed_write_to_stream;
+	data_wrapper_class->construct_from_stream = multipart_signed_construct_from_stream;
 
-	/* first boundary */
-	count = camel_stream_printf(stream, "\n--%s\n", boundary);
-	if (count == -1)
-		return -1;
-	total += count;
+	multipart_class = CAMEL_MULTIPART_CLASS (class);
+	multipart_class->add_part = multipart_signed_add_part;
+	multipart_class->add_part_at = multipart_signed_add_part_at;
+	multipart_class->remove_part = multipart_signed_remove_part;
+	multipart_class->remove_part_at = multipart_signed_remove_part_at;
+	multipart_class->get_part = multipart_signed_get_part;
+	multipart_class->get_number = multipart_signed_get_number;
+	multipart_class->construct_from_parser = multipart_signed_construct_from_parser;
+}
 
-	/* output content part */
-	camel_stream_reset(mps->contentraw);
-	count = camel_stream_write_to_stream(mps->contentraw, stream);
-	if (count == -1)
-		return -1;
-	total += count;
+static void
+multipart_signed_init (CamelMultipartSigned *multipart)
+{
+	camel_data_wrapper_set_mime_type (
+		CAMEL_DATA_WRAPPER (multipart), "multipart/signed");
 
-	/* boundary */
-	count = camel_stream_printf(stream, "\n--%s\n", boundary);
-	if (count == -1)
-		return -1;
-	total += count;
+	multipart->start1 = -1;
+}
 
-	/* signature */
-	count = camel_data_wrapper_write_to_stream((CamelDataWrapper *)mps->signature, stream);
-	if (count == -1)
-		return -1;
-	total += count;
+GType
+camel_multipart_signed_get_type (void)
+{
+	static GType type = G_TYPE_INVALID;
 
-	/* write the terminating boudary delimiter */
-	count = camel_stream_printf(stream, "\n--%s--\n", boundary);
-	if (count == -1)
-		return -1;
-	total += count;
+	if (G_UNLIKELY (type == G_TYPE_INVALID))
+		type = g_type_register_static_simple (
+			CAMEL_TYPE_MULTIPART,
+			"CamelMultipartSigned",
+			sizeof (CamelMultipartSignedClass),
+			(GClassInitFunc) multipart_signed_class_init,
+			sizeof (CamelMultipartSigned),
+			(GInstanceInitFunc) multipart_signed_init,
+			0);
 
-	/* and finally the postface */
-	if (mp->postface) {
-		count = camel_stream_write_string(stream, mp->postface);
-		if (count == -1)
-			return -1;
-		total += count;
-	}
+	return type;
+}
 
-	return total;
+/**
+ * camel_multipart_signed_new:
+ *
+ * Create a new #CamelMultipartSigned object.
+ *
+ * A MultipartSigned should be used to store and create parts of
+ * type "multipart/signed".  This is because multipart/signed is
+ * entirely broken-by-design (tm) and uses completely
+ * different semantics to other mutlipart types.  It must be treated
+ * as opaque data by any transport.  See rfc 3156 for details.
+ *
+ * There are 3 ways to create the part:
+ * Use construct_from_stream.  If this is used, then you must
+ * set the mime_type appropriately to match the data uses, so
+ * that the multiple parts my be extracted.
+ *
+ * Use construct_from_parser.  The parser MUST be in the #CAMEL_MIME_PARSER_STATE_HEADER
+ * state, and the current content_type MUST be "multipart/signed" with
+ * the appropriate boundary and it SHOULD include the appropriate protocol
+ * and hash specifiers.
+ *
+ * Use sign_part.  A signature part will automatically be created
+ * and the whole part may be written using write_to_stream to
+ * create a 'transport-safe' version (as safe as can be expected with
+ * such a broken specification).
+ *
+ * Returns: a new #CamelMultipartSigned object
+ **/
+CamelMultipartSigned *
+camel_multipart_signed_new (void)
+{
+	return g_object_new (CAMEL_TYPE_MULTIPART_SIGNED, NULL);
 }
 
 /**
@@ -607,7 +615,7 @@ camel_multipart_signed_get_content_stream (CamelMultipartSigned *mps,
 		CamelStream *sub;
 		CamelMimeFilter *canon_filter;
 
-		if (mps->start1 == -1 && parse_content(mps) == -1) {
+		if (mps->start1 == -1 && multipart_signed_parse_content(mps) == -1) {
 			g_set_error (
 				error, CAMEL_ERROR,
 				CAMEL_ERROR_SYSTEM,
diff --git a/camel/camel-multipart.c b/camel/camel-multipart.c
index dbf03e7..1b853a5 100644
--- a/camel/camel-multipart.c
+++ b/camel/camel-multipart.c
@@ -37,27 +37,6 @@
 
 #define d(x)
 
-static gboolean              is_offline        (CamelDataWrapper *data_wrapper);
-static void                  add_part          (CamelMultipart *multipart,
-						CamelMimePart *part);
-static void                  add_part_at       (CamelMultipart *multipart,
-						CamelMimePart *part,
-						guint index);
-static void                  remove_part       (CamelMultipart *multipart,
-						CamelMimePart *part);
-static CamelMimePart *       remove_part_at    (CamelMultipart *multipart,
-						guint index);
-static CamelMimePart *       get_part          (CamelMultipart *multipart,
-						guint index);
-static guint                 get_number        (CamelMultipart *multipart);
-static void                  set_boundary      (CamelMultipart *multipart,
-						const gchar *boundary);
-static const gchar *         get_boundary      (CamelMultipart *multipart);
-static gssize               write_to_stream   (CamelDataWrapper *data_wrapper,
-						CamelStream *stream);
-
-static gint construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp);
-
 static gpointer parent_class;
 
 static void
@@ -85,6 +64,260 @@ multipart_finalize (GObject *object)
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+/* this is MIME specific, doesn't belong here really */
+static gssize
+multipart_write_to_stream (CamelDataWrapper *data_wrapper,
+                           CamelStream *stream,
+                           GError **error)
+{
+	CamelMultipart *multipart = CAMEL_MULTIPART (data_wrapper);
+	const gchar *boundary;
+	gssize total = 0;
+	gssize count;
+	GList *node;
+
+	/* get the bundary text */
+	boundary = camel_multipart_get_boundary (multipart);
+
+	/* we cannot write a multipart without a boundary string */
+	g_return_val_if_fail (boundary, -1);
+
+	/*
+	 * write the preface text (usually something like
+	 *   "This is a mime message, if you see this, then
+	 *    your mail client probably doesn't support ...."
+	 */
+	if (multipart->preface) {
+		count = camel_stream_write_string (
+			stream, multipart->preface, error);
+		if (count == -1)
+			return -1;
+		total += count;
+	}
+
+	/*
+	 * Now, write all the parts, separated by the boundary
+	 * delimiter
+	 */
+	node = multipart->parts;
+	while (node) {
+		count = camel_stream_printf (
+			stream, error, "\n--%s\n", boundary);
+		if (count == -1)
+			return -1;
+		total += count;
+
+		count = camel_data_wrapper_write_to_stream (
+			CAMEL_DATA_WRAPPER (node->data), stream, error);
+		if (count == -1)
+			return -1;
+		total += count;
+		node = node->next;
+	}
+
+	/* write the terminating boudary delimiter */
+	count = camel_stream_printf (
+		stream, error, "\n--%s--\n", boundary);
+	if (count == -1)
+		return -1;
+	total += count;
+
+	/* and finally the postface */
+	if (multipart->postface) {
+		count = camel_stream_write_string (
+			stream, multipart->postface, error);
+		if (count == -1)
+			return -1;
+		total += count;
+	}
+
+	return total;
+}
+
+static gboolean
+multipart_is_offline (CamelDataWrapper *data_wrapper)
+{
+	CamelMultipart *multipart = CAMEL_MULTIPART (data_wrapper);
+	GList *node;
+	CamelDataWrapper *part;
+
+	if (CAMEL_DATA_WRAPPER_CLASS (parent_class)->is_offline (data_wrapper))
+		return TRUE;
+	for (node = multipart->parts; node; node = node->next) {
+		part = node->data;
+		if (camel_data_wrapper_is_offline (part))
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void
+multipart_add_part (CamelMultipart *multipart, CamelMimePart *part)
+{
+	multipart->parts = g_list_append (
+		multipart->parts, g_object_ref (part));
+}
+
+static void
+multipart_add_part_at (CamelMultipart *multipart,
+                       CamelMimePart *part,
+                       guint index)
+{
+	multipart->parts = g_list_insert (
+		multipart->parts, g_object_ref (part), index);
+}
+
+static void
+multipart_remove_part (CamelMultipart *multipart,
+                       CamelMimePart *part)
+{
+	/* Make sure we don't unref a part we don't have. */
+	if (g_list_find (multipart->parts, part) == NULL)
+		return;
+
+	multipart->parts = g_list_remove (multipart->parts, part);
+	g_object_unref (part);
+}
+
+static CamelMimePart *
+multipart_remove_part_at (CamelMultipart *multipart,
+                          guint index)
+{
+	CamelMimePart *removed_part;
+	GList *link;
+
+	if (!(multipart->parts))
+		return NULL;
+
+	link = g_list_nth (multipart->parts, index);
+	if (link == NULL) {
+		g_warning ("CamelMultipart::remove_part_at: "
+			   "part to remove is NULL\n");
+		return NULL;
+	}
+	removed_part = CAMEL_MIME_PART (link->data);
+
+	multipart->parts = g_list_remove_link (multipart->parts, link);
+	if (link->data)
+		g_object_unref (link->data);
+	g_list_free_1 (link);
+
+	return removed_part;
+}
+
+static CamelMimePart *
+multipart_get_part (CamelMultipart *multipart,
+                    guint index)
+{
+	GList *part;
+
+	if (!(multipart->parts))
+		return NULL;
+
+	part = g_list_nth (multipart->parts, index);
+	if (part)
+		return CAMEL_MIME_PART (part->data);
+	else
+		return NULL;
+}
+
+static guint
+multipart_get_number (CamelMultipart *multipart)
+{
+	return g_list_length (multipart->parts);
+}
+
+static void
+multipart_set_boundary (CamelMultipart *multipart,
+                        const gchar *boundary)
+{
+	CamelDataWrapper *cdw = CAMEL_DATA_WRAPPER (multipart);
+	gchar *bgen, bbuf[27], *p;
+	guint8 *digest;
+	gsize length;
+	gint state, save;
+
+	g_return_if_fail (cdw->mime_type != NULL);
+
+	length = g_checksum_type_get_length (G_CHECKSUM_MD5);
+	digest = g_alloca (length);
+
+	if (!boundary) {
+		GChecksum *checksum;
+
+		/* Generate a fairly random boundary string. */
+		bgen = g_strdup_printf ("%p:%lu:%lu", (gpointer) multipart,
+					(gulong) getpid(),
+					(gulong) time(NULL));
+
+		checksum = g_checksum_new (G_CHECKSUM_MD5);
+		g_checksum_update (checksum, (guchar *) bgen, -1);
+		g_checksum_get_digest (checksum, digest, &length);
+		g_checksum_free (checksum);
+
+		g_free (bgen);
+		strcpy (bbuf, "=-");
+		p = bbuf + 2;
+		state = save = 0;
+		p += g_base64_encode_step (
+			(guchar *) digest, length, FALSE, p, &state, &save);
+		*p = '\0';
+
+		boundary = bbuf;
+	}
+
+	camel_content_type_set_param (cdw->mime_type, "boundary", boundary);
+}
+
+static const gchar *
+multipart_get_boundary (CamelMultipart *multipart)
+{
+	CamelDataWrapper *cdw = CAMEL_DATA_WRAPPER (multipart);
+
+	g_return_val_if_fail (cdw->mime_type != NULL, NULL);
+	return camel_content_type_param (cdw->mime_type, "boundary");
+}
+
+static gint
+multipart_construct_from_parser (CamelMultipart *multipart,
+                                 CamelMimeParser *mp)
+{
+	gint err;
+	CamelContentType *content_type;
+	CamelMimePart *bodypart;
+	gchar *buf;
+	gsize len;
+
+	g_assert(camel_mime_parser_state(mp) == CAMEL_MIME_PARSER_STATE_MULTIPART);
+
+	/* FIXME: we should use a came-mime-mutlipart, not jsut a camel-multipart, but who cares */
+	d(printf("Creating multi-part\n"));
+
+	content_type = camel_mime_parser_content_type(mp);
+	camel_multipart_set_boundary(multipart,
+				     camel_content_type_param(content_type, "boundary"));
+
+	while (camel_mime_parser_step(mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_MULTIPART_END) {
+		camel_mime_parser_unstep(mp);
+		bodypart = camel_mime_part_new();
+		camel_mime_part_construct_from_parser (bodypart, mp, NULL);
+		camel_multipart_add_part(multipart, bodypart);
+		g_object_unref (bodypart);
+	}
+
+	/* these are only return valid data in the MULTIPART_END state */
+	camel_multipart_set_preface(multipart, camel_mime_parser_preface (mp));
+	camel_multipart_set_postface(multipart, camel_mime_parser_postface (mp));
+
+	err = camel_mime_parser_errno(mp);
+	if (err != 0) {
+		errno = err;
+		return -1;
+	} else
+		return 0;
+}
+
 static void
 multipart_class_init (CamelMultipartClass *class)
 {
@@ -98,19 +331,19 @@ multipart_class_init (CamelMultipartClass *class)
 	object_class->finalize = multipart_finalize;
 
 	data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (class);
-	data_wrapper_class->write_to_stream = write_to_stream;
-	data_wrapper_class->decode_to_stream = write_to_stream;
-	data_wrapper_class->is_offline = is_offline;
-
-	class->add_part = add_part;
-	class->add_part_at = add_part_at;
-	class->remove_part = remove_part;
-	class->remove_part_at = remove_part_at;
-	class->get_part = get_part;
-	class->get_number = get_number;
-	class->set_boundary = set_boundary;
-	class->get_boundary = get_boundary;
-	class->construct_from_parser = construct_from_parser;
+	data_wrapper_class->write_to_stream = multipart_write_to_stream;
+	data_wrapper_class->decode_to_stream = multipart_write_to_stream;
+	data_wrapper_class->is_offline = multipart_is_offline;
+
+	class->add_part = multipart_add_part;
+	class->add_part_at = multipart_add_part_at;
+	class->remove_part = multipart_remove_part;
+	class->remove_part_at = multipart_remove_part_at;
+	class->get_part = multipart_get_part;
+	class->get_number = multipart_get_number;
+	class->set_boundary = multipart_set_boundary;
+	class->get_boundary = multipart_get_boundary;
+	class->construct_from_parser = multipart_construct_from_parser;
 }
 
 static void
@@ -161,13 +394,6 @@ camel_multipart_new (void)
 	return multipart;
 }
 
-static void
-add_part (CamelMultipart *multipart, CamelMimePart *part)
-{
-	multipart->parts = g_list_append (multipart->parts, part);
-	g_object_ref (part);
-}
-
 /**
  * camel_multipart_add_part:
  * @multipart: a #CamelMultipart object
@@ -190,13 +416,6 @@ camel_multipart_add_part (CamelMultipart *multipart,
 	class->add_part (multipart, part);
 }
 
-static void
-add_part_at (CamelMultipart *multipart, CamelMimePart *part, guint index)
-{
-	multipart->parts = g_list_insert (multipart->parts, part, index);
-	g_object_ref (part);
-}
-
 /**
  * camel_multipart_add_part_at:
  * @multipart: a #CamelMultipart object
@@ -222,15 +441,6 @@ camel_multipart_add_part_at (CamelMultipart *multipart,
 	class->add_part_at (multipart, part, index);
 }
 
-static void
-remove_part (CamelMultipart *multipart, CamelMimePart *part)
-{
-	if (!multipart->parts)
-		return;
-	multipart->parts = g_list_remove (multipart->parts, part);
-	g_object_unref (part);
-}
-
 /**
  * camel_multipart_remove_part:
  * @multipart: a #CamelMultipart object
@@ -253,33 +463,6 @@ camel_multipart_remove_part (CamelMultipart *multipart,
 	class->remove_part (multipart, part);
 }
 
-static CamelMimePart *
-remove_part_at (CamelMultipart *multipart, guint index)
-{
-	GList *parts_list;
-	GList *part_to_remove;
-	CamelMimePart *removed_part;
-
-	if (!(multipart->parts))
-		return NULL;
-
-	parts_list = multipart->parts;
-	part_to_remove = g_list_nth (parts_list, index);
-	if (!part_to_remove) {
-		g_warning ("CamelMultipart::remove_part_at: "
-			   "part to remove is NULL\n");
-		return NULL;
-	}
-	removed_part = CAMEL_MIME_PART (part_to_remove->data);
-
-	multipart->parts = g_list_remove_link (parts_list, part_to_remove);
-	if (part_to_remove->data)
-		g_object_unref (part_to_remove->data);
-	g_list_free_1 (part_to_remove);
-
-	return removed_part;
-}
-
 /**
  * camel_multipart_remove_part_at:
  * @multipart: a #CamelMultipart object
@@ -304,21 +487,6 @@ camel_multipart_remove_part_at (CamelMultipart *multipart,
 	return class->remove_part_at (multipart, index);
 }
 
-static CamelMimePart *
-get_part (CamelMultipart *multipart, guint index)
-{
-	GList *part;
-
-	if (!(multipart->parts))
-		return NULL;
-
-	part = g_list_nth (multipart->parts, index);
-	if (part)
-		return CAMEL_MIME_PART (part->data);
-	else
-		return NULL;
-}
-
 /**
  * camel_multipart_get_part:
  * @multipart: a #CamelMultipart object
@@ -340,12 +508,6 @@ camel_multipart_get_part (CamelMultipart *multipart,
 	return class->get_part (multipart, index);
 }
 
-static guint
-get_number (CamelMultipart *multipart)
-{
-	return g_list_length (multipart->parts);
-}
-
 /**
  * camel_multipart_get_number:
  * @multipart: a #CamelMultipart object
@@ -365,47 +527,6 @@ camel_multipart_get_number (CamelMultipart *multipart)
 	return class->get_number (multipart);
 }
 
-static void
-set_boundary (CamelMultipart *multipart, const gchar *boundary)
-{
-	CamelDataWrapper *cdw = CAMEL_DATA_WRAPPER (multipart);
-	gchar *bgen, bbuf[27], *p;
-	guint8 *digest;
-	gsize length;
-	gint state, save;
-
-	g_return_if_fail (cdw->mime_type != NULL);
-
-	length = g_checksum_type_get_length (G_CHECKSUM_MD5);
-	digest = g_alloca (length);
-
-	if (!boundary) {
-		GChecksum *checksum;
-
-		/* Generate a fairly random boundary string. */
-		bgen = g_strdup_printf ("%p:%lu:%lu", (gpointer) multipart,
-					(gulong) getpid(),
-					(gulong) time(NULL));
-
-		checksum = g_checksum_new (G_CHECKSUM_MD5);
-		g_checksum_update (checksum, (guchar *) bgen, -1);
-		g_checksum_get_digest (checksum, digest, &length);
-		g_checksum_free (checksum);
-
-		g_free (bgen);
-		strcpy (bbuf, "=-");
-		p = bbuf + 2;
-		state = save = 0;
-		p += g_base64_encode_step (
-			(guchar *) digest, length, FALSE, p, &state, &save);
-		*p = '\0';
-
-		boundary = bbuf;
-	}
-
-	camel_content_type_set_param (cdw->mime_type, "boundary", boundary);
-}
-
 /**
  * camel_multipart_set_boundary:
  * @multipart: a #CamelMultipart object
@@ -430,15 +551,6 @@ camel_multipart_set_boundary (CamelMultipart *multipart,
 	class->set_boundary (multipart, boundary);
 }
 
-static const gchar *
-get_boundary (CamelMultipart *multipart)
-{
-	CamelDataWrapper *cdw = CAMEL_DATA_WRAPPER (multipart);
-
-	g_return_val_if_fail (cdw->mime_type != NULL, NULL);
-	return camel_content_type_param (cdw->mime_type, "boundary");
-}
-
 /**
  * camel_multipart_get_boundary:
  * @multipart: a #CamelMultipart object
@@ -458,87 +570,6 @@ camel_multipart_get_boundary (CamelMultipart *multipart)
 	return class->get_boundary (multipart);
 }
 
-static gboolean
-is_offline (CamelDataWrapper *data_wrapper)
-{
-	CamelMultipart *multipart = CAMEL_MULTIPART (data_wrapper);
-	GList *node;
-	CamelDataWrapper *part;
-
-	if (CAMEL_DATA_WRAPPER_CLASS (parent_class)->is_offline (data_wrapper))
-		return TRUE;
-	for (node = multipart->parts; node; node = node->next) {
-		part = node->data;
-		if (camel_data_wrapper_is_offline (part))
-			return TRUE;
-	}
-
-	return FALSE;
-}
-
-/* this is MIME specific, doesn't belong here really */
-static gssize
-write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
-{
-	CamelMultipart *multipart = CAMEL_MULTIPART (data_wrapper);
-	const gchar *boundary;
-	gssize total = 0;
-	gssize count;
-	GList *node;
-
-	/* get the bundary text */
-	boundary = camel_multipart_get_boundary (multipart);
-
-	/* we cannot write a multipart without a boundary string */
-	g_return_val_if_fail (boundary, -1);
-
-	/*
-	 * write the preface text (usually something like
-	 *   "This is a mime message, if you see this, then
-	 *    your mail client probably doesn't support ...."
-	 */
-	if (multipart->preface) {
-		count = camel_stream_write_string (stream, multipart->preface);
-		if (count == -1)
-			return -1;
-		total += count;
-	}
-
-	/*
-	 * Now, write all the parts, separated by the boundary
-	 * delimiter
-	 */
-	node = multipart->parts;
-	while (node) {
-		count = camel_stream_printf (stream, "\n--%s\n", boundary);
-		if (count == -1)
-			return -1;
-		total += count;
-
-		count = camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (node->data), stream);
-		if (count == -1)
-			return -1;
-		total += count;
-		node = node->next;
-	}
-
-	/* write the terminating boudary delimiter */
-	count = camel_stream_printf (stream, "\n--%s--\n", boundary);
-	if (count == -1)
-		return -1;
-	total += count;
-
-	/* and finally the postface */
-	if (multipart->postface) {
-		count = camel_stream_write_string (stream, multipart->postface);
-		if (count == -1)
-			return -1;
-		total += count;
-	}
-
-	return total;
-}
-
 /**
  * camel_multipart_set_preface:
  * @multipart: a #CamelMultipart object
@@ -583,44 +614,6 @@ camel_multipart_set_postface(CamelMultipart *multipart, const gchar *postface)
 	}
 }
 
-static gint
-construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp)
-{
-	gint err;
-	CamelContentType *content_type;
-	CamelMimePart *bodypart;
-	gchar *buf;
-	gsize len;
-
-	g_assert(camel_mime_parser_state(mp) == CAMEL_MIME_PARSER_STATE_MULTIPART);
-
-	/* FIXME: we should use a came-mime-mutlipart, not jsut a camel-multipart, but who cares */
-	d(printf("Creating multi-part\n"));
-
-	content_type = camel_mime_parser_content_type(mp);
-	camel_multipart_set_boundary(multipart,
-				     camel_content_type_param(content_type, "boundary"));
-
-	while (camel_mime_parser_step(mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_MULTIPART_END) {
-		camel_mime_parser_unstep(mp);
-		bodypart = camel_mime_part_new();
-		camel_mime_part_construct_from_parser(bodypart, mp);
-		camel_multipart_add_part(multipart, bodypart);
-		g_object_unref (bodypart);
-	}
-
-	/* these are only return valid data in the MULTIPART_END state */
-	camel_multipart_set_preface(multipart, camel_mime_parser_preface (mp));
-	camel_multipart_set_postface(multipart, camel_mime_parser_postface (mp));
-
-	err = camel_mime_parser_errno(mp);
-	if (err != 0) {
-		errno = err;
-		return -1;
-	} else
-		return 0;
-}
-
 /**
  * camel_multipart_construct_from_parser:
  * @multipart: a #CamelMultipart object
diff --git a/camel/camel-partition-table.c b/camel/camel-partition-table.c
index 66260e6..08aa629 100644
--- a/camel/camel-partition-table.c
+++ b/camel/camel-partition-table.c
@@ -31,6 +31,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <glib/gi18n-lib.h>
+
 #include "camel-block-file.h"
 #include "camel-list-utils.h"
 #include "camel-partition-table.h"
@@ -195,7 +197,10 @@ static CamelBlock *find_partition (CamelPartitionTable *cpi, camel_hash_t id, gi
 	return NULL;
 }
 
-CamelPartitionTable *camel_partition_table_new (struct _CamelBlockFile *bs, camel_block_t root)
+CamelPartitionTable *
+camel_partition_table_new (struct _CamelBlockFile *bs,
+                           camel_block_t root,
+                           GError **error)
 {
 	CamelPartitionTable *cpi;
 	CamelPartitionMapBlock *ptb;
@@ -209,7 +214,7 @@ CamelPartitionTable *camel_partition_table_new (struct _CamelBlockFile *bs, came
 
 	/* read the partition table into memory */
 	do {
-		block = camel_block_file_get_block (bs, root);
+		block = camel_block_file_get_block (bs, root, error);
 		if (block == NULL)
 			goto fail;
 
@@ -219,7 +224,7 @@ CamelPartitionTable *camel_partition_table_new (struct _CamelBlockFile *bs, came
 
 		/* if we have no data, prime initial block */
 		if (ptb->used == 0 && camel_dlist_empty (&cpi->partition) && ptb->next == 0) {
-			pblock = camel_block_file_new_block (bs);
+			pblock = camel_block_file_new_block (bs, error);
 			if (pblock == NULL) {
 				camel_block_file_unref_block (bs, block);
 				goto fail;
@@ -275,7 +280,10 @@ fail:
 	return ret;
 }
 
-camel_key_t camel_partition_table_lookup (CamelPartitionTable *cpi, const gchar *key)
+camel_key_t
+camel_partition_table_lookup (CamelPartitionTable *cpi,
+                              const gchar *key,
+                              GError **error)
 {
 	CamelPartitionKeyBlock *pkb;
 	CamelPartitionMapBlock *ptb;
@@ -294,7 +302,8 @@ camel_key_t camel_partition_table_lookup (CamelPartitionTable *cpi, const gchar
 		return 0;
 	}
 	ptb = (CamelPartitionMapBlock *)&ptblock->data;
-	block = camel_block_file_get_block (cpi->blocks, ptb->partition[index].blockid);
+	block = camel_block_file_get_block (
+		cpi->blocks, ptb->partition[index].blockid, error);
 	if (block == NULL) {
 		CAMEL_PARTITION_TABLE_UNLOCK (cpi, lock);
 		return 0;
@@ -319,7 +328,10 @@ camel_key_t camel_partition_table_lookup (CamelPartitionTable *cpi, const gchar
 	return keyid;
 }
 
-void camel_partition_table_remove (CamelPartitionTable *cpi, const gchar *key)
+gboolean
+camel_partition_table_remove (CamelPartitionTable *cpi,
+                              const gchar *key,
+                              GError **error)
 {
 	CamelPartitionKeyBlock *pkb;
 	CamelPartitionMapBlock *ptb;
@@ -334,13 +346,14 @@ void camel_partition_table_remove (CamelPartitionTable *cpi, const gchar *key)
 	ptblock = find_partition (cpi, hashid, &index);
 	if (ptblock == NULL) {
 		CAMEL_PARTITION_TABLE_UNLOCK (cpi, lock);
-		return;
+		return TRUE;
 	}
 	ptb = (CamelPartitionMapBlock *)&ptblock->data;
-	block = camel_block_file_get_block (cpi->blocks, ptb->partition[index].blockid);
+	block = camel_block_file_get_block (
+		cpi->blocks, ptb->partition[index].blockid, error);
 	if (block == NULL) {
 		CAMEL_PARTITION_TABLE_UNLOCK (cpi, lock);
-		return;
+		return FALSE;
 	}
 	pkb = (CamelPartitionKeyBlock *)&block->data;
 
@@ -364,6 +377,8 @@ void camel_partition_table_remove (CamelPartitionTable *cpi, const gchar *key)
 	CAMEL_PARTITION_TABLE_UNLOCK (cpi, lock);
 
 	camel_block_file_unref_block (cpi->blocks, block);
+
+	return TRUE;
 }
 
 static gint
@@ -381,7 +396,10 @@ keys_cmp (gconstpointer ap, gconstpointer bp)
 }
 
 gint
-camel_partition_table_add (CamelPartitionTable *cpi, const gchar *key, camel_key_t keyid)
+camel_partition_table_add (CamelPartitionTable *cpi,
+                           const gchar *key,
+                           camel_key_t keyid,
+                           GError **error)
 {
 	camel_hash_t hashid, partid;
 	gint index, newindex = 0; /* initialisation of this and pkb/nkb is just to silence compiler */
@@ -401,7 +419,8 @@ camel_partition_table_add (CamelPartitionTable *cpi, const gchar *key, camel_key
 		return -1;
 	}
 	ptb = (CamelPartitionMapBlock *)&ptblock->data;
-	block = camel_block_file_get_block (cpi->blocks, ptb->partition[index].blockid);
+	block = camel_block_file_get_block (
+		cpi->blocks, ptb->partition[index].blockid, error);
 	if (block == NULL) {
 		CAMEL_PARTITION_TABLE_UNLOCK (cpi, lock);
 		return -1;
@@ -423,13 +442,17 @@ camel_partition_table_add (CamelPartitionTable *cpi, const gchar *key, camel_key
 		/* TODO: Should look at next/previous partition table block as well ... */
 
 		if (index > 0) {
-			pblock = camel_block_file_get_block (cpi->blocks, ptb->partition[index-1].blockid);
+			pblock = camel_block_file_get_block (
+				cpi->blocks, ptb->partition[index-1].blockid,
+				error);
 			if (pblock == NULL)
 				goto fail;
 			pkb = (CamelPartitionKeyBlock *)&pblock->data;
 		}
 		if (index < (ptb->used-1)) {
-			nblock = camel_block_file_get_block (cpi->blocks, ptb->partition[index+1].blockid);
+			nblock = camel_block_file_get_block (
+				cpi->blocks, ptb->partition[index+1].blockid,
+				error);
 			if (nblock == NULL) {
 				if (pblock)
 					camel_block_file_unref_block (cpi->blocks, pblock);
@@ -463,7 +486,7 @@ camel_partition_table_add (CamelPartitionTable *cpi, const gchar *key, camel_key
 			/* See if we have room in the partition table for this block or need to split that too */
 			if (ptb->used >= G_N_ELEMENTS (ptb->partition)) {
 				/* TODO: Could check next block to see if it'll fit there first */
-				ptnblock = camel_block_file_new_block (cpi->blocks);
+				ptnblock = camel_block_file_new_block (cpi->blocks, error);
 				if (ptnblock == NULL) {
 					if (nblock)
 						camel_block_file_unref_block (cpi->blocks, nblock);
@@ -505,7 +528,7 @@ camel_partition_table_add (CamelPartitionTable *cpi, const gchar *key, camel_key
 			}
 
 			/* try get newblock before modifying existing */
-			newblock = camel_block_file_new_block (cpi->blocks);
+			newblock = camel_block_file_new_block (cpi->blocks, error);
 			if (newblock == NULL) {
 				if (nblock)
 					camel_block_file_unref_block (cpi->blocks, nblock);
@@ -663,7 +686,9 @@ camel_key_table_get_type (void)
 }
 
 CamelKeyTable *
-camel_key_table_new (CamelBlockFile *bs, camel_block_t root)
+camel_key_table_new (CamelBlockFile *bs,
+                     camel_block_t root,
+                     GError **error)
 {
 	CamelKeyTable *ki;
 
@@ -673,7 +698,7 @@ camel_key_table_new (CamelBlockFile *bs, camel_block_t root)
 	g_object_ref (bs);
 	ki->rootid = root;
 
-	ki->root_block = camel_block_file_get_block (bs, ki->rootid);
+	ki->root_block = camel_block_file_get_block (bs, ki->rootid, error);
 	if (ki->root_block == NULL) {
 		g_object_unref (ki);
 		ki = NULL;
@@ -699,7 +724,11 @@ camel_key_table_sync (CamelKeyTable *ki)
 }
 
 camel_key_t
-camel_key_table_add (CamelKeyTable *ki, const gchar *key, camel_block_t data, guint flags)
+camel_key_table_add (CamelKeyTable *ki,
+                     const gchar *key,
+                     camel_block_t data,
+                     guint flags,
+                     GError **error)
 {
 	CamelBlock *last, *next;
 	CamelKeyBlock *kblast, *kbnext;
@@ -715,14 +744,15 @@ camel_key_table_add (CamelKeyTable *ki, const gchar *key, camel_block_t data, gu
 	CAMEL_KEY_TABLE_LOCK (ki, lock);
 
 	if (ki->root->last == 0) {
-		last = camel_block_file_new_block (ki->blocks);
+		last = camel_block_file_new_block (ki->blocks, error);
 		if (last == NULL)
 			goto fail;
 		ki->root->last = ki->root->first = last->id;
 		camel_block_file_touch_block (ki->blocks, ki->root_block);
 		k (printf ("adding first block, first = %u\n", ki->root->first));
 	} else {
-		last = camel_block_file_get_block (ki->blocks, ki->root->last);
+		last = camel_block_file_get_block (
+			ki->blocks, ki->root->last, error);
 		if (last == NULL)
 			goto fail;
 	}
@@ -740,7 +770,7 @@ camel_key_table_add (CamelKeyTable *ki, const gchar *key, camel_block_t data, gu
 			 sizeof (kblast->u.keydata) - kblast->u.keys[kblast->used-1].offset,
 			 left, len));
 		if (left < len) {
-			next = camel_block_file_new_block (ki->blocks);
+			next = camel_block_file_new_block (ki->blocks, error);
 			if (next == NULL) {
 				camel_block_file_unref_block (ki->blocks, last);
 				goto fail;
@@ -792,23 +822,25 @@ fail:
 	return keyid;
 }
 
-void
-camel_key_table_set_data (CamelKeyTable *ki, camel_key_t keyid, camel_block_t data)
+gboolean
+camel_key_table_set_data (CamelKeyTable *ki,
+                          camel_key_t keyid,
+                          camel_block_t data,
+                          GError **error)
 {
 	CamelBlock *bl;
 	camel_block_t blockid;
 	gint index;
 	CamelKeyBlock *kb;
 
-	if (keyid == 0)
-		return;
+	g_return_val_if_fail (keyid != 0, FALSE);
 
 	blockid =  keyid & (~(CAMEL_BLOCK_SIZE-1));
 	index = keyid & (CAMEL_BLOCK_SIZE-1);
 
-	bl = camel_block_file_get_block (ki->blocks, blockid);
+	bl = camel_block_file_get_block (ki->blocks, blockid, error);
 	if (bl == NULL)
-		return;
+		return FALSE;
 	kb = (CamelKeyBlock *)&bl->data;
 
 	CAMEL_KEY_TABLE_LOCK (ki, lock);
@@ -821,10 +853,16 @@ camel_key_table_set_data (CamelKeyTable *ki, camel_key_t keyid, camel_block_t da
 	CAMEL_KEY_TABLE_UNLOCK (ki, lock);
 
 	camel_block_file_unref_block (ki->blocks, bl);
+
+	return TRUE;
 }
 
-void
-camel_key_table_set_flags (CamelKeyTable *ki, camel_key_t keyid, guint flags, guint set)
+gboolean
+camel_key_table_set_flags (CamelKeyTable *ki,
+                           camel_key_t keyid,
+                           guint flags,
+                           guint set,
+                           GError **error)
 {
 	CamelBlock *bl;
 	camel_block_t blockid;
@@ -832,26 +870,23 @@ camel_key_table_set_flags (CamelKeyTable *ki, camel_key_t keyid, guint flags, gu
 	CamelKeyBlock *kb;
 	guint old;
 
-	if (keyid == 0)
-		return;
+	g_return_val_if_fail (keyid != 0, FALSE);
 
 	blockid =  keyid & (~(CAMEL_BLOCK_SIZE-1));
 	index = keyid & (CAMEL_BLOCK_SIZE-1);
 
-	bl = camel_block_file_get_block (ki->blocks, blockid);
+	bl = camel_block_file_get_block (ki->blocks, blockid, error);
 	if (bl == NULL)
-		return;
+		return FALSE;
 	kb = (CamelKeyBlock *)&bl->data;
 
-#if 0
-	g_assert (kb->used < 127); /* this should be more accurate */
-	g_assert (index < kb->used);
-#else
 	if (kb->used >=127 || index >= kb->used) {
-		g_warning ("Block %x: Invalid index or content: index %d used %d\n", blockid, index, kb->used);
-		return;
+		g_set_error (
+			error, CAMEL_ERROR, CAMEL_ERROR_SYSTEM,
+			_("Block %x: Invalid index or content: "
+			  "index %d used %d"), blockid, index, kb->used);
+		return FALSE;
 	}
-#endif
 
 	CAMEL_KEY_TABLE_LOCK (ki, lock);
 
@@ -864,10 +899,16 @@ camel_key_table_set_flags (CamelKeyTable *ki, camel_key_t keyid, guint flags, gu
 	CAMEL_KEY_TABLE_UNLOCK (ki, lock);
 
 	camel_block_file_unref_block (ki->blocks, bl);
+
+	return TRUE;
 }
 
 camel_block_t
-camel_key_table_lookup (CamelKeyTable *ki, camel_key_t keyid, gchar **keyp, guint *flags)
+camel_key_table_lookup (CamelKeyTable *ki,
+                        camel_key_t keyid,
+                        gchar **keyp,
+                        guint *flags,
+                        GError **error)
 {
 	CamelBlock *bl;
 	camel_block_t blockid;
@@ -875,31 +916,29 @@ camel_key_table_lookup (CamelKeyTable *ki, camel_key_t keyid, gchar **keyp, guin
 	gchar *key;
 	CamelKeyBlock *kb;
 
+	g_return_val_if_fail (keyid != 0, 0);
+
 	if (keyp)
 		*keyp = NULL;
 	if (flags)
 		*flags = 0;
-	if (keyid == 0)
-		return 0;
 
 	blockid =  keyid & (~(CAMEL_BLOCK_SIZE-1));
 	index = keyid & (CAMEL_BLOCK_SIZE-1);
 
-	bl = camel_block_file_get_block (ki->blocks, blockid);
+	bl = camel_block_file_get_block (ki->blocks, blockid, error);
 	if (bl == NULL)
 		return 0;
 
 	kb = (CamelKeyBlock *)&bl->data;
 
-#if 0
-	g_assert (kb->used < 127); /* this should be more accurate */
-	g_assert (index < kb->used);
-#else
 	if (kb->used >=127 || index >= kb->used) {
-		g_warning ("Block %x: Invalid index or content: index %d used %d\n", blockid, index, kb->used);
+		g_set_error (
+			error, CAMEL_ERROR, CAMEL_ERROR_SYSTEM,
+			_("Block %x: Invalid index or content: "
+			  "index %d used %d\n"), blockid, index, kb->used);
 		return 0;
 	}
-#endif
 
 	CAMEL_KEY_TABLE_LOCK (ki, lock);
 
@@ -927,7 +966,12 @@ camel_key_table_lookup (CamelKeyTable *ki, camel_key_t keyid, gchar **keyp, guin
 
 /* iterate through all keys */
 camel_key_t
-camel_key_table_next (CamelKeyTable *ki, camel_key_t next, gchar **keyp, guint *flagsp, camel_block_t *datap)
+camel_key_table_next (CamelKeyTable *ki,
+                      camel_key_t next,
+                      gchar **keyp,
+                      guint *flagsp,
+                      camel_block_t *datap,
+                      GError **error)
 {
 	CamelBlock *bl;
 	CamelKeyBlock *kb;
@@ -956,7 +1000,7 @@ camel_key_table_next (CamelKeyTable *ki, camel_key_t next, gchar **keyp, guint *
 		blockid =  next & (~(CAMEL_BLOCK_SIZE-1));
 		index = next & (CAMEL_BLOCK_SIZE-1);
 
-		bl = camel_block_file_get_block (ki->blocks, blockid);
+		bl = camel_block_file_get_block (ki->blocks, blockid, error);
 		if (bl == NULL) {
 			CAMEL_KEY_TABLE_UNLOCK (ki, lock);
 			return 0;
diff --git a/camel/camel-partition-table.h b/camel/camel-partition-table.h
index 8b22e57..6a8f6d5 100644
--- a/camel/camel-partition-table.h
+++ b/camel/camel-partition-table.h
@@ -123,13 +123,22 @@ struct _CamelPartitionTableClass {
 	CamelObjectClass parent;
 };
 
-GType camel_partition_table_get_type(void);
-
-CamelPartitionTable *camel_partition_table_new(struct _CamelBlockFile *bs, camel_block_t root);
-gint camel_partition_table_sync(CamelPartitionTable *cpi);
-gint camel_partition_table_add(CamelPartitionTable *cpi, const gchar *key, camel_key_t keyid);
-camel_key_t camel_partition_table_lookup(CamelPartitionTable *cpi, const gchar *key);
-void camel_partition_table_remove(CamelPartitionTable *cpi, const gchar *key);
+GType		camel_partition_table_get_type	(void);
+CamelPartitionTable *
+		camel_partition_table_new	(struct _CamelBlockFile *bs,
+						 camel_block_t root,
+						 GError **error);
+gint		camel_partition_table_sync	(CamelPartitionTable *cpi);
+gint		camel_partition_table_add	(CamelPartitionTable *cpi,
+						 const gchar *key,
+						 camel_key_t keyid,
+						 GError **error);
+camel_key_t	camel_partition_table_lookup	(CamelPartitionTable *cpi,
+						 const gchar *key,
+						 GError **error);
+gboolean	camel_partition_table_remove	(CamelPartitionTable *cpi,
+						 const gchar *key,
+						 GError **error);
 
 /* ********************************************************************** */
 
@@ -181,15 +190,36 @@ struct _CamelKeyTableClass {
 	CamelObjectClass parent;
 };
 
-GType camel_key_table_get_type(void);
-
-CamelKeyTable * camel_key_table_new(CamelBlockFile *bs, camel_block_t root);
-gint camel_key_table_sync(CamelKeyTable *ki);
-camel_key_t camel_key_table_add(CamelKeyTable *ki, const gchar *key, camel_block_t data, guint flags);
-void camel_key_table_set_data(CamelKeyTable *ki, camel_key_t keyid, camel_block_t data);
-void camel_key_table_set_flags(CamelKeyTable *ki, camel_key_t keyid, guint flags, guint set);
-camel_block_t camel_key_table_lookup(CamelKeyTable *ki, camel_key_t keyid, gchar **key, guint *flags);
-camel_key_t camel_key_table_next(CamelKeyTable *ki, camel_key_t next, gchar **keyp, guint *flagsp, camel_block_t *datap);
+GType		camel_key_table_get_type	(void);
+CamelKeyTable *	camel_key_table_new		(CamelBlockFile *bs,
+						 camel_block_t root,
+						 GError **error);
+gint		camel_key_table_sync		(CamelKeyTable *ki);
+camel_key_t	camel_key_table_add		(CamelKeyTable *ki,
+						 const gchar *key,
+						 camel_block_t data,
+						 guint flags,
+						 GError **error);
+gboolean	camel_key_table_set_data	(CamelKeyTable *ki,
+						 camel_key_t keyid,
+						 camel_block_t data,
+						 GError **error);
+gboolean	camel_key_table_set_flags	(CamelKeyTable *ki,
+						 camel_key_t keyid,
+						 guint flags,
+						 guint set,
+						 GError **error);
+camel_block_t	camel_key_table_lookup		(CamelKeyTable *ki,
+						 camel_key_t keyid,
+						 gchar **key,
+						 guint *flags,
+						 GError **error);
+camel_key_t	camel_key_table_next		(CamelKeyTable *ki,
+						 camel_key_t next,
+						 gchar **keyp,
+						 guint *flagsp,
+						 camel_block_t *datap,
+						 GError **error);
 
 G_END_DECLS
 
diff --git a/camel/camel-search-private.c b/camel/camel-search-private.c
index da3efc0..757c05f 100644
--- a/camel/camel-search-private.c
+++ b/camel/camel-search-private.c
@@ -481,8 +481,8 @@ camel_search_message_body_contains (CamelDataWrapper *object, regex_t *pattern)
 
 		byte_array = g_byte_array_new ();
 		stream = camel_stream_mem_new_with_byte_array (byte_array);
-		camel_data_wrapper_write_to_stream (containee, stream);
-		camel_stream_write (stream, "", 1);
+		camel_data_wrapper_write_to_stream (containee, stream, NULL);
+		camel_stream_write (stream, "", 1, NULL);
 		truth = regexec (pattern, (gchar *) byte_array->data, 0, NULL, 0) == 0;
 		g_object_unref (stream);
 	}
diff --git a/camel/camel-seekable-stream.c b/camel/camel-seekable-stream.c
index e18b34c..d956d1b 100644
--- a/camel/camel-seekable-stream.c
+++ b/camel/camel-seekable-stream.c
@@ -30,7 +30,8 @@
 static gpointer parent_class;
 
 static gint
-seekable_stream_reset (CamelStream *stream)
+seekable_stream_reset (CamelStream *stream,
+                       GError **error)
 {
 	CamelSeekableStream *seekable_stream;
 
@@ -38,7 +39,7 @@ seekable_stream_reset (CamelStream *stream)
 
 	return camel_seekable_stream_seek (
 		seekable_stream, seekable_stream->bound_start,
-		CAMEL_STREAM_SET);
+		CAMEL_STREAM_SET, error);
 }
 
 static off_t
@@ -50,7 +51,8 @@ seekable_stream_tell (CamelSeekableStream *stream)
 static gint
 seekable_stream_set_bounds (CamelSeekableStream *stream,
                             off_t start,
-                            off_t end)
+                            off_t end,
+                            GError **error)
 {
 	/* store the bounds */
 	stream->bound_start = start;
@@ -58,7 +60,7 @@ seekable_stream_set_bounds (CamelSeekableStream *stream,
 
 	if (start > stream->position)
 		return camel_seekable_stream_seek (
-			stream, start, CAMEL_STREAM_SET);
+			stream, start, CAMEL_STREAM_SET, error);
 
 	return 0;
 }
@@ -107,6 +109,7 @@ camel_seekable_stream_get_type (void)
  * @stream: a #CamelStream object
  * @offset: offset value
  * @policy: what to do with the offset
+ * @error: return location for a #GError, or %NULL
  *
  * Seek to the specified position in @stream.
  *
@@ -127,7 +130,8 @@ camel_seekable_stream_get_type (void)
 off_t
 camel_seekable_stream_seek (CamelSeekableStream *stream,
                             off_t offset,
-                            CamelStreamSeekPolicy policy)
+                            CamelStreamSeekPolicy policy,
+                            GError **error)
 {
 	CamelSeekableStreamClass *class;
 
@@ -136,7 +140,7 @@ camel_seekable_stream_seek (CamelSeekableStream *stream,
 	class = CAMEL_SEEKABLE_STREAM_GET_CLASS (stream);
 	g_return_val_if_fail (class->seek != NULL, -1);
 
-	return class->seek (stream, offset, policy);
+	return class->seek (stream, offset, policy, error);
 }
 
 /**
@@ -165,6 +169,7 @@ camel_seekable_stream_tell (CamelSeekableStream *stream)
  * @stream: a #CamelSeekableStream object
  * @start: the first valid position
  * @end: the first invalid position, or #CAMEL_STREAM_UNBOUND
+ * @error: return location for a #GError, or %NULL
  *
  * Set the range of valid data this stream is allowed to cover.  If
  * there is to be no @end value, then @end should be set to
@@ -175,7 +180,8 @@ camel_seekable_stream_tell (CamelSeekableStream *stream)
 gint
 camel_seekable_stream_set_bounds (CamelSeekableStream *stream,
                                   off_t start,
-                                  off_t end)
+                                  off_t end,
+                                  GError **error)
 {
 	CamelSeekableStreamClass *class;
 
@@ -185,5 +191,5 @@ camel_seekable_stream_set_bounds (CamelSeekableStream *stream,
 	class = CAMEL_SEEKABLE_STREAM_GET_CLASS (stream);
 	g_return_val_if_fail (class->set_bounds != NULL, -1);
 
-	return class->set_bounds (stream, start, end);
+	return class->set_bounds (stream, start, end, error);
 }
diff --git a/camel/camel-seekable-stream.h b/camel/camel-seekable-stream.h
index b7743a9..1cf2801 100644
--- a/camel/camel-seekable-stream.h
+++ b/camel/camel-seekable-stream.h
@@ -76,21 +76,27 @@ struct _CamelSeekableStream {
 struct _CamelSeekableStreamClass {
 	CamelStreamClass parent_class;
 
-	/* Virtual methods */
-	off_t (*seek)       (CamelSeekableStream *stream, off_t offset,
-			     CamelStreamSeekPolicy policy);
-	off_t (*tell)	    (CamelSeekableStream *stream);
-	gint  (*set_bounds)  (CamelSeekableStream *stream,
-			     off_t start, off_t end);
+	off_t		(*seek)			(CamelSeekableStream *stream,
+						 off_t offset,
+						 CamelStreamSeekPolicy policy,
+						 GError **error);
+	off_t		(*tell)			(CamelSeekableStream *stream);
+	gint		(*set_bounds)		(CamelSeekableStream *stream,
+						 off_t start,
+						 off_t end,
+						 GError **error);
 };
 
-GType camel_seekable_stream_get_type (void);
-
-/* public methods */
-off_t    camel_seekable_stream_seek            (CamelSeekableStream *stream, off_t offset,
-						CamelStreamSeekPolicy policy);
-off_t	 camel_seekable_stream_tell	       (CamelSeekableStream *stream);
-gint	 camel_seekable_stream_set_bounds      (CamelSeekableStream *stream, off_t start, off_t end);
+GType		camel_seekable_stream_get_type	(void);
+off_t		camel_seekable_stream_seek	(CamelSeekableStream *stream,
+						 off_t offset,
+						 CamelStreamSeekPolicy policy,
+						 GError **error);
+off_t		camel_seekable_stream_tell	(CamelSeekableStream *stream);
+gint		camel_seekable_stream_set_bounds(CamelSeekableStream *stream,
+						 off_t start,
+						 off_t end,
+						 GError **error);
 
 G_END_DECLS
 
diff --git a/camel/camel-seekable-substream.c b/camel/camel-seekable-substream.c
index 7c8d8fe..a6ec79c 100644
--- a/camel/camel-seekable-substream.c
+++ b/camel/camel-seekable-substream.c
@@ -38,7 +38,9 @@ seekable_substream_parent_reset (CamelSeekableSubstream *seekable_substream,
 	if (camel_seekable_stream_tell (parent) == seekable_stream->position)
 		return TRUE;
 
-	return camel_seekable_stream_seek (parent, (off_t) seekable_stream->position, CAMEL_STREAM_SET) == seekable_stream->position;
+	return camel_seekable_stream_seek (
+		parent, (off_t) seekable_stream->position,
+		CAMEL_STREAM_SET, NULL) == seekable_stream->position;
 }
 
 static void
@@ -60,7 +62,8 @@ seekable_substream_dispose (GObject *object)
 static gssize
 seekable_substream_read (CamelStream *stream,
                          gchar *buffer,
-                         gsize n)
+                         gsize n,
+                         GError **error)
 {
 	CamelSeekableStream *parent;
 	CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream);
@@ -87,7 +90,7 @@ seekable_substream_read (CamelStream *stream,
 		return 0;
 	}
 
-	v = camel_stream_read (CAMEL_STREAM (parent), buffer, n);
+	v = camel_stream_read (CAMEL_STREAM (parent), buffer, n, error);
 
 	/* ignore <0 - it's an error, let the caller deal */
 	if (v > 0)
@@ -99,7 +102,8 @@ seekable_substream_read (CamelStream *stream,
 static gssize
 seekable_substream_write (CamelStream *stream,
                           const gchar *buffer,
-                          gsize n)
+                          gsize n,
+                          GError **error)
 {
 	CamelSeekableStream *parent;
 	CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM(stream);
@@ -126,7 +130,7 @@ seekable_substream_write (CamelStream *stream,
 		return 0;
 	}
 
-	v = camel_stream_write((CamelStream *)parent, buffer, n);
+	v = camel_stream_write (CAMEL_STREAM (parent), buffer, n, error);
 
 	/* ignore <0 - it's an error, let the caller deal */
 	if (v > 0)
@@ -137,15 +141,17 @@ seekable_substream_write (CamelStream *stream,
 }
 
 static gint
-seekable_substream_flush (CamelStream *stream)
+seekable_substream_flush (CamelStream *stream,
+                          GError **error)
 {
 	CamelSeekableSubstream *sus = (CamelSeekableSubstream *)stream;
 
-	return camel_stream_flush(CAMEL_STREAM(sus->parent_stream));
+	return camel_stream_flush (CAMEL_STREAM (sus->parent_stream), error);
 }
 
 static gint
-seekable_substream_close (CamelStream *stream)
+seekable_substream_close (CamelStream *stream,
+                          GError **error)
 {
 	/* we dont really want to close the substream ... */
 	return 0;
@@ -178,12 +184,16 @@ seekable_substream_eos (CamelStream *stream)
 static off_t
 seekable_substream_seek (CamelSeekableStream *seekable_stream,
                          off_t offset,
-                         CamelStreamSeekPolicy policy)
+                         CamelStreamSeekPolicy policy,
+                         GError **error)
 {
-	CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM(seekable_stream);
-	CamelStream *stream = CAMEL_STREAM(seekable_stream);
+	CamelStream *stream;
+	CamelSeekableSubstream *seekable_substream;
 	off_t real_offset = 0;
 
+	stream = CAMEL_STREAM (seekable_stream);
+	seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (seekable_stream);
+
 	stream->eos = FALSE;
 
 	switch (policy) {
@@ -197,9 +207,9 @@ seekable_substream_seek (CamelSeekableStream *seekable_stream,
 
 	case CAMEL_STREAM_END:
 		if (seekable_stream->bound_end == CAMEL_STREAM_UNBOUND) {
-			real_offset = camel_seekable_stream_seek(seekable_substream->parent_stream,
-								 offset,
-								 CAMEL_STREAM_END);
+			real_offset = camel_seekable_stream_seek(
+				seekable_substream->parent_stream,
+				offset, CAMEL_STREAM_END, error);
 			if (real_offset != -1) {
 				if (real_offset<seekable_stream->bound_start)
 					real_offset = seekable_stream->bound_start;
@@ -218,6 +228,7 @@ seekable_substream_seek (CamelSeekableStream *seekable_stream,
 		real_offset = seekable_stream->bound_start;
 
 	seekable_stream->position = real_offset;
+
 	return real_offset;
 }
 
@@ -295,9 +306,10 @@ camel_seekable_substream_new(CamelSeekableStream *parent_stream, off_t start, of
 	g_object_ref (parent_stream);
 
 	/* Set the bound of the substream. We can ignore any possible error
-	 * here, because if we fail to seek now, it will try again later.
-	 */
-	camel_seekable_stream_set_bounds ((CamelSeekableStream *)seekable_substream, start, end);
+	 * here, because if we fail to seek now, it will try again later. */
+	camel_seekable_stream_set_bounds (
+		CAMEL_SEEKABLE_STREAM (seekable_substream),
+		start, end, NULL);
 
 	return CAMEL_STREAM (seekable_substream);
 }
diff --git a/camel/camel-smime-context.c b/camel/camel-smime-context.c
index 621d246..ca0a387 100644
--- a/camel/camel-smime-context.c
+++ b/camel/camel-smime-context.c
@@ -81,7 +81,7 @@ static gpointer parent_class;
 static void
 sm_write_stream (gpointer arg, const gchar *buf, gulong len)
 {
-	camel_stream_write ((CamelStream *)arg, buf, len);
+	camel_stream_write ((CamelStream *)arg, buf, len, NULL);
 }
 
 static PK11SymKey *
@@ -547,7 +547,7 @@ sm_verify_cmsg (CamelCipherContext *context,
 
 			buffer = g_byte_array_new ();
 			mem = camel_stream_mem_new_with_byte_array (buffer);
-			camel_stream_write_to_stream (extstream, mem);
+			camel_stream_write_to_stream (extstream, mem, NULL);
 			NSS_CMSDigestContext_Update (digcx, buffer->data, buffer->len);
 			g_object_unref (mem);
 
@@ -725,15 +725,13 @@ smime_context_sign (CamelCipherContext *context,
 	buffer = g_byte_array_new ();
 	istream = camel_stream_mem_new_with_byte_array (buffer);
 
-	if (camel_cipher_canonical_to_stream (ipart,
-					     CAMEL_MIME_FILTER_CANON_STRIP
-					     |CAMEL_MIME_FILTER_CANON_CRLF
-					     |CAMEL_MIME_FILTER_CANON_FROM, istream) == -1) {
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Could not generate signing data: %s"),
-			g_strerror (errno));
+	if (camel_cipher_canonical_to_stream (
+		ipart, CAMEL_MIME_FILTER_CANON_STRIP |
+		CAMEL_MIME_FILTER_CANON_CRLF |
+		CAMEL_MIME_FILTER_CANON_FROM,
+		istream, error) == -1) {
+		g_prefix_error (
+			error, _("Could not generate signing data: "));
 		goto fail;
 	}
 
@@ -762,8 +760,8 @@ smime_context_sign (CamelCipherContext *context,
 	res = 0;
 
 	dw = camel_data_wrapper_new ();
-	camel_stream_reset (ostream);
-	camel_data_wrapper_construct_from_stream (dw, ostream);
+	camel_stream_reset (ostream, NULL);
+	camel_data_wrapper_construct_from_stream (dw, ostream, NULL);
 	dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY;
 
 	if (((CamelSMIMEContext *)context)->priv->sign_mode == CAMEL_SMIME_SIGN_CLEARSIGN) {
@@ -792,7 +790,7 @@ smime_context_sign (CamelCipherContext *context,
 
 		mps->signature = sigpart;
 		mps->contentraw = istream;
-		camel_stream_reset (istream);
+		camel_stream_reset (istream, NULL);
 		g_object_ref (istream);
 
 		camel_medium_set_content ((CamelMedium *)opart, (CamelDataWrapper *)mps);
@@ -888,7 +886,9 @@ smime_context_verify (CamelCipherContext *context,
 				   NULL, NULL,	/* password callback    */
 				   NULL, NULL); /* decrypt key callback */
 
-	camel_data_wrapper_decode_to_stream (camel_medium_get_content ((CamelMedium *)sigpart), mem);
+	camel_data_wrapper_decode_to_stream (
+		camel_medium_get_content (CAMEL_MEDIUM (sigpart)),
+		mem, NULL);
 	(void)NSS_CMSDecoder_Update (dec, (gchar *) buffer->data, buffer->len);
 	cmsg = NSS_CMSDecoder_Finish (dec);
 	if (cmsg == NULL) {
@@ -1033,7 +1033,7 @@ smime_context_encrypt (CamelCipherContext *context,
 	/* FIXME: Canonicalise the input? */
 	buffer = g_byte_array_new ();
 	mem = camel_stream_mem_new_with_byte_array (buffer);
-	camel_data_wrapper_write_to_stream ((CamelDataWrapper *)ipart, mem);
+	camel_data_wrapper_write_to_stream ((CamelDataWrapper *)ipart, mem, NULL);
 	if (NSS_CMSEncoder_Update (enc, (gchar *) buffer->data, buffer->len) != SECSuccess) {
 		NSS_CMSEncoder_Cancel (enc);
 		g_object_unref (mem);
@@ -1054,7 +1054,7 @@ smime_context_encrypt (CamelCipherContext *context,
 	PORT_FreeArena (poolp, PR_FALSE);
 
 	dw = camel_data_wrapper_new ();
-	camel_data_wrapper_construct_from_stream (dw, ostream);
+	camel_data_wrapper_construct_from_stream (dw, ostream, NULL);
 	g_object_unref (ostream);
 	dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY;
 
@@ -1114,8 +1114,8 @@ smime_context_decrypt (CamelCipherContext *context,
 	/* FIXME: stream this to the decoder incrementally */
 	buffer = g_byte_array_new ();
 	istream = camel_stream_mem_new_with_byte_array (buffer);
-	camel_data_wrapper_decode_to_stream (camel_medium_get_content ((CamelMedium *)ipart), istream);
-	camel_stream_reset (istream);
+	camel_data_wrapper_decode_to_stream (camel_medium_get_content ((CamelMedium *)ipart), istream, NULL);
+	camel_stream_reset (istream, NULL);
 
 	dec = NSS_CMSDecoder_Start (NULL,
 				   sm_write_stream, ostream, /* content callback     */
@@ -1144,11 +1144,11 @@ smime_context_decrypt (CamelCipherContext *context,
 	}
 #endif
 
-	camel_stream_reset (ostream);
-	camel_data_wrapper_construct_from_stream ((CamelDataWrapper *)opart, ostream);
+	camel_stream_reset (ostream, NULL);
+	camel_data_wrapper_construct_from_stream ((CamelDataWrapper *)opart, ostream, NULL);
 
 	if (NSS_CMSMessage_IsSigned (cmsg)) {
-		camel_stream_reset (ostream);
+		camel_stream_reset (ostream, NULL);
 		valid = sm_verify_cmsg (context, cmsg, ostream, error);
 	} else {
 		valid = camel_cipher_validity_new ();
@@ -1275,8 +1275,8 @@ camel_smime_context_describe_part (CamelSMIMEContext *context, CamelMimePart *pa
 		/* FIXME: stream this to the decoder incrementally */
 		buffer = g_byte_array_new ();
 		istream = camel_stream_mem_new_with_byte_array (buffer);
-		camel_data_wrapper_decode_to_stream (camel_medium_get_content ((CamelMedium *)part), istream);
-		camel_stream_reset (istream);
+		camel_data_wrapper_decode_to_stream (camel_medium_get_content ((CamelMedium *)part), istream, NULL);
+		camel_stream_reset (istream, NULL);
 
 		dec = NSS_CMSDecoder_Start (NULL,
 					   NULL, NULL,
diff --git a/camel/camel-stream-buffer.c b/camel/camel-stream-buffer.c
index 1dca0ee..3752a32 100644
--- a/camel/camel-stream-buffer.c
+++ b/camel/camel-stream-buffer.c
@@ -63,12 +63,13 @@ enum {
 static gssize
 stream_write_all (CamelStream *stream,
                   const gchar *buffer,
-                  gsize n)
+                  gsize n,
+                  GError **error)
 {
 	gsize left = n, w;
 
 	while (left > 0) {
-		w = camel_stream_write (stream, buffer, left);
+		w = camel_stream_write (stream, buffer, left, error);
 		if (w == -1)
 			return -1;
 		left -= w;
@@ -140,7 +141,8 @@ stream_buffer_finalize (GObject *object)
 static gssize
 stream_buffer_read (CamelStream *stream,
                     gchar *buffer,
-                    gsize n)
+                    gsize n,
+                    GError **error)
 {
 	CamelStreamBufferPrivate *priv;
 	gssize bytes_read = 1;
@@ -165,7 +167,7 @@ stream_buffer_read (CamelStream *stream,
 			/* if we are reading a lot, then read directly to the destination buffer */
 			if (n >= priv->size/3) {
 				bytes_read = camel_stream_read (
-					priv->stream, bptr, n);
+					priv->stream, bptr, n, error);
 				if (bytes_read>0) {
 					n -= bytes_read;
 					bptr += bytes_read;
@@ -173,7 +175,7 @@ stream_buffer_read (CamelStream *stream,
 			} else {
 				bytes_read = camel_stream_read (
 					priv->stream, (gchar *)
-					priv->buf, priv->size);
+					priv->buf, priv->size, error);
 				if (bytes_read>0) {
 					gsize bytes_used = bytes_read > n ? n : bytes_read;
 					priv->ptr = priv->buf;
@@ -198,7 +200,8 @@ stream_buffer_read (CamelStream *stream,
 static gssize
 stream_buffer_write (CamelStream *stream,
                      const gchar *buffer,
-                     gsize n)
+                     gsize n,
+                     GError **error)
 {
 	CamelStreamBufferPrivate *priv;
 	gssize total = n;
@@ -222,8 +225,8 @@ stream_buffer_write (CamelStream *stream,
 	/* if we've filled the buffer, write it out, reset buffer */
 	if (left == todo) {
 		if (stream_write_all (
-			priv->stream, (gchar *)
-			priv->buf, priv->size) == -1)
+			priv->stream, (gchar *) priv->buf,
+			priv->size, error) == -1)
 			return -1;
 
 		priv->ptr = priv->buf;
@@ -232,7 +235,8 @@ stream_buffer_write (CamelStream *stream,
 	/* if we still have more, write directly, or copy to buffer */
 	if (n > 0) {
 		if (n >= priv->size/3) {
-			if (stream_write_all(priv->stream, buffer, n) == -1)
+			if (stream_write_all (
+				priv->stream, buffer, n, error) == -1)
 				return -1;
 		} else {
 			memcpy(priv->ptr, buffer, n);
@@ -244,7 +248,8 @@ stream_buffer_write (CamelStream *stream,
 }
 
 static gint
-stream_buffer_flush (CamelStream *stream)
+stream_buffer_flush (CamelStream *stream,
+                     GError **error)
 {
 	CamelStreamBufferPrivate *priv;
 
@@ -254,7 +259,7 @@ stream_buffer_flush (CamelStream *stream)
 		gsize len = priv->ptr - priv->buf;
 
 		if (camel_stream_write (
-			priv->stream, (gchar *) priv->buf, len) == -1)
+			priv->stream, (gchar *) priv->buf, len, error) == -1)
 			return -1;
 
 		priv->ptr = priv->buf;
@@ -262,20 +267,21 @@ stream_buffer_flush (CamelStream *stream)
 		/* nothing to do for read mode 'flush' */
 	}
 
-	return camel_stream_flush (priv->stream);
+	return camel_stream_flush (priv->stream, error);
 }
 
 static gint
-stream_buffer_close (CamelStream *stream)
+stream_buffer_close (CamelStream *stream,
+                     GError **error)
 {
 	CamelStreamBufferPrivate *priv;
 
 	priv = CAMEL_STREAM_BUFFER_GET_PRIVATE (stream);
 
-	if (stream_buffer_flush (stream) == -1)
+	if (stream_buffer_flush (stream, error) == -1)
 		return -1;
 
-	return camel_stream_close (priv->stream);
+	return camel_stream_close (priv->stream, error);
 }
 
 static gboolean
@@ -467,6 +473,7 @@ camel_stream_buffer_new_with_vbuf (CamelStream *stream, CamelStreamBufferMode mo
  * @sbf: a #CamelStreamBuffer object
  * @buf: Memory to write the string to.
  * @max: Maxmimum number of characters to store.
+ * @error: return location for a #GError, or %NULL
  *
  * Read a line of characters up to the next newline character or
  * @max-1 characters.
@@ -478,7 +485,10 @@ camel_stream_buffer_new_with_vbuf (CamelStream *stream, CamelStreamBufferMode mo
  * and %-1 on error.
  **/
 gint
-camel_stream_buffer_gets(CamelStreamBuffer *sbf, gchar *buf, guint max)
+camel_stream_buffer_gets (CamelStreamBuffer *sbf,
+                          gchar *buf,
+                          guint max,
+                          GError **error)
 {
 	register gchar *outptr, *inptr, *inend, c, *outend;
 	gint bytes_read;
@@ -503,7 +513,7 @@ camel_stream_buffer_gets(CamelStreamBuffer *sbf, gchar *buf, guint max)
 
 		bytes_read = camel_stream_read (
 			sbf->priv->stream, (gchar *)
-			sbf->priv->buf, sbf->priv->size);
+			sbf->priv->buf, sbf->priv->size, error);
 		if (bytes_read == -1) {
 			if (buf == outptr)
 				return -1;
@@ -523,8 +533,9 @@ camel_stream_buffer_gets(CamelStreamBuffer *sbf, gchar *buf, guint max)
 }
 
 /**
- * camel_stream_buffer_read_line: read a complete line from the stream
+ * camel_stream_buffer_read_line:
  * @sbf: a #CamelStreamBuffer object
+ * @error: return location for a #GError, or %NULL
  *
  * This function reads a complete newline-terminated line from the stream
  * and returns it in allocated memory. The trailing newline (and carriage
@@ -534,7 +545,8 @@ camel_stream_buffer_gets(CamelStreamBuffer *sbf, gchar *buf, guint max)
  * or %NULL on eof. If an error occurs, @ex will be set.
  **/
 gchar *
-camel_stream_buffer_read_line (CamelStreamBuffer *sbf)
+camel_stream_buffer_read_line (CamelStreamBuffer *sbf,
+                               GError **error)
 {
 	guchar *p;
 	gint nread;
@@ -544,7 +556,7 @@ camel_stream_buffer_read_line (CamelStreamBuffer *sbf)
 	while (1) {
 		nread = camel_stream_buffer_gets (
 			sbf, (gchar *) p, sbf->priv->linesize -
-			(p - sbf->priv->linebuf));
+			(p - sbf->priv->linebuf), error);
 		if (nread <=0) {
 			if (p > sbf->priv->linebuf)
 				break;
diff --git a/camel/camel-stream-buffer.h b/camel/camel-stream-buffer.h
index 2ccbe08..ee15f6e 100644
--- a/camel/camel-stream-buffer.h
+++ b/camel/camel-stream-buffer.h
@@ -96,8 +96,10 @@ CamelStream *	camel_stream_buffer_new_with_vbuf
 /* read a line of characters */
 gint		camel_stream_buffer_gets	(CamelStreamBuffer *sbf,
 						 gchar *buf,
-						 guint max);
-gchar *		camel_stream_buffer_read_line	(CamelStreamBuffer *sbf);
+						 guint max,
+						 GError **error);
+gchar *		camel_stream_buffer_read_line	(CamelStreamBuffer *sbf,
+						 GError **error);
 
 G_END_DECLS
 
diff --git a/camel/camel-stream-filter.c b/camel/camel-stream-filter.c
index 71f4d93..d5b6cec 100644
--- a/camel/camel-stream-filter.c
+++ b/camel/camel-stream-filter.c
@@ -90,7 +90,8 @@ stream_filter_finalize (GObject *object)
 static gssize
 stream_filter_read (CamelStream *stream,
                     gchar *buffer,
-                    gsize n)
+                    gsize n,
+                    GError **error)
 {
 	CamelStreamFilterPrivate *priv;
 	gssize size;
@@ -105,7 +106,8 @@ stream_filter_read (CamelStream *stream,
 	if (priv->filteredlen<=0) {
 		gsize presize = READ_PAD;
 
-		size = camel_stream_read(priv->source, priv->buffer, READ_SIZE);
+		size = camel_stream_read (
+			priv->source, priv->buffer, READ_SIZE, error);
 		if (size <= 0) {
 			/* this is somewhat untested */
 			if (camel_stream_eos(priv->source)) {
@@ -162,7 +164,8 @@ stream_filter_read (CamelStream *stream,
 static gssize
 stream_filter_write (CamelStream *stream,
                      const gchar *buf,
-                     gsize n)
+                     gsize n,
+                     GError **error)
 {
 	CamelStreamFilterPrivate *priv;
 	struct _filter *f;
@@ -201,7 +204,7 @@ stream_filter_write (CamelStream *stream,
 			f = f->next;
 		}
 
-		if (camel_stream_write(priv->source, buffer, len) != len)
+		if (camel_stream_write (priv->source, buffer, len, error) != len)
 			return -1;
 	}
 
@@ -211,7 +214,8 @@ stream_filter_write (CamelStream *stream,
 }
 
 static gint
-stream_filter_flush (CamelStream *stream)
+stream_filter_flush (CamelStream *stream,
+                     GError **error)
 {
 	CamelStreamFilterPrivate *priv;
 	struct _filter *f;
@@ -242,22 +246,25 @@ stream_filter_flush (CamelStream *stream)
 
 		f = f->next;
 	}
-	if (len > 0 && camel_stream_write(priv->source, buffer, len) == -1)
+
+	if (len > 0 && camel_stream_write (priv->source, buffer, len, error) == -1)
 		return -1;
-	return camel_stream_flush(priv->source);
+
+	return camel_stream_flush (priv->source, error);
 }
 
 static gint
-stream_filter_close (CamelStream *stream)
+stream_filter_close (CamelStream *stream,
+                     GError **error)
 {
 	CamelStreamFilterPrivate *priv;
 
 	priv = CAMEL_STREAM_FILTER_GET_PRIVATE (stream);
 
 	if (!priv->last_was_read)
-		stream_filter_flush(stream);
+		stream_filter_flush (stream, NULL);
 
-	return camel_stream_close(priv->source);
+	return camel_stream_close (priv->source, error);
 }
 
 static gboolean
@@ -277,7 +284,8 @@ stream_filter_eos (CamelStream *stream)
 }
 
 static gint
-stream_filter_reset (CamelStream *stream)
+stream_filter_reset (CamelStream *stream,
+                     GError **error)
 {
 	CamelStreamFilterPrivate *priv;
 	struct _filter *f;
@@ -290,11 +298,11 @@ stream_filter_reset (CamelStream *stream)
 	/* and reset filters */
 	f = priv->filters;
 	while (f) {
-		camel_mime_filter_reset(f->filter);
+		camel_mime_filter_reset (f->filter);
 		f = f->next;
 	}
 
-	return camel_stream_reset(priv->source);
+	return camel_stream_reset (priv->source, error);
 }
 
 static void
diff --git a/camel/camel-stream-fs.c b/camel/camel-stream-fs.c
index ebc3bfc..efb5cd1 100644
--- a/camel/camel-stream-fs.c
+++ b/camel/camel-stream-fs.c
@@ -32,6 +32,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <gio/gio.h>
 #include <glib/gstdio.h>
 
 #include "camel-file-utils.h"
@@ -66,7 +67,8 @@ stream_fs_finalize (GObject *object)
 static gssize
 stream_fs_read (CamelStream *stream,
                 gchar *buffer,
-                gsize n)
+                gsize n,
+                GError **error)
 {
 	CamelStreamFsPrivate *priv;
 	CamelSeekableStream *seekable;
@@ -78,7 +80,7 @@ stream_fs_read (CamelStream *stream,
 	if (seekable->bound_end != CAMEL_STREAM_UNBOUND)
 		n = MIN (seekable->bound_end - seekable->position, n);
 
-	if ((nread = camel_read (priv->fd, buffer, n)) > 0)
+	if ((nread = camel_read (priv->fd, buffer, n, error)) > 0)
 		seekable->position += nread;
 	else if (nread == 0)
 		stream->eos = TRUE;
@@ -89,7 +91,8 @@ stream_fs_read (CamelStream *stream,
 static gssize
 stream_fs_write (CamelStream *stream,
                  const gchar *buffer,
-                 gsize n)
+                 gsize n,
+                 GError **error)
 {
 	CamelStreamFsPrivate *priv;
 	CamelSeekableStream *seekable;
@@ -101,31 +104,47 @@ stream_fs_write (CamelStream *stream,
 	if (seekable->bound_end != CAMEL_STREAM_UNBOUND)
 		n = MIN (seekable->bound_end - seekable->position, n);
 
-	if ((nwritten = camel_write (priv->fd, buffer, n)) > 0)
+	if ((nwritten = camel_write (priv->fd, buffer, n, error)) > 0)
 		seekable->position += nwritten;
 
 	return nwritten;
 }
 
 static gint
-stream_fs_flush (CamelStream *stream)
+stream_fs_flush (CamelStream *stream,
+                 GError **error)
 {
 	CamelStreamFsPrivate *priv;
+	gint retval;
 
 	priv = CAMEL_STREAM_FS_GET_PRIVATE (stream);
 
-	return fsync (priv->fd);
+	retval = fsync (priv->fd);
+
+	if (retval == -1)
+		g_set_error (
+			error, G_IO_ERROR,
+			g_io_error_from_errno (errno),
+			"%s", g_strerror (errno));
+
+	return retval;
 }
 
 static gint
-stream_fs_close (CamelStream *stream)
+stream_fs_close (CamelStream *stream,
+                 GError **error)
 {
 	CamelStreamFsPrivate *priv;
 
 	priv = CAMEL_STREAM_FS_GET_PRIVATE (stream);
 
-	if (close (priv->fd) == -1)
+	if (close (priv->fd) == -1) {
+		g_set_error (
+			error, G_IO_ERROR,
+			g_io_error_from_errno (errno),
+			"%s", g_strerror (errno));
 		return -1;
+	}
 
 	priv->fd = -1;
 
@@ -135,7 +154,8 @@ stream_fs_close (CamelStream *stream)
 static off_t
 stream_fs_seek (CamelSeekableStream *stream,
                 off_t offset,
-                CamelStreamSeekPolicy policy)
+                CamelStreamSeekPolicy policy,
+                GError **error)
 {
 	CamelStreamFsPrivate *priv;
 	off_t real = 0;
@@ -156,7 +176,11 @@ stream_fs_seek (CamelSeekableStream *stream,
 				if (real<stream->bound_start)
 					real = stream->bound_start;
 				stream->position = real;
-			}
+			} else
+				g_set_error (
+					error, G_IO_ERROR,
+					g_io_error_from_errno (errno),
+					"%s", g_strerror (errno));
 			return real;
 		}
 		real = stream->bound_end + offset;
@@ -168,8 +192,13 @@ stream_fs_seek (CamelSeekableStream *stream,
 	real = MAX (real, stream->bound_start);
 
 	real = lseek(priv->fd, real, SEEK_SET);
-	if (real == -1)
+	if (real == -1) {
+		g_set_error (
+			error, G_IO_ERROR,
+			g_io_error_from_errno (errno),
+			"%s", g_strerror (errno));
 		return -1;
+	}
 
 	if (real != stream->position && ((CamelStream *)stream)->eos)
 		((CamelStream *)stream)->eos = FALSE;
@@ -279,7 +308,7 @@ camel_stream_fs_new_with_fd_and_bounds (gint fd, off_t start, off_t end)
 
 	stream = camel_stream_fs_new_with_fd (fd);
 	camel_seekable_stream_set_bounds (
-		CAMEL_SEEKABLE_STREAM (stream), start, end);
+		CAMEL_SEEKABLE_STREAM (stream), start, end, NULL);
 
 	return stream;
 }
@@ -289,6 +318,7 @@ camel_stream_fs_new_with_fd_and_bounds (gint fd, off_t start, off_t end)
  * @name: a local filename
  * @flags: flags as in open(2)
  * @mode: a file mode
+ * @error: return location for a #GError, or %NULL
  *
  * Creates a new #CamelStreamFs corresponding to the named file, flags,
  * and mode.
@@ -296,12 +326,19 @@ camel_stream_fs_new_with_fd_and_bounds (gint fd, off_t start, off_t end)
  * Returns: the new stream, or %NULL on error.
  **/
 CamelStream *
-camel_stream_fs_new_with_name (const gchar *name, gint flags, mode_t mode)
+camel_stream_fs_new_with_name (const gchar *name,
+                               gint flags,
+                               mode_t mode,
+                               GError **error)
 {
 	gint fd;
 
 	fd = g_open (name, flags|O_BINARY, mode);
 	if (fd == -1) {
+		g_set_error (
+			error, G_IO_ERROR,
+			g_io_error_from_errno (errno),
+			"%s", g_strerror (errno));
 		return NULL;
 	}
 
@@ -315,23 +352,29 @@ camel_stream_fs_new_with_name (const gchar *name, gint flags, mode_t mode)
  * @mode: a file mode
  * @start: the first valid position in the file
  * @end: the first invalid position in the file, or #CAMEL_STREAM_UNBOUND
+ * @error: return location for a #GError, or %NULL
  *
  * Creates a new CamelStream corresponding to the given arguments.
  *
  * Returns: the stream, or %NULL on error.
  **/
 CamelStream *
-camel_stream_fs_new_with_name_and_bounds (const gchar *name, gint flags,
-					  mode_t mode, off_t start, off_t end)
+camel_stream_fs_new_with_name_and_bounds (const gchar *name,
+                                          gint flags,
+                                          mode_t mode,
+                                          off_t start,
+                                          off_t end,
+                                          GError **error)
 {
 	CamelStream *stream;
 
-	stream = camel_stream_fs_new_with_name (name, flags, mode);
+	stream = camel_stream_fs_new_with_name (name, flags, mode, error);
 	if (stream == NULL)
 		return NULL;
 
-	camel_seekable_stream_set_bounds (CAMEL_SEEKABLE_STREAM (stream),
-					  start, end);
+	camel_seekable_stream_set_bounds (
+		CAMEL_SEEKABLE_STREAM (stream),
+		start, end, error);
 
 	return stream;
 }
diff --git a/camel/camel-stream-fs.h b/camel/camel-stream-fs.h
index 4223318..78b8546 100644
--- a/camel/camel-stream-fs.h
+++ b/camel/camel-stream-fs.h
@@ -72,13 +72,15 @@ struct _CamelStreamFsClass {
 GType		camel_stream_fs_get_type	(void);
 CamelStream *	camel_stream_fs_new_with_name	(const gchar *name,
 						 gint flags,
-						 mode_t mode);
+						 mode_t mode,
+						 GError **error);
 CamelStream *	camel_stream_fs_new_with_name_and_bounds
 						(const gchar *name,
 						 gint flags,
 						 mode_t mode,
 						 off_t start,
-						 off_t end);
+						 off_t end,
+						 GError **error);
 CamelStream *	camel_stream_fs_new_with_fd	(gint fd);
 CamelStream *	camel_stream_fs_new_with_fd_and_bounds
 						(gint fd,
diff --git a/camel/camel-stream-mem.c b/camel/camel-stream-mem.c
index 8b770a4..c98ada5 100644
--- a/camel/camel-stream-mem.c
+++ b/camel/camel-stream-mem.c
@@ -88,7 +88,8 @@ stream_mem_finalize (GObject *object)
 static gssize
 stream_mem_read (CamelStream *stream,
                  gchar *buffer,
-                 gsize n)
+                 gsize n,
+                 GError **error)
 {
 	CamelStreamMemPrivate *priv;
 	CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream);
@@ -112,7 +113,8 @@ stream_mem_read (CamelStream *stream,
 static gssize
 stream_mem_write (CamelStream *stream,
                   const gchar *buffer,
-                  gsize n)
+                  gsize n,
+                  GError **error)
 {
 	CamelStreamMemPrivate *priv;
 	CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream);
@@ -149,7 +151,8 @@ stream_mem_eos (CamelStream *stream)
 static off_t
 stream_mem_seek (CamelSeekableStream *stream,
                  off_t offset,
-                 CamelStreamSeekPolicy policy)
+                 CamelStreamSeekPolicy policy,
+                 GError **error)
 {
 	CamelStreamMemPrivate *priv;
 	off_t position;
diff --git a/camel/camel-stream-null.c b/camel/camel-stream-null.c
index fd6d249..e495fea 100644
--- a/camel/camel-stream-null.c
+++ b/camel/camel-stream-null.c
@@ -33,7 +33,8 @@ static gpointer parent_class;
 static gssize
 stream_null_write (CamelStream *stream,
                    const gchar *buffer,
-                   gsize n)
+                   gsize n,
+                   GError **error)
 {
 	CAMEL_STREAM_NULL (stream)->written += n;
 
@@ -47,7 +48,8 @@ stream_null_eos (CamelStream *stream)
 }
 
 static gint
-stream_null_reset (CamelStream *stream)
+stream_null_reset (CamelStream *stream,
+                   GError **error)
 {
 	CAMEL_STREAM_NULL (stream)->written = 0;
 
diff --git a/camel/camel-stream-process.c b/camel/camel-stream-process.c
index a469f02..9a54210 100644
--- a/camel/camel-stream-process.c
+++ b/camel/camel-stream-process.c
@@ -51,7 +51,7 @@ stream_process_finalize (GObject *object)
 {
 	/* Ensure we clean up after ourselves -- kill
 	   the child process and reap it. */
-	camel_stream_close (CAMEL_STREAM (object));
+	camel_stream_close (CAMEL_STREAM (object), NULL);
 
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -60,25 +60,28 @@ stream_process_finalize (GObject *object)
 static gssize
 stream_process_read (CamelStream *stream,
                      gchar *buffer,
-                     gsize n)
+                     gsize n,
+                     GError **error)
 {
 	CamelStreamProcess *stream_process = CAMEL_STREAM_PROCESS (stream);
 
-	return camel_read (stream_process->sockfd, buffer, n);
+	return camel_read (stream_process->sockfd, buffer, n, error);
 }
 
 static gssize
 stream_process_write (CamelStream *stream,
                       const gchar *buffer,
-                      gsize n)
+                      gsize n,
+                      GError **error)
 {
 	CamelStreamProcess *stream_process = CAMEL_STREAM_PROCESS (stream);
 
-	return camel_write (stream_process->sockfd, buffer, n);
+	return camel_write (stream_process->sockfd, buffer, n, error);
 }
 
 static gint
-stream_process_close (CamelStream *object)
+stream_process_close (CamelStream *object,
+                      GError **error)
 {
 	CamelStreamProcess *stream = CAMEL_STREAM_PROCESS (object);
 
@@ -127,7 +130,8 @@ stream_process_close (CamelStream *object)
 }
 
 static gint
-stream_process_flush (CamelStream *stream)
+stream_process_flush (CamelStream *stream,
+                      GError **error)
 {
 	return 0;
 }
@@ -234,12 +238,14 @@ do_exec_command (gint fd, const gchar *command, gchar **env)
 }
 
 gint
-camel_stream_process_connect (CamelStreamProcess *stream, const gchar *command, const gchar **env)
+camel_stream_process_connect (CamelStreamProcess *stream,
+                              const gchar *command,
+                              const gchar **env)
 {
 	gint sockfds[2];
 
 	if (stream->sockfd != -1 || stream->childpid)
-		camel_stream_close (CAMEL_STREAM (stream));
+		camel_stream_close (CAMEL_STREAM (stream), NULL);
 
 	if (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfds))
 		return -1;
diff --git a/camel/camel-stream-vfs.c b/camel/camel-stream-vfs.c
index c526e27..adaa0e9 100644
--- a/camel/camel-stream-vfs.c
+++ b/camel/camel-stream-vfs.c
@@ -54,24 +54,21 @@ stream_vfs_dispose (GObject *object)
 static gssize
 stream_vfs_read (CamelStream *stream,
                  gchar *buffer,
-                 gsize n)
+                 gsize n,
+                 GError **error)
 {
 	gssize nread;
-	GError *error = NULL;
 	CamelStreamVFS *stream_vfs = CAMEL_STREAM_VFS (stream);
 
 	g_return_val_if_fail (G_IS_INPUT_STREAM (stream_vfs->stream), 0);
 
-	nread = g_input_stream_read (G_INPUT_STREAM (stream_vfs->stream), buffer, n, NULL, &error);
+	nread = g_input_stream_read (
+		G_INPUT_STREAM (stream_vfs->stream),
+		buffer, n, NULL, error);
 
-	if (nread == 0 || error)
+	if (nread <= 0)
 		stream->eos = TRUE;
 
-	if (error) {
-		g_warning ("%s", error->message);
-		g_error_free (error);
-	}
-
 	return nread;
 }
 
diff --git a/camel/camel-stream.c b/camel/camel-stream.c
index f05df4a..14b2a21 100644
--- a/camel/camel-stream.c
+++ b/camel/camel-stream.c
@@ -35,7 +35,8 @@ static gpointer parent_class;
 static gssize
 stream_read (CamelStream *stream,
              gchar *buffer,
-             gsize n)
+             gsize n,
+             GError **error)
 {
 	return 0;
 }
@@ -43,19 +44,22 @@ stream_read (CamelStream *stream,
 static gssize
 stream_write (CamelStream *stream,
               const gchar *buffer,
-              gsize n)
+              gsize n,
+              GError **error)
 {
 	return n;
 }
 
 static gint
-stream_close (CamelStream *stream)
+stream_close (CamelStream *stream,
+              GError **error)
 {
 	return 0;
 }
 
 static gint
-stream_flush (CamelStream *stream)
+stream_flush (CamelStream *stream,
+              GError **error)
 {
 	return 0;
 }
@@ -67,7 +71,8 @@ stream_eos (CamelStream *stream)
 }
 
 static gint
-stream_reset (CamelStream *stream)
+stream_reset (CamelStream *stream,
+              GError **error)
 {
 	return 0;
 }
@@ -108,16 +113,17 @@ camel_stream_get_type (void)
  * @stream: a #CamelStream object.
  * @buffer: output buffer
  * @n: max number of bytes to read.
+ * @error: return location for a #GError, or %NULL
  *
  * Attempts to read up to @len bytes from @stream into @buf.
  *
- * Returns: the number of bytes actually read, or %-1 on error and set
- * errno.
+ * Returns: the number of bytes actually read, or %-1 on error
  **/
 gssize
 camel_stream_read (CamelStream *stream,
                    gchar *buffer,
-                   gsize n)
+                   gsize n,
+                   GError **error)
 {
 	CamelStreamClass *class;
 
@@ -127,7 +133,7 @@ camel_stream_read (CamelStream *stream,
 	class = CAMEL_STREAM_GET_CLASS (stream);
 	g_return_val_if_fail (class->read != NULL, -1);
 
-	return class->read (stream, buffer, n);
+	return class->read (stream, buffer, n, error);
 }
 
 /**
@@ -135,6 +141,7 @@ camel_stream_read (CamelStream *stream,
  * @stream: a #CamelStream object
  * @buffer: buffer to write.
  * @n: number of bytes to write
+ * @error: return location for a #GError, or %NULL
  *
  * Attempts to write up to @n bytes of @buffer into @stream.
  *
@@ -144,7 +151,8 @@ camel_stream_read (CamelStream *stream,
 gssize
 camel_stream_write (CamelStream *stream,
                     const gchar *buffer,
-                    gsize n)
+                    gsize n,
+                    GError **error)
 {
 	CamelStreamClass *class;
 
@@ -154,12 +162,13 @@ camel_stream_write (CamelStream *stream,
 	class = CAMEL_STREAM_GET_CLASS (stream);
 	g_return_val_if_fail (class->write != NULL, -1);
 
-	return class->write (stream, buffer, n);
+	return class->write (stream, buffer, n, error);
 }
 
 /**
  * camel_stream_flush:
  * @stream: a #CamelStream object
+ * @error: return location for a #GError, or %NULL
  *
  * Flushes any buffered data to the stream's backing store.  Only
  * meaningful for writable streams.
@@ -167,7 +176,8 @@ camel_stream_write (CamelStream *stream,
  * Returns: %0 on success or %-1 on fail along with setting errno.
  **/
 gint
-camel_stream_flush (CamelStream *stream)
+camel_stream_flush (CamelStream *stream,
+                    GError **error)
 {
 	CamelStreamClass *class;
 
@@ -176,19 +186,21 @@ camel_stream_flush (CamelStream *stream)
 	class = CAMEL_STREAM_GET_CLASS (stream);
 	g_return_val_if_fail (class->flush != NULL, -1);
 
-	return class->flush (stream);
+	return class->flush (stream, error);
 }
 
 /**
  * camel_stream_close:
  * @stream: a #CamelStream object
+ * @error: return location for a #GError, or %NULL
  *
  * Closes the stream.
  *
  * Returns: %0 on success or %-1 on error.
  **/
 gint
-camel_stream_close (CamelStream *stream)
+camel_stream_close (CamelStream *stream,
+                    GError **error)
 {
 	CamelStreamClass *class;
 
@@ -197,7 +209,7 @@ camel_stream_close (CamelStream *stream)
 	class = CAMEL_STREAM_GET_CLASS (stream);
 	g_return_val_if_fail (class->close != NULL, -1);
 
-	return class->close (stream);
+	return class->close (stream, error);
 }
 
 /**
@@ -224,15 +236,17 @@ camel_stream_eos (CamelStream *stream)
 /**
  * camel_stream_reset:
  * @stream: a #CamelStream object
+ * @error: return location for a #GError, or %NULL
  *
  * Resets the stream. That is, put it in a state where it can be read
  * from the beginning again. Not all streams in Camel are seekable,
  * but they must all be resettable.
  *
- * Returns: %0 on success or %-1 on error along with setting errno.
+ * Returns: %0 on success or %-1 on error
  **/
 gint
-camel_stream_reset (CamelStream *stream)
+camel_stream_reset (CamelStream *stream,
+                    GError **error)
 {
 	CamelStreamClass *class;
 
@@ -241,7 +255,7 @@ camel_stream_reset (CamelStream *stream)
 	class = CAMEL_STREAM_GET_CLASS (stream);
 	g_return_val_if_fail (class->reset != NULL, -1);
 
-	return class->reset (stream);
+	return class->reset (stream, error);
 }
 
 /***************** Utility functions ********************/
@@ -250,20 +264,24 @@ camel_stream_reset (CamelStream *stream)
  * camel_stream_write_string:
  * @stream: a #CamelStream object
  * @string: a string
+ * @error: return location for a #GError, or %NULL
  *
  * Writes the string to the stream.
  *
  * Returns: the number of characters written or %-1 on error.
  **/
 gssize
-camel_stream_write_string (CamelStream *stream, const gchar *string)
+camel_stream_write_string (CamelStream *stream,
+                           const gchar *string,
+                           GError **error)
 {
-	return camel_stream_write (stream, string, strlen (string));
+	return camel_stream_write (stream, string, strlen (string), error);
 }
 
 /**
  * camel_stream_printf:
  * @stream: a #CamelStream object
+ * @error: return location for a #GError, or %NULL
  * @fmt: a printf-style format string
  *
  * Write formatted output to a stream.
@@ -271,7 +289,9 @@ camel_stream_write_string (CamelStream *stream, const gchar *string)
  * Returns: the number of characters written or %-1 on error.
  **/
 gssize
-camel_stream_printf (CamelStream *stream, const gchar *fmt, ... )
+camel_stream_printf (CamelStream *stream,
+                     GError **error,
+                     const gchar *fmt, ... )
 {
 	va_list args;
 	gchar *string;
@@ -283,11 +303,9 @@ camel_stream_printf (CamelStream *stream, const gchar *fmt, ... )
 	string = g_strdup_vprintf (fmt, args);
 	va_end (args);
 
-	if (!string)
-		return -1;
-
-	ret = camel_stream_write (stream, string, strlen (string));
+	ret = camel_stream_write (stream, string, strlen (string), error);
 	g_free (string);
+
 	return ret;
 }
 
@@ -295,6 +313,7 @@ camel_stream_printf (CamelStream *stream, const gchar *fmt, ... )
  * camel_stream_write_to_stream:
  * @stream: source #CamelStream object
  * @output_stream: destination #CamelStream object
+ * @error: return location for a #GError, or %NULL
  *
  * Write all of a stream (until eos) into another stream, in a
  * blocking fashion.
@@ -303,7 +322,9 @@ camel_stream_printf (CamelStream *stream, const gchar *fmt, ... )
  * copied across streams.
  **/
 gssize
-camel_stream_write_to_stream (CamelStream *stream, CamelStream *output_stream)
+camel_stream_write_to_stream (CamelStream *stream,
+                              CamelStream *output_stream,
+                              GError **error)
 {
 	gchar tmp_buf[4096];
 	gssize total = 0;
@@ -314,15 +335,17 @@ camel_stream_write_to_stream (CamelStream *stream, CamelStream *output_stream)
 	g_return_val_if_fail (CAMEL_IS_STREAM (output_stream), -1);
 
 	while (!camel_stream_eos (stream)) {
-		nb_read = camel_stream_read (stream, tmp_buf, sizeof (tmp_buf));
+		nb_read = camel_stream_read (
+			stream, tmp_buf, sizeof (tmp_buf), error);
 		if (nb_read < 0)
 			return -1;
 		else if (nb_read > 0) {
 			nb_written = 0;
 
 			while (nb_written < nb_read) {
-				gssize len = camel_stream_write (output_stream, tmp_buf + nb_written,
-								  nb_read - nb_written);
+				gssize len = camel_stream_write (
+					output_stream, tmp_buf + nb_written,
+					nb_read - nb_written, error);
 				if (len < 0)
 					return -1;
 				nb_written += len;
diff --git a/camel/camel-stream.h b/camel/camel-stream.h
index 51d450c..03ddf0f 100644
--- a/camel/camel-stream.h
+++ b/camel/camel-stream.h
@@ -66,35 +66,54 @@ struct _CamelStream {
 struct _CamelStreamClass {
 	CamelObjectClass parent_class;
 
-	/* Virtual methods */
-
-	gssize   (*read)       (CamelStream *stream, gchar *buffer, gsize n);
-	gssize   (*write)      (CamelStream *stream, const gchar *buffer, gsize n);
-	gint       (*close)      (CamelStream *stream);
-	gint       (*flush)      (CamelStream *stream);
-	gboolean  (*eos)        (CamelStream *stream);
-	gint       (*reset)      (CamelStream *stream);
+	gssize		(*read)			(CamelStream *stream,
+					 	 gchar *buffer,
+						 gsize n,
+						 GError **error);
+	gssize		(*write)		(CamelStream *stream,
+						 const gchar *buffer,
+						 gsize n,
+						 GError **error);
+	gint		(*close)		(CamelStream *stream,
+						 GError **error);
+	gint		(*flush)		(CamelStream *stream,
+						 GError **error);
+	gboolean	(*eos)			(CamelStream *stream);
+	gint		(*reset)		(CamelStream *stream,
+						 GError **error);
 };
 
-GType camel_stream_get_type (void);
-
-/* public methods */
-gssize    camel_stream_read       (CamelStream *stream, gchar *buffer, gsize n);
-gssize    camel_stream_write      (CamelStream *stream, const gchar *buffer, gsize n);
-gint        camel_stream_flush      (CamelStream *stream);
-gint        camel_stream_close      (CamelStream *stream);
-gboolean   camel_stream_eos        (CamelStream *stream);
-gint        camel_stream_reset      (CamelStream *stream);
+GType		camel_stream_get_type		(void);
+gssize		camel_stream_read		(CamelStream *stream,
+						 gchar *buffer,
+						 gsize n,
+						 GError **error);
+gssize		camel_stream_write		(CamelStream *stream,
+						 const gchar *buffer,
+						 gsize n,
+						 GError **error);
+gint		camel_stream_flush		(CamelStream *stream,
+						 GError **error);
+gint		camel_stream_close		(CamelStream *stream,
+						 GError **error);
+gboolean	camel_stream_eos		(CamelStream *stream);
+gint		camel_stream_reset		(CamelStream *stream,
+						 GError **error);
 
 /* utility macros and funcs */
-gssize camel_stream_write_string (CamelStream *stream, const gchar *string);
-gssize camel_stream_printf (CamelStream *stream, const gchar *fmt, ... ) G_GNUC_PRINTF (2, 3);
-gssize camel_stream_vprintf (CamelStream *stream, const gchar *fmt, va_list ap);
+gssize		camel_stream_write_string	(CamelStream *stream,
+						 const gchar *string,
+						 GError **error);
+gssize		camel_stream_printf		(CamelStream *stream,
+						 GError **error,
+						 const gchar *fmt,
+						 ...) G_GNUC_PRINTF (3, 4);
 
 /* Write a whole stream to another stream, until eof or error on
- * either stream.
- */
-gssize camel_stream_write_to_stream (CamelStream *stream, CamelStream *output_stream);
+ * either stream.  */
+gssize		camel_stream_write_to_stream	(CamelStream *stream,
+						 CamelStream *output_stream,
+						 GError **error);
 
 G_END_DECLS
 
diff --git a/camel/camel-tcp-stream-raw.c b/camel/camel-tcp-stream-raw.c
index e0f649e..29e4472 100644
--- a/camel/camel-tcp-stream-raw.c
+++ b/camel/camel-tcp-stream-raw.c
@@ -32,6 +32,8 @@
 #include <sys/time.h>
 #include <sys/types.h>
 
+#include <gio/gio.h>
+
 #include "camel-file-utils.h"
 #include "camel-operation.h"
 #include "camel-tcp-stream-raw.h"
@@ -334,34 +336,43 @@ tcp_stream_raw_finalize (GObject *object)
 static gssize
 tcp_stream_raw_read (CamelStream *stream,
                      gchar *buffer,
-                     gsize n)
+                     gsize n,
+                     GError **error)
 {
 	CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
 
-	return camel_read_socket (raw->sockfd, buffer, n);
+	return camel_read_socket (raw->sockfd, buffer, n, error);
 }
 
 static gssize
 tcp_stream_raw_write (CamelStream *stream,
                       const gchar *buffer,
-                      gsize n)
+                      gsize n,
+                      GError **error)
 {
 	CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
 
-	return camel_write_socket (raw->sockfd, buffer, n);
+	return camel_write_socket (raw->sockfd, buffer, n, error);
 }
 
 static gint
-tcp_stream_raw_flush (CamelStream *stream)
+tcp_stream_raw_flush (CamelStream *stream,
+                      GError **error)
 {
 	return 0;
 }
 
 static gint
-tcp_stream_raw_close (CamelStream *stream)
+tcp_stream_raw_close (CamelStream *stream,
+                      GError **error)
 {
-	if (SOCKET_CLOSE (((CamelTcpStreamRaw *)stream)->sockfd) == -1)
+	if (SOCKET_CLOSE (((CamelTcpStreamRaw *)stream)->sockfd) == -1) {
+		g_set_error (
+			error, G_IO_ERROR,
+			g_io_error_from_errno (errno),
+			"%s", g_strerror (errno));
 		return -1;
+	}
 
 	((CamelTcpStreamRaw *)stream)->sockfd = -1;
 	return 0;
@@ -369,7 +380,8 @@ tcp_stream_raw_close (CamelStream *stream)
 
 static gint
 tcp_stream_raw_connect (CamelTcpStream *stream,
-                        struct addrinfo *host)
+                        struct addrinfo *host,
+                        GError **error)
 {
 	CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
 
diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c
index 8155cbe..204f127 100644
--- a/camel/camel-tcp-stream-ssl.c
+++ b/camel/camel-tcp-stream-ssl.c
@@ -49,6 +49,7 @@
 #include <certdb.h>
 #include <pk11func.h>
 
+#include <gio/gio.h>
 #include <glib/gi18n-lib.h>
 #include <glib/gstdio.h>
 
@@ -69,14 +70,14 @@
 
 static gpointer parent_class;
 
-static gssize stream_read (CamelStream *stream, gchar *buffer, gsize n);
-static gssize stream_write (CamelStream *stream, const gchar *buffer, gsize n);
-static gint stream_flush  (CamelStream *stream);
-static gint stream_close  (CamelStream *stream);
+static gssize stream_read (CamelStream *stream, gchar *buffer, gsize n, GError **error);
+static gssize stream_write (CamelStream *stream, const gchar *buffer, gsize n, GError **error);
+static gint stream_flush  (CamelStream *stream, GError **error);
+static gint stream_close  (CamelStream *stream, GError **error);
 
 static PRFileDesc *enable_ssl (CamelTcpStreamSSL *ssl, PRFileDesc *fd);
 
-static gint stream_connect    (CamelTcpStream *stream, struct addrinfo *host);
+static gint stream_connect    (CamelTcpStream *stream, struct addrinfo *host, GError **error);
 static gint stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
 static gint stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
 static struct sockaddr *stream_get_local_address (CamelTcpStream *stream, socklen_t *len);
@@ -343,13 +344,17 @@ camel_tcp_stream_ssl_enable_ssl (CamelTcpStreamSSL *ssl)
 }
 
 static gssize
-stream_read (CamelStream *stream, gchar *buffer, gsize n)
+stream_read (CamelStream *stream, gchar *buffer, gsize n, GError **error)
 {
 	CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream);
 	PRFileDesc *cancel_fd;
 	gssize nread;
 
 	if (camel_operation_cancel_check (NULL)) {
+		g_set_error (
+			error, G_IO_ERROR,
+			G_IO_ERROR_CANCELLED,
+			_("Cancelled read"));
 		errno = EINTR;
 		return -1;
 	}
@@ -426,13 +431,20 @@ stream_read (CamelStream *stream, gchar *buffer, gsize n)
 }
 
 static gssize
-stream_write (CamelStream *stream, const gchar *buffer, gsize n)
+stream_write (CamelStream *stream,
+              const gchar *buffer,
+              gsize n,
+              GError **error)
 {
 	CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream);
 	gssize w, written = 0;
 	PRFileDesc *cancel_fd;
 
 	if (camel_operation_cancel_check (NULL)) {
+		g_set_error (
+			error, G_IO_ERROR,
+			G_IO_ERROR_CANCELLED,
+			_("Cancelled write"));
 		errno = EINTR;
 		return -1;
 	}
@@ -514,23 +526,34 @@ stream_write (CamelStream *stream, const gchar *buffer, gsize n)
 		errno = error;
 	}
 
-	if (w == -1)
+	if (errno != 0) {
+		g_set_error (
+			error, G_IO_ERROR,
+			g_io_error_from_errno (errno),
+			"%s", g_strerror (errno));
 		return -1;
+	}
 
 	return written;
 }
 
 static gint
-stream_flush (CamelStream *stream)
+stream_flush (CamelStream *stream,
+              GError **error)
 {
 	/*return PR_Sync (((CamelTcpStreamSSL *)stream)->priv->sockfd);*/
 	return 0;
 }
 
 static gint
-stream_close (CamelStream *stream)
+stream_close (CamelStream *stream,
+              GError **error)
 {
 	if (((CamelTcpStreamSSL *)stream)->priv->sockfd == NULL) {
+		g_set_error (
+			error, G_IO_ERROR,
+			G_IO_ERROR_INVALID_ARGUMENT,
+			_("Cannot close SSL stream"));
 		errno = EINVAL;
 		return -1;
 	}
@@ -811,13 +834,16 @@ camel_certdb_nss_cert_set(CamelCertDB *certdb, CamelCert *ccert, CERTCertificate
 	path = g_strdup_printf ("%s/%s", dir, fingerprint);
 	g_free (dir);
 
-	stream = camel_stream_fs_new_with_name (path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+	stream = camel_stream_fs_new_with_name (
+		path, O_WRONLY | O_CREAT | O_TRUNC, 0600, NULL);
 	if (stream != NULL) {
-		if (camel_stream_write (stream, (const gchar *) ccert->rawcert->data, ccert->rawcert->len) == -1) {
+		if (camel_stream_write (
+			stream, (const gchar *) ccert->rawcert->data,
+			ccert->rawcert->len, NULL) == -1) {
 			g_warning ("Could not save cert: %s: %s", path, g_strerror (errno));
 			g_unlink (path);
 		}
-		camel_stream_close (stream);
+		camel_stream_close (stream, NULL);
 		g_object_unref (stream);
 	} else {
 		g_warning ("Could not save cert: %s: %s", path, g_strerror (errno));
@@ -1230,7 +1256,9 @@ socket_connect(CamelTcpStream *stream, struct addrinfo *host)
 }
 
 static gint
-stream_connect(CamelTcpStream *stream, struct addrinfo *host)
+stream_connect (CamelTcpStream *stream,
+                struct addrinfo *host,
+                GError **error)
 {
 	while (host) {
 		if (socket_connect(stream, host) == 0)
diff --git a/camel/camel-tcp-stream.c b/camel/camel-tcp-stream.c
index a6c726d..2943f69 100644
--- a/camel/camel-tcp-stream.c
+++ b/camel/camel-tcp-stream.c
@@ -61,6 +61,7 @@ camel_tcp_stream_get_type (void)
  * @stream: a #CamelTcpStream object
  * @host: a linked list of addrinfo structures to try to connect, in
  * the order of most likely to least likely to work.
+ * @error: return location for a #GError, or %NULL
  *
  * Create a socket and connect based upon the data provided.
  *
@@ -68,7 +69,8 @@ camel_tcp_stream_get_type (void)
  **/
 gint
 camel_tcp_stream_connect (CamelTcpStream *stream,
-                          struct addrinfo *host)
+                          struct addrinfo *host,
+                          GError **error)
 {
 	CamelTcpStreamClass *class;
 
@@ -77,7 +79,7 @@ camel_tcp_stream_connect (CamelTcpStream *stream,
 	class = CAMEL_TCP_STREAM_GET_CLASS (stream);
 	g_return_val_if_fail (class->connect != NULL, -1);
 
-	return class->connect (stream, host);
+	return class->connect (stream, host, error);
 }
 
 /**
diff --git a/camel/camel-tcp-stream.h b/camel/camel-tcp-stream.h
index 778c61d..f4ffddc 100644
--- a/camel/camel-tcp-stream.h
+++ b/camel/camel-tcp-stream.h
@@ -116,24 +116,38 @@ struct _CamelTcpStream {
 struct _CamelTcpStreamClass {
 	CamelStreamClass parent_class;
 
-	/* Virtual methods */
-	gint (*connect)    (CamelTcpStream *stream, struct addrinfo *host);
-	gint (*getsockopt) (CamelTcpStream *stream, CamelSockOptData *data);
-	gint (*setsockopt) (CamelTcpStream *stream, const CamelSockOptData *data);
-
-	struct sockaddr * (*get_local_address)  (CamelTcpStream *stream, socklen_t *len);
-	struct sockaddr * (*get_remote_address) (CamelTcpStream *stream, socklen_t *len);
+	gint		(*connect)		(CamelTcpStream *stream,
+						 struct addrinfo *host,
+						 GError **error);
+	gint		(*getsockopt)		(CamelTcpStream *stream,
+						 CamelSockOptData *data);
+	gint		(*setsockopt)		(CamelTcpStream *stream,
+						 const CamelSockOptData *data);
+
+	struct sockaddr *
+			(*get_local_address)	(CamelTcpStream *stream,
+						 socklen_t *len);
+	struct sockaddr *
+			(*get_remote_address)	(CamelTcpStream *stream,
+						 socklen_t *len);
 };
 
-GType camel_tcp_stream_get_type (void);
-
-/* public methods */
-gint         camel_tcp_stream_connect    (CamelTcpStream *stream, struct addrinfo *host);
-gint         camel_tcp_stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
-gint         camel_tcp_stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
-
-struct sockaddr *camel_tcp_stream_get_local_address  (CamelTcpStream *stream, socklen_t *len);
-struct sockaddr *camel_tcp_stream_get_remote_address (CamelTcpStream *stream, socklen_t *len);
+GType		camel_tcp_stream_get_type	(void);
+gint		camel_tcp_stream_connect	(CamelTcpStream *stream,
+						 struct addrinfo *host,
+						 GError **error);
+gint		camel_tcp_stream_getsockopt	(CamelTcpStream *stream,
+						 CamelSockOptData *data);
+gint		camel_tcp_stream_setsockopt	(CamelTcpStream *stream,
+						 const CamelSockOptData *data);
+struct sockaddr *
+		camel_tcp_stream_get_local_address
+						(CamelTcpStream *stream,
+						 socklen_t *len);
+struct sockaddr *
+		camel_tcp_stream_get_remote_address
+						(CamelTcpStream *stream,
+						 socklen_t *len);
 
 G_END_DECLS
 
diff --git a/camel/camel-text-index.c b/camel/camel-text-index.c
index 8b3ae22..0bb6210 100644
--- a/camel/camel-text-index.c
+++ b/camel/camel-text-index.c
@@ -34,6 +34,7 @@
 #include <sys/types.h>
 
 #include <glib/gstdio.h>
+#include <glib/gi18n-lib.h>
 
 #include <libedataserver/e-memory.h>
 
@@ -58,7 +59,7 @@
 #define CAMEL_TEXT_INDEX_UNLOCK(kf, lock) \
 	(g_static_rec_mutex_unlock (&((CamelTextIndex *)kf)->priv->lock))
 
-static gint text_index_compress_nosync (CamelIndex *idx);
+static gint text_index_compress_nosync (CamelIndex *idx, GError **error);
 
 /* ********************************************************************** */
 
@@ -181,7 +182,7 @@ text_index_dispose (GObject *object)
 
 	/* Only run this the first time. */
 	if (priv->word_index != NULL)
-		camel_index_sync (CAMEL_INDEX (object));
+		camel_index_sync (CAMEL_INDEX (object), NULL);
 
 	if (priv->word_index != NULL) {
 		g_object_unref (priv->word_index);
@@ -236,8 +237,11 @@ text_index_finalize (GObject *object)
 }
 
 /* call locked */
-static void
-text_index_add_name_to_word (CamelIndex *idx, const gchar *word, camel_key_t nameid)
+static gboolean
+text_index_add_name_to_word (CamelIndex *idx,
+                             const gchar *word,
+                             camel_key_t nameid,
+                             GError **error)
 {
 	struct _CamelTextIndexWord *w, *wp, *ww;
 	CamelTextIndexPrivate *p = CAMEL_TEXT_INDEX_GET_PRIVATE (idx);
@@ -247,28 +251,34 @@ text_index_add_name_to_word (CamelIndex *idx, const gchar *word, camel_key_t nam
 
 	w = g_hash_table_lookup (p->words, word);
 	if (w == NULL) {
-		wordid = camel_partition_table_lookup (p->word_hash, word);
+		wordid = camel_partition_table_lookup (p->word_hash, word, NULL);
 		if (wordid == 0) {
 			data = 0;
-			wordid = camel_key_table_add (p->word_index, word, 0, 0);
+			wordid = camel_key_table_add (
+				p->word_index, word, 0, 0, error);
 			if (wordid == 0) {
-				g_warning ("Could not create key entry for word '%s': %s\n",
-					   word, g_strerror (errno));
-				return;
+				g_prefix_error (
+					error, _("Could not create key "
+					"entry for word '%s': "), word);
+				return FALSE;
 			}
-			if (camel_partition_table_add (p->word_hash, word, wordid) == -1) {
-				g_warning ("Could not create hash entry for word '%s': %s\n",
-					   word, g_strerror (errno));
-				return;
+			if (camel_partition_table_add (
+				p->word_hash, word, wordid, error) == -1) {
+				g_prefix_error (
+					error, _("Could not create hash "
+					"entry for word '%s': "), word);
+				return FALSE;
 			}
 			rb->words++;
 			camel_block_file_touch_block (p->blocks, p->blocks->root_block);
 		} else {
-			data = camel_key_table_lookup (p->word_index, wordid, NULL, NULL);
+			data = camel_key_table_lookup (
+				p->word_index, wordid, NULL, NULL, error);
 			if (data == 0) {
-				g_warning ("Could not find key entry for word '%s': %s\n",
-					   word, g_strerror (errno));
-				return;
+				g_prefix_error (
+					error, _("Could not find key "
+					"entry for word '%s': "), word);
+				return FALSE;
 			}
 		}
 
@@ -291,7 +301,9 @@ text_index_add_name_to_word (CamelIndex *idx, const gchar *word, camel_key_t nam
 				rb->keys++;
 				camel_block_file_touch_block (p->blocks, p->blocks->root_block);
 				/* if this call fails - we still point to the old data - not fatal */
-				camel_key_table_set_data (p->word_index, ww->wordid, ww->data);
+				camel_key_table_set_data (
+					p->word_index, ww->wordid,
+					ww->data, NULL);
 				camel_dlist_remove ((CamelDListNode *)ww);
 				g_hash_table_remove (p->words, ww->word);
 				g_free (ww->word);
@@ -312,16 +324,21 @@ text_index_add_name_to_word (CamelIndex *idx, const gchar *word, camel_key_t nam
 				rb->keys++;
 				camel_block_file_touch_block (p->blocks, p->blocks->root_block);
 				/* if this call fails - we still point to the old data - not fatal */
-				camel_key_table_set_data (p->word_index, w->wordid, w->data);
+				camel_key_table_set_data (
+					p->word_index, w->wordid,
+					w->data, NULL);
 			}
 			/* FIXME: what to on error?  lost data? */
 			w->used = 0;
 		}
 	}
+
+	return TRUE;
 }
 
 static gint
-text_index_sync (CamelIndex *idx)
+text_index_sync (CamelIndex *idx,
+                 GError **error)
 {
 	CamelTextIndexPrivate *p = CAMEL_TEXT_INDEX_GET_PRIVATE (idx);
 	struct _CamelTextIndexWord *ww;
@@ -355,7 +372,9 @@ text_index_sync (CamelIndex *idx)
 				io (printf ("  new data [%x]\n", ww->data));
 				rb->keys++;
 				camel_block_file_touch_block (p->blocks, p->blocks->root_block);
-				camel_key_table_set_data (p->word_index, ww->wordid, ww->data);
+				camel_key_table_set_data (
+					p->word_index, ww->wordid,
+					ww->data, NULL);
 			} else {
 				ret = -1;
 			}
@@ -380,10 +399,11 @@ text_index_sync (CamelIndex *idx)
 
 	if (ret == 0) {
 		if (wfrag > 30 || nfrag > 20)
-			ret = text_index_compress_nosync (idx);
+			ret = text_index_compress_nosync (idx, error);
 	}
 
-	ret = camel_block_file_sync (p->blocks);
+	if (ret == 0)
+		ret = camel_block_file_sync (p->blocks);
 
 	CAMEL_TEXT_INDEX_UNLOCK (idx, lock);
 
@@ -405,15 +425,16 @@ static void tmp_name (const gchar *in, gchar *o)
 }
 
 static gint
-text_index_compress (CamelIndex *idx)
+text_index_compress (CamelIndex *idx,
+                     GError **error)
 {
 	gint ret;
 
 	CAMEL_TEXT_INDEX_LOCK (idx, lock);
 
-	ret = camel_index_sync (idx);
+	ret = camel_index_sync (idx, error);
 	if (ret != -1)
-		ret = text_index_compress_nosync (idx);
+		ret = text_index_compress_nosync (idx, error);
 
 	CAMEL_TEXT_INDEX_UNLOCK (idx, lock);
 
@@ -422,7 +443,8 @@ text_index_compress (CamelIndex *idx)
 
 /* Attempt to recover index space by compressing the indices */
 static gint
-text_index_compress_nosync (CamelIndex *idx)
+text_index_compress_nosync (CamelIndex *idx,
+                            GError **error)
 {
 	CamelTextIndex *newidx;
 	CamelTextIndexPrivate *newp, *oldp;
@@ -454,7 +476,7 @@ text_index_compress_nosync (CamelIndex *idx)
 	d (printf ("New: %s\n", newpath));
 	d (printf ("Save: %s\n", savepath));
 
-	newidx = camel_text_index_new (newpath, O_RDWR|O_CREAT);
+	newidx = camel_text_index_new (newpath, O_RDWR|O_CREAT, error);
 	if (newidx == NULL)
 		return -1;
 
@@ -483,14 +505,16 @@ text_index_compress_nosync (CamelIndex *idx)
 	remap = g_hash_table_new (NULL, NULL);
 	oldkeyid = 0;
 	deleted = 0;
-	while ( (oldkeyid = camel_key_table_next (oldp->name_index, oldkeyid, &name, &flags, &data)) ) {
+	while ( (oldkeyid = camel_key_table_next (oldp->name_index, oldkeyid, &name, &flags, &data, NULL)) ) {
 		if ((flags&1) == 0) {
 			io (printf ("copying name '%s'\n", name));
-			newkeyid = camel_key_table_add (newp->name_index, name, data, flags);
+			newkeyid = camel_key_table_add (
+				newp->name_index, name, data, flags, error);
 			if (newkeyid == 0)
 				goto fail;
 			rb->names++;
-			camel_partition_table_add (newp->name_hash, name, newkeyid);
+			camel_partition_table_add (
+				newp->name_hash, name, newkeyid, NULL);
 			g_hash_table_insert (remap, GINT_TO_POINTER (oldkeyid), GINT_TO_POINTER (newkeyid));
 		} else {
 			io (printf ("deleted name '%s'\n", name));
@@ -504,7 +528,7 @@ text_index_compress_nosync (CamelIndex *idx)
 	/* We re-block the data into 256 entry lots while we're at it, since we only
 	   have to do 1 at a time and its cheap */
 	oldkeyid = 0;
-	while ( (oldkeyid = camel_key_table_next (oldp->word_index, oldkeyid, &name, &flags, &data)) ) {
+	while ( (oldkeyid = camel_key_table_next (oldp->word_index, oldkeyid, &name, &flags, &data, NULL)) ) {
 		io (printf ("copying word '%s'\n", name));
 		newdata = 0;
 		newcount = 0;
@@ -539,10 +563,12 @@ text_index_compress_nosync (CamelIndex *idx)
 		}
 
 		if (newdata != 0) {
-			newkeyid = camel_key_table_add (newp->word_index, name, newdata, flags);
+			newkeyid = camel_key_table_add (
+				newp->word_index, name, newdata, flags, error);
 			if (newkeyid == 0)
 				goto fail;
-			camel_partition_table_add (newp->word_hash, name, newkeyid);
+			camel_partition_table_add (
+				newp->word_hash, name, newkeyid, NULL);
 		}
 		g_free (name);
 		name = NULL;
@@ -550,7 +576,7 @@ text_index_compress_nosync (CamelIndex *idx)
 
 	camel_block_file_touch_block (newp->blocks, newp->blocks->root_block);
 
-	if (camel_index_sync ((CamelIndex *)newidx) == -1)
+	if (camel_index_sync (CAMEL_INDEX (newidx), error) == -1)
 		goto fail;
 
 	/* Rename underlying files to match */
@@ -648,7 +674,7 @@ text_index_has_name (CamelIndex *idx, const gchar *name)
 {
 	CamelTextIndexPrivate *p = CAMEL_TEXT_INDEX_GET_PRIVATE (idx);
 
-	return camel_partition_table_lookup (p->name_hash, name) != 0;
+	return camel_partition_table_lookup (p->name_hash, name, NULL) != 0;
 }
 
 static CamelIndexName *
@@ -668,18 +694,18 @@ text_index_add_name (CamelIndex *idx, const gchar *name)
 	}
 
 	/* If we have it already replace it */
-	keyid = camel_partition_table_lookup (p->name_hash, name);
+	keyid = camel_partition_table_lookup (p->name_hash, name, NULL);
 	if (keyid != 0) {
 		/* TODO: We could just update the partition table's
 		   key pointer rather than having to delete it */
 		rb->deleted++;
-		camel_key_table_set_flags (p->name_index, keyid, 1, 1);
-		camel_partition_table_remove (p->name_hash, name);
+		camel_key_table_set_flags (p->name_index, keyid, 1, 1, NULL);
+		camel_partition_table_remove (p->name_hash, name, NULL);
 	}
 
-	keyid = camel_key_table_add (p->name_index, name, 0, 0);
+	keyid = camel_key_table_add (p->name_index, name, 0, 0, NULL);
 	if (keyid != 0) {
-		camel_partition_table_add (p->name_hash, name, keyid);
+		camel_partition_table_add (p->name_hash, name, keyid, NULL);
 		rb->names++;
 	}
 
@@ -701,7 +727,7 @@ hash_write_word (gchar *word, gpointer data, CamelIndexName *idn)
 {
 	CamelTextIndexName *tin = (CamelTextIndexName *)idn;
 
-	text_index_add_name_to_word (idn->index, word, tin->priv->nameid);
+	text_index_add_name_to_word (idn->index, word, tin->priv->nameid, NULL);
 }
 
 static gint
@@ -742,12 +768,12 @@ text_index_delete_name (CamelIndex *idx, const gchar *name)
 	CAMEL_TEXT_INDEX_LOCK (idx, lock);
 
 	/* We just mark the key deleted, and remove it from the hash table */
-	keyid = camel_partition_table_lookup (p->name_hash, name);
+	keyid = camel_partition_table_lookup (p->name_hash, name, NULL);
 	if (keyid != 0) {
 		rb->deleted++;
 		camel_block_file_touch_block (p->blocks, p->blocks->root_block);
-		camel_key_table_set_flags (p->name_index, keyid, 1, 1);
-		camel_partition_table_remove (p->name_hash, name);
+		camel_key_table_set_flags (p->name_index, keyid, 1, 1, NULL);
+		camel_partition_table_remove (p->name_hash, name, NULL);
 	}
 
 	CAMEL_TEXT_INDEX_UNLOCK (idx, lock);
@@ -764,9 +790,10 @@ text_index_find (CamelIndex *idx, const gchar *word)
 
 	CAMEL_TEXT_INDEX_LOCK (idx, lock);
 
-	keyid = camel_partition_table_lookup (p->word_hash, word);
+	keyid = camel_partition_table_lookup (p->word_hash, word, NULL);
 	if (keyid != 0) {
-		data = camel_key_table_lookup (p->word_index, keyid, NULL, &flags);
+		data = camel_key_table_lookup (
+			p->word_index, keyid, NULL, &flags, NULL);
 		if (flags & 1)
 			data = 0;
 	}
@@ -870,7 +897,9 @@ text_index_normalise (CamelIndex *idx, const gchar *in, gpointer data)
 }
 
 CamelTextIndex *
-camel_text_index_new (const gchar *path, gint flags)
+camel_text_index_new (const gchar *path,
+                      gint flags,
+                      GError **error)
 {
 	CamelTextIndex *idx = g_object_new (CAMEL_TYPE_TEXT_INDEX, NULL);
 	CamelTextIndexPrivate *p = CAMEL_TEXT_INDEX_GET_PRIVATE (idx);
@@ -881,18 +910,23 @@ camel_text_index_new (const gchar *path, gint flags)
 	camel_index_construct ((CamelIndex *)idx, path, flags);
 	camel_index_set_normalise ((CamelIndex *)idx, text_index_normalise, NULL);
 
-	p->blocks = camel_block_file_new (idx->parent.path, flags, CAMEL_TEXT_INDEX_VERSION, CAMEL_BLOCK_SIZE);
+	p->blocks = camel_block_file_new (
+		idx->parent.path, flags, CAMEL_TEXT_INDEX_VERSION,
+		CAMEL_BLOCK_SIZE, error);
+	if (p->blocks == NULL)
+		goto fail;
+
 	link = alloca (strlen (idx->parent.path)+7);
 	sprintf (link, "%s.data", idx->parent.path);
 	p->links = camel_key_file_new (link, flags, CAMEL_TEXT_INDEX_KEY_VERSION);
 
-	if (p->blocks == NULL || p->links == NULL)
+	if (p->links == NULL)
 		goto fail;
 
 	rb = (struct _CamelTextIndexRoot *)p->blocks->root;
 
 	if (rb->word_index_root == 0) {
-		bl = camel_block_file_new_block (p->blocks);
+		bl = camel_block_file_new_block (p->blocks, error);
 
 		if (bl == NULL)
 			goto fail;
@@ -903,7 +937,7 @@ camel_text_index_new (const gchar *path, gint flags)
 	}
 
 	if (rb->word_hash_root == 0) {
-		bl = camel_block_file_new_block (p->blocks);
+		bl = camel_block_file_new_block (p->blocks, error);
 
 		if (bl == NULL)
 			goto fail;
@@ -914,7 +948,7 @@ camel_text_index_new (const gchar *path, gint flags)
 	}
 
 	if (rb->name_index_root == 0) {
-		bl = camel_block_file_new_block (p->blocks);
+		bl = camel_block_file_new_block (p->blocks, error);
 
 		if (bl == NULL)
 			goto fail;
@@ -925,7 +959,7 @@ camel_text_index_new (const gchar *path, gint flags)
 	}
 
 	if (rb->name_hash_root == 0) {
-		bl = camel_block_file_new_block (p->blocks);
+		bl = camel_block_file_new_block (p->blocks, error);
 
 		if (bl == NULL)
 			goto fail;
@@ -935,16 +969,25 @@ camel_text_index_new (const gchar *path, gint flags)
 		camel_block_file_touch_block (p->blocks, p->blocks->root_block);
 	}
 
-	p->word_index = camel_key_table_new (p->blocks, rb->word_index_root);
-	p->word_hash = camel_partition_table_new (p->blocks, rb->word_hash_root);
-	p->name_index = camel_key_table_new (p->blocks, rb->name_index_root);
-	p->name_hash = camel_partition_table_new (p->blocks, rb->name_hash_root);
+	p->word_index = camel_key_table_new (
+		p->blocks, rb->word_index_root, error);
+	if (p->word_index == NULL)
+		goto fail;
 
-	if (p->word_index == NULL || p->word_hash == NULL
-	    || p->name_index == NULL || p->name_hash == NULL) {
-		g_object_unref (idx);
-		idx = NULL;
-	}
+	p->word_hash = camel_partition_table_new (
+		p->blocks, rb->word_hash_root, error);
+	if (p->word_hash == NULL)
+		goto fail;
+
+	p->name_index = camel_key_table_new (
+		p->blocks, rb->name_index_root, error);
+	if (p->name_index == NULL)
+		goto fail;
+
+	p->name_hash = camel_partition_table_new (
+		p->blocks, rb->name_hash_root, NULL);
+	if (p->name_hash == NULL)
+		goto fail;
 
 	return idx;
 
@@ -955,7 +998,8 @@ fail:
 
 /* returns 0 if the index exists, is valid, and synced, -1 otherwise */
 gint
-camel_text_index_check (const gchar *path)
+camel_text_index_check (const gchar *path,
+                        GError **error)
 {
 	gchar *block, *key;
 	CamelBlockFile *blocks;
@@ -963,11 +1007,11 @@ camel_text_index_check (const gchar *path)
 
 	block = alloca (strlen (path)+7);
 	sprintf (block, "%s.index", path);
-	blocks = camel_block_file_new (block, O_RDONLY, CAMEL_TEXT_INDEX_VERSION, CAMEL_BLOCK_SIZE);
-	if (blocks == NULL) {
-		io (printf ("Check failed: No block file: %s\n", g_strerror (errno)));
+	blocks = camel_block_file_new (
+		block, O_RDONLY, CAMEL_TEXT_INDEX_VERSION,
+		CAMEL_BLOCK_SIZE, error);
+	if (blocks == NULL)
 		return -1;
-	}
 	key = alloca (strlen (path)+12);
 	sprintf (key, "%s.index.data", path);
 	keys = camel_key_file_new (key, O_RDONLY, CAMEL_TEXT_INDEX_KEY_VERSION);
@@ -1251,7 +1295,7 @@ camel_text_index_dump (CamelTextIndex *idx)
 	printf ("UID's in index\n");
 
 	keyid = 0;
-	while ( (keyid = camel_key_table_next (p->name_index, keyid, &word, &flags, &data)) ) {
+	while ( (keyid = camel_key_table_next (p->name_index, keyid, &word, &flags, &data, NULL)) ) {
 		if ((flags & 1) == 0)
 			printf (" %s\n", word);
 		else
@@ -1262,7 +1306,7 @@ camel_text_index_dump (CamelTextIndex *idx)
 	printf ("Word's in index\n");
 
 	keyid = 0;
-	while ( (keyid = camel_key_table_next (p->word_index, keyid, &word, &flags, &data)) ) {
+	while ( (keyid = camel_key_table_next (p->word_index, keyid, &word, &flags, &data, NULL)) ) {
 		CamelIndexCursor *idc;
 
 		printf ("Word: '%s':\n", word);
@@ -1324,7 +1368,7 @@ camel_text_index_validate (CamelTextIndex *idx)
 	printf ("Checking UID consistency\n");
 
 	keyid = 0;
-	while ( (keyid = camel_key_table_next (p->name_index, keyid, &word, &flags, &data)) ) {
+	while ( (keyid = camel_key_table_next (p->name_index, keyid, &word, &flags, &data, NULL)) ) {
 		if ((oldword = g_hash_table_lookup (names, GINT_TO_POINTER (keyid))) != NULL
 		    || (oldword = g_hash_table_lookup (deleted, GINT_TO_POINTER (keyid))) != NULL) {
 			printf ("Warning, name '%s' duplicates key (%x) with name '%s'\n", word, keyid, oldword);
@@ -1342,7 +1386,7 @@ camel_text_index_validate (CamelTextIndex *idx)
 	printf ("Checking WORD member consistency\n");
 
 	keyid = 0;
-	while ( (keyid = camel_key_table_next (p->word_index, keyid, &word, &flags, &data)) ) {
+	while ( (keyid = camel_key_table_next (p->word_index, keyid, &word, &flags, &data, NULL)) ) {
 		CamelIndexCursor *idc;
 		GHashTable *used;
 
@@ -1660,7 +1704,9 @@ text_index_cursor_next (CamelIndexCursor *idc)
 		}
 
 		g_free (p->current);
-		camel_key_table_lookup (tip->name_index, p->records[p->record_index], &p->current, &flags);
+		camel_key_table_lookup (
+			tip->name_index, p->records[p->record_index],
+			&p->current, &flags, NULL);
 		if (flags & 1) {
 			g_free (p->current);
 			p->current = NULL;
@@ -1790,7 +1836,7 @@ text_index_key_cursor_next (CamelIndexCursor *idc)
 	g_free (p->current);
 	p->current = NULL;
 
-	while ( (p->keyid = camel_key_table_next (p->table, p->keyid, &p->current, &p->flags, &p->data)) ) {
+	while ( (p->keyid = camel_key_table_next (p->table, p->keyid, &p->current, &p->flags, &p->data, NULL)) ) {
 		if ((p->flags & 1) == 0) {
 			return p->current;
 		} else {
diff --git a/camel/camel-text-index.h b/camel/camel-text-index.h
index 75da888..b8952e9 100644
--- a/camel/camel-text-index.h
+++ b/camel/camel-text-index.h
@@ -172,17 +172,21 @@ struct _CamelTextIndexClass {
 	CamelIndexClass parent_class;
 };
 
-GType           camel_text_index_get_type	(void);
-CamelTextIndex    *camel_text_index_new(const gchar *path, gint flags);
+GType		camel_text_index_get_type	(void);
+CamelTextIndex *camel_text_index_new		(const gchar *path,
+						 gint flags,
+						 GError **error);
 
 /* static utility functions */
-gint camel_text_index_check(const gchar *path);
-gint camel_text_index_rename(const gchar *old, const gchar *new);
-gint camel_text_index_remove(const gchar *old);
-
-void camel_text_index_dump(CamelTextIndex *idx);
-void camel_text_index_info(CamelTextIndex *idx);
-void camel_text_index_validate(CamelTextIndex *idx);
+gint		camel_text_index_check		(const gchar *path,
+						 GError **error);
+gint		camel_text_index_rename		(const gchar *old,
+						 const gchar *new);
+gint		camel_text_index_remove		(const gchar *old);
+
+void		camel_text_index_dump		(CamelTextIndex *idx);
+void		camel_text_index_info		(CamelTextIndex *idx);
+void		camel_text_index_validate	(CamelTextIndex *idx);
 
 G_END_DECLS
 
diff --git a/camel/camel-uid-cache.c b/camel/camel-uid-cache.c
index 0a5c5a5..8880f0a 100644
--- a/camel/camel-uid-cache.c
+++ b/camel/camel-uid-cache.c
@@ -81,7 +81,7 @@ camel_uid_cache_new (const gchar *filename)
 
 	buf = g_malloc (st.st_size + 1);
 
-	if (st.st_size > 0 && camel_read (fd, buf, st.st_size) == -1) {
+	if (st.st_size > 0 && camel_read (fd, buf, st.st_size, NULL) == -1) {
 		close (fd);
 		g_free (buf);
 		return NULL;
@@ -126,8 +126,8 @@ maybe_write_uid (gpointer key, gpointer value, gpointer data)
 		return;
 
 	if (state && state->level == cache->level && state->save) {
-		if (camel_write (cache->fd, key, strlen (key)) == -1 ||
-		    camel_write (cache->fd, "\n", 1) == -1) {
+		if (camel_write (cache->fd, key, strlen (key), NULL) == -1 ||
+		    camel_write (cache->fd, "\n", 1, NULL) == -1) {
 			cache->fd = -1;
 		} else {
 			cache->size += strlen (key) + 1;
diff --git a/camel/providers/groupwise/camel-groupwise-folder.c b/camel/providers/groupwise/camel-groupwise-folder.c
index c5e30f4..5e5ee80 100644
--- a/camel/providers/groupwise/camel-groupwise-folder.c
+++ b/camel/providers/groupwise/camel-groupwise-folder.c
@@ -140,10 +140,10 @@ groupwise_folder_get_message( CamelFolder *folder, const gchar *uid, GError **er
 	stream = camel_stream_mem_new ();
 	if (cache_stream) {
 		msg = camel_mime_message_new ();
-		camel_stream_reset (stream);
-		camel_stream_write_to_stream (cache_stream, stream);
-		camel_stream_reset (stream);
-		if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) msg, stream) == -1) {
+		camel_stream_reset (stream, NULL);
+		camel_stream_write_to_stream (cache_stream, stream, NULL);
+		camel_stream_reset (stream, NULL);
+		if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) msg, stream, NULL) == -1) {
 			if (errno == EINTR) {
 				g_set_error (
 					error, CAMEL_ERROR,
@@ -230,8 +230,8 @@ groupwise_folder_get_message( CamelFolder *folder, const gchar *uid, GError **er
 	/* add to cache */
 	CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
 	if ((cache_stream = camel_data_cache_add (gw_folder->cache, "cache", uid, NULL))) {
-		if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) msg, cache_stream) == -1
-				|| camel_stream_flush (cache_stream) == -1)
+		if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) msg, cache_stream, error) == -1
+				|| camel_stream_flush (cache_stream, error) == -1)
 			camel_data_cache_remove (gw_folder->cache, "cache", uid, NULL);
 		g_object_unref (cache_stream);
 	}
@@ -1721,7 +1721,7 @@ gw_update_cache (CamelFolder *folder, GList *list, GError **error, gboolean uid_
 
 						CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
 						if ((cache_stream = camel_data_cache_add (gw_folder->cache, "cache", id, NULL))) {
-								if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) mail_msg,	cache_stream) == -1 || camel_stream_flush (cache_stream) == -1)
+								if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) mail_msg,	cache_stream, error) == -1 || camel_stream_flush (cache_stream, error) == -1)
 										camel_data_cache_remove (gw_folder->cache, "cache", id, NULL);
 								g_object_unref (cache_stream);
 						}
@@ -2063,7 +2063,7 @@ groupwise_folder_item_to_msg( CamelFolder *folder,
 	msg = camel_mime_message_new ();
 	if (has_mime_822 && body) {
 		temp_stream = camel_stream_mem_new_with_buffer (body, body_len);
-		if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) msg, temp_stream) == -1) {
+		if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) msg, temp_stream, error) == -1) {
 			g_object_unref (msg);
 			g_object_unref (temp_stream);
 			msg = NULL;
diff --git a/camel/providers/groupwise/camel-groupwise-journal.c b/camel/providers/groupwise/camel-groupwise-journal.c
index 0aff116..29520db 100644
--- a/camel/providers/groupwise/camel-groupwise-journal.c
+++ b/camel/providers/groupwise/camel-groupwise-journal.c
@@ -185,7 +185,7 @@ groupwise_entry_play_append (CamelOfflineJournal *journal, CamelGroupwiseJournal
 		goto done;
 
 	message = camel_mime_message_new ();
-	if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream) == -1) {
+	if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream, error) == -1) {
 		g_object_unref (message);
 		g_object_unref (stream);
 		goto done;
@@ -327,13 +327,10 @@ update_cache (CamelGroupwiseJournal *groupwise_journal, CamelMimeMessage *messag
 		return FALSE;
 	}
 
-	if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) message, cache) == -1
-	    || camel_stream_flush (cache) == -1) {
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Cannot append message in offline mode: %s"),
-			g_strerror (errno));
+	if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) message, cache, error) == -1
+	    || camel_stream_flush (cache, error) == -1) {
+		g_prefix_error (
+			error, _("Cannot append message in offline mode: "));
 		camel_data_cache_remove (groupwise_folder->cache, "cache", uid, NULL);
 		folder->summary->nextuid--;
 		g_object_unref (cache);
diff --git a/camel/providers/groupwise/camel-groupwise-utils.c b/camel/providers/groupwise/camel-groupwise-utils.c
index 01e7a6b..2765924 100644
--- a/camel/providers/groupwise/camel-groupwise-utils.c
+++ b/camel/providers/groupwise/camel-groupwise-utils.c
@@ -445,14 +445,14 @@ camel_groupwise_util_item_from_message (EGwConnection *cnc, CamelMimeMessage *me
 				g_object_ref (content);
 			}
 
-			camel_data_wrapper_decode_to_stream (dw, filtered_stream);
-			camel_stream_flush (filtered_stream);
+			camel_data_wrapper_decode_to_stream (dw, filtered_stream, NULL);
+			camel_stream_flush (filtered_stream, NULL);
 			g_object_unref (filtered_stream);
 
-			camel_stream_write (content, "", 1);
+			camel_stream_write (content, "", 1, NULL);
 			e_gw_item_set_message (item, (const gchar *)buffer->data);
 		} else {
-			camel_data_wrapper_decode_to_stream (dw, (CamelStream *) content);
+			camel_data_wrapper_decode_to_stream (dw, (CamelStream *) content, NULL);
 			send_as_attachment (cnc, item, content, type, dw, NULL, NULL, &attach_list);
 		}
 
@@ -649,7 +649,7 @@ do_multipart (EGwConnection *cnc, EGwItem *item, CamelMultipart *mp, GSList **at
 			if (temp_part) {
 				is_alternative = TRUE;
 				temp_dw = camel_medium_get_content (CAMEL_MEDIUM (temp_part));
-				camel_data_wrapper_write_to_stream(temp_dw, temp_content);
+				camel_data_wrapper_write_to_stream(temp_dw, temp_content, NULL);
 				filename = camel_mime_part_get_filename (temp_part);
 				disposition = camel_mime_part_get_disposition (temp_part);
 				cid = camel_mime_part_get_content_id (temp_part);
@@ -681,18 +681,18 @@ do_multipart (EGwConnection *cnc, EGwItem *item, CamelMultipart *mp, GSList **at
 				g_object_ref (content);
 			}
 
-			camel_data_wrapper_decode_to_stream (dw, filtered_stream);
-			camel_stream_flush (filtered_stream);
+			camel_data_wrapper_decode_to_stream (dw, filtered_stream, NULL);
+			camel_stream_flush (filtered_stream, NULL);
 			g_object_unref (filtered_stream);
 
-			camel_stream_write (content, "", 1);
+			camel_stream_write (content, "", 1, NULL);
 			e_gw_item_set_message (item, (const gchar *)buffer->data);
 		} else {
 			filename = camel_mime_part_get_filename (part);
 			disposition = camel_mime_part_get_disposition (part);
 			content_id = camel_mime_part_get_content_id (part);
 
-			camel_data_wrapper_decode_to_stream (dw, content);
+			camel_data_wrapper_decode_to_stream (dw, content, NULL);
 			send_as_attachment (cnc, item, content, type, dw, filename, content_id, attach_list);
 		}
 
diff --git a/camel/providers/imap/camel-imap-command.c b/camel/providers/imap/camel-imap-command.c
index ccb14fd..22141be 100644
--- a/camel/providers/imap/camel-imap-command.c
+++ b/camel/providers/imap/camel-imap-command.c
@@ -229,21 +229,11 @@ imap_command_start (CamelImapStore *store,
 		fprintf (stderr, "sending : %c%.5u %s\r\n", store->tag_prefix, store->command, mask);
 	}
 
-	nwritten = camel_stream_printf (store->ostream, "%c%.5u %s\r\n",
-					store->tag_prefix, store->command++, cmd);
+	nwritten = camel_stream_printf (
+		store->ostream, error, "%c%.5u %s\r\n",
+		store->tag_prefix, store->command++, cmd);
 
 	if (nwritten == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("Operation cancelled"));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				"%s", g_strerror (errno));
-
 		camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
 		return FALSE;
 	}
@@ -256,7 +246,7 @@ imap_command_start (CamelImapStore *store,
  * @store: the IMAP store
  * @cmd: buffer containing the response/request data
  * @cmdlen: command length
- * @ex: a CamelException
+ * @error: return location for a #GError, or %NULL
  *
  * This method is for sending continuing responses to the IMAP server
  * after camel_imap_command() or camel_imap_command_response() returns
@@ -292,18 +282,13 @@ camel_imap_command_continuation (CamelImapStore *store,
 		return NULL;
 	}
 
-	if (camel_stream_write (store->ostream, cmd, cmdlen) == -1 ||
-	    camel_stream_write (store->ostream, "\r\n", 2) == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("Operation cancelled"));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				"%s", g_strerror (errno));
+	if (camel_stream_write (store->ostream, cmd, cmdlen, error) == -1) {
+		camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
+		CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
+		return NULL;
+	}
+
+	if (camel_stream_write (store->ostream, "\r\n", 2, error) == -1) {
 		camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
 		CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
 		return NULL;
@@ -516,17 +501,11 @@ imap_read_untagged (CamelImapStore *store, gchar *line, GError **error)
 		nread = 0;
 
 		do {
-			if ((n = camel_stream_read (store->istream, str->str + nread + 1, length - nread)) == -1) {
-				if (errno == EINTR)
-					g_set_error (
-						error, CAMEL_ERROR,
-						CAMEL_ERROR_USER_CANCEL,
-						_("Operation cancelled"));
-				else
-					g_set_error (
-						error, CAMEL_SERVICE_ERROR,
-						CAMEL_SERVICE_ERROR_UNAVAILABLE,
-						"%s", g_strerror (errno));
+			n = camel_stream_read (
+				store->istream,
+				str->str + nread + 1,
+				length - nread, error);
+			if (n == -1) {
 				camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
 				g_string_free (str, TRUE);
 				goto lose;
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index 35c1e7a..1e9570c 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -1993,12 +1993,13 @@ do_append (CamelFolder *folder,
 	camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (memstream), ba);
 
 	streamfilter = camel_stream_filter_new (memstream);
-	crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE,
-						  CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
+	crlf_filter = camel_mime_filter_crlf_new (
+		CAMEL_MIME_FILTER_CRLF_ENCODE,
+		CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
 	camel_stream_filter_add (
 		CAMEL_STREAM_FILTER (streamfilter), crlf_filter);
 	camel_data_wrapper_write_to_stream (
-		CAMEL_DATA_WRAPPER (message), streamfilter);
+		CAMEL_DATA_WRAPPER (message), streamfilter, NULL);
 	g_object_unref (streamfilter);
 	g_object_unref (crlf_filter);
 	g_object_unref (memstream);
@@ -2798,7 +2799,8 @@ get_content (CamelImapFolder *imap_folder, const gchar *uid,
 
 		stream = camel_imap_folder_fetch_data (imap_folder, uid, spec, FALSE, error);
 		if (stream) {
-			ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (body_mp), stream);
+			ret = camel_data_wrapper_construct_from_stream (
+				CAMEL_DATA_WRAPPER (body_mp), stream, error);
 			g_object_unref (CAMEL_OBJECT (stream));
 			if (ret == -1) {
 				g_object_unref ( body_mp);
@@ -2839,7 +2841,8 @@ get_content (CamelImapFolder *imap_folder, const gchar *uid,
 				gint ret;
 
 				part = camel_mime_part_new ();
-				ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (part), stream);
+				ret = camel_data_wrapper_construct_from_stream (
+					CAMEL_DATA_WRAPPER (part), stream, error);
 				g_object_unref (CAMEL_OBJECT (stream));
 				if (ret == -1) {
 					g_object_unref (CAMEL_OBJECT (part));
@@ -2935,7 +2938,8 @@ get_message (CamelImapFolder *imap_folder, const gchar *uid,
 		return NULL;
 
 	msg = camel_mime_message_new ();
-	ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream);
+	ret = camel_data_wrapper_construct_from_stream (
+		CAMEL_DATA_WRAPPER (msg), stream, error);
 	g_object_unref (CAMEL_OBJECT (stream));
 	if (ret == -1) {
 		g_object_unref (CAMEL_OBJECT (msg));
@@ -2981,15 +2985,11 @@ get_message_simple (CamelImapFolder *imap_folder, const gchar *uid,
 	}
 
 	msg = camel_mime_message_new ();
-	ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg),
-							stream);
+	ret = camel_data_wrapper_construct_from_stream (
+		CAMEL_DATA_WRAPPER (msg), stream, error);
 	g_object_unref (CAMEL_OBJECT (stream));
 	if (ret == -1) {
-		g_set_error (
-			error, CAMEL_SERVICE_ERROR,
-			CAMEL_SERVICE_ERROR_UNAVAILABLE,
-			_("Unable to retrieve message: %s"),
-			g_strerror (errno));
+		g_prefix_error (error, _("Unable to retrieve message: "));
 		g_object_unref (CAMEL_OBJECT (msg));
 		return NULL;
 	}
@@ -3386,7 +3386,8 @@ add_message_from_data (CamelFolder *folder, GPtrArray *messages,
 		g_ptr_array_set_size (messages, seq - first + 1);
 
 	msg = camel_mime_message_new ();
-	if (camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream) == -1) {
+	if (camel_data_wrapper_construct_from_stream (
+		CAMEL_DATA_WRAPPER (msg), stream, NULL) == -1) {
 		g_object_unref (CAMEL_OBJECT (msg));
 		return;
 	}
diff --git a/camel/providers/imap/camel-imap-message-cache.c b/camel/providers/imap/camel-imap-message-cache.c
index c714c7d..f200ec3 100644
--- a/camel/providers/imap/camel-imap-message-cache.c
+++ b/camel/providers/imap/camel-imap-message-cache.c
@@ -356,11 +356,14 @@ insert_abort (gchar *path, CamelStream *stream)
 }
 
 static CamelStream *
-insert_finish (CamelImapMessageCache *cache, const gchar *uid, gchar *path,
-	       gchar *key, CamelStream *stream)
+insert_finish (CamelImapMessageCache *cache,
+               const gchar *uid,
+               gchar *path,
+               gchar *key,
+               CamelStream *stream)
 {
-	camel_stream_flush (stream);
-	camel_stream_reset (stream);
+	camel_stream_flush (stream, NULL);
+	camel_stream_reset (stream, NULL);
 	cache_put (cache, uid, key, stream);
 	g_free (path);
 
@@ -395,12 +398,9 @@ camel_imap_message_cache_insert (CamelImapMessageCache *cache,
 	if (!stream)
 		return NULL;
 
-	if (camel_stream_write (stream, data, len) == -1) {
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Failed to cache message %s: %s"),
-			uid, g_strerror (errno));
+	if (camel_stream_write (stream, data, len, error) == -1) {
+		g_prefix_error (
+			error, _("Failed to cache message %s: "), uid);
 		return insert_abort (path, stream);
 	}
 
@@ -430,12 +430,9 @@ camel_imap_message_cache_insert_stream (CamelImapMessageCache *cache,
 	if (!stream)
 		return;
 
-	if (camel_stream_write_to_stream (data_stream, stream) == -1) {
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Failed to cache message %s: %s"),
-			uid, g_strerror (errno));
+	if (camel_stream_write_to_stream (data_stream, stream, error) == -1) {
+		g_prefix_error (
+			error, _("Failed to cache message %s: "), uid);
 		insert_abort (path, stream);
 	} else {
 		insert_finish (cache, uid, path, key, stream);
@@ -466,12 +463,9 @@ camel_imap_message_cache_insert_wrapper (CamelImapMessageCache *cache,
 	if (!stream)
 		return;
 
-	if (camel_data_wrapper_write_to_stream (wrapper, stream) == -1) {
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Failed to cache message %s: %s"),
-			uid, g_strerror (errno));
+	if (camel_data_wrapper_write_to_stream (wrapper, stream, error) == -1) {
+		g_prefix_error (
+			error, _("Failed to cache message %s: "), uid);
 		insert_abort (path, stream);
 	} else {
 		insert_finish (cache, uid, path, key, stream);
@@ -539,22 +533,17 @@ camel_imap_message_cache_get (CamelImapMessageCache *cache, const gchar *uid,
 
 	stream = g_hash_table_lookup (cache->parts, key);
 	if (stream) {
-		camel_stream_reset (CAMEL_STREAM (stream));
-		g_object_ref (CAMEL_OBJECT (stream));
+		camel_stream_reset (CAMEL_STREAM (stream), NULL);
+		g_object_ref (stream);
 		g_free (path);
 		return stream;
 	}
 
-	stream = camel_stream_fs_new_with_name (path, O_RDONLY, 0);
-	if (stream) {
+	stream = camel_stream_fs_new_with_name (path, O_RDONLY, 0, error);
+	if (stream)
 		cache_put (cache, uid, key, stream);
-	} else {
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Failed to cache %s: %s"),
-			part_spec, g_strerror (errno));
-	}
+	else
+		g_prefix_error (error, _("Failed to cache %s: "), part_spec);
 
 	g_free (path);
 
diff --git a/camel/providers/imap/camel-imap-search.c b/camel/providers/imap/camel-imap-search.c
index f84df81..b49f2ab 100644
--- a/camel/providers/imap/camel-imap-search.c
+++ b/camel/providers/imap/camel-imap-search.c
@@ -265,10 +265,10 @@ save_match(CamelImapSearch *is, struct _match_record *mr)
 	header.lastuid = mr->lastuid;
 	header.validity = mr->validity;
 
-	if (camel_stream_write(stream, (gchar *)&header, sizeof(header)) != sizeof(header)
-	    || camel_stream_write(stream, mr->matches->data, mr->matches->len*sizeof(guint32)) != mr->matches->len*sizeof(guint32)
-	    || camel_seekable_stream_seek((CamelSeekableStream *)stream, 0, CAMEL_STREAM_SET) == -1
-	    || camel_stream_write(stream, (gchar *)&mark, sizeof(mark)) != sizeof(mark)) {
+	if (camel_stream_write(stream, (gchar *)&header, sizeof(header), NULL) != sizeof(header)
+	    || camel_stream_write(stream, mr->matches->data, mr->matches->len*sizeof(guint32), NULL) != mr->matches->len*sizeof(guint32)
+	    || camel_seekable_stream_seek((CamelSeekableStream *)stream, 0, CAMEL_STREAM_SET, NULL) == -1
+	    || camel_stream_write(stream, (gchar *)&mark, sizeof(mark), NULL) != sizeof(mark)) {
 		d(printf(" saving failed, removing cache entry\n"));
 		camel_data_cache_remove(is->cache, "search/body-contains", mr->hash, NULL);
 		ret = -1;
@@ -309,13 +309,13 @@ load_match(CamelImapSearch *is, gchar hash[17], gint argc, struct _ESExpResult *
 		   should be sufficient to key it */
 		/* This check should also handle endianness changes, we just throw away
 		   the data (its only a cache) */
-		if (camel_stream_read(stream, (gchar *)&header, sizeof(header)) == sizeof(header)
+		if (camel_stream_read(stream, (gchar *)&header, sizeof(header), NULL) == sizeof(header)
 		    && header.validity == is->validity
 		    && header.mark == MATCH_MARK
 		    && header.termcount == 0) {
 			d(printf(" found %d matches\n", header.matchcount));
 			g_array_set_size(mr->matches, header.matchcount);
-			camel_stream_read(stream, mr->matches->data, sizeof(guint32)*header.matchcount);
+			camel_stream_read(stream, mr->matches->data, sizeof(guint32)*header.matchcount, NULL);
 		} else {
 			d(printf(" file format invalid/validity changed\n"));
 			memset(&header, 0, sizeof(header));
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index e0d83c9..1c38beb 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -557,7 +557,9 @@ connect_to_server (CamelService *service, struct addrinfo *ai, gint ssl_mode, GE
 		else
 			tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS);
 #else
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+		g_set_error (
+			error, CAMEL_SERVICE_ERROR,
+			CAMEL_SERVICE_ERROR_UNAVAILABLE,
 			_("Could not connect to %s: %s"),
 			service->url->host, _("SSL unavailable"));
 
@@ -567,20 +569,11 @@ connect_to_server (CamelService *service, struct addrinfo *ai, gint ssl_mode, GE
 	} else
 		tcp_stream = camel_tcp_stream_raw_new ();
 
-	if (camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai) == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR, CAMEL_ERROR_USER_CANCEL,
-				_("Connection cancelled"));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("Could not connect to %s: %s"),
-				service->url->host, g_strerror (errno));
-
+	if (camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai, error) == -1) {
+		g_prefix_error (
+			error, _("Could not connect to %s: "),
+			service->url->host);
 		g_object_unref (tcp_stream);
-
 		return FALSE;
 	}
 
@@ -1605,13 +1598,13 @@ imap_disconnect (CamelService *service, gboolean clean, GError **error)
 	}
 
 	if (store->istream) {
-		camel_stream_close(store->istream);
+		camel_stream_close(store->istream, NULL);
 		g_object_unref (store->istream);
 		store->istream = NULL;
 	}
 
 	if (store->ostream) {
-		camel_stream_close(store->ostream);
+		camel_stream_close(store->ostream, NULL);
 		g_object_unref (store->ostream);
 		store->ostream = NULL;
 	}
@@ -3156,7 +3149,7 @@ camel_imap_store_readline (CamelImapStore *store, gchar **dest, GError **error)
 	stream = CAMEL_STREAM_BUFFER (store->istream);
 
 	ba = g_byte_array_new ();
-	while ((nread = camel_stream_buffer_gets (stream, linebuf, sizeof (linebuf))) > 0) {
+	while ((nread = camel_stream_buffer_gets (stream, linebuf, sizeof (linebuf), NULL)) > 0) {
 		g_byte_array_append (ba, (const guint8 *) linebuf, nread);
 		if (linebuf[nread - 1] == '\n')
 			break;
diff --git a/camel/providers/imap/camel-imap-wrapper.c b/camel/providers/imap/camel-imap-wrapper.c
index 8674390..26550fd 100644
--- a/camel/providers/imap/camel-imap-wrapper.c
+++ b/camel/providers/imap/camel-imap-wrapper.c
@@ -44,7 +44,23 @@ struct _CamelImapWrapperPrivate {
 
 static gpointer parent_class;
 
-static gssize write_to_stream (CamelDataWrapper *imap_wrapper, CamelStream *stream);
+static void
+imap_wrapper_hydrate (CamelImapWrapper *imap_wrapper,
+                      CamelStream *stream)
+{
+	CamelDataWrapper *data_wrapper = (CamelDataWrapper *) imap_wrapper;
+
+	g_object_ref (stream);
+	data_wrapper->stream = stream;
+	data_wrapper->offline = FALSE;
+
+	g_object_unref (imap_wrapper->folder);
+	imap_wrapper->folder = NULL;
+	g_free (imap_wrapper->uid);
+	imap_wrapper->uid = NULL;
+	g_free (imap_wrapper->part_spec);
+	imap_wrapper->part_spec = NULL;
+}
 
 static void
 imap_wrapper_dispose (GObject *object)
@@ -74,6 +90,40 @@ imap_wrapper_finalize (GObject *object)
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static gssize
+imap_wrapper_write_to_stream (CamelDataWrapper *data_wrapper,
+                              CamelStream *stream,
+                              GError **error)
+{
+	CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (data_wrapper);
+
+	CAMEL_IMAP_WRAPPER_LOCK (imap_wrapper, lock);
+	if (data_wrapper->offline) {
+		CamelStream *datastream;
+
+		datastream = camel_imap_folder_fetch_data (
+			imap_wrapper->folder, imap_wrapper->uid,
+			imap_wrapper->part_spec, FALSE, NULL);
+		if (!datastream) {
+			CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock);
+#ifdef ENETUNREACH
+			errno = ENETUNREACH;
+#else
+/* FIXME[disk-summary] what errno to use if no ENETUNREACH */
+			errno = EINVAL;
+#endif
+			return -1;
+		}
+
+		imap_wrapper_hydrate (imap_wrapper, datastream);
+		g_object_unref (datastream);
+	}
+	CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock);
+
+	return CAMEL_DATA_WRAPPER_CLASS (parent_class)->
+		write_to_stream (data_wrapper, stream, error);
+}
+
 static void
 imap_wrapper_class_init (CamelImapWrapperClass *class)
 {
@@ -88,7 +138,7 @@ imap_wrapper_class_init (CamelImapWrapperClass *class)
 	object_class->finalize = imap_wrapper_finalize;
 
 	data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (class);
-	data_wrapper_class->write_to_stream = write_to_stream;
+	data_wrapper_class->write_to_stream = imap_wrapper_write_to_stream;
 }
 
 static void
@@ -116,55 +166,6 @@ camel_imap_wrapper_get_type (void)
 	return type;
 }
 
-static void
-imap_wrapper_hydrate (CamelImapWrapper *imap_wrapper, CamelStream *stream)
-{
-	CamelDataWrapper *data_wrapper = (CamelDataWrapper *) imap_wrapper;
-
-	g_object_ref (stream);
-	data_wrapper->stream = stream;
-	data_wrapper->offline = FALSE;
-
-	g_object_unref (imap_wrapper->folder);
-	imap_wrapper->folder = NULL;
-	g_free (imap_wrapper->uid);
-	imap_wrapper->uid = NULL;
-	g_free (imap_wrapper->part_spec);
-	imap_wrapper->part_spec = NULL;
-}
-
-static gssize
-write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
-{
-	CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (data_wrapper);
-
-	CAMEL_IMAP_WRAPPER_LOCK (imap_wrapper, lock);
-	if (data_wrapper->offline) {
-		CamelStream *datastream;
-
-		datastream = camel_imap_folder_fetch_data (
-			imap_wrapper->folder, imap_wrapper->uid,
-			imap_wrapper->part_spec, FALSE, NULL);
-		if (!datastream) {
-			CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock);
-#ifdef ENETUNREACH
-			errno = ENETUNREACH;
-#else
-/* FIXME[disk-summary] what errno to use if no ENETUNREACH */
-			errno = EINVAL;
-#endif
-			return -1;
-		}
-
-		imap_wrapper_hydrate (imap_wrapper, datastream);
-		g_object_unref (datastream);
-	}
-	CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock);
-
-	return CAMEL_DATA_WRAPPER_CLASS (parent_class)->
-		write_to_stream (data_wrapper, stream);
-}
-
 CamelDataWrapper *
 camel_imap_wrapper_new (CamelImapFolder *imap_folder,
 			CamelContentType *type, CamelTransferEncoding encoding,
diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c
index a4a4772..54b10c5 100644
--- a/camel/providers/local/camel-local-folder.c
+++ b/camel/providers/local/camel-local-folder.c
@@ -282,14 +282,14 @@ camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, con
 	/* FIXME: Need to run indexing off of the setv method */
 
 	/* if we have no/invalid index file, force it */
-	forceindex = camel_text_index_check(lf->index_path) == -1;
+	forceindex = camel_text_index_check(lf->index_path, NULL) == -1;
 	if (lf->flags & CAMEL_STORE_FOLDER_BODY_INDEX) {
 		gint flag = O_RDWR|O_CREAT;
 
 		if (forceindex)
 			flag |= O_TRUNC;
 
-		lf->index = (CamelIndex *)camel_text_index_new(lf->index_path, flag);
+		lf->index = (CamelIndex *)camel_text_index_new(lf->index_path, flag, NULL);
 		if (lf->index == NULL) {
 			/* yes, this isn't fatal at all */
 			g_warning("Could not open/create index file: %s: indexing not performed", g_strerror (errno));
diff --git a/camel/providers/local/camel-local-summary.c b/camel/providers/local/camel-local-summary.c
index 1553021..88ae044 100644
--- a/camel/providers/local/camel-local-summary.c
+++ b/camel/providers/local/camel-local-summary.c
@@ -458,18 +458,24 @@ local_summary_sync (CamelLocalSummary *cls,
                     CamelFolderChangeInfo *changeinfo,
                     GError **error)
 {
-	gint ret = 0;
+	CamelFolderSummary *folder_summary;
 
-	ret = camel_folder_summary_save_to_db ((CamelFolderSummary *)cls, error);
-	if (ret == -1) {
-		g_warning ("Could not save summary for local providers");
-		return -1;
-	}
+	folder_summary = CAMEL_FOLDER_SUMMARY (cls);
 
-	if (cls->index && camel_index_sync(cls->index) == -1)
-		g_warning ("Could not sync index for %s: %s", cls->folder_path, g_strerror (errno));
+	if (camel_folder_summary_save_to_db (folder_summary, error) == -1)
+		goto error;
 
-	return ret;
+	if (cls->index && camel_index_sync(cls->index, error) == -1)
+		goto error;
+
+	return 0;
+
+error:
+	g_prefix_error (
+		error, _("Could not sync index for %s: "),
+		cls->folder_path);
+
+	return -1;
 }
 
 static gint
@@ -547,7 +553,7 @@ local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMess
 		if (mi->info.size == 0) {
 			CamelStreamNull *sn = (CamelStreamNull *)camel_stream_null_new();
 
-			camel_data_wrapper_write_to_stream((CamelDataWrapper *)msg, (CamelStream *)sn);
+			camel_data_wrapper_write_to_stream((CamelDataWrapper *)msg, (CamelStream *)sn, NULL);
 			mi->info.size = sn->written;
 			g_object_unref (sn);
 		}
diff --git a/camel/providers/local/camel-maildir-folder.c b/camel/providers/local/camel-maildir-folder.c
index fe5f826..8b734f9 100644
--- a/camel/providers/local/camel-maildir-folder.c
+++ b/camel/providers/local/camel-maildir-folder.c
@@ -194,12 +194,13 @@ maildir_append_message (CamelFolder *folder,
 
 	/* write it out to tmp, use the uid we got from the summary */
 	name = g_strdup_printf ("%s/tmp/%s", lf->folder_path, camel_message_info_uid(mi));
-	output_stream = camel_stream_fs_new_with_name (name, O_WRONLY|O_CREAT, 0600);
+	output_stream = camel_stream_fs_new_with_name (
+		name, O_WRONLY|O_CREAT, 0600, error);
 	if (output_stream == NULL)
 		goto fail_write;
 
-	if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, output_stream) == -1
-	    || camel_stream_close (output_stream) == -1)
+	if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, output_stream, error) == -1
+	    || camel_stream_close (output_stream, error) == -1)
 		goto fail_write;
 
 	/* now move from tmp to cur (bypass new, does it matter?) */
@@ -316,29 +317,18 @@ maildir_get_message (CamelFolder *folder,
 
 	camel_message_info_free(info);
 
-	if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0)) == NULL) {
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Cannot get message: %s from folder %s\n  %s"),
-			uid, lf->folder_path, g_strerror(errno));
+	if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0, error)) == NULL) {
+		g_prefix_error (
+			error, _("Cannot get message: %s from "
+			"folder %s\n  "), uid, lf->folder_path);
 		goto fail;
 	}
 
 	message = camel_mime_message_new();
-	if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, message_stream) == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("Cannot get message: %s from folder %s\n  %s"),
-				uid, lf->folder_path, _("Invalid message contents"));
-		else
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_SYSTEM,
-				_("Cannot get message: %s from folder %s\n  %s"),
-				uid, lf->folder_path, _("Invalid message contents"));
+	if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, message_stream, error) == -1) {
+		g_prefix_error (
+			error, _("Cannot get message: %s from "
+			"folder %s\n  "), uid, lf->folder_path);
 		g_object_unref (message);
 		message = NULL;
 
diff --git a/camel/providers/local/camel-mbox-folder.c b/camel/providers/local/camel-mbox-folder.c
index fdcd87b..d1723cb 100644
--- a/camel/providers/local/camel-mbox-folder.c
+++ b/camel/providers/local/camel-mbox-folder.c
@@ -200,13 +200,13 @@ mbox_append_message (CamelFolder *folder,
 	if ((camel_message_info_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) && !camel_mime_message_has_attachment (message))
 		camel_message_info_set_flags (mi, CAMEL_MESSAGE_ATTACHMENTS, 0);
 
-	output_stream = camel_stream_fs_new_with_name(lf->folder_path, O_WRONLY | O_APPEND | O_LARGEFILE, 0666);
+	output_stream = camel_stream_fs_new_with_name (
+		lf->folder_path, O_WRONLY | O_APPEND |
+		O_LARGEFILE, 0666, error);
 	if (output_stream == NULL) {
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Cannot open mailbox: %s: %s\n"),
-			lf->folder_path, g_strerror (errno));
+		g_prefix_error (
+			error, _("Cannot open mailbox: %s"),
+			lf->folder_path);
 		goto fail;
 	}
 
@@ -224,7 +224,7 @@ mbox_append_message (CamelFolder *folder,
 
 	/* we must write this to the non-filtered stream ... */
 	fromline = camel_mime_message_build_mbox_from(message);
-	if (camel_stream_write(output_stream, fromline, strlen(fromline)) == -1)
+	if (camel_stream_write(output_stream, fromline, strlen(fromline), error) == -1)
 		goto fail_write;
 
 	/* and write the content to the filtering stream, that translates '\nFrom' into '\n>From' */
@@ -233,9 +233,9 @@ mbox_append_message (CamelFolder *folder,
 	camel_stream_filter_add((CamelStreamFilter *) filter_stream, filter_from);
 	g_object_unref (filter_from);
 
-	if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) message, filter_stream) == -1 ||
-	    camel_stream_write (filter_stream, "\n", 1) == -1 ||
-	    camel_stream_flush (filter_stream) == -1)
+	if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) message, filter_stream, error) == -1 ||
+	    camel_stream_write (filter_stream, "\n", 1, error) == -1 ||
+	    camel_stream_flush (filter_stream, error) == -1)
 		goto fail_write;
 
 	/* filter stream ref's the output stream itself, so we need to unref it too */
@@ -269,17 +269,9 @@ mbox_append_message (CamelFolder *folder,
 	return TRUE;
 
 fail_write:
-	if (errno == EINTR)
-		g_set_error (
-			error, CAMEL_ERROR,
-			CAMEL_ERROR_USER_CANCEL,
-			_("Mail append canceled"));
-	else
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Cannot append message to mbox file: %s: %s"),
-			lf->folder_path, g_strerror (errno));
+	g_prefix_error (
+		error, _("Cannot append message to mbox file: %s"),
+		lf->folder_path);
 
 	if (output_stream) {
 		gint fd;
@@ -464,21 +456,12 @@ retry:
 	}
 
 	message = camel_mime_message_new();
-	if (camel_mime_part_construct_from_parser((CamelMimePart *)message, parser) == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("Cannot get message: %s from folder %s\n  %s"),
-				uid, lf->folder_path,
-				_("Message construction failed."));
-		else
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_SYSTEM,
-				_("Cannot get message: %s from folder %s\n  %s"),
-				uid, lf->folder_path,
-				_("Message construction failed."));
+	if (camel_mime_part_construct_from_parser((CamelMimePart *)message, parser, error) == -1) {
+		g_set_error (
+			error, CAMEL_ERROR,
+			CAMEL_ERROR_USER_CANCEL,
+			_("Cannot get message: %s from folder %s\n  "),
+			uid, lf->folder_path);
 		g_object_unref (message);
 		message = NULL;
 		goto fail;
diff --git a/camel/providers/local/camel-mh-folder.c b/camel/providers/local/camel-mh-folder.c
index 5129d8d..1b5756f 100644
--- a/camel/providers/local/camel-mh-folder.c
+++ b/camel/providers/local/camel-mh-folder.c
@@ -142,12 +142,13 @@ mh_append_message (CamelFolder *folder,
 
 	/* write it out, use the uid we got from the summary */
 	name = g_strdup_printf("%s/%s", lf->folder_path, camel_message_info_uid(mi));
-	output_stream = camel_stream_fs_new_with_name(name, O_WRONLY|O_CREAT, 0600);
+	output_stream = camel_stream_fs_new_with_name (
+		name, O_WRONLY|O_CREAT, 0600, error);
 	if (output_stream == NULL)
 		goto fail_write;
 
-	if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, output_stream) == -1
-	    || camel_stream_close (output_stream) == -1)
+	if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, output_stream, error) == -1
+	    || camel_stream_close (output_stream, error) == -1)
 		goto fail_write;
 
 	/* close this? */
@@ -236,23 +237,18 @@ mh_get_message (CamelFolder *folder,
 	camel_message_info_free(info);
 
 	name = g_strdup_printf("%s/%s", lf->folder_path, uid);
-	if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0)) == NULL) {
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Cannot get message: %s from folder %s\n  %s"),
-			name, lf->folder_path, g_strerror (errno));
+	if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0, error)) == NULL) {
+		g_prefix_error (
+			error, _("Cannot get message: %s from "
+			"folder %s\n  "), name, lf->folder_path);
 		goto fail;
 	}
 
 	message = camel_mime_message_new();
-	if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, message_stream) == -1) {
-		g_set_error (
-			error, CAMEL_ERROR,
-			CAMEL_ERROR_SYSTEM,
-			_("Cannot get message: %s from folder %s\n  %s"),
-			name, lf->folder_path,
-			_("Message construction failed."));
+	if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, message_stream, error) == -1) {
+		g_prefix_error (
+			error, _("Cannot get message: %s from "
+			"folder %s\n  "), name, lf->folder_path);
 		g_object_unref (message);
 		message = NULL;
 
diff --git a/camel/providers/local/camel-mh-store.c b/camel/providers/local/camel-mh-store.c
index f0d16dc..ec8f750 100644
--- a/camel/providers/local/camel-mh-store.c
+++ b/camel/providers/local/camel-mh-store.c
@@ -125,24 +125,25 @@ folders_update (const gchar *root,
 	tmpnew = g_alloca (strlen (root) + 16);
 	sprintf (tmpnew, "%s.folders~", root);
 
-	out = camel_stream_fs_new_with_name(tmpnew, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+	out = camel_stream_fs_new_with_name (
+		tmpnew, O_WRONLY|O_CREAT|O_TRUNC, 0666, NULL);
 	if (out == NULL)
 		goto fail;
 
 	tmp = g_alloca (strlen (root) + 16);
 	sprintf (tmp, "%s.folders", root);
-	stream = camel_stream_fs_new_with_name(tmp, O_RDONLY, 0);
+	stream = camel_stream_fs_new_with_name (tmp, O_RDONLY, 0, NULL);
 	if (stream) {
 		in = camel_stream_buffer_new(stream, CAMEL_STREAM_BUFFER_READ);
 		g_object_unref (stream);
 	}
 	if (in == NULL || stream == NULL) {
-		if (mode == UPDATE_ADD && camel_stream_printf(out, "%s\n", folder) == -1)
+		if (mode == UPDATE_ADD && camel_stream_printf (out, NULL, "%s\n", folder) == -1)
 			goto fail;
 		goto done;
 	}
 
-	while ((line = camel_stream_buffer_read_line((CamelStreamBuffer *)in))) {
+	while ((line = camel_stream_buffer_read_line((CamelStreamBuffer *)in, NULL))) {
 		gint copy = TRUE;
 
 		switch (mode) {
@@ -153,9 +154,9 @@ folders_update (const gchar *root,
 		case UPDATE_RENAME:
 			if (strncmp(line, folder, flen) == 0
 			    && (line[flen] == 0 || line[flen] == '/')) {
-				if (camel_stream_write(out, new, strlen(new)) == -1
-				    || camel_stream_write(out, line+flen, strlen(line)-flen) == -1
-				    || camel_stream_write(out, "\n", 1) == -1)
+				if (camel_stream_write(out, new, strlen(new), NULL) == -1
+				    || camel_stream_write(out, line+flen, strlen(line)-flen, NULL) == -1
+				    || camel_stream_write(out, "\n", 1, NULL) == -1)
 					goto fail;
 				copy = FALSE;
 			}
@@ -165,7 +166,7 @@ folders_update (const gchar *root,
 
 			if (cmp > 0) {
 				/* found insertion point */
-				if (camel_stream_printf(out, "%s\n", folder) == -1)
+				if (camel_stream_printf(out, NULL, "%s\n", folder) == -1)
 					goto fail;
 				mode = UPDATE_NONE;
 			} else if (tmp == NULL) {
@@ -177,7 +178,7 @@ folders_update (const gchar *root,
 			break;
 		}
 
-		if (copy && camel_stream_printf(out, "%s\n", line) == -1)
+		if (copy && camel_stream_printf(out, NULL, "%s\n", line) == -1)
 			goto fail;
 
 		g_free(line);
@@ -185,10 +186,10 @@ folders_update (const gchar *root,
 	}
 
 	/* add to end? */
-	if (mode == UPDATE_ADD && camel_stream_printf(out, "%s\n", folder) == -1)
+	if (mode == UPDATE_ADD && camel_stream_printf(out, NULL, "%s\n", folder) == -1)
 		goto fail;
 
-	if (camel_stream_close(out) == -1)
+	if (camel_stream_close(out, NULL) == -1)
 		goto fail;
 
 done:
@@ -509,7 +510,7 @@ folders_scan (CamelStore *store,
 
 	tmp = g_alloca (strlen (root) + 16);
 	sprintf (tmp, "%s/.folders", root);
-	stream = camel_stream_fs_new_with_name(tmp, 0, O_RDONLY);
+	stream = camel_stream_fs_new_with_name(tmp, 0, O_RDONLY, NULL);
 	if (stream == NULL)
 		return;
 
@@ -521,7 +522,7 @@ folders_scan (CamelStore *store,
 	visited = g_hash_table_new(g_str_hash, g_str_equal);
 	folders = g_ptr_array_new();
 
-	while ( (len = camel_stream_buffer_gets((CamelStreamBuffer *)in, line, sizeof(line))) > 0) {
+	while ( (len = camel_stream_buffer_gets((CamelStreamBuffer *)in, line, sizeof(line), NULL)) > 0) {
 		/* ignore blank lines */
 		if (len <= 1)
 			continue;
diff --git a/camel/providers/nntp/camel-nntp-folder.c b/camel/providers/nntp/camel-nntp-folder.c
index 1998f91..62fa70e 100644
--- a/camel/providers/nntp/camel-nntp-folder.c
+++ b/camel/providers/nntp/camel-nntp-folder.c
@@ -164,9 +164,9 @@ nntp_folder_download_message (CamelNNTPFolder *nntp_folder, const gchar *id, con
 	if (ret == 220) {
 		stream = camel_data_cache_add (nntp_store->cache, "cache", msgid, NULL);
 		if (stream) {
-			if (camel_stream_write_to_stream ((CamelStream *) nntp_store->stream, stream) == -1)
+			if (camel_stream_write_to_stream ((CamelStream *) nntp_store->stream, stream, error) == -1)
 				goto fail;
-			if (camel_stream_reset (stream) == -1)
+			if (camel_stream_reset (stream, error) == -1)
 				goto fail;
 		} else {
 			stream = (CamelStream *) nntp_store->stream;
@@ -185,18 +185,8 @@ nntp_folder_download_message (CamelNNTPFolder *nntp_folder, const gchar *id, con
 
 	return stream;
 
- fail:
-	if (errno == EINTR)
-		g_set_error (
-			error, CAMEL_ERROR,
-			CAMEL_ERROR_USER_CANCEL,
-			_("User canceled"));
-	else
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Cannot get message %s: %s"),
-			msgid, g_strerror (errno));
+fail:
+	g_prefix_error (error, _("Cannot get message %s: "), msgid);
 
 	return NULL;
 }
@@ -279,18 +269,8 @@ nntp_folder_get_message (CamelFolder *folder, const gchar *uid, GError **error)
 	}
 
 	message = camel_mime_message_new ();
-	if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream) == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("User canceled"));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("Cannot get message %s: %s"),
-				uid, g_strerror (errno));
+	if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream, error) == -1) {
+		g_prefix_error (error, _("Cannot get message %s: "), uid);
 		g_object_unref (message);
 		message = NULL;
 	}
@@ -442,25 +422,13 @@ nntp_folder_append_message_online (CamelFolder *folder,
 	camel_header_raw_extract (header_queue, &save_queue, "Bcc");
 
 	/* write the message */
-	if (camel_stream_write(stream, group, strlen(group)) == -1
-	    || camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (mime_message), filtered_stream) == -1
-	    || camel_stream_flush (filtered_stream) == -1
-	    || camel_stream_write (stream, "\r\n.\r\n", 5) == -1
-	    || (ret = camel_nntp_stream_line (nntp_store->stream, (guchar **)&line, &u)) == -1) {
-		if (errno == EINTR) {
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("User canceled"));
-			success = FALSE;
-		} else {
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("Posting failed: %s"),
-				g_strerror (errno));
-			success = FALSE;
-		}
+	if (camel_stream_write(stream, group, strlen(group), error) == -1
+	    || camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (mime_message), filtered_stream, error) == -1
+	    || camel_stream_flush (filtered_stream, error) == -1
+	    || camel_stream_write (stream, "\r\n.\r\n", 5, error) == -1
+	    || (ret = camel_nntp_stream_line (nntp_store->stream, (guchar **)&line, &u, error)) == -1) {
+		g_prefix_error (error, "Posting failed: ");
+		success = FALSE;
 	} else if (atoi(line) != 240) {
 		g_set_error (
 			error, CAMEL_ERROR, CAMEL_ERROR_SYSTEM,
diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c
index fc7a221..c0705a4 100644
--- a/camel/providers/nntp/camel-nntp-store.c
+++ b/camel/providers/nntp/camel-nntp-store.c
@@ -161,7 +161,7 @@ xover_setup(CamelNNTPStore *store, GError **error)
 	last = (struct _xover_header *)&store->xover;
 
 	/* supported command */
-	while ((ret = camel_nntp_stream_line(store->stream, (guchar **)&line, &len)) > 0) {
+	while ((ret = camel_nntp_stream_line(store->stream, (guchar **)&line, &len, error)) > 0) {
 		p = (guchar *) line;
 		xover = g_malloc0(sizeof(*xover));
 		last->next = xover;
@@ -227,28 +227,17 @@ connect_to_server (CamelService *service, struct addrinfo *ai, gint ssl_mode, GE
 			CAMEL_SERVICE_ERROR_UNAVAILABLE,
 			_("Could not connect to %s: %s"),
 			service->url->host, _("SSL unavailable"));
-
 		goto fail;
 #endif /* HAVE_SSL */
 	} else {
 		tcp_stream = camel_tcp_stream_raw_new ();
 	}
 
-	if (camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai) == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("Connection canceled"));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("Could not connect to %s: %s"),
-				service->url->host, g_strerror (errno));
-
+	if (camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai, error) == -1) {
+		g_prefix_error (
+			error, _("Could not connect to %s: "),
+			service->url->host);
 		g_object_unref (tcp_stream);
-
 		goto fail;
 	}
 
@@ -256,19 +245,10 @@ connect_to_server (CamelService *service, struct addrinfo *ai, gint ssl_mode, GE
 	g_object_unref (tcp_stream);
 
 	/* Read the greeting, if any. */
-	if (camel_nntp_stream_line (store->stream, &buf, &len) == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("Connection canceled"));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("Could not read greeting from %s: %s"),
-				service->url->host, g_strerror (errno));
-
+	if (camel_nntp_stream_line (store->stream, &buf, &len, error) == -1) {
+		g_prefix_error (
+			error, _("Could not read greeting from %s: "),
+			service->url->host);
 		g_object_unref (store->stream);
 		store->stream = NULL;
 
@@ -864,7 +844,7 @@ nntp_store_get_folder_info_all(CamelNNTPStore *nntp_store, const gchar *top, gui
 				goto do_complete_list;
 			}
 
-			while ((ret = camel_nntp_stream_line (nntp_store->stream, &line, &len)) > 0)
+			while ((ret = camel_nntp_stream_line (nntp_store->stream, &line, &len, error)) > 0)
 				nntp_store_info_update(nntp_store, (gchar *) line);
 		} else {
 			GHashTable *all;
@@ -890,7 +870,7 @@ nntp_store_get_folder_info_all(CamelNNTPStore *nntp_store, const gchar *top, gui
 			for (i = 0; (si = (CamelNNTPStoreInfo *)camel_store_summary_index ((CamelStoreSummary *)nntp_store->summary, i)); i++)
 				g_hash_table_insert(all, si->info.path, si);
 
-			while ((ret = camel_nntp_stream_line(nntp_store->stream, &line, &len)) > 0) {
+			while ((ret = camel_nntp_stream_line(nntp_store->stream, &line, &len, error)) > 0) {
 				si = nntp_store_info_update(nntp_store, (gchar *) line);
 				g_hash_table_remove(all, si->info.path);
 			}
@@ -1307,32 +1287,32 @@ camel_nntp_raw_commandv (CamelNNTPStore *store, GError **error, gchar **line, co
 		switch (c) {
 		case '%':
 			c = *p++;
-			camel_stream_write ((CamelStream *) store->mem, (const gchar *) ps, p - ps - (c == '%' ? 1 : 2));
+			camel_stream_write ((CamelStream *) store->mem, (const gchar *) ps, p - ps - (c == '%' ? 1 : 2), NULL);
 			ps = p;
 			switch (c) {
 			case 's':
 				s = va_arg(ap, gchar *);
-				camel_stream_write((CamelStream *)store->mem, s, strlen(s));
+				camel_stream_write((CamelStream *)store->mem, s, strlen(s), NULL);
 				break;
 			case 'd':
 				d = va_arg(ap, gint);
-				camel_stream_printf((CamelStream *)store->mem, "%d", d);
+				camel_stream_printf((CamelStream *)store->mem, NULL, "%d", d);
 				break;
 			case 'u':
 				u = va_arg(ap, guint);
-				camel_stream_printf((CamelStream *)store->mem, "%u", u);
+				camel_stream_printf((CamelStream *)store->mem, NULL, "%u", u);
 				break;
 			case 'm':
 				s = va_arg(ap, gchar *);
-				camel_stream_printf((CamelStream *)store->mem, "<%s>", s);
+				camel_stream_printf((CamelStream *)store->mem, NULL, "<%s>", s);
 				break;
 			case 'r':
 				u = va_arg(ap, guint);
 				u2 = va_arg(ap, guint);
 				if (u == u2)
-					camel_stream_printf((CamelStream *)store->mem, "%u", u);
+					camel_stream_printf((CamelStream *)store->mem, NULL, "%u", u);
 				else
-					camel_stream_printf((CamelStream *)store->mem, "%u-%u", u, u2);
+					camel_stream_printf((CamelStream *)store->mem, NULL, "%u-%u", u, u2);
 				break;
 			default:
 				g_warning("Passing unknown format to nntp_command: %c\n", c);
@@ -1341,19 +1321,19 @@ camel_nntp_raw_commandv (CamelNNTPStore *store, GError **error, gchar **line, co
 		}
 	}
 
-	camel_stream_write ((CamelStream *) store->mem, (const gchar *) ps, p-ps-1);
-	camel_stream_write ((CamelStream *) store->mem, "\r\n", 2);
+	camel_stream_write ((CamelStream *) store->mem, (const gchar *) ps, p-ps-1, NULL);
+	camel_stream_write ((CamelStream *) store->mem, "\r\n", 2, NULL);
 
 	buffer = camel_stream_mem_get_byte_array (store->mem);
 
-	if (camel_stream_write((CamelStream *) store->stream, (const gchar *) buffer->data, buffer->len) == -1)
+	if (camel_stream_write((CamelStream *) store->stream, (const gchar *) buffer->data, buffer->len, error) == -1)
 		goto ioerror;
 
 	/* FIXME: hack */
-	camel_stream_reset ((CamelStream *) store->mem);
+	camel_stream_reset ((CamelStream *) store->mem, NULL);
 	g_byte_array_set_size (buffer, 0);
 
-	if (camel_nntp_stream_line (store->stream, (guchar **) line, &u) == -1)
+	if (camel_nntp_stream_line (store->stream, (guchar **) line, &u, error) == -1)
 		goto ioerror;
 
 	u = strtoul (*line, NULL, 10);
@@ -1365,17 +1345,7 @@ camel_nntp_raw_commandv (CamelNNTPStore *store, GError **error, gchar **line, co
 	return u;
 
 ioerror:
-	if (errno == EINTR)
-		g_set_error (
-			error, CAMEL_ERROR,
-			CAMEL_ERROR_USER_CANCEL,
-			_("Canceled."));
-	else
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("NNTP Command failed: %s"),
-			g_strerror(errno));
+	g_prefix_error (error, _("NNTP Command failed: "));
 	return -1;
 }
 
@@ -1448,7 +1418,7 @@ camel_nntp_command (CamelNNTPStore *store, GError **error, CamelNNTPFolder *fold
 		/* Check for unprocessed data, ! */
 		if (store->stream->mode == CAMEL_NNTP_STREAM_DATA) {
 			g_warning("Unprocessed data left in stream, flushing");
-			while (camel_nntp_stream_getd(store->stream, (guchar **)&p, &u) > 0)
+			while (camel_nntp_stream_getd(store->stream, (guchar **)&p, &u, NULL) > 0)
 				;
 		}
 		camel_nntp_stream_set_mode(store->stream, CAMEL_NNTP_STREAM_LINE);
diff --git a/camel/providers/nntp/camel-nntp-stream.c b/camel/providers/nntp/camel-nntp-stream.c
index c03432d..6d5d5c0 100644
--- a/camel/providers/nntp/camel-nntp-stream.c
+++ b/camel/providers/nntp/camel-nntp-stream.c
@@ -68,7 +68,8 @@ nntp_stream_finalize (GObject *object)
 }
 
 static gint
-stream_fill (CamelNNTPStream *is)
+nntp_stream_fill (CamelNNTPStream *is,
+                  GError **error)
 {
 	gint left = 0;
 
@@ -77,7 +78,7 @@ stream_fill (CamelNNTPStream *is)
 		memcpy (is->buf, is->ptr, left);
 		is->end = is->buf + left;
 		is->ptr = is->buf;
-		left = camel_stream_read (is->source, (gchar *) is->end, CAMEL_NNTP_STREAM_SIZE - (is->end - is->buf));
+		left = camel_stream_read (is->source, (gchar *) is->end, CAMEL_NNTP_STREAM_SIZE - (is->end - is->buf), error);
 		if (left > 0) {
 			is->end += left;
 			is->end[0] = '\n';
@@ -94,7 +95,10 @@ stream_fill (CamelNNTPStream *is)
 }
 
 static gssize
-stream_read (CamelStream *stream, gchar *buffer, gsize n)
+nntp_stream_read (CamelStream *stream,
+                  gchar *buffer,
+                  gsize n,
+                  GError **error)
 {
 	CamelNNTPStream *is = (CamelNNTPStream *)stream;
 	gchar *o, *oe;
@@ -117,7 +121,7 @@ stream_read (CamelStream *stream, gchar *buffer, gsize n)
 	case 0:		/* start of line, always read at least 3 chars */
 		while (e - p < 3) {
 			is->ptr = p;
-			if (stream_fill (is) == -1)
+			if (nntp_stream_fill (is, error) == -1)
 				return -1;
 			p = is->ptr;
 			e = is->end;
@@ -141,7 +145,7 @@ stream_read (CamelStream *stream, gchar *buffer, gsize n)
 				/* end of input sentinal check */
 				if (p > e) {
 					is->ptr = e;
-					if (stream_fill (is) == -1)
+					if (nntp_stream_fill (is, error) == -1)
 						return -1;
 					p = is->ptr;
 					e = is->end;
@@ -166,29 +170,34 @@ stream_read (CamelStream *stream, gchar *buffer, gsize n)
 }
 
 static gssize
-stream_write (CamelStream *stream, const gchar *buffer, gsize n)
+nntp_stream_write (CamelStream *stream,
+                   const gchar *buffer,
+                   gsize n,
+                   GError **error)
 {
 	CamelNNTPStream *is = (CamelNNTPStream *)stream;
 
-	return camel_stream_write (is->source, buffer, n);
+	return camel_stream_write (is->source, buffer, n, error);
 }
 
 static gint
-stream_close (CamelStream *stream)
+nntp_stream_close (CamelStream *stream,
+                   GError **error)
 {
 	/* nop? */
 	return 0;
 }
 
 static gint
-stream_flush (CamelStream *stream)
+nntp_stream_flush (CamelStream *stream,
+                   GError **error)
 {
 	/* nop? */
 	return 0;
 }
 
 static gboolean
-stream_eos (CamelStream *stream)
+nntp_stream_eos (CamelStream *stream)
 {
 	CamelNNTPStream *is = (CamelNNTPStream *)stream;
 
@@ -196,7 +205,8 @@ stream_eos (CamelStream *stream)
 }
 
 static gint
-stream_reset (CamelStream *stream)
+nntp_stream_reset (CamelStream *stream,
+                   GError **error)
 {
 	/* nop?  reset literal mode? */
 	return 0;
@@ -215,12 +225,12 @@ nntp_stream_class_init (CamelStreamClass *class)
 	object_class->finalize = nntp_stream_finalize;
 
 	stream_class = CAMEL_STREAM_CLASS (class);
-	stream_class->read = stream_read;
-	stream_class->write = stream_write;
-	stream_class->close = stream_close;
-	stream_class->flush = stream_flush;
-	stream_class->eos = stream_eos;
-	stream_class->reset = stream_reset;
+	stream_class->read = nntp_stream_read;
+	stream_class->write = nntp_stream_write;
+	stream_class->close = nntp_stream_close;
+	stream_class->flush = nntp_stream_flush;
+	stream_class->eos = nntp_stream_eos;
+	stream_class->reset = nntp_stream_reset;
 }
 
 static void
@@ -277,7 +287,10 @@ camel_nntp_stream_new (CamelStream *source)
 
 /* Get one line from the nntp stream */
 gint
-camel_nntp_stream_line (CamelNNTPStream *is, guchar **data, guint *len)
+camel_nntp_stream_line (CamelNNTPStream *is,
+                        guchar **data,
+                        guint *len,
+                        GError **error)
 {
 	register guchar c, *p, *o, *oe;
 	gint newlen, oldlen;
@@ -299,7 +312,7 @@ camel_nntp_stream_line (CamelNNTPStream *is, guchar **data, guint *len)
 		/* need at least 3 chars in buffer */
 		while (e-p < 3) {
 			is->ptr = p;
-			if (stream_fill (is) == -1)
+			if (nntp_stream_fill (is, error) == -1)
 				return -1;
 			p = is->ptr;
 			e = is->end;
@@ -329,7 +342,7 @@ camel_nntp_stream_line (CamelNNTPStream *is, guchar **data, guint *len)
 				/* sentinal? */
 				if (p> e) {
 					is->ptr = e;
-					if (stream_fill (is) == -1)
+					if (nntp_stream_fill (is, error) == -1)
 						return -1;
 					p = is->ptr;
 					e = is->end;
@@ -361,7 +374,11 @@ camel_nntp_stream_line (CamelNNTPStream *is, guchar **data, guint *len)
 }
 
 /* returns -1 on error, 0 if last lot of data, >0 if more remaining */
-gint camel_nntp_stream_gets (CamelNNTPStream *is, guchar **start, guint *len)
+gint
+camel_nntp_stream_gets (CamelNNTPStream *is,
+                        guchar **start,
+                        guint *len,
+                        GError **error)
 {
 	gint max;
 	guchar *end;
@@ -370,7 +387,7 @@ gint camel_nntp_stream_gets (CamelNNTPStream *is, guchar **start, guint *len)
 
 	max = is->end - is->ptr;
 	if (max == 0) {
-		max = stream_fill (is);
+		max = nntp_stream_fill (is, error);
 		if (max <= 0)
 			return max;
 	}
@@ -394,7 +411,11 @@ void camel_nntp_stream_set_mode (CamelNNTPStream *is, camel_nntp_stream_mode_t m
 }
 
 /* returns -1 on erorr, 0 if last data, >0 if more data left */
-gint camel_nntp_stream_getd (CamelNNTPStream *is, guchar **start, guint *len)
+gint
+camel_nntp_stream_getd (CamelNNTPStream *is,
+                        guchar **start,
+                        guint *len,
+                        GError **error)
 {
 	guchar *p, *e, *s;
 	gint state;
@@ -415,7 +436,7 @@ gint camel_nntp_stream_getd (CamelNNTPStream *is, guchar **start, guint *len)
 
 	while (e - p < 3) {
 		is->ptr = p;
-		if (stream_fill (is) == -1)
+		if (nntp_stream_fill (is, error) == -1)
 			return -1;
 		p = is->ptr;
 		e = is->end;
diff --git a/camel/providers/nntp/camel-nntp-stream.h b/camel/providers/nntp/camel-nntp-stream.h
index 38171c5..b6e212d 100644
--- a/camel/providers/nntp/camel-nntp-stream.h
+++ b/camel/providers/nntp/camel-nntp-stream.h
@@ -69,15 +69,24 @@ struct _CamelNNTPStreamClass {
 	CamelStreamClass parent_class;
 };
 
-GType		 camel_nntp_stream_get_type	(void);
-
-CamelStream     *camel_nntp_stream_new		(CamelStream *source);
-
-void		 camel_nntp_stream_set_mode     (CamelNNTPStream *is, camel_nntp_stream_mode_t mode);
-
-gint              camel_nntp_stream_line		(CamelNNTPStream *is, guchar **data, guint *len);
-gint		 camel_nntp_stream_gets		(CamelNNTPStream *is, guchar **start, guint *len);
-gint		 camel_nntp_stream_getd		(CamelNNTPStream *is, guchar **start, guint *len);
+GType		camel_nntp_stream_get_type	(void);
+
+CamelStream *	camel_nntp_stream_new		(CamelStream *source);
+
+void		camel_nntp_stream_set_mode	(CamelNNTPStream *is,
+						 camel_nntp_stream_mode_t mode);
+gint		camel_nntp_stream_line		(CamelNNTPStream *is,
+						 guchar **data,
+						 guint *len,
+						 GError **error);
+gint		camel_nntp_stream_gets		(CamelNNTPStream *is,
+						 guchar **start,
+						 guint *len,
+						 GError **error);
+gint		camel_nntp_stream_getd		(CamelNNTPStream *is,
+						 guchar **start,
+						 guint *len,
+						 GError **error);
 
 G_END_DECLS
 
diff --git a/camel/providers/nntp/camel-nntp-summary.c b/camel/providers/nntp/camel-nntp-summary.c
index b27b137..5657c1c 100644
--- a/camel/providers/nntp/camel-nntp-summary.c
+++ b/camel/providers/nntp/camel-nntp-summary.c
@@ -268,7 +268,7 @@ add_range_xover (CamelNNTPSummary *cns, CamelNNTPStore *store, guint high, guint
 
 	count = 0;
 	total = high-low+1;
-	while ((ret = camel_nntp_stream_line (store->stream, (guchar **)&line, &len)) > 0) {
+	while ((ret = camel_nntp_stream_line (store->stream, (guchar **)&line, &len, error)) > 0) {
 		camel_operation_progress (NULL, (count * 100) / total);
 		count++;
 		n = strtoul (line, &tab, 10);
@@ -385,7 +385,7 @@ add_range_head (CamelNNTPSummary *cns, CamelNNTPStore *store, guint high, guint
 			line[1] = 0;
 			cns->priv->uid = g_strdup_printf ("%u,%s\n", n, msgid);
 			if (!GPOINTER_TO_INT (g_hash_table_lookup (summary_table, cns->priv->uid))) {
-				if (camel_mime_parser_init_with_stream (mp, (CamelStream *)store->stream) == -1)
+				if (camel_mime_parser_init_with_stream (mp, (CamelStream *)store->stream, error) == -1)
 					goto error;
 				mi = camel_folder_summary_add_from_parser (s, mp);
 				while (camel_mime_parser_step (mp, NULL, NULL) != CAMEL_MIME_PARSER_STATE_EOF)
@@ -404,23 +404,11 @@ add_range_head (CamelNNTPSummary *cns, CamelNNTPStore *store, guint high, guint
 	}
 
 	ret = 0;
+
 error:
+	g_prefix_error (error, _("Operation failed: "));
 
-	if (ret == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("User cancel"));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("Operation failed: %s"),
-				g_strerror (errno));
-	}
 ioerror:
-
 	if (cns->priv->uid) {
 		g_free (cns->priv->uid);
 		cns->priv->uid = NULL;
diff --git a/camel/providers/pop3/camel-pop3-engine.c b/camel/providers/pop3/camel-pop3-engine.c
index 993343a..028615e 100644
--- a/camel/providers/pop3/camel-pop3-engine.c
+++ b/camel/providers/pop3/camel-pop3-engine.c
@@ -271,7 +271,7 @@ engine_command_queue(CamelPOP3Engine *pe, CamelPOP3Command *pc)
 	}
 
 	/* ??? */
-	if (camel_stream_write((CamelStream *)pe->stream, pc->data, strlen(pc->data)) == -1) {
+	if (camel_stream_write((CamelStream *)pe->stream, pc->data, strlen(pc->data), NULL) == -1) {
 		camel_dlist_addtail(&pe->queue, (CamelDListNode *)pc);
 		return FALSE;
 	}
@@ -352,7 +352,7 @@ camel_pop3_engine_iterate(CamelPOP3Engine *pe, CamelPOP3Command *pcwait)
 		    && pe->current != NULL)
 			break;
 
-		if (camel_stream_write((CamelStream *)pe->stream, pw->data, strlen(pw->data)) == -1)
+		if (camel_stream_write((CamelStream *)pe->stream, pw->data, strlen(pw->data), NULL) == -1)
 			goto ioerror;
 
 		camel_dlist_remove((CamelDListNode *)pw);
diff --git a/camel/providers/pop3/camel-pop3-folder.c b/camel/providers/pop3/camel-pop3-folder.c
index eb9b5d9..f43fc52 100644
--- a/camel/providers/pop3/camel-pop3-folder.c
+++ b/camel/providers/pop3/camel-pop3-folder.c
@@ -156,7 +156,7 @@ cmd_builduid(CamelPOP3Engine *pe, CamelPOP3Stream *stream, gpointer data)
 
 	checksum = g_checksum_new (G_CHECKSUM_MD5);
 	mp = camel_mime_parser_new();
-	camel_mime_parser_init_with_stream(mp, (CamelStream *)stream);
+	camel_mime_parser_init_with_stream(mp, (CamelStream *)stream, NULL);
 	switch (camel_mime_parser_step(mp, NULL, NULL)) {
 	case CAMEL_MIME_PARSER_STATE_HEADER:
 	case CAMEL_MIME_PARSER_STATE_MESSAGE:
@@ -396,12 +396,12 @@ pop3_get_message_time_from_cache (CamelFolder *folder, const gchar *uid, time_t
 	g_return_val_if_fail (pop3_store->cache != NULL, FALSE);
 
 	if ((stream = camel_data_cache_get (pop3_store->cache, "cache", uid, NULL)) != NULL
-	    && camel_stream_read (stream, buffer, 1) == 1
+	    && camel_stream_read (stream, buffer, 1, NULL) == 1
 	    && buffer[0] == '#') {
 		CamelMimeMessage *message;
 
 		message = camel_mime_message_new ();
-		if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *)message, stream) == -1) {
+		if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *)message, stream, NULL) == -1) {
 			g_warning (_("Cannot get message %s: %s"), uid, g_strerror (errno));
 			g_object_unref (message);
 			message = NULL;
@@ -504,11 +504,11 @@ cmd_tocache(CamelPOP3Engine *pe, CamelPOP3Stream *stream, gpointer data)
 
 	/* We write an '*' to the start of the stream to say its not complete yet */
 	/* This should probably be part of the cache code */
-	if ((n = camel_stream_write(fi->stream, "*", 1)) == -1)
+	if ((n = camel_stream_write (fi->stream, "*", 1, NULL)) == -1)
 		goto done;
 
-	while ((n = camel_stream_read((CamelStream *)stream, buffer, sizeof(buffer))) > 0) {
-		n = camel_stream_write(fi->stream, buffer, n);
+	while ((n = camel_stream_read((CamelStream *)stream, buffer, sizeof(buffer), NULL)) > 0) {
+		n = camel_stream_write(fi->stream, buffer, n, NULL);
 		if (n == -1)
 			break;
 
@@ -521,8 +521,8 @@ cmd_tocache(CamelPOP3Engine *pe, CamelPOP3Stream *stream, gpointer data)
 
 	/* it all worked, output a '#' to say we're a-ok */
 	if (n != -1) {
-		camel_stream_reset(fi->stream);
-		n = camel_stream_write(fi->stream, "#", 1);
+		camel_stream_reset(fi->stream, NULL);
+		n = camel_stream_write(fi->stream, "#", 1, NULL);
 	}
 done:
 	if (n == -1) {
@@ -615,7 +615,7 @@ pop3_get_message (CamelFolder *folder, const gchar *uid, GError **error)
 	/* check to see if we have safely written flag set */
 	if (pop3_store->cache == NULL
 	    || (stream = camel_data_cache_get(pop3_store->cache, "cache", fi->uid, NULL)) == NULL
-	    || camel_stream_read(stream, buffer, 1) != 1
+	    || camel_stream_read(stream, buffer, 1, NULL) != 1
 	    || buffer[0] != '#') {
 
 		/* Initiate retrieval, if disk backing fails, use a memory backing */
@@ -659,7 +659,7 @@ pop3_get_message (CamelFolder *folder, const gchar *uid, GError **error)
 		/* getting error code? */
 		/*g_assert (pcr->state == CAMEL_POP3_COMMAND_DATA);*/
 		camel_pop3_engine_command_free(pop3_store->engine, pcr);
-		camel_stream_reset(stream);
+		camel_stream_reset(stream, NULL);
 
 		/* Check to see we have safely written flag set */
 		if (fi->err != 0) {
@@ -677,7 +677,7 @@ pop3_get_message (CamelFolder *folder, const gchar *uid, GError **error)
 			goto done;
 		}
 
-		if (camel_stream_read(stream, buffer, 1) != 1 || buffer[0] != '#') {
+		if (camel_stream_read(stream, buffer, 1, NULL) != 1 || buffer[0] != '#') {
 			g_set_error (
 				error, CAMEL_ERROR, CAMEL_ERROR_SYSTEM,
 				_("Cannot get message %s: %s"),
@@ -687,18 +687,8 @@ pop3_get_message (CamelFolder *folder, const gchar *uid, GError **error)
 	}
 
 	message = camel_mime_message_new ();
-	if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, stream) == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("User canceled"));
-		else
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_SYSTEM,
-				_("Cannot get message %s: %s"),
-				uid, g_strerror (errno));
+	if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, stream, error) == -1) {
+		g_prefix_error (error, _("Cannot get message %s: "), uid);
 		g_object_unref (message);
 		message = NULL;
 	}
diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c
index af8601b..87ed14c 100644
--- a/camel/providers/pop3/camel-pop3-store.c
+++ b/camel/providers/pop3/camel-pop3-store.c
@@ -161,20 +161,10 @@ connect_to_server (CamelService *service,
 	} else
 		tcp_stream = camel_tcp_stream_raw_new ();
 
-	if ((ret = camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai)) == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("Connection canceled"));
-		else
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_SERVICE_ERROR_UNAVAILABLE,
-				_("Could not connect to %s: %s"),
-				service->url->host,
-				g_strerror (errno));
-
+	if ((ret = camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai, error)) == -1) {
+		g_prefix_error (
+			error, _("Could not connect to %s: "),
+			service->url->host);
 		g_object_unref (tcp_stream);
 
 		return FALSE;
@@ -418,7 +408,7 @@ try_sasl (CamelPOP3Store *store,
 		return -1;
 	}
 
-	if (camel_stream_printf((CamelStream *)stream, "AUTH %s\r\n", mech) == -1)
+	if (camel_stream_printf((CamelStream *)stream, error, "AUTH %s\r\n", mech) == -1)
 		goto ioerror;
 
 	while (1) {
@@ -439,7 +429,7 @@ try_sasl (CamelPOP3Store *store,
 		if (strncmp((gchar *) line, "+ ", 2) != 0
 		    || camel_sasl_get_authenticated(sasl)
 		    || (resp = (guchar *) camel_sasl_challenge_base64(sasl, (const gchar *) line+2, error)) == NULL) {
-			camel_stream_printf((CamelStream *)stream, "*\r\n");
+			camel_stream_printf((CamelStream *)stream, NULL, "*\r\n");
 			camel_pop3_stream_line(stream, &line, &len);
 			g_set_error (
 				error, CAMEL_SERVICE_ERROR,
@@ -450,7 +440,7 @@ try_sasl (CamelPOP3Store *store,
 			goto done;
 		}
 
-		ret = camel_stream_printf((CamelStream *)stream, "%s\r\n", resp);
+		ret = camel_stream_printf((CamelStream *)stream, error, "%s\r\n", resp);
 		g_free(resp);
 		if (ret == -1)
 			goto ioerror;
@@ -460,16 +450,10 @@ try_sasl (CamelPOP3Store *store,
 	return 0;
 
  ioerror:
-	if (errno == EINTR) {
-		g_set_error (
-			error, CAMEL_ERROR,
-			CAMEL_ERROR_USER_CANCEL, _("Canceled"));
-	} else {
-		g_set_error (
-			error, CAMEL_ERROR, CAMEL_ERROR_SYSTEM,
-			_("Failed to authenticate on POP server %s: %s"),
-			CAMEL_SERVICE (store)->url->host, g_strerror (errno));
-	}
+	g_prefix_error (
+		error, _("Failed to authenticate on POP server %s: "),
+		CAMEL_SERVICE (store)->url->host);
+
  done:
 	g_object_unref (sasl);
 	return -1;
diff --git a/camel/providers/pop3/camel-pop3-stream.c b/camel/providers/pop3/camel-pop3-stream.c
index 7413f60..780e651 100644
--- a/camel/providers/pop3/camel-pop3-stream.c
+++ b/camel/providers/pop3/camel-pop3-stream.c
@@ -76,7 +76,9 @@ stream_fill (CamelPOP3Stream *is)
 		memmove (is->buf, is->ptr, left);
 		is->end = is->buf + left;
 		is->ptr = is->buf;
-		left = camel_stream_read (is->source, (gchar *) is->end, CAMEL_POP3_STREAM_SIZE - (is->end - is->buf));
+		left = camel_stream_read (
+			is->source, (gchar *) is->end,
+			CAMEL_POP3_STREAM_SIZE - (is->end - is->buf), NULL);
 		if (left > 0) {
 			is->end += left;
 			is->end[0] = '\n';
@@ -91,7 +93,7 @@ stream_fill (CamelPOP3Stream *is)
 }
 
 static gssize
-stream_read (CamelStream *stream, gchar *buffer, gsize n)
+stream_read (CamelStream *stream, gchar *buffer, gsize n, GError **error)
 {
 	CamelPOP3Stream *is = (CamelPOP3Stream *)stream;
 	gchar *o, *oe;
@@ -163,7 +165,10 @@ stream_read (CamelStream *stream, gchar *buffer, gsize n)
 }
 
 static gssize
-stream_write (CamelStream *stream, const gchar *buffer, gsize n)
+stream_write (CamelStream *stream,
+              const gchar *buffer,
+              gsize n,
+              GError **error)
 {
 	CamelPOP3Stream *is = (CamelPOP3Stream *)stream;
 
@@ -172,18 +177,20 @@ stream_write (CamelStream *stream, const gchar *buffer, gsize n)
 	else
 		dd (printf ("POP3_STREAM_WRITE (%d):\nPASS xxxxxxxx\n", (gint)n));
 
-	return camel_stream_write (is->source, buffer, n);
+	return camel_stream_write (is->source, buffer, n, error);
 }
 
 static gint
-stream_close (CamelStream *stream)
+stream_close (CamelStream *stream,
+              GError **error)
 {
 	/* nop? */
 	return 0;
 }
 
 static gint
-stream_flush (CamelStream *stream)
+stream_flush (CamelStream *stream,
+              GError **error)
 {
 	/* nop? */
 	return 0;
@@ -198,7 +205,8 @@ stream_eos (CamelStream *stream)
 }
 
 static gint
-stream_reset (CamelStream *stream)
+stream_reset (CamelStream *stream,
+              GError **error)
 {
 	/* nop?  reset literal mode? */
 	return 0;
diff --git a/camel/providers/sendmail/camel-sendmail-transport.c b/camel/providers/sendmail/camel-sendmail-transport.c
index 9eb98c0..7760ef9 100644
--- a/camel/providers/sendmail/camel-sendmail-transport.c
+++ b/camel/providers/sendmail/camel-sendmail-transport.c
@@ -186,14 +186,12 @@ sendmail_send_to (CamelTransport *transport,
 	g_object_unref (out);
 
 	out = filter;
-	if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), out) == -1
-	    || camel_stream_close (out) == -1) {
+	if (camel_data_wrapper_write_to_stream (
+		CAMEL_DATA_WRAPPER (message), out, error) == -1 ||
+		camel_stream_close (out, error) == -1) {
+
 		g_object_unref (CAMEL_OBJECT (out));
-		g_set_error (
-			error, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			_("Could not send message: %s"),
-			g_strerror (errno));
+		g_prefix_error (error, _("Could not send message: "));
 
 		/* Wait for sendmail to exit. */
 		while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR)
diff --git a/camel/providers/smtp/camel-smtp-transport.c b/camel/providers/smtp/camel-smtp-transport.c
index ff9ed7c..413b171 100644
--- a/camel/providers/smtp/camel-smtp-transport.c
+++ b/camel/providers/smtp/camel-smtp-transport.c
@@ -231,18 +231,10 @@ connect_to_server (CamelService *service,
 		tcp_stream = camel_tcp_stream_raw_new ();
 	}
 
-	if ((ret = camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai)) == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("Connection canceled"));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("Could not connect to %s: %s"),
-				service->url->host, g_strerror (errno));
+	if ((ret = camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai, error)) == -1) {
+		g_prefix_error (
+			error, _("Could not connect to %s: "),
+			service->url->host);
 
 		g_object_unref (tcp_stream);
 
@@ -261,9 +253,14 @@ connect_to_server (CamelService *service,
 	do {
 		/* Check for "220" */
 		g_free (respbuf);
-		respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-		if (!respbuf || strncmp (respbuf, "220", 3)) {
-			smtp_set_exception (transport, FALSE, respbuf, _("Welcome response error"), error);
+		respbuf = camel_stream_buffer_read_line (
+			CAMEL_STREAM_BUFFER (transport->istream), error);
+		if (respbuf == NULL)
+			return FALSE;
+		if (strncmp (respbuf, "220", 3) != 0) {
+			smtp_set_exception (
+				transport, FALSE, respbuf,
+				_("Welcome response error"), error);
 			g_free (respbuf);
 			return FALSE;
 		}
@@ -306,19 +303,8 @@ connect_to_server (CamelService *service,
 	}
 
 	d(fprintf (stderr, "sending : STARTTLS\r\n"));
-	if (camel_stream_write (tcp_stream, "STARTTLS\r\n", 10) == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("STARTTLS command failed: %s"),
-				g_strerror (errno));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("STARTTLS command failed: %s"),
-				g_strerror (errno));
+	if (camel_stream_write (tcp_stream, "STARTTLS\r\n", 10, error) == -1) {
+		g_prefix_error (error, _("STARTTLS command failed: "));
 		goto exception_cleanup;
 	}
 
@@ -327,12 +313,14 @@ connect_to_server (CamelService *service,
 	do {
 		/* Check for "220 Ready for TLS" */
 		g_free (respbuf);
-		respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
-		d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
-		if (!respbuf || strncmp (respbuf, "220", 3)) {
-			smtp_set_exception (transport, FALSE, respbuf, _("STARTTLS command failed"), error);
+		respbuf = camel_stream_buffer_read_line (
+			CAMEL_STREAM_BUFFER (transport->istream), error);
+		if (respbuf == NULL)
+			goto exception_cleanup;
+		if (strncmp (respbuf, "220", 3) != 0) {
+			smtp_set_exception (
+				transport, FALSE, respbuf,
+				_("STARTTLS command failed"), error);
 			g_free (respbuf);
 			goto exception_cleanup;
 		}
@@ -932,7 +920,8 @@ smtp_set_exception (CamelSmtpTransport *transport,
 			g_string_append (string, token);
 			if (*(rbuf + 3) == '-') {
 				g_free (buffer);
-				buffer = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
+				buffer = camel_stream_buffer_read_line (
+					CAMEL_STREAM_BUFFER (transport->istream), NULL);
 				g_string_append_c (string, '\n');
 			} else {
 				g_free (buffer);
@@ -1022,20 +1011,9 @@ smtp_helo (CamelSmtpTransport *transport, GError **error)
 	g_free (name);
 
 	d(fprintf (stderr, "sending : %s", cmdbuf));
-	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
+	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf), error) == -1) {
 		g_free (cmdbuf);
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("HELO command failed: %s"),
-				g_strerror (errno));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("HELO command failed: %s"),
-				g_strerror (errno));
+		g_prefix_error (error, _("HELO command failed: "));
 		camel_operation_end (NULL);
 
 		camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
@@ -1047,15 +1025,18 @@ smtp_helo (CamelSmtpTransport *transport, GError **error)
 	do {
 		/* Check for "250" */
 		g_free (respbuf);
-		respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
-		d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
-		if (!respbuf || strncmp (respbuf, "250", 3)) {
-			smtp_set_exception (transport, FALSE, respbuf, _("HELO command failed"), error);
+		respbuf = camel_stream_buffer_read_line (
+			CAMEL_STREAM_BUFFER (transport->istream), error);
+		if (respbuf == NULL) {
+			camel_operation_end (NULL);
+			return FALSE;
+		}
+		if (strncmp (respbuf, "250", 3) != 0) {
+			smtp_set_exception (
+				transport, FALSE, respbuf,
+				_("HELO command failed"), error);
 			camel_operation_end (NULL);
 			g_free (respbuf);
-
 			return FALSE;
 		}
 
@@ -1141,46 +1122,28 @@ smtp_auth (CamelSmtpTransport *transport,
 	}
 
 	d(fprintf (stderr, "sending : %s", cmdbuf));
-	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
+	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf), error) == -1) {
 		g_free (cmdbuf);
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR, CAMEL_ERROR_USER_CANCEL,
-				_("AUTH command failed: %s"),
-				g_strerror (errno));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("AUTH command failed: %s"),
-				g_strerror (errno));
+		g_prefix_error (error, _("AUTH command failed: "));
 		goto lose;
 	}
 	g_free (cmdbuf);
 
-	respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-	d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
+	respbuf = camel_stream_buffer_read_line (
+		CAMEL_STREAM_BUFFER (transport->istream), error);
 
 	while (!camel_sasl_get_authenticated (sasl)) {
-		if (!respbuf) {
-			if (errno == EINTR)
-				g_set_error (
-					error, CAMEL_ERROR,
-					CAMEL_ERROR_USER_CANCEL,
-					_("AUTH command failed: %s"),
-					g_strerror (errno));
-			else
-				g_set_error (
-					error, G_FILE_ERROR,
-					g_file_error_from_errno (errno),
-					_("AUTH command failed: %s"),
-					g_strerror (errno));
+
+		if (respbuf == NULL) {
+			g_prefix_error (error, _("AUTH command failed: "));
 			goto lose;
 		}
 
 		/* the server challenge/response should follow a 334 code */
 		if (strncmp (respbuf, "334", 3) != 0) {
-			smtp_set_exception (transport, FALSE, respbuf, _("AUTH command failed"), error);
+			smtp_set_exception (
+				transport, FALSE, respbuf,
+				_("AUTH command failed"), error);
 			goto lose;
 		}
 
@@ -1206,19 +1169,15 @@ smtp_auth (CamelSmtpTransport *transport,
 		cmdbuf = g_strdup_printf ("%s\r\n", challenge);
 		g_free (challenge);
 		d(fprintf (stderr, "sending : %s", cmdbuf));
-		if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
-			g_set_error (
-				error, CAMEL_SERVICE_ERROR,
-				CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
-				_("Bad authentication response from server."));
+		if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf), error) == -1) {
 			g_free (cmdbuf);
 			goto lose;
 		}
 		g_free (cmdbuf);
 
 		/* get the server's response */
-		respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-		d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
+		respbuf = camel_stream_buffer_read_line (
+			CAMEL_STREAM_BUFFER (transport->istream), error);
 	}
 
 	if (respbuf == NULL) {
@@ -1257,8 +1216,9 @@ smtp_auth (CamelSmtpTransport *transport,
  break_and_lose:
 	/* Get the server out of "waiting for continuation data" mode. */
 	d(fprintf (stderr, "sending : *\n"));
-	camel_stream_write (transport->ostream, "*\r\n", 3);
-	respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
+	camel_stream_write (transport->ostream, "*\r\n", 3, NULL);
+	respbuf = camel_stream_buffer_read_line (
+		CAMEL_STREAM_BUFFER (transport->istream), NULL);
 	d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
 
  lose:
@@ -1283,22 +1243,10 @@ smtp_mail (CamelSmtpTransport *transport, const gchar *sender, gboolean has_8bit
 
 	d(fprintf (stderr, "sending : %s", cmdbuf));
 
-	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
+	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf), error) == -1) {
 		g_free (cmdbuf);
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR, CAMEL_ERROR_USER_CANCEL,
-				_("MAIL FROM command failed: %s: mail not sent"),
-				g_strerror (errno));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("MAIL FROM command failed: %s: mail not sent"),
-				g_strerror (errno));
-
+		g_prefix_error (error, _("MAIL FROM command failed: "));
 		camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
-
 		return FALSE;
 	}
 	g_free (cmdbuf);
@@ -1306,12 +1254,14 @@ smtp_mail (CamelSmtpTransport *transport, const gchar *sender, gboolean has_8bit
 	do {
 		/* Check for "250 Sender OK..." */
 		g_free (respbuf);
-		respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
-		d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
-		if (!respbuf || strncmp (respbuf, "250", 3)) {
-			smtp_set_exception (transport, TRUE, respbuf, _("MAIL FROM command failed"), error);
+		respbuf = camel_stream_buffer_read_line (
+			CAMEL_STREAM_BUFFER (transport->istream), error);
+		if (respbuf == NULL)
+			return FALSE;
+		if (strncmp (respbuf, "250", 3) != 0) {
+			smtp_set_exception (
+				transport, TRUE, respbuf,
+				_("MAIL FROM command failed"), error);
 			g_free (respbuf);
 			return FALSE;
 		}
@@ -1332,20 +1282,9 @@ smtp_rcpt (CamelSmtpTransport *transport, const gchar *recipient, GError **error
 
 	d(fprintf (stderr, "sending : %s", cmdbuf));
 
-	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
+	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf), error) == -1) {
 		g_free (cmdbuf);
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR, CAMEL_ERROR_USER_CANCEL,
-				_("RCPT TO command failed: %s: mail not sent"),
-				g_strerror (errno));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("RCPT TO command failed: %s: mail not sent"),
-				g_strerror (errno));
-
+		g_prefix_error (error, _("RCPT TO command failed: "));
 		camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
 
 		return FALSE;
@@ -1355,17 +1294,20 @@ smtp_rcpt (CamelSmtpTransport *transport, const gchar *recipient, GError **error
 	do {
 		/* Check for "250 Recipient OK..." */
 		g_free (respbuf);
-		respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
-		d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
-		if (!respbuf || strncmp (respbuf, "250", 3)) {
+		respbuf = camel_stream_buffer_read_line (
+			CAMEL_STREAM_BUFFER (transport->istream), error);
+		if (respbuf == NULL)
+			return FALSE;
+		if (strncmp (respbuf, "250", 3) != 0) {
 			gchar *message;
 
-			message = g_strdup_printf (_("RCPT TO <%s> failed"), recipient);
-			smtp_set_exception (transport, TRUE, respbuf, message, error);
+			message = g_strdup_printf (
+				_("RCPT TO <%s> failed"), recipient);
+			smtp_set_exception (
+				transport, TRUE, respbuf, message, error);
 			g_free (message);
 			g_free (respbuf);
+
 			return FALSE;
 		}
 	} while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */
@@ -1401,35 +1343,25 @@ smtp_data (CamelSmtpTransport *transport, CamelMimeMessage *message, GError **er
 
 	d(fprintf (stderr, "sending : %s", cmdbuf));
 
-	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
+	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf), error) == -1) {
 		g_free (cmdbuf);
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR, CAMEL_ERROR_USER_CANCEL,
-				_("DATA command failed: %s: mail not sent"),
-				g_strerror (errno));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("DATA command failed: %s: mail not sent"),
-				g_strerror (errno));
-
+		g_prefix_error (error, _("DATA command failed: "));
 		camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
-
 		return FALSE;
 	}
 	g_free (cmdbuf);
 
-	respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
-	d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
-	if (!respbuf || strncmp (respbuf, "354", 3)) {
+	respbuf = camel_stream_buffer_read_line (
+		CAMEL_STREAM_BUFFER (transport->istream), error);
+	if (respbuf == NULL)
+		return FALSE;
+	if (strncmp (respbuf, "354", 3) != 0) {
 		/* we should have gotten instructions on how to use the DATA command:
 		 * 354 Enter mail, end with "." on a line by itself
 		 */
-		smtp_set_exception (transport, TRUE, respbuf, _("DATA command failed"), error);
+		smtp_set_exception (
+			transport, TRUE, respbuf,
+			_("DATA command failed"), error);
 		g_free (respbuf);
 		return FALSE;
 	}
@@ -1445,7 +1377,7 @@ smtp_data (CamelSmtpTransport *transport, CamelMimeMessage *message, GError **er
 	/* find out how large the message is... */
 	null = CAMEL_STREAM_NULL (camel_stream_null_new ());
 	camel_data_wrapper_write_to_stream (
-		CAMEL_DATA_WRAPPER (message), CAMEL_STREAM (null));
+		CAMEL_DATA_WRAPPER (message), CAMEL_STREAM (null), NULL);
 
 	filtered_stream = camel_stream_filter_new (transport->ostream);
 
@@ -1466,65 +1398,42 @@ smtp_data (CamelSmtpTransport *transport, CamelMimeMessage *message, GError **er
 
 	/* write the message */
 	ret = camel_data_wrapper_write_to_stream (
-		CAMEL_DATA_WRAPPER (message), filtered_stream);
+		CAMEL_DATA_WRAPPER (message), filtered_stream, error);
 
 	/* restore the bcc headers */
 	camel_header_raw_append_queue (header_queue, &bcc_queue);
 
 	if (ret == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR, CAMEL_ERROR_USER_CANCEL,
-				_("DATA command failed: %s: mail not sent"),
-				g_strerror (errno));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				 _("DATA command failed: %s: mail not sent"),
-				 g_strerror (errno));
-
+		g_prefix_error (error, _("DATA command failed: "));
 		g_object_unref (filtered_stream);
-
 		camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
-
 		return FALSE;
 	}
 
-	camel_stream_flush (filtered_stream);
+	camel_stream_flush (filtered_stream, NULL);
 	g_object_unref (filtered_stream);
 
 	/* terminate the message body */
 
 	d(fprintf (stderr, "sending : \\r\\n.\\r\\n\n"));
 
-	if (camel_stream_write (transport->ostream, "\r\n.\r\n", 5) == -1) {
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR, CAMEL_ERROR_USER_CANCEL,
-				_("DATA command failed: %s: mail not sent"),
-				g_strerror (errno));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("DATA command failed: %s: mail not sent"),
-				g_strerror (errno));
-
+	if (camel_stream_write (transport->ostream, "\r\n.\r\n", 5, error) == -1) {
+		g_prefix_error (error, _("DATA command failed: "));
 		camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
-
 		return FALSE;
 	}
 
 	do {
 		/* Check for "250 Sender OK..." */
 		g_free (respbuf);
-		respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
-		d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
-		if (!respbuf || strncmp (respbuf, "250", 3)) {
-			smtp_set_exception (transport, TRUE, respbuf, _("DATA command failed"), error);
+		respbuf = camel_stream_buffer_read_line (
+			CAMEL_STREAM_BUFFER (transport->istream), error);
+		if (respbuf == NULL)
+			return FALSE;
+		if (strncmp (respbuf, "250", 3) != 0) {
+			smtp_set_exception (
+				transport, TRUE, respbuf,
+				_("DATA command failed"), error);
 			g_free (respbuf);
 			return FALSE;
 		}
@@ -1544,23 +1453,10 @@ smtp_rset (CamelSmtpTransport *transport, GError **error)
 
 	d(fprintf (stderr, "sending : %s", cmdbuf));
 
-	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
+	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf), error) == -1) {
 		g_free (cmdbuf);
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("RSET command failed: %s"),
-				g_strerror (errno));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("RSET command failed: %s"),
-				g_strerror (errno));
-
+		g_prefix_error (error, _("RSET command failed: "));
 		camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
-
 		return FALSE;
 	}
 	g_free (cmdbuf);
@@ -1568,11 +1464,11 @@ smtp_rset (CamelSmtpTransport *transport, GError **error)
 	do {
 		/* Check for "250" */
 		g_free (respbuf);
-		respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
-		d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
-		if (!respbuf || strncmp (respbuf, "250", 3)) {
+		respbuf = camel_stream_buffer_read_line (
+			CAMEL_STREAM_BUFFER (transport->istream), error);
+		if (respbuf == NULL)
+			return FALSE;
+		if (strncmp (respbuf, "250", 3) != 0) {
 			smtp_set_exception (
 				transport, TRUE, respbuf,
 				_("RSET command failed"), error);
@@ -1595,21 +1491,9 @@ smtp_quit (CamelSmtpTransport *transport, GError **error)
 
 	d(fprintf (stderr, "sending : %s", cmdbuf));
 
-	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
+	if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf), error) == -1) {
 		g_free (cmdbuf);
-		if (errno == EINTR)
-			g_set_error (
-				error, CAMEL_ERROR,
-				CAMEL_ERROR_USER_CANCEL,
-				_("QUIT command failed: %s"),
-				g_strerror (errno));
-		else
-			g_set_error (
-				error, G_FILE_ERROR,
-				g_file_error_from_errno (errno),
-				_("QUIT command failed: %s"),
-				g_strerror (errno));
-
+		g_prefix_error (error, _("QUIT command failed: "));
 		return FALSE;
 	}
 	g_free (cmdbuf);
@@ -1617,11 +1501,11 @@ smtp_quit (CamelSmtpTransport *transport, GError **error)
 	do {
 		/* Check for "221" */
 		g_free (respbuf);
-		respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
-		d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
-		if (!respbuf || strncmp (respbuf, "221", 3)) {
+		respbuf = camel_stream_buffer_read_line (
+			CAMEL_STREAM_BUFFER (transport->istream), error);
+		if (respbuf == NULL)
+			return FALSE;
+		if (strncmp (respbuf, "221", 3) != 0) {
 			smtp_set_exception (
 				transport, FALSE, respbuf,
 				_("QUIT command failed"), error);
diff --git a/docs/reference/calendar/libedata-cal/tmpl/e-data-cal-common.sgml b/docs/reference/calendar/libedata-cal/tmpl/e-data-cal-common.sgml
index 5da7a51..5a9808a 100644
--- a/docs/reference/calendar/libedata-cal/tmpl/e-data-cal-common.sgml
+++ b/docs/reference/calendar/libedata-cal/tmpl/e-data-cal-common.sgml
@@ -79,6 +79,7 @@ e-data-cal-common
 @get_ldap_attribute: 
 @get_static_capabilities: 
 @open: 
+ refresh: 
 @remove: 
 @create_object: 
 @modify_object: 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]