[balsa/fix-gmime-2.6] Go back to GMime 2.6



commit 3422e991138fb1e85eadcaa75d5d9a001121fee6
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Sun May 10 12:44:31 2020 -0400

    Go back to GMime 2.6

 README                             |   4 +-
 configure.ac                       |   8 +-
 libbalsa/.cvsignore                |   4 -
 libbalsa/abook-completion.c        |   2 +-
 libbalsa/address-book-gpe.c        |   3 +-
 libbalsa/address-book-ldap.c       |  16 +-
 libbalsa/address-view.c            |  17 +-
 libbalsa/address.c                 |   4 +-
 libbalsa/autocrypt.c               | 416 ++++++++++++++++++++++++-------------
 libbalsa/body.c                    |  27 +--
 libbalsa/filter.c                  |   6 +-
 libbalsa/gmime-application-pkcs7.c |  28 ++-
 libbalsa/gmime-multipart-crypt.c   |  38 ++--
 libbalsa/gmime-part-rfc2440.c      |  16 +-
 libbalsa/identity.c                |   2 +-
 libbalsa/imap/.cvsignore           |   2 -
 libbalsa/imap/imap-handle.c        |  26 +--
 libbalsa/libbalsa-gpgme-keys.c     |   6 +-
 libbalsa/libbalsa-gpgme-keys.h     |   8 +-
 libbalsa/libbalsa.c                |  54 +++--
 libbalsa/mailbox.c                 |   3 +-
 libbalsa/mailbox_imap.c            |  30 +--
 libbalsa/mailbox_local.c           |  10 +-
 libbalsa/mailbox_maildir.c         |   4 +-
 libbalsa/mailbox_mbox.c            |  33 ++-
 libbalsa/mailbox_mh.c              |   3 +-
 libbalsa/message.c                 | 243 ++++++++++------------
 libbalsa/message.h                 |   5 -
 libbalsa/misc.c                    |  22 +-
 libbalsa/misc.h                    |   4 -
 libbalsa/rfc3156.c                 |   2 +-
 libbalsa/send.c                    | 125 +++++------
 meson.build                        |   4 +-
 src/.cvsignore                     |  10 -
 src/ab-main.c                      |   5 +-
 src/balsa-message.c                |  14 +-
 src/balsa-mime-widget-message.c    |  10 +-
 src/balsa-mime-widget-text.c       |   3 +-
 src/balsa-mime-widget-vcalendar.c  |   4 +-
 src/balsa-print-object-header.c    |   2 +-
 src/main-window.c                  |   7 +-
 src/message-window.c               |   2 +-
 src/print-gtk.c                    |   2 +-
 src/sendmsg-window.c               |  36 ++--
 src/store-address.c                |   2 +-
 45 files changed, 667 insertions(+), 605 deletions(-)
---
diff --git a/README b/README
index 35c996744..470f62b0b 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Balsa E-Mail Client 2.6.x
+Balsa E-Mail Client 2.5.x
 =========================
 
 See ChangeLog for the list of the recent changes and NEWS for highlights.
@@ -41,7 +41,7 @@ complete descriptions are here.
 Basically, Balsa requires
 - glib-2.0 >= 2.48.0
 - gtk+-3.0 >= 3.18.0
-- gmime-3.0 >= 3.2.6
+- gmime-2.6
 - gio-2.0
 - gthread-2.0
 - gnutls >= 3.0
diff --git a/configure.ac b/configure.ac
index 5c72714d5..425de5ea0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -8,9 +8,9 @@ dnl ###########################################################################
 dnl Boilerplace and versioning
 dnl ###########################################################################
 
-# if autoconf is used not in a git source tree, use version=2.6.0
+# if autoconf is used not in a git source tree, use version=2.5.10
 AC_INIT([balsa],
-        m4_esyscmd([test -d .git && echo -n `git describe --tags` || echo -n 2.6.0]),
+        m4_esyscmd([test -d .git && echo -n `git describe --tags` || echo -n 2.5.10]),
         [])
 
 AM_INIT_AUTOMAKE
@@ -225,7 +225,7 @@ dnl #####################################################################
 PKG_CHECK_MODULES(BALSA, [
 glib-2.0 >= 2.48.0
 gtk+-3.0 >= 3.18.0
-gmime-3.0 >= 3.2.6
+gmime-2.6
 gio-2.0
 gthread-2.0
 gnutls >= 3.0
@@ -236,7 +236,7 @@ libical >= 2.0.0
 PKG_CHECK_MODULES(BALSA_AB, [
    glib-2.0
    gtk+-3.0
-   gmime-3.0 >= 3.2.6
+   gmime-2.6
 ])
 
 PKG_CHECK_MODULES(LIBNETCLIENT, [
diff --git a/libbalsa/abook-completion.c b/libbalsa/abook-completion.c
index 6240baab1..2d15c9c03 100644
--- a/libbalsa/abook-completion.c
+++ b/libbalsa/abook-completion.c
@@ -51,7 +51,7 @@ completion_data_new(InternetAddress * ia, const gchar * nick_name)
     string = g_string_new(nick_name);
     if (string->len > 0)
        g_string_append_c(string, ' ');
-    address_string = internet_address_to_string(ia, NULL, FALSE);
+    address_string = internet_address_to_string(ia, FALSE);
     /* Remove '"' and '<'. */
     for (p = q = address_string; *p; p++)
         if (*p != '"' && *p != '<')
diff --git a/libbalsa/address-book-gpe.c b/libbalsa/address-book-gpe.c
index 8558c845d..c909e0d6b 100644
--- a/libbalsa/address-book-gpe.c
+++ b/libbalsa/address-book-gpe.c
@@ -630,7 +630,8 @@ libbalsa_address_book_gpe_modify_address(LibBalsaAddressBook *ab,
 
     /* do the real work here */
 #ifdef HAVE_SQLITE3
-    if (sqlite3_exec(ab_gpe->db, "begin transaction", NULL, NULL, &err) != SQLITE_OK) {
+    if ((r = sqlite3_exec(ab_gpe->db, "begin transaction",
+                          NULL, NULL, &err)) != SQLITE_OK) {
         libbalsa_address_book_set_status(ab, err);
         sqlite3_free(err);              /* failed, so soon!? */
         return LBABERR_CANNOT_WRITE;
diff --git a/libbalsa/address-book-ldap.c b/libbalsa/address-book-ldap.c
index 19150b205..a357d20ef 100644
--- a/libbalsa/address-book-ldap.c
+++ b/libbalsa/address-book-ldap.c
@@ -429,12 +429,13 @@ libbalsa_address_book_ldap_load(LibBalsaAddressBook * ab,
     /*
      * Connect to the server.
      */
-    for (attempt = 0; attempt < 2; attempt++) {
+    for(attempt=0; attempt<2; attempt++) {
         if (ab_ldap->directory == NULL) {
-            if (libbalsa_address_book_ldap_open_connection(ab_ldap) != LDAP_SUCCESS)
+            if ((rc=libbalsa_address_book_ldap_open_connection(ab_ldap))
+                != LDAP_SUCCESS)
                 return LBABERR_CANNOT_CONNECT;
         }
-
+        
         /* 
          * Attempt to search for e-mail addresses. It returns success 
          * or failure, but not all the matches. 
@@ -750,7 +751,8 @@ libbalsa_address_book_ldap_remove_address(LibBalsaAddressBook *ab,
     g_return_val_if_fail(addr != NULL, LBABERR_CANNOT_WRITE);
 
     if (ab_ldap->directory == NULL) {
-        if (libbalsa_address_book_ldap_open_connection(ab_ldap) != LDAP_SUCCESS)
+        if( (rc=libbalsa_address_book_ldap_open_connection(ab_ldap))
+           != LDAP_SUCCESS)
            return LBABERR_CANNOT_CONNECT;
     }
 
@@ -824,7 +826,8 @@ libbalsa_address_book_ldap_modify_address(LibBalsaAddressBook *ab,
     /* the email address has not changed, continue with changing other
      * attributes. */
     if (ab_ldap->directory == NULL) {
-        if (libbalsa_address_book_ldap_open_connection(ab_ldap) != LDAP_SUCCESS)
+        if ((rc = libbalsa_address_book_ldap_open_connection(ab_ldap))
+           != LDAP_SUCCESS)
            return LBABERR_CANNOT_CONNECT;
     }
 
@@ -1056,7 +1059,8 @@ libbalsa_address_book_ldap_alias_complete(LibBalsaAddressBook * ab,
         return NULL;
 
     if (ab_ldap->directory == NULL) {
-        if (libbalsa_address_book_ldap_open_connection(ab_ldap) != LDAP_SUCCESS)
+        if( (rc=libbalsa_address_book_ldap_open_connection(ab_ldap))
+           != LDAP_SUCCESS)
            return NULL;
     }
 
diff --git a/libbalsa/address-view.c b/libbalsa/address-view.c
index 7e003cf84..c56b9291b 100644
--- a/libbalsa/address-view.c
+++ b/libbalsa/address-view.c
@@ -220,7 +220,7 @@ lbav_append_addresses(LibBalsaAddressView * address_view,
 
     for (; match; match = match->next) {
         InternetAddress *ia = match->data;
-        name = internet_address_to_string(ia, NULL, FALSE);
+        name = internet_address_to_string(ia, FALSE);
         gtk_list_store_append(store, &iter);
         gtk_list_store_set(store, &iter, COMPLETION_NAME_COL, name, -1);
         g_free(name);
@@ -392,7 +392,7 @@ lbav_add_from_list(LibBalsaAddressView * address_view,
 
     for (i = 0; i < internet_address_list_length(list); i++) {
         InternetAddress *ia = internet_address_list_get_address(list, i);
-        gchar *name = internet_address_to_string(ia, NULL, FALSE);
+        gchar *name = internet_address_to_string(ia, FALSE);
 
         libbalsa_utf8_sanitize(&name, address_view->fallback, NULL);
         lbav_clean_text(name);
@@ -419,8 +419,7 @@ static gboolean
 lbav_add_from_string(LibBalsaAddressView * address_view,
                      GtkTreeIter * iter, const gchar * string)
 {
-    InternetAddressList *list = internet_address_list_parse(libbalsa_parser_options(), string);
-
+    InternetAddressList *list = internet_address_list_parse_string(string);
     gboolean retval = FALSE;
 
     if (list) {
@@ -751,8 +750,8 @@ lbav_focus_out_cb(GtkEntry * entry, GdkEventFocus * event,
         if (match) {
             if (!match->next) {
                 gchar *the_addr =
-                    internet_address_to_string((InternetAddress *) match->data,
-                                                NULL, FALSE);
+                    internet_address_to_string((InternetAddress *) match->
+                                               data, FALSE);
 
                 g_signal_handlers_block_by_func(entry,
                                                 lbav_entry_changed_cb,
@@ -1254,10 +1253,10 @@ libbalsa_address_view_get_list(LibBalsaAddressView * address_view,
                            ADDRESS_TYPE_COL, &this_type,
                            ADDRESS_NAME_COL, &name, -1);
 
-        if (this_type == type && name != NULL) {
+        if (this_type == type) {
             InternetAddressList *tmp_list =
-                internet_address_list_parse(libbalsa_parser_options(), name);
-            if (tmp_list != NULL) {
+                internet_address_list_parse_string(name);
+            if (tmp_list) {
                 internet_address_list_append(address_list, tmp_list);
                 g_object_unref(tmp_list);
             }
diff --git a/libbalsa/address.c b/libbalsa/address.c
index 4e1f8f0d9..5ba9cb5ad 100644
--- a/libbalsa/address.c
+++ b/libbalsa/address.c
@@ -565,7 +565,7 @@ rfc2822_mailbox(const gchar * full_name, const gchar * address)
     gchar *new_str;
 
     ia = internet_address_mailbox_new(full_name, address);
-    new_str = internet_address_to_string(ia, NULL, FALSE);
+    new_str = internet_address_to_string(ia, FALSE);
     g_object_unref(ia);
 
     return new_str;
@@ -585,7 +585,7 @@ rfc2822_group(const gchar *full_name, GList *addr_list)
        internet_address_group_add_member(INTERNET_ADDRESS_GROUP(ia), member);
        g_object_unref(member);
     }
-    res = internet_address_to_string(ia, NULL, FALSE);
+    res = internet_address_to_string(ia, FALSE);
     g_object_unref(ia);
 
     return res;
diff --git a/libbalsa/autocrypt.c b/libbalsa/autocrypt.c
index 632d8c28e..1609edb50 100644
--- a/libbalsa/autocrypt.c
+++ b/libbalsa/autocrypt.c
@@ -91,24 +91,23 @@ enum {
 };
 
 
-typedef struct {
-       gconstpointer keydata;
-       gsize keysize;
-       gchar *fingerprint;
-       gint64 expires;
-} ac_key_data_t;
-
-
 static void autocrypt_close(void);
-static gboolean extract_ac_keydata(GMimeAutocryptHeader  *autocrypt_header,
-                                                                  ac_key_data_t         *dest,
-                                                                  GError               **error);
-static void add_or_update_user_info(GMimeAutocryptHeader    *autocrypt_header,
-                                                                       const ac_key_data_t     *ac_key_data,
-                                                                       gboolean                 update,
-                                                                       GError                  **error);
-static void update_last_seen(GMimeAutocryptHeader  *autocrypt_header,
-                                                        GError                   **error);
+static AutocryptData *scan_autocrypt_headers(GList * const  header_list,
+                                                                                        const gchar   
*from_addr)
+       G_GNUC_WARN_UNUSED_RESULT;
+static AutocryptData *parse_autocrypt_header(const gchar *value)
+       G_GNUC_WARN_UNUSED_RESULT;
+static gboolean eval_autocrypt_attr(const gchar   *attr,
+                                                                       const gchar   *value,
+                                                                       gboolean      *seen,
+                                                                       AutocryptData *target);
+static void add_or_update_user_info(const AutocryptData  *user_info,
+                                                                       time_t                date_header,
+                                                                       gboolean              update,
+                                                                       GError              **error);
+static void update_last_seen(const gchar  *addr,
+                                                        time_t        date_header,
+                                                        GError      **error);
 static AutocryptData *autocrypt_user_info(const gchar  *mailbox,
                                                                                  GError      **error)
        G_GNUC_WARN_UNUSED_RESULT;
@@ -133,13 +132,13 @@ gboolean
 autocrypt_init(GError **error)
 {
        static const gchar * const prepare_statements[NUM_QUERIES] = {
-               "SELECT * FROM autocrypt WHERE addr = LOWER(?)",
-               "INSERT INTO autocrypt VALUES (LOWER(?1), ?2, ?2, ?3, ?4, ?5, ?6)",
+               "SELECT * FROM autocrypt WHERE LOWER(addr) = ?",
+               "INSERT INTO autocrypt VALUES (?1, ?2, ?2, ?3, ?4, ?5, ?6)",
                "UPDATE autocrypt SET last_seen = MAX(?2, last_seen), ac_timestamp = ?2, pubkey = ?3, 
fingerprint = ?4,"
-               " expires = ?5, prefer_encrypt = ?6 WHERE addr = LOWER(?1)",
-               "UPDATE autocrypt SET last_seen = ?2 WHERE addr = LOWER(?1) AND last_seen < ?2 AND 
ac_timestamp < ?2",
+               " expires = ?5, prefer_encrypt = ?6 WHERE addr = ?1",
+               "UPDATE autocrypt SET last_seen = ?2 WHERE addr = ?1 AND last_seen < ?2 AND ac_timestamp < 
?2",
                "SELECT pubkey FROM autocrypt WHERE fingerprint LIKE ?",
-               "SELECT addr, last_seen, ac_timestamp, prefer_encrypt, pubkey FROM autocrypt ORDER BY addr 
ASC"
+               "SELECT addr, last_seen, ac_timestamp, prefer_encrypt, pubkey FROM autocrypt ORDER BY 
LOWER(addr) ASC"
        };
        gboolean result;
 
@@ -200,22 +199,17 @@ void
 autocrypt_from_message(LibBalsaMessage  *message,
                                           GError          **error)
 {
-       LibBalsaMessageHeaders *headers;
-       ac_key_data_t ac_key_data;
-       time_t ac_header_time;
+       const gchar *from_addr;
+       AutocryptData *autocrypt;
+        LibBalsaMessageHeaders *headers;
 
        g_return_if_fail(LIBBALSA_IS_MESSAGE(message));
-       headers = libbalsa_message_get_headers(message);
+        headers = libbalsa_message_get_headers(message);
        g_return_if_fail(headers != NULL);
+       g_return_if_fail(headers->from != NULL);
+       g_return_if_fail(headers->content_type != NULL);
        g_return_if_fail(autocrypt_db != NULL);
 
-       /* return silently if there is no gmime autocrypt header
-        * note that it will *always* contain a valid sender address and effective date if it exists, so 
there is no need to validate
-        * the data returned from the g_mime_autocrypt_header_get_* accessor functions, except for the key 
data */
-       if (headers->autocrypt_hdr == NULL) {
-               return;
-       }
-
        // FIXME - we should ignore spam - how can we detect it?
 
        /* check for content types which shall be ignored
@@ -227,36 +221,47 @@ autocrypt_from_message(LibBalsaMessage  *message,
                return;
        }
 
-    /* ignore messages without a Date: header or with a date in the future */
-       ac_header_time = 
g_date_time_to_unix(g_mime_autocrypt_header_get_effective_date(headers->autocrypt_hdr));
-    if (ac_header_time > time(NULL)) {
-       g_debug("no Date: header or value in the future, ignored");
-       return;
-    }
+       /* check for exactly one From: mailbox address - others shall be ignored */
+       if ((internet_address_list_length(headers->from) != 1) ||
+               !INTERNET_ADDRESS_IS_MAILBOX(internet_address_list_get_address(headers->from, 0))) {
+               g_debug("require exactly one From: address, ignored");
+               return;
+       }
+
+       /* ignore messages without a Date: header or with a date in the future */
+       if ((headers->date == 0) || (headers->date > time(NULL))) {
+               g_debug("no Date: header or value in the future, ignored");
+               return;
+       }
+
+       /* get the From: address (is a mailbox, checked above) */
+       from_addr =
+               
internet_address_mailbox_get_addr(INTERNET_ADDRESS_MAILBOX(internet_address_list_get_address(headers->from, 
0)));
+       g_debug("message from '%s', date %ld", from_addr, headers->date);
+
+       /* scan for Autocrypt headers */
+       autocrypt = scan_autocrypt_headers(headers->user_hdrs, from_addr);
 
     /* update the database */
     G_LOCK(db_mutex);
-    if (extract_ac_keydata(headers->autocrypt_hdr, &ac_key_data, error)) {
+    if (autocrypt != NULL) {
        AutocryptData *db_info;
 
-       db_info = autocrypt_user_info(g_mime_autocrypt_header_get_address_as_string(headers->autocrypt_hdr), 
error);
+       db_info = autocrypt_user_info(autocrypt->addr, error);
        if (db_info != NULL) {
-               if (ac_header_time > db_info->ac_timestamp) {
-                       add_or_update_user_info(headers->autocrypt_hdr, &ac_key_data, TRUE, error);
+               if (headers->date > db_info->ac_timestamp) {
+                       add_or_update_user_info(autocrypt, headers->date, TRUE, error);
                } else {
                        g_info("message timestamp %ld not newer than autocrypt db timestamp %ld, ignore 
message",
                                (long) headers->date, (long) db_info->ac_timestamp);
                }
                autocrypt_free(db_info);
        } else {
-               add_or_update_user_info(headers->autocrypt_hdr, &ac_key_data, FALSE, error);
+               add_or_update_user_info(autocrypt, headers->date, FALSE, error);
        }
-       g_free(ac_key_data.fingerprint);
+       autocrypt_free(autocrypt);
     } else {
-       /* note: we update the last seen db field if there is no key (i.e. the message did not contain an 
Autocrypt: header) *and*
-        * if the key data is broken, or gpgme failed to handle it for some other reason.  We /might/ want to 
distinguish between
-        * these two cases. */
-        update_last_seen(headers->autocrypt_hdr, error);
+       update_last_seen(from_addr, headers->date, error);
     }
     G_UNLOCK(db_mutex);
 }
@@ -269,9 +274,9 @@ autocrypt_header(LibBalsaIdentity *identity, GError **error)
        const gchar *mailbox;
        gchar *use_fpr = NULL;
        gchar *result = NULL;
-       InternetAddress *ia;
-       const gchar *force_gpg_key_id;
-       AutocryptMode autocrypt_mode;
+        InternetAddress *ia;
+        const gchar *force_gpg_key_id;
+        AutocryptMode autocrypt_mode;
 
        g_return_val_if_fail(identity != NULL, NULL);
        autocrypt_mode = libbalsa_identity_get_autocrypt_mode(identity);
@@ -281,7 +286,7 @@ autocrypt_header(LibBalsaIdentity *identity, GError **error)
        mailbox = internet_address_mailbox_get_addr(INTERNET_ADDRESS_MAILBOX(ia));
 
        /* no key fingerprint has been passed - try to find the fingerprint of a secret key matching the 
passed mailbox */
-       force_gpg_key_id = libbalsa_identity_get_force_gpg_key_id(identity);
+        force_gpg_key_id = libbalsa_identity_get_force_gpg_key_id(identity);
        if ((force_gpg_key_id == NULL) || (force_gpg_key_id[0] == '\0')) {
                gpgme_ctx_t ctx;
 
@@ -312,24 +317,25 @@ autocrypt_header(LibBalsaIdentity *identity, GError **error)
        }
 
        if (use_fpr != NULL) {
-               GBytes *keydata;
+               gchar *keydata;
 
                keydata = libbalsa_gpgme_export_autocrypt_key(use_fpr, mailbox, error);
                g_free(use_fpr);
                if (keydata != NULL) {
-                       GMimeAutocryptHeader *header;
+                       GString *buffer;
+                       gssize ins_fws;
 
-                       header = g_mime_autocrypt_header_new();
-                       g_mime_autocrypt_header_set_address_from_string(header, mailbox);
+                       buffer = g_string_new(NULL);
+                       g_string_append_printf(buffer, "addr=%s;", mailbox);
                        if (autocrypt_mode == AUTOCRYPT_PREFER_ENCRYPT) {
-                               g_mime_autocrypt_header_set_prefer_encrypt(header, 
GMIME_AUTOCRYPT_PREFER_ENCRYPT_MUTUAL);
-                       } else {
-                               g_mime_autocrypt_header_set_prefer_encrypt(header, 
GMIME_AUTOCRYPT_PREFER_ENCRYPT_NONE);
+                               g_string_append(buffer, "prefer-encrypt=mutual;");
+                       }
+                       g_string_append_printf(buffer, "keydata=%s", keydata);
+                       for (ins_fws = 66; ins_fws < (gssize) buffer->len; ins_fws += 78) {
+                               g_string_insert(buffer, ins_fws, "\n\t");
                        }
-                       g_mime_autocrypt_header_set_keydata(header, keydata);
-                       g_bytes_unref(keydata);
-                       result = g_mime_autocrypt_header_to_string(header, FALSE);
-                       g_object_unref(header);
+                       result = g_string_free(buffer, FALSE);
+                       g_free(keydata);
                }
        }
 
@@ -621,58 +627,102 @@ autocrypt_close(void)
 }
 
 
+/** \brief Extract Autocrypt data from message headers
+ *
+ * \param header_list list of headers pointing to gchar** (name, value) pairs
+ * \param from_addr sender mailbox extracted from the From: header
+ * \return the data extracted from the Autocrypt header, or NULL if no valid data is present
+ *
+ * The following rules apply according to the Autocrypt Level 1 standard:
+ * - invalid Autocrypt headers are just discarded, but checking for more Autocrypt headers continues (see 
section 2.1 <em>The
+ *   Autocrypt Header</em>, https://autocrypt.org/level1.html#the-autocrypt-header);
+ * - if the \em addr attribute of an otherwise valid Autocrypt header does not match the mailbox extracted 
from the From: message
+ *   header, the Autocrypt header shall be treated as being invalid and discarded (see section 2.1);
+ * - if more than one valid Autocrypt header is present, \em all Autocrypt headers shall be discarded (see 
section 2.3 <em>Updating
+ *   Autocrypt Peer State</em>, https://autocrypt.org/level1.html#updating-autocrypt-peer-state);
+ *
+ * Thus, this function returns a newly allocated Autocrypt data structure iff the passed headers list 
contains exactly \em one valid
+ * Autocrypt header.
+ */
 static AutocryptData *
-autocrypt_user_info(const gchar *mailbox, GError **error)
+scan_autocrypt_headers(GList * const header_list, const gchar *from_addr)
 {
-       int sqlite_res;
-       AutocryptData *user_info = NULL;
+       GList *header;
+       AutocryptData *result = NULL;
+
+       for (header = header_list; header != NULL; header = header->next) {
+               const gchar **header_parts = (const gchar **) header->data;
+
+               if ((g_ascii_strcasecmp(header_parts[0], "Autocrypt") == 0) && (header_parts[1] != NULL)) {
+                       AutocryptData *new_data;
+
+                       new_data = parse_autocrypt_header(header_parts[1]);
+                       if (new_data != NULL) {
+                               if (result == NULL) {
+                               if (g_ascii_strcasecmp(new_data->addr, from_addr) != 0) {
+                                       g_info("Autocrypt header for '%s' in message from '%s', ignore 
header", new_data->addr, from_addr);
+                                       autocrypt_free(new_data);
+                               } else {
+                                       result = new_data;
+                               }
+                               } else {
+                                       g_info("more than one valid Autocrypt header");
+                                       autocrypt_free(result);
+                                       autocrypt_free(new_data);
+                                       return NULL;
+                               }
+                       }
+               }
+       }
 
-       g_return_val_if_fail((mailbox != NULL) && (autocrypt_db != NULL), NULL);
+       return result;
+}
 
-       sqlite_res = sqlite3_bind_text(query[0], 1, mailbox, -1, SQLITE_STATIC);
-       if (sqlite_res == SQLITE_OK) {
-               sqlite_res = sqlite3_step(query[0]);
-               if (sqlite_res == SQLITE_ROW) {
-                       user_info = g_new0(AutocryptData, 1U);
-                       user_info->addr = g_strdup((const gchar *) sqlite3_column_text(query[0], 0));
-                       user_info->last_seen = sqlite3_column_int64(query[0], 1);
-                       user_info->ac_timestamp = sqlite3_column_int64(query[0], 2);
-                       user_info->keydata = g_bytes_new(sqlite3_column_blob(query[0], 3), 
sqlite3_column_bytes(query[0], 3));
-                       user_info->fingerprint = g_strdup((const gchar *) sqlite3_column_text(query[0], 4));
-                       user_info->expires = sqlite3_column_int64(query[0], 5);
-                       user_info->prefer_encrypt = (sqlite3_column_int(query[0], 6) != 0);
-                       sqlite_res = sqlite3_step(query[0]);
-               }
 
-               if (sqlite_res != SQLITE_DONE) {
-                       g_set_error(error, AUTOCRYPT_ERROR_QUARK, sqlite_res, _("error reading Autocrypt data 
for “%s”: %s"), mailbox,
-                               sqlite3_errmsg(autocrypt_db));
-                       autocrypt_free(user_info);
-                       user_info = NULL;
-               }
+static AutocryptData *
+parse_autocrypt_header(const gchar *value)
+{
+       gchar **attributes;
+       gboolean attr_seen[3] = { FALSE, FALSE, FALSE };
+       AutocryptData *new_data;
+       gint n;
+       gboolean broken;
+
+       new_data = g_new0(AutocryptData, 1U);
+       attributes = g_strsplit(value, ";", -1);
+       if (attributes == NULL) {
+               g_info("empty Autocrypt header");
+               broken = TRUE;
        } else {
-               g_set_error(error, AUTOCRYPT_ERROR_QUARK, sqlite_res, _("error reading Autocrypt data for 
“%s”: %s"), mailbox,
-                       sqlite3_errmsg(autocrypt_db));
+               broken = FALSE;
        }
-       sqlite3_reset(query[0]);
 
-       return user_info;
-}
+       for (n = 0; !broken && (attributes[n] != NULL); n++) {
+               gchar **items;
 
+               items = g_strsplit(attributes[n], "=", 2);
+               if ((items == NULL) || (items[0] == NULL) || (items[1] == NULL)) {
+                       g_info("bad Autocrypt header attribute");
+                       broken = TRUE;
+               } else {
+                       broken = !eval_autocrypt_attr(g_strstrip(items[0]), g_strstrip(items[1]), attr_seen, 
new_data);
+               }
+               g_strfreev(items);
+       }
+       g_strfreev(attributes);
 
-static gboolean
-extract_ac_keydata(GMimeAutocryptHeader *autocrypt_header, ac_key_data_t *dest, GError **error)
-{
-       GBytes *keydata;
-       gboolean success = FALSE;
+       if (!broken) {
+               if (!attr_seen[0] || !attr_seen[2]) {
+                       g_info("missing mandatory Autocrypt header attribute");
+                       broken = TRUE;
+               }
+       }
 
-       keydata = g_mime_autocrypt_header_get_keydata(autocrypt_header);
-       if (keydata) {
+       /* try to import the key into a temporary context */
+       if (!broken) {
+               gboolean success = FALSE;
                gpgme_ctx_t ctx;
 
-               dest->keydata = g_bytes_get_data(keydata, &dest->keysize);
-
-               /* try to import the key into a temporary context: validate, get fingerprint and expiry date 
*/
                ctx = libbalsa_gpgme_new_with_proto(GPGME_PROTOCOL_OpenPGP, NULL, NULL, NULL);
                if (ctx != NULL) {
                        gchar *temp_dir = NULL;
@@ -681,25 +731,24 @@ extract_ac_keydata(GMimeAutocryptHeader *autocrypt_header, ac_key_data_t *dest,
                                g_warning("Failed to create a temporary folder");
                        } else {
                                GList *keys = NULL;
-                               GError *gpg_error = NULL;
+                               GError *error = NULL;
                                guint bad_keys = 0U;
 
-                               success = libbalsa_gpgme_ctx_set_home(ctx, temp_dir, &gpg_error) &&
-                                       libbalsa_gpgme_import_bin_key(ctx, keydata, NULL, &gpg_error) &&
-                                       libbalsa_gpgme_list_keys(ctx, &keys, &bad_keys, NULL, FALSE, FALSE, 
FALSE, &gpg_error);
+                               success = libbalsa_gpgme_ctx_set_home(ctx, temp_dir, &error) &&
+                                       libbalsa_gpgme_import_bin_key(ctx, new_data->keydata, NULL, &error) &&
+                                       libbalsa_gpgme_list_keys(ctx, &keys, &bad_keys, NULL, FALSE, FALSE, 
FALSE, &error);
                                if (success && (keys != NULL) && (keys->next == NULL)) {
                                        gpgme_key_t key = (gpgme_key_t) keys->data;
 
                                        if ((key != NULL) && (key->subkeys != NULL)) {
-                                               dest->fingerprint = g_strdup(key->subkeys->fpr);
-                                               dest->expires = key->subkeys->expires;
+                                               new_data->fingerprint = g_strdup(key->subkeys->fpr);
+                                               new_data->expires = key->subkeys->expires;
                                        }
                                } else {
-                                       g_warning("Failed to import or list key data for '%s': %s (%u keys, 
%u bad)",
-                                               
g_mime_autocrypt_header_get_address_as_string(autocrypt_header),
-                                               (gpg_error != NULL) ? gpg_error->message : "unknown", (keys 
!= NULL) ? g_list_length(keys) : 0U, bad_keys);
+                                       g_warning("Failed to import or list key data for '%s': %s (%u keys, 
%u bad)", new_data->addr,
+                                               (error != NULL) ? error->message : "unknown", (keys != NULL) 
? g_list_length(keys) : 0U, bad_keys);
                                }
-                               g_clear_error(&gpg_error);
+                               g_clear_error(&error);
 
                                g_list_free_full(keys, (GDestroyNotify) gpgme_key_release);
                                libbalsa_delete_directory_contents(temp_dir);
@@ -710,52 +759,139 @@ extract_ac_keydata(GMimeAutocryptHeader *autocrypt_header, ac_key_data_t *dest,
                }
        }
 
-       return success;
+       /* check if a broken header has been detected, or if importing the key failed */
+       if (broken || (new_data->fingerprint == NULL)) {
+               autocrypt_free(new_data);
+               new_data = NULL;
+       } else {
+               g_debug("valid Autocrypt header for '%s', prefer encrypt %d, key fingerprint %s", 
new_data->addr, new_data->prefer_encrypt,
+                       new_data->fingerprint);
+       }
+
+       return new_data;
 }
 
 
-static void
-add_or_update_user_info(GMimeAutocryptHeader *autocrypt_header, const ac_key_data_t *ac_key_data, gboolean 
update, GError **error)
+static gboolean
+eval_autocrypt_attr(const gchar *attr, const gchar *value, gboolean *seen, AutocryptData *target)
 {
-       guint query_idx;
-       const gchar *addr;
-       gint64 date_header;
-       gint prefer_encrypt;
+       gboolean result = FALSE;
 
-       query_idx = update ? 2 : 1;
+       if (seen[2]) {
+               g_info("broken Autocrypt header, extra attribute after keydata");
+       } else if (strcmp(attr, "addr") == 0) {
+               if (seen[0]) {
+                       g_info("duplicated Autocrypt header attribute 'addr'");
+               } else {
+                       seen[0] = TRUE;
+                       /* note: not exactly the canonicalisation as required by the Autocrypt standard, but 
should work in all practical use
+                        * cases... */
+                       target->addr = g_ascii_strdown(value, -1);
+                       result = TRUE;
+               }
+       } else if (strcmp(attr, "prefer-encrypt") == 0) {
+               if (seen[1]) {
+                       g_info("duplicated Autocrypt header attribute 'addr'");
+               } else {
+                       seen[1] = TRUE;
+                       if (strcmp(value, "mutual") == 0) {
+                               target->prefer_encrypt = TRUE;
+                               result = TRUE;
+                       } else {
+                               g_info("bad value '%s' for Autocrypt header attribute 'prefer-encrypt'", 
value);
+                       }
+               }
+       } else if (strcmp(attr, "keydata") == 0) {
+               guchar *data;
+               gsize len;
+
+               seen[2] = TRUE;
+               data = g_base64_decode(value, &len);
+               if (data == NULL) {
+                       g_info("invalid keydata in Autocrypt header");
+               } else {
+                       target->keydata = g_bytes_new_take(data, len);
+                       result = TRUE;
+               }
+       } else if (attr[0] == '_') {
+               g_debug("ignoring non-critical Autocrypt header attribute '%s'", attr);
+               result = TRUE;          /* note that this is no error */
+       } else {
+               g_info("unexpected Autocrypt header attribute '%s'", attr);
+       }
+
+       return result;
+}
+
+
+static AutocryptData *
+autocrypt_user_info(const gchar *mailbox, GError **error)
+{
+       int sqlite_res;
+       AutocryptData *user_info = NULL;
+
+       g_return_val_if_fail((mailbox != NULL) && (autocrypt_db != NULL), NULL);
+
+       sqlite_res = sqlite3_bind_text(query[0], 1, mailbox, -1, SQLITE_STATIC);
+       if (sqlite_res == SQLITE_OK) {
+               sqlite_res = sqlite3_step(query[0]);
+               if (sqlite_res == SQLITE_ROW) {
+                       user_info = g_new0(AutocryptData, 1U);
+                       user_info->addr = g_strdup((const gchar *) sqlite3_column_text(query[0], 0));
+                       user_info->last_seen = sqlite3_column_int64(query[0], 1);
+                       user_info->ac_timestamp = sqlite3_column_int64(query[0], 2);
+                       user_info->keydata = g_bytes_new(sqlite3_column_blob(query[0], 3), 
sqlite3_column_bytes(query[0], 3));
+                       user_info->fingerprint = g_strdup((const gchar *) sqlite3_column_text(query[0], 4));
+                       user_info->expires = sqlite3_column_int64(query[0], 5);
+                       user_info->prefer_encrypt = (sqlite3_column_int(query[0], 6) != 0);
+                       sqlite_res = sqlite3_step(query[0]);
+               }
 
-       addr = g_mime_autocrypt_header_get_address_as_string(autocrypt_header);
-       date_header = g_date_time_to_unix(g_mime_autocrypt_header_get_effective_date(autocrypt_header));
-       if (g_mime_autocrypt_header_get_prefer_encrypt(autocrypt_header) == 
GMIME_AUTOCRYPT_PREFER_ENCRYPT_MUTUAL) {
-               prefer_encrypt = (gint) AUTOCRYPT_PREFER_ENCRYPT;
+               if (sqlite_res != SQLITE_DONE) {
+                       g_set_error(error, AUTOCRYPT_ERROR_QUARK, sqlite_res, _("error reading Autocrypt data 
for “%s”: %s"), mailbox,
+                               sqlite3_errmsg(autocrypt_db));
+                       autocrypt_free(user_info);
+                       user_info = NULL;
+               }
        } else {
-               prefer_encrypt = (gint) AUTOCRYPT_NOPREFERENCE;
+               g_set_error(error, AUTOCRYPT_ERROR_QUARK, sqlite_res, _("error reading Autocrypt data for 
“%s”: %s"), mailbox,
+                       sqlite3_errmsg(autocrypt_db));
        }
+       sqlite3_reset(query[0]);
+
+       return user_info;
+}
 
-       if ((sqlite3_bind_text(query[query_idx], 1, addr, -1, SQLITE_STATIC) != SQLITE_OK) ||
+
+static void
+add_or_update_user_info(const AutocryptData *user_info, time_t date_header, gboolean update, GError **error)
+{
+       guint query_idx;
+       gconstpointer keyvalue;
+       gsize keysize;
+
+       query_idx = update ? 2 : 1;
+       keyvalue = g_bytes_get_data(user_info->keydata, &keysize);
+       if ((sqlite3_bind_text(query[query_idx], 1, user_info->addr, -1, SQLITE_STATIC) != SQLITE_OK) ||
                (sqlite3_bind_int64(query[query_idx], 2, date_header) != SQLITE_OK) ||
-               (sqlite3_bind_blob(query[query_idx], 3, ac_key_data->keydata, ac_key_data->keysize, 
SQLITE_STATIC) != SQLITE_OK) ||
-               (sqlite3_bind_text(query[query_idx], 4, ac_key_data->fingerprint, -1, SQLITE_STATIC) != 
SQLITE_OK) ||
-               (sqlite3_bind_int64(query[query_idx], 5, ac_key_data->expires) != SQLITE_OK) ||
-               (sqlite3_bind_int(query[query_idx], 6, prefer_encrypt) != SQLITE_OK) ||
+               (sqlite3_bind_blob(query[query_idx], 3, keyvalue, keysize, SQLITE_STATIC) != SQLITE_OK) ||
+               (sqlite3_bind_text(query[query_idx], 4, user_info->fingerprint, -1, SQLITE_STATIC) != 
SQLITE_OK) ||
+               (sqlite3_bind_int64(query[query_idx], 5, user_info->expires) != SQLITE_OK) ||
+               (sqlite3_bind_int(query[query_idx], 6, user_info->prefer_encrypt) != SQLITE_OK) ||
                (sqlite3_step(query[query_idx]) != SQLITE_DONE)) {
-               g_set_error(error, AUTOCRYPT_ERROR_QUARK, -1, update ? _("update user “%s” failed: %s") : 
_("insert user “%s” failed: %s"),
-                       addr, sqlite3_errmsg(autocrypt_db));
+               g_set_error(error, AUTOCRYPT_ERROR_QUARK, -1,
+                        update ? _("update user “%s” failed: %s") : _("insert user “%s” failed: %s"),
+                       user_info->addr, sqlite3_errmsg(autocrypt_db));
        } else {
-               g_debug("%s user '%s': %d", update ? "updated" : "inserted", addr, 
sqlite3_changes(autocrypt_db));
+               g_debug("%s user '%s': %d", update ? "updated" : "inserted", user_info->addr, 
sqlite3_changes(autocrypt_db));
        }
        sqlite3_reset(query[query_idx]);
 }
 
 
 static void
-update_last_seen(GMimeAutocryptHeader *autocrypt_header, GError **error)
+update_last_seen(const gchar *addr, time_t date_header, GError **error)
 {
-       const gchar *addr;
-       time_t date_header;
-
-       addr = g_mime_autocrypt_header_get_address_as_string(autocrypt_header);
-       date_header = g_date_time_to_unix(g_mime_autocrypt_header_get_effective_date(autocrypt_header));
        if ((sqlite3_bind_text(query[3], 1, addr, -1, SQLITE_STATIC) != SQLITE_OK) ||
                (sqlite3_bind_int64(query[3], 2, date_header) != SQLITE_OK) ||
                (sqlite3_step(query[3]) != SQLITE_DONE)) {
diff --git a/libbalsa/body.c b/libbalsa/body.c
index 4db6f7cf7..1ff135c7e 100644
--- a/libbalsa/body.c
+++ b/libbalsa/body.c
@@ -103,7 +103,7 @@ libbalsa_message_body_extract_embedded_headers(GMimeMessage* msg)
 {
     LibBalsaMessageHeaders *ehdr;
     const char *subj;
-    GDateTime *datetime;
+    int offset;
 
     ehdr = g_new0(LibBalsaMessageHeaders, 1);
 
@@ -113,14 +113,11 @@ libbalsa_message_body_extract_embedded_headers(GMimeMessage* msg)
     subj = g_mime_message_get_subject(msg);
     if (subj) {
        ehdr->subject =
-           g_mime_utils_header_decode_text(libbalsa_parser_options(), subj);
+           g_mime_utils_header_decode_text(subj);
        libbalsa_utf8_sanitize(&ehdr->subject, TRUE, NULL);
-    } else
+    } else 
        ehdr->subject = g_strdup(_("(No subject)"));
-
-    datetime = g_mime_message_get_date(msg);
-    if (datetime != NULL)
-        ehdr->date = g_date_time_to_unix(datetime);
+    g_mime_message_get_date(msg, &ehdr->date, &offset);
 
     return ehdr;
 }
@@ -167,7 +164,7 @@ libbalsa_message_body_set_types(LibBalsaMessageBody * body)
     else body->body_type = LIBBALSA_MESSAGE_BODY_TYPE_OTHER;
 
     g_free(body->content_type);
-    body->content_type = g_mime_content_type_get_mime_type(type);
+    body->content_type = g_mime_content_type_to_string(type);
 }
 
 static LibBalsaMessageBody **
@@ -230,9 +227,8 @@ libbalsa_message_body_set_text_rfc822headers(LibBalsaMessageBody *body)
 
        g_mime_stream_reset(headers);
        parser = g_mime_parser_new_with_stream(headers);
-        g_mime_parser_set_format(parser, GMIME_FORMAT_MESSAGE);
        g_object_unref(headers);
-       dummy_msg = g_mime_parser_construct_message(parser, libbalsa_parser_options());
+       dummy_msg = g_mime_parser_construct_message(parser);
        g_object_unref(parser);
 
        body->embhdrs = libbalsa_message_body_extract_embedded_headers(dummy_msg);
@@ -306,7 +302,7 @@ libbalsa_message_body_get_parameter(LibBalsaMessageBody * body,
        type = g_mime_object_get_content_type(body->mime_part);
        res = g_strdup(g_mime_content_type_get_parameter(type, param));
     } else if (body->content_type) {
-       type = g_mime_content_type_parse(libbalsa_parser_options(), body->content_type);
+       type = g_mime_content_type_new_from_string(body->content_type);
        res = g_strdup(g_mime_content_type_get_parameter(type, param));
        g_object_unref(type);
     }
@@ -484,7 +480,7 @@ libbalsa_message_body_get_part_stream(LibBalsaMessageBody * body,
     gchar *mime_type = NULL;
     const gchar *charset;
 
-    wrapper = g_mime_part_get_content(GMIME_PART(body->mime_part));
+    wrapper = g_mime_part_get_content_object(GMIME_PART(body->mime_part));
     if (!wrapper) {
         /* part is incomplete. */
         g_set_error(err, LIBBALSA_MAILBOX_ERROR,
@@ -564,7 +560,7 @@ libbalsa_message_body_get_message_part_stream(LibBalsaMessageBody * body,
     mailbox = libbalsa_message_get_mailbox(body->message);
     libbalsa_mailbox_lock_store(mailbox);
     bytes_written =
-        g_mime_object_write_to_stream(GMIME_OBJECT(msg), NULL, stream);
+        g_mime_object_write_to_stream(GMIME_OBJECT(msg), stream);
     libbalsa_mailbox_unlock_store(mailbox);
     printf("Written %ld bytes of embedded message\n",
            (long) bytes_written);
@@ -748,8 +744,7 @@ libbalsa_message_body_save_stream(LibBalsaMessageBody * body,
         g_mime_stream_reset(stream);
 
         if (filter_crlf) {
-            GMimeFilter *filter = g_mime_filter_dos2unix_new(FALSE);
-
+            GMimeFilter *filter = g_mime_filter_crlf_new(FALSE, FALSE);
             stream =
                 libbalsa_message_body_stream_add_filter(stream, filter);
         }
@@ -758,7 +753,7 @@ libbalsa_message_body_save_stream(LibBalsaMessageBody * body,
         g_object_unref(stream);
     } else
         /* body->mime_part is neither a GMimePart nor a GMimeMessagePart. */
-        len = g_mime_object_write_to_stream(body->mime_part, NULL, dest);
+        len = g_mime_object_write_to_stream(body->mime_part, dest);
 
     libbalsa_mailbox_unlock_store(mailbox);
     g_object_unref(dest);
diff --git a/libbalsa/filter.c b/libbalsa/filter.c
index d5cbf4101..a9efa66d7 100644
--- a/libbalsa/filter.c
+++ b/libbalsa/filter.c
@@ -131,13 +131,13 @@ libbalsa_condition_matches(LibBalsaCondition* cond,
         }
         /* do the work */
        if (CONDITION_CHKMATCH(cond,CONDITION_MATCH_TO) && headers->to_list != NULL) {
-            str = internet_address_list_to_string(headers->to_list, NULL, FALSE);
+            str = internet_address_list_to_string(headers->to_list, FALSE);
            match = libbalsa_utf8_strstr(str,cond->match.string.string);
            g_free(str);
             if(match) break;
        }
        if (CONDITION_CHKMATCH(cond,CONDITION_MATCH_FROM) && headers->from != NULL) {
-            str = internet_address_list_to_string(headers->from, NULL, FALSE);
+            str = internet_address_list_to_string(headers->from, FALSE);
            match=libbalsa_utf8_strstr(str,cond->match.string.string);
            g_free(str);
            if (match) break;
@@ -150,7 +150,7 @@ libbalsa_condition_matches(LibBalsaCondition* cond,
             }
        }
        if (CONDITION_CHKMATCH(cond,CONDITION_MATCH_CC) && headers->cc_list != NULL) {
-            str = internet_address_list_to_string(headers->cc_list, NULL, FALSE);
+            str = internet_address_list_to_string(headers->cc_list, FALSE);
            match=libbalsa_utf8_strstr(str,cond->match.string.string);
            g_free(str);
            if (match) break;
diff --git a/libbalsa/gmime-application-pkcs7.c b/libbalsa/gmime-application-pkcs7.c
index 285879013..790bc6dd5 100644
--- a/libbalsa/gmime-application-pkcs7.c
+++ b/libbalsa/gmime-application-pkcs7.c
@@ -23,11 +23,19 @@
 
 #include <string.h>
 
-#include <gmime/gmime.h>
+#include <gmime/gmime-stream-filter.h>
+#include <gmime/gmime-filter-crlf.h>
+#include <gmime/gmime-filter-from.h>
+#include <gmime/gmime-filter-basic.h>
+#include <gmime/gmime-stream-mem.h>
+#include <gmime/gmime-parser.h>
+#include <gmime/gmime-message-part.h>
+#include <gmime/gmime-multipart.h>
+#include <gmime/gmime-multipart-signed.h>
+#include <gmime/gmime-multipart-encrypted.h>
 #include "libbalsa-gpgme.h"
 #include "gmime-application-pkcs7.h"
 #include <glib/gi18n.h>
-#include "misc.h"
 
 
 #ifdef G_LOG_DOMAIN
@@ -72,7 +80,7 @@ g_mime_application_pkcs7_decrypt_verify(GMimePart * pkcs7,
     }
 
     /* get the ciphertext stream */
-    wrapper = g_mime_part_get_content(GMIME_PART(pkcs7));
+    wrapper = g_mime_part_get_content_object(GMIME_PART(pkcs7));
     g_return_val_if_fail(wrapper, NULL); /* Incomplete part. */
     ciphertext = g_mime_stream_mem_new();
     g_mime_data_wrapper_write_to_stream(wrapper, ciphertext);
@@ -80,7 +88,7 @@ g_mime_application_pkcs7_decrypt_verify(GMimePart * pkcs7,
 
     stream = g_mime_stream_mem_new();
     filtered_stream = g_mime_stream_filter_new(stream);
-    crlf_filter = g_mime_filter_dos2unix_new(FALSE);
+    crlf_filter = g_mime_filter_crlf_new(FALSE, FALSE);
     g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_stream),
                             crlf_filter);
     g_object_unref(crlf_filter);
@@ -107,11 +115,11 @@ g_mime_application_pkcs7_decrypt_verify(GMimePart * pkcs7,
     g_object_unref(ciphertext);
 
     g_mime_stream_reset(stream);
-    parser = g_mime_parser_new_with_stream(stream);
-    g_mime_parser_set_format(parser, GMIME_FORMAT_MESSAGE);
+    parser = g_mime_parser_new();
+    g_mime_parser_init_with_stream(parser, stream);
     g_object_unref(stream);
 
-    decrypted = g_mime_parser_construct_part(parser, libbalsa_parser_options());
+    decrypted = g_mime_parser_construct_part(parser);
     g_object_unref(parser);
 
     if (decrypted)
@@ -148,12 +156,12 @@ g_mime_application_pkcs7_encrypt(GMimePart * pkcs7, GMimeObject * content,
     stream = g_mime_stream_mem_new();
     filtered_stream = g_mime_stream_filter_new(stream);
        
-    crlf_filter = g_mime_filter_unix2dos_new(FALSE);
+    crlf_filter = g_mime_filter_crlf_new(TRUE, FALSE);
     g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_stream),
                             crlf_filter);
     g_object_unref(crlf_filter);
        
-    g_mime_object_write_to_stream(content, NULL, filtered_stream);
+    g_mime_object_write_to_stream(content, filtered_stream);
     g_mime_stream_flush(filtered_stream);
     g_object_unref(filtered_stream);
        
@@ -177,7 +185,7 @@ g_mime_application_pkcs7_encrypt(GMimePart * pkcs7, GMimeObject * content,
     wrapper = g_mime_data_wrapper_new();
     g_mime_data_wrapper_set_stream(wrapper, ciphertext);
     g_object_unref(ciphertext);
-    g_mime_part_set_content(GMIME_PART(pkcs7), wrapper);
+    g_mime_part_set_content_object(GMIME_PART(pkcs7), wrapper);
     g_mime_part_set_filename(GMIME_PART(pkcs7), "smime.p7m");
     g_mime_part_set_content_encoding(GMIME_PART(pkcs7),
                                     GMIME_CONTENT_ENCODING_BASE64);
diff --git a/libbalsa/gmime-multipart-crypt.c b/libbalsa/gmime-multipart-crypt.c
index 2aad4dd1f..a260039ec 100644
--- a/libbalsa/gmime-multipart-crypt.c
+++ b/libbalsa/gmime-multipart-crypt.c
@@ -32,7 +32,6 @@
 #include <glib/gi18n.h>
 #include <glib.h>
 #include <gtk/gtk.h>
-#include "libbalsa.h"
 #include "libbalsa-gpgme.h"
 #include "gmime-multipart-crypt.h"
 
@@ -126,14 +125,14 @@ g_mime_gpgme_mps_sign(GMimeMultipartSigned * mps, GMimeObject * content,
     g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered), filter);
     g_object_unref(filter);
 
-    g_mime_object_write_to_stream(content, NULL, filtered);
+    g_mime_object_write_to_stream(content, filtered);
     g_mime_stream_flush(filtered);
     g_object_unref(filtered);
     g_mime_stream_reset(stream);
 
     /* Note: see rfc2015 or rfc3156, section 5.1 */
     filtered = g_mime_stream_filter_new(stream);
-    filter = g_mime_filter_unix2dos_new(FALSE);
+    filter = g_mime_filter_crlf_new(TRUE, FALSE);
     g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered), filter);
     g_object_unref(filter);
 
@@ -173,8 +172,7 @@ g_mime_gpgme_mps_sign(GMimeMultipartSigned * mps, GMimeObject * content,
 
     /* construct the content part */
     parser = g_mime_parser_new_with_stream(stream);
-    g_mime_parser_set_format(parser, GMIME_FORMAT_MESSAGE);
-    content = g_mime_parser_construct_part(parser, libbalsa_parser_options());
+    content = g_mime_parser_construct_part(parser);
     g_object_unref(stream);
     g_object_unref(parser);
 
@@ -183,7 +181,7 @@ g_mime_gpgme_mps_sign(GMimeMultipartSigned * mps, GMimeObject * content,
 
     wrapper = g_mime_data_wrapper_new();
     g_mime_data_wrapper_set_stream(wrapper, sigstream);
-    g_mime_part_set_content(signature, wrapper);
+    g_mime_part_set_content_object(signature, wrapper);
     g_object_unref(sigstream);
     g_object_unref(wrapper);
 
@@ -260,7 +258,7 @@ g_mime_gpgme_mps_verify(GMimeMultipartSigned * mps, GError ** error)
                                  GMIME_MULTIPART_SIGNED_SIGNATURE);
 
     /* make sure the protocol matches the signature content-type */
-    content_type = g_mime_content_type_get_mime_type(signature->content_type);
+    content_type = g_mime_content_type_to_string(signature->content_type);
     if (g_ascii_strcasecmp(content_type, protocol) != 0) {
        g_set_error(error, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR, "%s",
                    _
@@ -279,18 +277,18 @@ g_mime_gpgme_mps_verify(GMimeMultipartSigned * mps, GError ** error)
     filtered_stream = g_mime_stream_filter_new(stream);
 
     /* Note: see rfc2015 or rfc3156, section 5.1 */
-    crlf_filter = g_mime_filter_unix2dos_new(FALSE);
+    crlf_filter = g_mime_filter_crlf_new(TRUE, FALSE);
     g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_stream),
                             crlf_filter);
     g_object_unref(crlf_filter);
 
-    g_mime_object_write_to_stream(content, NULL, filtered_stream);
+    g_mime_object_write_to_stream(content, filtered_stream);
     g_mime_stream_flush(filtered_stream);
     g_object_unref(filtered_stream);
     g_mime_stream_reset(stream);
 
     /* get the signature stream */
-    wrapper = g_mime_part_get_content(GMIME_PART(signature));
+    wrapper = g_mime_part_get_content_object(GMIME_PART(signature));
 
     /* a s/mime signature is always encoded, a pgp signature shouldn't,
      * but there exist implementations which encode it... */
@@ -330,12 +328,12 @@ g_mime_gpgme_mpe_encrypt(GMimeMultipartEncrypted * mpe,
     stream = g_mime_stream_mem_new();
     filtered_stream = g_mime_stream_filter_new(stream);
 
-    crlf_filter = g_mime_filter_unix2dos_new(FALSE);
+    crlf_filter = g_mime_filter_crlf_new(TRUE, FALSE);
     g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_stream),
                             crlf_filter);
     g_object_unref(crlf_filter);
 
-    g_mime_object_write_to_stream(content, NULL, filtered_stream);
+    g_mime_object_write_to_stream(content, filtered_stream);
     g_mime_stream_flush(filtered_stream);
     g_object_unref(filtered_stream);
 
@@ -366,7 +364,7 @@ g_mime_gpgme_mpe_encrypt(GMimeMultipartEncrypted * mpe,
     wrapper =
        g_mime_data_wrapper_new_with_stream(stream,
                                            GMIME_CONTENT_ENCODING_7BIT);
-    g_mime_part_set_content(version_part, wrapper);
+    g_mime_part_set_content_object(version_part, wrapper);
     g_object_unref(wrapper);
     g_object_unref(stream);
 
@@ -378,7 +376,7 @@ g_mime_gpgme_mpe_encrypt(GMimeMultipartEncrypted * mpe,
     wrapper =
        g_mime_data_wrapper_new_with_stream(ciphertext,
                                            GMIME_CONTENT_ENCODING_7BIT);
-    g_mime_part_set_content(encrypted_part, wrapper);
+    g_mime_part_set_content_object(encrypted_part, wrapper);
     g_object_unref(ciphertext);
     g_object_unref(wrapper);
 
@@ -470,7 +468,7 @@ g_mime_gpgme_mpe_decrypt(GMimeMultipartEncrypted * mpe,
                                  GMIME_MULTIPART_ENCRYPTED_VERSION);
 
     /* make sure the protocol matches the version part's content-type */
-    content_type = g_mime_content_type_get_mime_type(version->content_type);
+    content_type = g_mime_content_type_to_string(version->content_type);
     if (g_ascii_strcasecmp(content_type, protocol) != 0) {
        g_set_error(err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR, "%s",
                    _
@@ -494,13 +492,13 @@ g_mime_gpgme_mpe_decrypt(GMimeMultipartEncrypted * mpe,
     }
 
     /* get the ciphertext stream */
-    wrapper = g_mime_part_get_content(GMIME_PART(encrypted));
+    wrapper = g_mime_part_get_content_object(GMIME_PART(encrypted));
     ciphertext = g_mime_data_wrapper_get_decoded_stream(wrapper);
     g_mime_stream_reset(ciphertext);
 
     stream = g_mime_stream_mem_new();
     filtered_stream = g_mime_stream_filter_new(stream);
-    crlf_filter = g_mime_filter_dos2unix_new(FALSE);
+    crlf_filter = g_mime_filter_crlf_new(FALSE, FALSE);
     g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_stream),
                             crlf_filter);
     g_object_unref(crlf_filter);
@@ -521,11 +519,11 @@ g_mime_gpgme_mpe_decrypt(GMimeMultipartEncrypted * mpe,
     g_object_unref(ciphertext);
 
     g_mime_stream_reset(stream);
-    parser = g_mime_parser_new_with_stream(stream);
-    g_mime_parser_set_format(parser, GMIME_FORMAT_MESSAGE);
+    parser = g_mime_parser_new();
+    g_mime_parser_init_with_stream(parser, stream);
     g_object_unref(stream);
 
-    decrypted = g_mime_parser_construct_part(parser, libbalsa_parser_options());
+    decrypted = g_mime_parser_construct_part(parser);
     g_object_unref(parser);
 
     if (!decrypted) {
diff --git a/libbalsa/gmime-part-rfc2440.c b/libbalsa/gmime-part-rfc2440.c
index 8a1f40330..9d4fde992 100644
--- a/libbalsa/gmime-part-rfc2440.c
+++ b/libbalsa/gmime-part-rfc2440.c
@@ -64,7 +64,7 @@ g_mime_part_check_rfc2440(GMimePart * part)
     static const char end_pgp_signature[]        = "-----END PGP SIGNATURE-----";
 
     /* try to get the content stream */
-    wrapper = g_mime_part_get_content(part);
+    wrapper = g_mime_part_get_content_object(part);
     g_return_val_if_fail(wrapper, GMIME_PART_RFC2440_NONE);
 
     stream = g_mime_data_wrapper_get_stream(wrapper);
@@ -153,7 +153,7 @@ g_mime_part_rfc2440_sign_encrypt(GMimePart * part, const char *sign_userid,
     g_return_val_if_fail(recipients != NULL || sign_userid != NULL, FALSE);
 
     /* get the raw content */
-    wrapper = g_mime_part_get_content(part);
+    wrapper = g_mime_part_get_content_object(part);
     g_return_val_if_fail(wrapper, FALSE); /* Incomplete part. */
     stream = g_mime_data_wrapper_get_stream(wrapper);
     g_mime_stream_reset(stream);
@@ -227,7 +227,7 @@ g_mime_part_rfc2440_sign_encrypt(GMimePart * part, const char *sign_userid,
                                                 "charset", "US-ASCII");
     }
 
-    g_mime_part_set_content(part, wrapper);
+    g_mime_part_set_content_object(part, wrapper);
     g_object_unref(cipherstream);
     g_object_unref(wrapper);
 
@@ -258,7 +258,7 @@ g_mime_part_rfc2440_verify(GMimePart * part, GError ** err)
     g_return_val_if_fail(GMIME_IS_PART(part), NULL);
 
     /* get the raw content */
-    wrapper = g_mime_part_get_content(GMIME_PART(part));
+    wrapper = g_mime_part_get_content_object(GMIME_PART(part));
     g_return_val_if_fail(wrapper, NULL); /* Incomplete part. */
     stream = g_mime_stream_mem_new();
     g_mime_data_wrapper_write_to_stream(wrapper, stream);
@@ -276,7 +276,7 @@ g_mime_part_rfc2440_verify(GMimePart * part, GError ** err)
     if (result && g_mime_stream_length(plainstream) > 0) {
        wrapper = g_mime_data_wrapper_new();
        g_mime_data_wrapper_set_stream(wrapper, plainstream);
-       g_mime_part_set_content(GMIME_PART(part), wrapper);
+       g_mime_part_set_content_object(GMIME_PART(part), wrapper);
        g_object_unref(wrapper);
     }
     g_object_unref(plainstream);
@@ -313,7 +313,7 @@ g_mime_part_rfc2440_decrypt(GMimePart * part, GtkWindow * parent,
     g_return_val_if_fail(GMIME_IS_PART(part), NULL);
 
     /* get the raw content */
-    wrapper = g_mime_part_get_content(part);
+    wrapper = g_mime_part_get_content_object(part);
     g_return_val_if_fail(wrapper, NULL); /* Incomplete part. */
     stream = g_mime_stream_mem_new();
     g_mime_data_wrapper_write_to_stream(wrapper, stream);
@@ -337,7 +337,7 @@ g_mime_part_rfc2440_decrypt(GMimePart * part, GtkWindow * parent,
 
        /* strip crlf off encrypted stuff coming from Winbloze crap */
        filter_stream = g_mime_stream_filter_new(plainstream);
-       filter = g_mime_filter_dos2unix_new(FALSE);
+       filter = g_mime_filter_crlf_new(FALSE, FALSE);
        g_mime_stream_filter_add(GMIME_STREAM_FILTER(filter_stream),
                                 filter);
        g_object_unref(filter);
@@ -346,7 +346,7 @@ g_mime_part_rfc2440_decrypt(GMimePart * part, GtkWindow * parent,
        out_stream = g_mime_stream_mem_new();
        wrapper = g_mime_data_wrapper_new();
        g_mime_data_wrapper_set_stream(wrapper, out_stream);
-       g_mime_part_set_content(part, wrapper);
+       g_mime_part_set_content_object(part, wrapper);
         g_object_unref(wrapper);
        g_mime_stream_reset(filter_stream);
        g_mime_stream_write_to_stream(filter_stream, out_stream);
diff --git a/libbalsa/identity.c b/libbalsa/identity.c
index 26d362341..a7e0367e2 100644
--- a/libbalsa/identity.c
+++ b/libbalsa/identity.c
@@ -2197,7 +2197,7 @@ libbalsa_identity_combo_box(GList       * identities,
         GtkTreeIter iter;
 
         ident = list->data;
-        from = internet_address_to_string(ident->ia, NULL, FALSE);
+        from = internet_address_to_string(ident->ia, FALSE);
        name = g_strconcat("(", ident->identity_name, ")", NULL);
 
         gtk_list_store_append(store, &iter);
diff --git a/libbalsa/imap/imap-handle.c b/libbalsa/imap/imap-handle.c
index fb90c6429..62e87cd81 100644
--- a/libbalsa/imap/imap-handle.c
+++ b/libbalsa/imap/imap-handle.c
@@ -3081,39 +3081,31 @@ ir_envelope(NetClientSioBuf *sio, ImapEnvelope *env)
 
   date = imap_get_nstring(sio);
   if(date) {
-    if (env != NULL) {
-      GDateTime *header_date;
-
-      header_date = g_mime_utils_header_decode_date(date);
-      if (header_date != NULL) {
-        env->date = (time_t) g_date_time_to_unix(header_date);
-        g_date_time_unref(header_date);
-      }
-    }
+    if(env) env->date = g_mime_utils_header_decode_date(date, NULL);
     g_free(date);
   }
-  if(sio_getc(sio) != ' ') return IMR_PROTOCOL;
+  if( (c=sio_getc(sio)) != ' ') return IMR_PROTOCOL;
   str = imap_get_nstring(sio);
   if(env) env->subject = str; else g_free(str);
-  if(sio_getc(sio) != ' ') return IMR_PROTOCOL;
+  if( (c=sio_getc(sio)) != ' ') return IMR_PROTOCOL;
   if(imap_get_addr_list(sio, env ? &env->from : NULL) != IMR_OK)
     return IMR_PROTOCOL;
-  if(sio_getc(sio) != ' ') return IMR_PROTOCOL;
+  if( (c=sio_getc(sio)) != ' ') return IMR_PROTOCOL;
   if(imap_get_addr_list(sio, env ? &env->sender : NULL) != IMR_OK)
     return IMR_PROTOCOL;
-  if(sio_getc(sio) != ' ') return IMR_PROTOCOL;
+  if( (c=sio_getc(sio)) != ' ') return IMR_PROTOCOL;
   if(imap_get_addr_list(sio, env ? &env->replyto : NULL) != IMR_OK)
     return IMR_PROTOCOL;
-  if(sio_getc(sio) != ' ') return IMR_PROTOCOL;
+  if( (c=sio_getc(sio)) != ' ') return IMR_PROTOCOL;
   if(imap_get_addr_list(sio, env ? &env->to : NULL) != IMR_OK)
     return IMR_PROTOCOL;
-  if(sio_getc(sio) != ' ') return IMR_PROTOCOL;
+  if( (c=sio_getc(sio)) != ' ') return IMR_PROTOCOL;
   if(imap_get_addr_list(sio, env ? &env->cc : NULL) != IMR_OK)
     return IMR_PROTOCOL;
-  if(sio_getc(sio) != ' ') return IMR_PROTOCOL;
+  if( (c=sio_getc(sio)) != ' ') return IMR_PROTOCOL;
   if(imap_get_addr_list(sio, env ? &env->bcc : NULL) != IMR_OK)
     return IMR_PROTOCOL;
-  if(sio_getc(sio) != ' ') return IMR_PROTOCOL;
+  if( (c=sio_getc(sio)) != ' ') return IMR_PROTOCOL;
   str = imap_get_nstring(sio);
   if(env) env->in_reply_to = str; else g_free(str);
   if( (c=sio_getc(sio)) != ' ') { g_debug("c=%c",c); return IMR_PROTOCOL;}
diff --git a/libbalsa/libbalsa-gpgme-keys.c b/libbalsa/libbalsa-gpgme-keys.c
index 768786ac4..d9af45489 100644
--- a/libbalsa/libbalsa-gpgme-keys.c
+++ b/libbalsa/libbalsa-gpgme-keys.c
@@ -271,13 +271,13 @@ libbalsa_gpgme_export_key(gpgme_ctx_t   ctx,
 
 
 /* documentation: see header file */
-GBytes *
+gchar *
 libbalsa_gpgme_export_autocrypt_key(const gchar *fingerprint, const gchar *mailbox, GError **error)
 {
        gchar *export_args[10] = { "", "--export", "--export-options", "export-minimal,no-export-attributes",
                NULL, NULL, NULL, NULL, NULL, NULL };
        gpgme_ctx_t ctx;
-       GBytes *result = NULL;
+       gchar *result = NULL;
 
        g_return_val_if_fail((fingerprint != NULL) && (mailbox != NULL), NULL);
 
@@ -323,7 +323,7 @@ libbalsa_gpgme_export_autocrypt_key(const gchar *fingerprint, const gchar *mailb
                                if ((keydata == NULL) || (keysize == 0U)) {
                                        g_set_error(error, GPGME_ERROR_QUARK, -1, _("cannot export minimal 
key for “%s”"), mailbox);
                                } else {
-                                       result = g_bytes_new(keydata, keysize);
+                                       result = g_base64_encode(keydata, keysize);
                                }
                                gpgme_free(keydata);
                        }
diff --git a/libbalsa/libbalsa-gpgme-keys.h b/libbalsa/libbalsa-gpgme-keys.h
index 8a4faa540..688483a88 100644
--- a/libbalsa/libbalsa-gpgme-keys.h
+++ b/libbalsa/libbalsa-gpgme-keys.h
@@ -120,15 +120,15 @@ gchar *libbalsa_gpgme_export_key(gpgme_ctx_t   ctx,
  * \param fingerprint key fingerprint, may be NULL
  * \param mailbox key uid
  * \param error filled with error information on error
- * \return a newly allocated buffer containing the key on success, NULL on error
+ * \return a newly allocated string containing the BASE64-encoded key on success, NULL on error
  *
  * Export the minimal key for using it in a Autocrypt: header.  If specified, the key is selected by the 
passed fingerprint,
  * otherwise the first key matching the passed mailbox is used.  Depending on the gpg backend version, all 
other uid's and all
  * subkeys which are not required are stripped.
  */
-GBytes *libbalsa_gpgme_export_autocrypt_key(const gchar  *fingerprint,
-                                                                                   const gchar  *mailbox,
-                                                                                   GError      **error)
+gchar *libbalsa_gpgme_export_autocrypt_key(const gchar  *fingerprint,
+                                                                                  const gchar  *mailbox,
+                                                                                  GError      **error)
        G_GNUC_WARN_UNUSED_RESULT;
 
 /** \brief Import an ASCII-armoured key
diff --git a/libbalsa/libbalsa.c b/libbalsa/libbalsa.c
index a3487239c..e30ae1b1a 100644
--- a/libbalsa/libbalsa.c
+++ b/libbalsa/libbalsa.c
@@ -67,8 +67,16 @@ libbalsa_init(void)
 {
     main_thread_id = g_thread_self();
 
-    g_mime_init(); /* Registers all GMime types */
-    libbalsa_parser_options_init();
+    g_mime_init(GMIME_ENABLE_RFC2047_WORKAROUNDS);
+
+    GMIME_TYPE_DATA_WRAPPER;
+    GMIME_TYPE_FILTER;
+    GMIME_TYPE_FILTER_CRLF;
+    GMIME_TYPE_PARSER;
+    GMIME_TYPE_STREAM;
+    GMIME_TYPE_STREAM_BUFFER;
+    GMIME_TYPE_STREAM_MEM;
+    GMIME_TYPE_STREAM_NULL;
 
     /* Register our types to avoid possible race conditions. See
        output of "valgrind --tool=helgrind --log-file=balsa.log balsa"
@@ -389,7 +397,7 @@ libbalsa_is_cert_known(GTlsCertificate      *cert,
 */
 struct AskCertData {
     GTlsCertificate *certificate;
-    gchar *explanation;
+    const char *explanation;
 };
 
 
@@ -404,9 +412,9 @@ ask_cert_real(void *data)
     GtkWidget *label;
 
     /* never accept if the certificate is broken, resulting in a NULL widget */
-    cert_widget = x509_cert_chain_tls(acd->certificate);
+    cert_widget = x509_cert_chain_tls(acd->certificate); // x509_cert_widget_from_cert(acd->certificate);
     if (cert_widget == NULL) {
-       libbalsa_information(LIBBALSA_INFORMATION_WARNING, _("broken TLS certificate"));
+       // FIXME - message?
        return CERT_ACCEPT_NO;
     }
 
@@ -448,7 +456,6 @@ ask_cert_real(void *data)
        break;
     }
     gtk_widget_destroy(dialog);
-    g_free(acd->explanation);
     return i;
 }
 
@@ -458,30 +465,21 @@ libbalsa_ask_for_cert_acceptance(GTlsCertificate      *cert,
                                                                 GTlsCertificateFlags  errors)
 {
     struct AskCertData acd;
-    static const gchar *reason_msg[] = {
-               N_("the signing certificate authority is not known"),
-               N_("the certificate does not match the expected identity of the site that it was retrieved 
from"),
-               N_("the certificate’s activation time is still in the future"),
-               N_("the certificate has expired"),
-               N_("the certificate has been revoked"),
-               N_("the certificate’s algorithm is considered insecure"),
-               N_("an error occurred validating the certificate")
-    };
-    GString *exp_buf = g_string_new(NULL);
-    gsize n;
-
     acd.certificate = cert;
-    for (n = 0U; n < G_N_ELEMENTS(reason_msg); n++) {
-       if ((errors & (1U << n)) != 0U) {
-               g_string_append_printf(exp_buf, "\n\342\200\242 %s", reason_msg[n]);
-       }
-    }
-
-    if (exp_buf->len > 0U) {
-       acd.explanation = g_string_free(exp_buf, FALSE);
+    if ((errors & G_TLS_CERTIFICATE_UNKNOWN_CA) == G_TLS_CERTIFICATE_UNKNOWN_CA) {
+       acd.explanation = _("the signing certificate authority is not known");
+    } else if ((errors & G_TLS_CERTIFICATE_BAD_IDENTITY) == G_TLS_CERTIFICATE_BAD_IDENTITY) {
+       acd.explanation = _("the certificate does not match the expected identity of the site that it was 
retrieved from");
+    } else if ((errors & G_TLS_CERTIFICATE_NOT_ACTIVATED) == G_TLS_CERTIFICATE_NOT_ACTIVATED) {
+       acd.explanation = _("the certificate’s activation time is still in the future");
+    } else if ((errors & G_TLS_CERTIFICATE_EXPIRED) == G_TLS_CERTIFICATE_EXPIRED) {
+       acd.explanation = _("the certificate has expired");
+    } else if ((errors & G_TLS_CERTIFICATE_REVOKED) == G_TLS_CERTIFICATE_REVOKED) {
+       acd.explanation = _("the certificate has been revoked ");
+    } else if ((errors & G_TLS_CERTIFICATE_INSECURE) == G_TLS_CERTIFICATE_INSECURE) {
+       acd.explanation = _("the certificate’s algorithm is considered insecure");
     } else {
-       g_string_free(exp_buf, TRUE);
-       acd.explanation = g_strdup_printf(_("unknown certificate validation error %u"), (unsigned) errors);
+       acd.explanation = _("an error occurred validating the certificate");
     }
     return libbalsa_ask(ask_cert_real, &acd);
 }
diff --git a/libbalsa/mailbox.c b/libbalsa/mailbox.c
index 42e34e5bf..25a9e3f87 100644
--- a/libbalsa/mailbox.c
+++ b/libbalsa/mailbox.c
@@ -4247,9 +4247,8 @@ lbm_get_mime_msg(LibBalsaMailbox * mailbox, LibBalsaMessage *message)
                                                      libbalsa_message_get_msgno(message),
                                                     TRUE);
         parser = g_mime_parser_new_with_stream(stream);
-        g_mime_parser_set_format(parser, GMIME_FORMAT_MESSAGE);
         g_object_unref(stream);
-        mime_msg = g_mime_parser_construct_message(parser, libbalsa_parser_options());
+        mime_msg = g_mime_parser_construct_message(parser);
         g_object_unref(parser);
     }
     libbalsa_mailbox_release_message(mailbox, message);
diff --git a/libbalsa/mailbox_imap.c b/libbalsa/mailbox_imap.c
index 1828db2a8..8dc8db560 100644
--- a/libbalsa/mailbox_imap.c
+++ b/libbalsa/mailbox_imap.c
@@ -1899,11 +1899,11 @@ libbalsa_mailbox_imap_sync(LibBalsaMailbox * mailbox, gboolean expunge)
 static InternetAddress*
 imap_address_to_gmime_mailbox(ImapAddress *addr)
 {
-    gchar *tmp = g_mime_utils_header_decode_text(libbalsa_parser_options(), addr->addr_spec);
+    gchar *tmp = g_mime_utils_header_decode_text(addr->addr_spec);
     InternetAddress *address = internet_address_mailbox_new(NULL, tmp);
     g_free(tmp);
     if (addr->name) {
-        tmp = g_mime_utils_header_decode_text(libbalsa_parser_options(), addr->name);
+        tmp = g_mime_utils_header_decode_text(addr->name);
         internet_address_set_name(address, tmp);
         g_free(tmp);
     }
@@ -1930,7 +1930,7 @@ internet_address_new_list_from_imap_address(ImapAddress *list,
                 /* Group head */
                 ImapAddress *imap_addr = NULL;
                 InternetAddressList *l;
-                gchar *tmp = g_mime_utils_header_decode_text(libbalsa_parser_options(), list->name);
+                gchar *tmp = g_mime_utils_header_decode_text(list->name);
                 addr = internet_address_group_new(tmp);
                 g_free(tmp);
                 l = internet_address_new_list_from_imap_address(list->next,
@@ -1980,7 +1980,7 @@ lb_set_headers(LibBalsaMessageHeaders *headers, ImapEnvelope *  envelope,
 
     if(is_embedded) {
         headers->subject =
-            g_mime_utils_header_decode_text(libbalsa_parser_options(), envelope->subject);
+            g_mime_utils_header_decode_text(envelope->subject);
         libbalsa_utf8_sanitize(&headers->subject, TRUE, NULL);
     }
 }
@@ -2114,7 +2114,7 @@ lbm_imap_construct_body(LibBalsaMessageBody *lbbody, ImapBody *imap_body)
     if(!str) str = imap_body_get_param(imap_body, "name");
     if(str) {
         lbbody->filename  =
-           g_mime_utils_header_decode_text(libbalsa_parser_options(), str);
+           g_mime_utils_header_decode_text(str);
         libbalsa_utf8_sanitize(&lbbody->filename, TRUE, NULL);
     }
     lbbody->charset   = g_strdup(imap_body_get_param(imap_body, "charset"));
@@ -2166,16 +2166,15 @@ get_struct_from_cache(LibBalsaMailbox *mailbox, LibBalsaMessage *message,
         fstream = g_mime_stream_filter_new(stream);
         g_object_unref(stream);
 
-        filter = g_mime_filter_dos2unix_new(FALSE);
+        filter = g_mime_filter_crlf_new(FALSE, FALSE);
         g_mime_stream_filter_add(GMIME_STREAM_FILTER(fstream), filter);
         g_object_unref(filter);
 
         mime_parser = g_mime_parser_new_with_stream(fstream);
-        g_mime_parser_set_format(mime_parser, GMIME_FORMAT_MESSAGE);
         g_object_unref(fstream);
 
-        g_mime_parser_set_format(mime_parser, GMIME_FORMAT_MESSAGE);
-        mime_msg = g_mime_parser_construct_message(mime_parser, libbalsa_parser_options());
+        g_mime_parser_set_scan_from(mime_parser, FALSE);
+        mime_msg = g_mime_parser_construct_message(mime_parser);
         g_object_unref(mime_parser);
 
         libbalsa_message_set_mime_message(message, mime_msg);
@@ -2544,8 +2543,7 @@ lbm_imap_get_msg_part_from_cache(LibBalsaMessage * message,
     {
         GMimeParser *parser =  
             g_mime_parser_new_with_stream (partstream);
-        g_mime_parser_set_format(parser, GMIME_FORMAT_MESSAGE);
-        part->mime_part = g_mime_parser_construct_part (parser, libbalsa_parser_options());
+        part->mime_part = g_mime_parser_construct_part (parser);
         g_object_unref (parser);
     }
     g_object_unref (partstream);
@@ -2569,7 +2567,7 @@ lbm_imap_get_msg_part(LibBalsaMessage * msg, LibBalsaMessageBody * part,
 
     if (!part->mime_part) {
         GMimeContentType *type =
-            g_mime_content_type_parse(libbalsa_parser_options(), part->content_type);
+            g_mime_content_type_new_from_string(part->content_type);
         if (g_mime_content_type_is_type(type, "multipart", "*")) {
             if (g_mime_content_type_is_type(type, "multipart", "signed"))
                 part->mime_part =
@@ -2725,7 +2723,9 @@ libbalsa_mailbox_imap_add_messages(LibBalsaMailbox * mailbox,
 
        tmpstream = g_mime_stream_filter_new(stream);
 
-       crlffilter = g_mime_filter_unix2dos_new(FALSE);
+       crlffilter =
+           g_mime_filter_crlf_new(TRUE,
+                                  FALSE);
        g_mime_stream_filter_add(GMIME_STREAM_FILTER(tmpstream), crlffilter);
        g_object_unref(crlffilter);
 
@@ -2848,7 +2848,9 @@ multi_append_cb(char * buf, size_t buflen,
 
        tmpstream = g_mime_stream_filter_new(stream);
 
-        crlffilter = g_mime_filter_unix2dos_new(FALSE);
+       crlffilter =
+           g_mime_filter_crlf_new(TRUE,
+                                  FALSE);
        g_mime_stream_filter_add(GMIME_STREAM_FILTER(tmpstream), crlffilter);
        g_object_unref(crlffilter);
 
diff --git a/libbalsa/mailbox_local.c b/libbalsa/mailbox_local.c
index ce4b52e2c..99b3650fe 100644
--- a/libbalsa/mailbox_local.c
+++ b/libbalsa/mailbox_local.c
@@ -878,7 +878,7 @@ message_match_real(LibBalsaMailbox *mailbox, guint msgno,
             headers = libbalsa_message_get_headers(message);
             if (headers->to_list != NULL) {
                 gchar *str =
-                    internet_address_list_to_string(headers->to_list, NULL, FALSE);
+                    internet_address_list_to_string(headers->to_list, FALSE);
                 match =
                     libbalsa_utf8_strstr(str, cond->match.string.string);
                 g_free(str);
@@ -907,7 +907,7 @@ message_match_real(LibBalsaMailbox *mailbox, guint msgno,
             headers = libbalsa_message_get_headers(message);
             if (headers->cc_list != NULL) {
                 gchar *str =
-                    internet_address_list_to_string(headers->cc_list, NULL, FALSE);
+                    internet_address_list_to_string(headers->cc_list, FALSE);
                 match =
                     libbalsa_utf8_strstr(str, cond->match.string.string);
                 g_free(str);
@@ -1030,7 +1030,7 @@ lbm_local_cache_message(LibBalsaMailboxLocal * local,
 
     headers = libbalsa_message_get_headers(message);
     if (headers->from != NULL)
-        info->sender = internet_address_list_to_string(headers->from, NULL, FALSE);
+        info->sender = internet_address_list_to_string(headers->from, FALSE);
     if (info->sender == NULL)
         info->sender = g_strdup("");
 
@@ -2082,8 +2082,8 @@ libbalsa_mailbox_local_get_mime_message(LibBalsaMailbox * mailbox,
        return NULL;
 
     mime_parser = g_mime_parser_new_with_stream(mime_stream);
-    g_mime_parser_set_format(mime_parser, GMIME_FORMAT_MESSAGE);
-    mime_message = g_mime_parser_construct_message(mime_parser, libbalsa_parser_options());
+    g_mime_parser_set_scan_from(mime_parser, FALSE);
+    mime_message = g_mime_parser_construct_message(mime_parser);
 
     g_object_unref(mime_parser);
     g_object_unref(mime_stream);
diff --git a/libbalsa/mailbox_maildir.c b/libbalsa/mailbox_maildir.c
index 0ec1828d7..0733f7e81 100644
--- a/libbalsa/mailbox_maildir.c
+++ b/libbalsa/mailbox_maildir.c
@@ -894,7 +894,9 @@ lbm_maildir_add_message(LibBalsaMailboxLocal * local,
     out_stream = g_mime_stream_fs_new(fd);
 
     in_stream = g_mime_stream_filter_new(stream);
-    crlffilter = g_mime_filter_dos2unix_new(FALSE);
+    crlffilter =
+        g_mime_filter_crlf_new(FALSE,
+                               FALSE);
     g_mime_stream_filter_add(GMIME_STREAM_FILTER(in_stream), crlffilter);
     g_object_unref(crlffilter);
  
diff --git a/libbalsa/mailbox_mbox.c b/libbalsa/mailbox_mbox.c
index f221ddb76..c054ac4ad 100644
--- a/libbalsa/mailbox_mbox.c
+++ b/libbalsa/mailbox_mbox.c
@@ -434,7 +434,7 @@ parse_mailbox(LibBalsaMailboxMbox * mbox)
     unsigned msgno = mbox->msgno_2_msg_info->len;
 
     gmime_parser = g_mime_parser_new_with_stream(mbox->gmime_stream);
-    g_mime_parser_set_format(gmime_parser, GMIME_FORMAT_MBOX);
+    g_mime_parser_set_scan_from(gmime_parser, TRUE);
     g_mime_parser_set_respect_content_length(gmime_parser, TRUE);
     g_mime_parser_set_header_regex(gmime_parser,
                                    "^Status|^X-Status|^MIME-Version",
@@ -449,7 +449,7 @@ parse_mailbox(LibBalsaMailboxMbox * mbox)
         off_t offset;
 
         msg_info.status = msg_info.x_status = msg_info.mime_version = -1;
-        mime_message   = g_mime_parser_construct_message(gmime_parser, libbalsa_parser_options());
+        mime_message   = g_mime_parser_construct_message(gmime_parser);
         if (mime_message == NULL) {
             /* Skip to the next message, if any */
             GMimeStream *mbox_stream;
@@ -469,10 +469,10 @@ parse_mailbox(LibBalsaMailboxMbox * mbox)
             g_mime_parser_init_with_stream(gmime_parser, mbox_stream);
             continue;
         }
-        msg_info.start = g_mime_parser_get_mbox_marker_offset(gmime_parser);
+        msg_info.start = g_mime_parser_get_from_offset(gmime_parser);
         msg_info.end   = g_mime_parser_tell(gmime_parser);
         if (msg_info.end <= msg_info.start
-            || !(from = g_mime_parser_get_mbox_marker(gmime_parser))) {
+            || !(from = g_mime_parser_get_from(gmime_parser))) {
            g_object_unref(mime_message);
             continue;
        }
@@ -1119,9 +1119,8 @@ lbm_mbox_get_mime_message(LibBalsaMailbox * mailbox,
        return NULL;
     libbalsa_mime_stream_shared_lock(stream);
     parser = g_mime_parser_new_with_stream(stream);
-    g_mime_parser_set_format(parser, GMIME_FORMAT_MESSAGE);
 
-    mime_message = g_mime_parser_construct_message(parser, libbalsa_parser_options());
+    mime_message = g_mime_parser_construct_message(parser);
     g_object_unref(parser);
     libbalsa_mime_stream_shared_unlock(stream);
     g_object_unref(stream);
@@ -1640,7 +1639,7 @@ libbalsa_mailbox_mbox_sync(LibBalsaMailbox * mailbox, gboolean expunge)
        return FALSE;
     }
     gmime_parser = g_mime_parser_new_with_stream(mbox_stream);
-    g_mime_parser_set_format(gmime_parser, GMIME_FORMAT_MBOX);
+    g_mime_parser_set_scan_from(gmime_parser, TRUE);
     g_mime_parser_set_respect_content_length(gmime_parser, TRUE);
     g_mime_parser_set_header_regex(gmime_parser,
                                    "^Status|^X-Status|^MIME-Version",
@@ -1669,11 +1668,11 @@ libbalsa_mailbox_mbox_sync(LibBalsaMailbox * mailbox, gboolean expunge)
            libbalsa_message_set_msgno(msg_info->local_info.message, j + 1);
 
        msg_info->status = msg_info->x_status = msg_info->mime_version = -1;
-       mime_msg = g_mime_parser_construct_message(gmime_parser, libbalsa_parser_options());
+       mime_msg = g_mime_parser_construct_message(gmime_parser);
         if (!mime_msg)
             /* Try to recover */
             continue;
-        msg_info->start = g_mime_parser_get_mbox_marker_offset(gmime_parser);
+        msg_info->start = g_mime_parser_get_from_offset(gmime_parser);
 
        /* Make sure we don't have offsets for any encapsulated headers. */
        if (!g_mime_object_get_header(GMIME_OBJECT(mime_msg), "Status"))
@@ -1683,7 +1682,7 @@ libbalsa_mailbox_mbox_sync(LibBalsaMailbox * mailbox, gboolean expunge)
        if (!g_mime_object_get_header(GMIME_OBJECT(mime_msg), "MIME-Version"))
            msg_info->mime_version = -1;
 
-       from = g_mime_parser_get_mbox_marker(gmime_parser);
+       from = g_mime_parser_get_from(gmime_parser);
         if (!from) {
             /* Try to recover */
             g_object_unref(mime_msg);
@@ -1807,10 +1806,10 @@ static void update_message_status_headers(GMimeMessage *message,
     /* Create headers with spaces in place of flags, if necessary, so we
      * can later update them in place. */
     lbm_mbox_status_hdr(flags, 2, new_header);
-    g_mime_object_set_header(GMIME_OBJECT(message), "Status", new_header->str, NULL);
+    g_mime_object_set_header(GMIME_OBJECT(message), "Status", new_header->str);
     g_string_truncate(new_header, 0);
     lbm_mbox_x_status_hdr(flags, 3, new_header);
-    g_mime_object_set_header(GMIME_OBJECT(message), "X-Status", new_header->str, NULL);
+    g_mime_object_set_header(GMIME_OBJECT(message), "X-Status", new_header->str);
     g_string_free(new_header, TRUE);
 }
 
@@ -1822,8 +1821,7 @@ lbm_mbox_armored_object(GMimeStream * stream)
     GMimeObject *object;
 
     parser = g_mime_parser_new_with_stream(stream);
-    g_mime_parser_set_format(parser, GMIME_FORMAT_MESSAGE);
-    object = GMIME_OBJECT(g_mime_parser_construct_message(parser, libbalsa_parser_options()));
+    object = GMIME_OBJECT(g_mime_parser_construct_message(parser));
     g_object_unref(parser);
     g_mime_object_encode(object, GMIME_ENCODING_CONSTRAINT_7BIT);
 
@@ -1838,7 +1836,8 @@ lbm_mbox_armored_stream(GMimeStream * stream)
     
     fstream = g_mime_stream_filter_new(stream);
 
-    filter = g_mime_filter_dos2unix_new(FALSE);
+    filter = g_mime_filter_crlf_new(FALSE,
+                                   FALSE);
     g_mime_stream_filter_add(GMIME_STREAM_FILTER(fstream), filter);
     g_object_unref(filter);
 
@@ -1879,7 +1878,7 @@ lbm_mbox_add_message(LibBalsaMailboxLocal * local,
     ctime_r(&(headers->date), date_string);
 
     sender = headers->from != NULL ?
-        internet_address_list_to_string(headers->from, NULL, FALSE) :
+        internet_address_list_to_string(headers->from, FALSE) :
        g_strdup("none");
 
     g_object_unref(message);
@@ -1945,7 +1944,7 @@ lbm_mbox_add_message(LibBalsaMailboxLocal * local,
         retval = lbm_mbox_newline(dest);
     if (retval < 0
         || g_mime_stream_write_string(dest, from) < (gint) strlen(from)
-       || g_mime_object_write_to_stream(armored_object, NULL, armored_dest) < 0) {
+       || g_mime_object_write_to_stream(armored_object, armored_dest) < 0) {
         g_set_error(err, LIBBALSA_MAILBOX_ERROR,
                     LIBBALSA_MAILBOX_APPEND_ERROR, _("Data copy error"));
        retval = -1;
diff --git a/libbalsa/mailbox_mh.c b/libbalsa/mailbox_mh.c
index 11db73860..5a2cd9745 100644
--- a/libbalsa/mailbox_mh.c
+++ b/libbalsa/mailbox_mh.c
@@ -1074,7 +1074,8 @@ lbm_mh_add_message(LibBalsaMailboxLocal * local,
     }
     out_stream = g_mime_stream_fs_new(fd);
 
-    crlffilter = g_mime_filter_dos2unix_new(FALSE);
+    crlffilter = g_mime_filter_crlf_new(FALSE,
+                                        FALSE);
     in_stream = g_mime_stream_filter_new(stream);
     g_mime_stream_filter_add(GMIME_STREAM_FILTER(in_stream), crlffilter);
     g_object_unref(crlffilter);
diff --git a/libbalsa/message.c b/libbalsa/message.c
index f48ed2c85..3371da668 100644
--- a/libbalsa/message.c
+++ b/libbalsa/message.c
@@ -276,13 +276,6 @@ libbalsa_message_headers_destroy(LibBalsaMessageHeaders *headers)
 
     lb_message_headers_extra_destroy(headers);
 
-#if defined ENABLE_AUTOCRYPT
-    if (headers->autocrypt_hdr != NULL) {
-       g_object_unref(headers->autocrypt_hdr);
-       headers->autocrypt_hdr = NULL;
-}
-#endif
-
     g_free(headers);
 }
 
@@ -510,7 +503,7 @@ prepend_header_misc(GList      *res,
     return
         g_list_prepend(res,
                        libbalsa_create_hdr_pair(name,
-                                                g_mime_utils_header_decode_text(libbalsa_parser_options(), 
value)));
+                                                g_mime_utils_header_decode_text(value)));
 }
 
 /* 
@@ -529,37 +522,38 @@ GList *
 libbalsa_message_user_hdrs_from_gmime(GMimeMessage * message)
 {
     GMimeHeaderList *hdrlist;
-    gint count;
-    gint i;
+    GMimeHeaderIter iter;
     GList *res = NULL;
     const char *value;
 
     g_return_val_if_fail(message != NULL, NULL);
 
     value = g_mime_message_get_message_id(message);
-    if (value)
-       res = g_list_prepend(res, libbalsa_create_hdr_pair("Message-ID",
-                                         g_strdup_printf("<%s>", value)));
+    if (value) {
+        res = g_list_prepend(res, libbalsa_create_hdr_pair("Message-ID",
+                                                           g_strdup_printf("<%s>", value)));
+    }
 
     /* FIXME: This duplicates References headers since they are
        already present in LibBalsaMessage::references field.  FWIW,
        mailbox driver does not copy references to user_headers.
-    */
+     */
     value = g_mime_object_get_header(GMIME_OBJECT(message), "References");
-    if (value != NULL) {
+    if (value) {
 #if BALSA_NEEDS_SEPARATE_USER_HEADERS
-       GMimeReferences *references, *reference;
-       references = g_mime_references_parse(NULL, value);
-       for (reference = references; reference != NULL; reference = reference->next) {
-           res =
-               g_list_prepend(res,
-                              libbalsa_create_hdr_pair("References",
-                                                       g_strdup_printf
-                                                       ("<%s>",
-                                                        reference->
-                                                        msgid)));
-       }
-       g_mime_references_clear(&references);
+        GMimeReferences *references, *reference;
+        reference = references = g_mime_references_decode(value);
+        while (reference) {
+            res =
+                g_list_prepend(res,
+                               libbalsa_create_hdr_pair("References",
+                                                        g_strdup_printf
+                                                            ("<%s>",
+                                                            reference->
+                                                            msgid)));
+            reference = reference->next;
+        }
+        g_mime_references_clear(&references);
 #else
         res = g_list_prepend(res,
                              libbalsa_create_hdr_pair("References",
@@ -573,18 +567,16 @@ libbalsa_message_user_hdrs_from_gmime(GMimeMessage * message)
             g_list_prepend(res,
                            libbalsa_create_hdr_pair
                                ("In-Reply-To",
-                               g_mime_utils_header_decode_text(libbalsa_parser_options(), value)));
+                               g_mime_utils_header_decode_text(value)));
     }
 
     hdrlist = g_mime_object_get_header_list (GMIME_OBJECT(message));
-    count = g_mime_header_list_get_count(hdrlist);
-    for (i = 0; i < count; i++) {
-        GMimeHeader *header;
-
-        header = g_mime_header_list_get_header_at(hdrlist, i);
-        res = prepend_header_misc(res,
-                                  g_mime_header_get_name(header),
-                                  g_mime_header_get_value(header));
+    if (g_mime_header_list_get_iter (hdrlist, &iter)) {
+        do {
+            res = prepend_header_misc(res,
+                                      g_mime_header_iter_get_name (&iter),
+                                      g_mime_header_iter_get_value (&iter));
+        } while (g_mime_header_iter_next (&iter));
     }
 
     return g_list_reverse(res);
@@ -997,44 +989,39 @@ libbalsa_message_get_no(LibBalsaMessage* msg)
 
 /* Populate headers from mime_msg, but only the members that are needed
  * all the time. */
-
 static InternetAddressList *
-lb_message_address_list_ref(InternetAddressList * list)
+lb_message_recipients(GMimeMessage      *message,
+                      GMimeRecipientType type)
 {
-    if (list != NULL && internet_address_list_length(list) > 0) {
-        return g_object_ref(list);
+    const InternetAddressList *list;
+    InternetAddressList *copy = NULL;
+
+    if ((list = g_mime_message_get_recipients (message, type))) {
+        copy = internet_address_list_new ();
+        internet_address_list_append (copy, (InternetAddressList *) list);
     }
 
-    return NULL;
+    return copy;
 }
 
-static InternetAddressList *
-lb_message_recipients(GMimeMessage   * message,
-                      GMimeAddressType type)
-{
-    return lb_message_address_list_ref(g_mime_message_get_addresses(message, type));
-}
 
 static void
 lb_message_headers_basic_from_gmime(LibBalsaMessageHeaders *headers,
                                     GMimeMessage           *mime_msg)
 {
-    if (headers->from == NULL) {
-        headers->from =
-            lb_message_address_list_ref(g_mime_message_get_from(mime_msg));
-    }
+    g_return_if_fail(headers);
+    g_return_if_fail(mime_msg != NULL);
 
-    if (headers->date == 0) {
-        GDateTime *datetime;
+    if (headers->from == NULL)
+        headers->from = internet_address_list_parse_string(mime_msg->from);
 
-        datetime = g_mime_message_get_date(mime_msg);
-        if (datetime != NULL)
-            headers->date = g_date_time_to_unix(datetime);
-    }
+    if (headers->date == 0)
+        g_mime_message_get_date(mime_msg, &headers->date, NULL);
 
-    if (headers->to_list == NULL)
+    if (headers->to_list == NULL) {
         headers->to_list =
-            lb_message_recipients(mime_msg, GMIME_ADDRESS_TYPE_TO);
+            lb_message_recipients(mime_msg, GMIME_RECIPIENT_TYPE_TO);
+    }
 
     if (headers->content_type == NULL) {
         /* If we could:
@@ -1044,75 +1031,69 @@ lb_message_headers_basic_from_gmime(LibBalsaMessageHeaders *headers,
          */
         GMimeContentType *content_type;
         gchar *str;
-
-        content_type = g_mime_object_get_content_type(mime_msg->mime_part);
-        str = g_mime_content_type_get_mime_type(content_type);
-        headers->content_type = g_mime_content_type_parse(libbalsa_parser_options(), str);
+        g_return_if_fail(headers->content_type == NULL);
+        content_type          = g_mime_object_get_content_type(mime_msg->mime_part);
+        str                   = g_mime_content_type_to_string(content_type);
+        headers->content_type = g_mime_content_type_new_from_string(str);
         g_free(str);
     }
 }
 
+
 /* Populate headers from mime_msg, but only the members not handled in
  * lb_message_headers_basic_from_gmime. */
 static void
 lb_message_headers_extra_from_gmime(LibBalsaMessageHeaders *headers,
                                     GMimeMessage           *mime_msg)
 {
+    g_return_if_fail(headers);
+    g_return_if_fail(mime_msg != NULL);
+
     if (headers->reply_to == NULL) {
         headers->reply_to =
-            lb_message_address_list_ref(g_mime_message_get_reply_to(mime_msg));
+            internet_address_list_parse_string(mime_msg->reply_to);
     }
 
     if (headers->dispnotify_to == NULL) {
-        const gchar *value =
-            g_mime_object_get_header(GMIME_OBJECT(mime_msg), "Disposition-Notification-To");
-
-        if (value != NULL)
-            headers->dispnotify_to =
-                internet_address_list_parse(libbalsa_parser_options(), value);
+        headers->dispnotify_to =
+            internet_address_list_parse_string(g_mime_object_get_header
+                                                   (GMIME_OBJECT(mime_msg),
+                                                   "Disposition-Notification-To"));
     }
 
     if (headers->cc_list == NULL) {
         headers->cc_list =
-            lb_message_recipients(mime_msg, GMIME_ADDRESS_TYPE_CC);
+            lb_message_recipients(mime_msg, GMIME_RECIPIENT_TYPE_CC);
     }
 
     if (headers->bcc_list == NULL) {
         headers->bcc_list =
-            lb_message_recipients(mime_msg, GMIME_ADDRESS_TYPE_BCC);
+            lb_message_recipients(mime_msg, GMIME_RECIPIENT_TYPE_BCC);
     }
 
     /* Get fcc from message */
     if (headers->fcc_url == NULL) {
-       headers->fcc_url =
-           g_strdup(g_mime_object_get_header(GMIME_OBJECT(mime_msg), "X-Balsa-Fcc"));
+        headers->fcc_url =
+            g_strdup(g_mime_object_get_header(GMIME_OBJECT(mime_msg), "X-Balsa-Fcc"));
     }
 }
 
+
 /* Populate headers from the info in mime_msg. */
 void
 libbalsa_message_headers_from_gmime(LibBalsaMessageHeaders *headers,
-                                   GMimeMessage *mime_msg)
+                                    GMimeMessage           *mime_msg)
 {
     lb_message_headers_basic_from_gmime(headers, mime_msg);
     lb_message_headers_extra_from_gmime(headers, mime_msg);
-#if defined ENABLE_AUTOCRYPT
-    if (headers->autocrypt_hdr == NULL) {
-       GDateTime *reftime;
-
-       /* set the reference date far in the future so we can ignore messages w/o Date: header */
-       reftime = g_date_time_new_from_unix_utc(time(NULL) + (365 * 24 * 60 * 60));
-       headers->autocrypt_hdr = g_mime_message_get_autocrypt_header(mime_msg, reftime);
-       g_date_time_unref(reftime);
-    }
-#endif
 }
 
+
 /* Populate message and message->headers from the info in mime_msg,
  * but only the members that are needed all the time. */
 void
-libbalsa_message_init_from_gmime(LibBalsaMessage * message,
-                                GMimeMessage *mime_msg)
+libbalsa_message_init_from_gmime(LibBalsaMessage *message,
+                                 GMimeMessage    *mime_msg)
 {
     const gchar *header;
 
@@ -1155,9 +1136,10 @@ libbalsa_message_refs_for_threading(LibBalsaMessage *message)
 
     g_return_val_if_fail(message != NULL, NULL);
 
-    if (message->in_reply_to != NULL && message->in_reply_to->next != NULL)
+    if (message->in_reply_to && message->in_reply_to->next)
         return NULL;
 
+
     tmp = g_list_copy(message->references);
 
     if (message->in_reply_to) {
@@ -1168,62 +1150,64 @@ libbalsa_message_refs_for_threading(LibBalsaMessage *message)
         foo = g_list_find_custom(tmp, message->in_reply_to->data,
                                  (GCompareFunc) strcmp);
 
-        if (foo != NULL)
-            tmp = g_list_delete_link(tmp, foo);
+        if (foo) {
+            tmp = g_list_remove_link(tmp, foo);
+            g_list_free_1(foo);
+        }
         tmp = g_list_append(tmp, message->in_reply_to->data);
     }
 
-    for (foo = tmp; foo != NULL; foo = foo->next)
+    for (foo = tmp; foo; foo = foo->next) {
         foo->data = g_strdup((gchar *) foo->data);
+    }
 
     return tmp;
 }
 
+
 static GList *
-references_decode(const gchar * str)
+references_decode(const gchar *str)
 {
-    GMimeReferences *references;
+    GMimeReferences *references, *reference;
     GList *list = NULL;
-    gint length;
-    gint i;
-
-    references = g_mime_references_parse(NULL, str);
-    length = g_mime_references_length(references);
-    for (i = 0; i < length; i++) {
-        const gchar *message_id;
 
-        message_id = g_mime_references_get_message_id(references, i);
-        list = g_list_prepend(list, g_strdup(message_id));
+    reference = references = g_mime_references_decode(str);
+    while (reference) {
+        list      = g_list_prepend(list, g_strdup(reference->msgid));
+        reference = reference->next;
     }
-    g_mime_references_free(references);
+    g_mime_references_clear(&references);
 
     return g_list_reverse(list);
 }
 
+
 void
-libbalsa_message_set_references_from_string(LibBalsaMessage * message,
-                                            const gchar     * str)
+libbalsa_message_set_references_from_string(LibBalsaMessage *message,
+                                            const gchar     *str)
 {
     /* Empty references are acceptable but require no action. Similarly,
-     * if references were set already, there is no reason to set them
-     * again - they are immutable anyway. */
+       if references were set already, there is not reason to set them
+       again - they are immutable anyway. */
     if (message->references == NULL && str != NULL)
         message->references = references_decode(str);
 }
 
+
 void
-libbalsa_message_set_in_reply_to_from_string(LibBalsaMessage * message,
-                                             const gchar     * str)
+libbalsa_message_set_in_reply_to_from_string(LibBalsaMessage *message,
+                                             const gchar     *str)
 {
     if (message->in_reply_to == NULL && str != NULL) {
         /* FIXME for Balsa's old non-compliant header */
         gchar *p = strrchr(str, ';');
-        p = p ? g_strndup(str, p - str) : g_strdup(str);
+        p                    = p ? g_strndup(str, p - str) : g_strdup(str);
         message->in_reply_to = references_decode(p);
         g_free(p);
     }
 }
 
+
 /* set a header, if (all) or if it's needed all the time:
  *   headers->from
  *   headers->date
@@ -1244,7 +1228,6 @@ lbmsg_set_header(LibBalsaMessage *message,
                  gboolean         all)
 {
     gchar *val = NULL;
-    LibBalsaMessageHeaders *headers = message->headers;
 
     if (libbalsa_text_attr_string(value)) {
         /* Broken header: force it to utf8 using Balsa's fallback
@@ -1252,7 +1235,7 @@ lbmsg_set_header(LibBalsaMessage *message,
          * appropriate GMime decoder. */
         gchar *tmp = g_strdup(value);
         libbalsa_utf8_sanitize(&tmp, TRUE, NULL);
-        val = g_mime_utils_header_encode_text(NULL, tmp, NULL);
+        val = g_mime_utils_header_encode_text(tmp);
         g_free(tmp);
 #ifdef DEBUG
         g_print("%s: non-ascii “%s” header “%s” encoded as “%s”\n",
@@ -1271,19 +1254,13 @@ lbmsg_set_header(LibBalsaMessage *message,
         libbalsa_message_set_subject_from_header(message, value);
 #endif /* MESSAGE_COPY_CONTENT */
     } else if (g_ascii_strcasecmp(name, "Date") == 0) {
-        GDateTime *datetime;
-
-        datetime = g_mime_utils_header_decode_date(value);
-        if (datetime != NULL) {
-            headers->date = g_date_time_to_unix(datetime);
-            g_date_time_unref(datetime);
-        }
-    } else if ((headers->from == NULL) &&
+        message->headers->date = g_mime_utils_header_decode_date(value, NULL);
+    } else if ((message->headers->from == NULL) &&
                (g_ascii_strcasecmp(name, "From") == 0)) {
-        headers->from = internet_address_list_parse(libbalsa_parser_options(), value);
-    } else if ((headers->to_list == NULL) &&
+        message->headers->from = internet_address_list_parse_string(value);
+    } else if ((message->headers->to_list == NULL) &&
                (g_ascii_strcasecmp(name, "To") == 0)) {
-        headers->to_list = internet_address_list_parse(libbalsa_parser_options(), value);
+        message->headers->to_list = internet_address_list_parse_string(value);
     } else if (g_ascii_strcasecmp(name, "In-Reply-To") == 0) {
         libbalsa_message_set_in_reply_to_from_string(message, value);
     } else if ((message->message_id == NULL) &&
@@ -1291,12 +1268,12 @@ lbmsg_set_header(LibBalsaMessage *message,
         message->message_id = g_mime_utils_decode_message_id(value);
     } else if (g_ascii_strcasecmp(name, "References") == 0) {
         libbalsa_message_set_references_from_string(message, value);
-    } else if ((headers->content_type == NULL) &&
+    } else if ((message->headers->content_type == NULL) &&
                (g_ascii_strcasecmp(name, "Content-Type") == 0)) {
-        headers->content_type = g_mime_content_type_parse(libbalsa_parser_options(), value);
-    } else if ((headers->dispnotify_to == NULL) &&
+        message->headers->content_type = g_mime_content_type_new_from_string(value);
+    } else if ((message->headers->dispnotify_to == NULL) &&
                (g_ascii_strcasecmp(name, "Disposition-Notification-To") == 0)) {
-        headers->dispnotify_to = internet_address_list_parse(libbalsa_parser_options(), value);
+        message->headers->dispnotify_to = internet_address_list_parse_string(value);
     } else
 #ifdef MESSAGE_COPY_CONTENT
     if (g_ascii_strcasecmp(name, "Content-Length") == 0) {
@@ -1304,8 +1281,8 @@ lbmsg_set_header(LibBalsaMessage *message,
     } else
 #endif /* MESSAGE_COPY_CONTENT */
     if (all) {
-        headers->user_hdrs =
-            g_list_prepend(headers->user_hdrs,
+        message->headers->user_hdrs =
+            g_list_prepend(message->headers->user_hdrs,
                            libbalsa_create_hdr_pair(name, g_strdup(value)));
     }
 
@@ -1376,7 +1353,9 @@ libbalsa_message_load_envelope_from_stream(LibBalsaMessage *message,
     gmime_stream_filter =
         g_mime_stream_filter_new(gmime_stream);
 
-    gmime_filter_crlf = g_mime_filter_dos2unix_new(FALSE);
+    gmime_filter_crlf =
+        g_mime_filter_crlf_new(FALSE,
+                               FALSE);
     g_mime_stream_filter_add(GMIME_STREAM_FILTER(gmime_stream_filter),
                              gmime_filter_crlf);
     g_object_unref(gmime_filter_crlf);
@@ -1456,7 +1435,7 @@ libbalsa_message_stream(LibBalsaMessage *message)
 
 
     mime_stream = g_mime_stream_mem_new();
-    g_mime_object_write_to_stream(GMIME_OBJECT(message->mime_msg), NULL,
+    g_mime_object_write_to_stream(GMIME_OBJECT(message->mime_msg),
                                   mime_stream);
     g_mime_stream_reset(mime_stream);
 
@@ -1514,7 +1493,7 @@ libbalsa_message_set_subject_from_header(LibBalsaMessage *message,
 
     if (header) {
         gchar *subject =
-            g_mime_utils_header_decode_text(libbalsa_parser_options(), header);
+            g_mime_utils_header_decode_text(header);
         libbalsa_message_set_subject(message, subject);
         g_free(subject);
     }
diff --git a/libbalsa/message.h b/libbalsa/message.h
index 519e1da47..634fd5055 100644
--- a/libbalsa/message.h
+++ b/libbalsa/message.h
@@ -144,11 +144,6 @@ struct _LibBalsaMessageHeaders {
 
     /* other headers */
     GList *user_hdrs;
-
-#if defined ENABLE_AUTOCRYPT
-    /* received Autocrypt header */
-    GMimeAutocryptHeader *autocrypt_hdr;
-#endif
 };
 
 /** FREE_HEADER_LIST() frees user_hdrs */
diff --git a/libbalsa/misc.c b/libbalsa/misc.c
index dd8f554b7..8a3fad79c 100644
--- a/libbalsa/misc.c
+++ b/libbalsa/misc.c
@@ -265,8 +265,7 @@ libbalsa_mktempdir (char **s)
 }
 
 /* libbalsa_set_fallback_codeset: sets the codeset for incorrectly
- * encoded characters.
- * Returns the previous codeset. */
+ * encoded characters. */
 static LibBalsaCodeset sanitize_fallback_codeset = WEST_EUROPE;
 LibBalsaCodeset
 libbalsa_set_fallback_codeset(LibBalsaCodeset codeset)
@@ -278,10 +277,9 @@ libbalsa_set_fallback_codeset(LibBalsaCodeset codeset)
         NULL
     };
 
-    g_mime_parser_options_set_fallback_charsets(libbalsa_parser_options(), charsets);
+    g_mime_set_user_charsets(charsets);
 
     sanitize_fallback_codeset = codeset;
-
     return ret;
 }
     
@@ -1241,19 +1239,3 @@ libbalsa_font_string_to_css(const gchar * font_string,
     return g_string_free(string, FALSE);
 #endif                          /* !GTK_CHECK_VERSION(3, 22,0) */
 }
-
-static GMimeParserOptions *parser_options;
-
-void
-libbalsa_parser_options_init(void)
-{
-    parser_options = g_mime_parser_options_new();
-    g_mime_parser_options_set_rfc2047_compliance_mode(parser_options,
-                                                      GMIME_RFC_COMPLIANCE_LOOSE);
-}
-
-GMimeParserOptions *
-libbalsa_parser_options(void)
-{
-    return parser_options;
-}
diff --git a/libbalsa/misc.h b/libbalsa/misc.h
index bbc7f9dbe..a0954743b 100644
--- a/libbalsa/misc.h
+++ b/libbalsa/misc.h
@@ -160,8 +160,4 @@ gchar * libbalsa_text_to_html(const gchar * title, const gchar * body, const gch
 GString * libbalsa_html_encode_hyperlinks(GString * paragraph);
 gchar *libbalsa_font_string_to_css(const gchar * font_string, const gchar * name);
 
-void libbalsa_parser_options_init(void);
-GMimeParserOptions *libbalsa_parser_options(void);
-
-
 #endif                         /* __LIBBALSA_MISC_H__ */
diff --git a/libbalsa/rfc3156.c b/libbalsa/rfc3156.c
index 1aec1a5ce..438aa0de2 100644
--- a/libbalsa/rfc3156.c
+++ b/libbalsa/rfc3156.c
@@ -68,7 +68,7 @@ body_is_type(LibBalsaMessageBody * body, const gchar * type,
        retval = g_mime_content_type_is_type(content_type, type, sub_type);
     } else {
        GMimeContentType *content_type =
-           g_mime_content_type_parse(libbalsa_parser_options(), body->content_type);
+           g_mime_content_type_new_from_string(body->content_type);
        retval = g_mime_content_type_is_type(content_type, type, sub_type);
        g_object_unref(content_type);
     }
diff --git a/libbalsa/send.c b/libbalsa/send.c
index c7faa3bfd..0cb397283 100644
--- a/libbalsa/send.c
+++ b/libbalsa/send.c
@@ -270,7 +270,7 @@ lbs_set_content(GMimePart *mime_part,
                                             GMIME_CONTENT_ENCODING_DEFAULT);
     g_object_unref(stream);
 
-    g_mime_part_set_content(mime_part, wrapper);
+    g_mime_part_set_content_object(mime_part, wrapper);
     g_object_unref(wrapper);
 }
 
@@ -341,7 +341,7 @@ add_mime_body_plain(LibBalsaMessageBody     *body,
                                                 GMIME_CONTENT_ENCODING_DEFAULT);
         g_object_unref(stream);
 
-        g_mime_part_set_content(mime_part, wrapper);
+        g_mime_part_set_content_object(mime_part, wrapper);
         g_object_unref(wrapper);
     } else {
         lbs_set_content(mime_part, body->buffer);
@@ -440,12 +440,12 @@ lbs_message_queue_real(LibBalsaMessage    *message,
     mime_msg = libbalsa_message_get_mime_message(message);
     if (fccbox != NULL) {
         g_mime_object_set_header(GMIME_OBJECT(mime_msg), "X-Balsa-Fcc",
-                                 libbalsa_mailbox_get_url(fccbox), NULL);
+                                 libbalsa_mailbox_get_url(fccbox));
     }
     g_mime_object_set_header(GMIME_OBJECT(mime_msg), "X-Balsa-DSN",
-                             libbalsa_message_get_request_dsn(message) ? "1" : "0", NULL);
+                             libbalsa_message_get_request_dsn(message) ? "1" : "0");
     g_mime_object_set_header(GMIME_OBJECT(mime_msg), "X-Balsa-SmtpServer",
-                             libbalsa_smtp_server_get_name(smtp_server), NULL);
+                             libbalsa_smtp_server_get_name(smtp_server));
 
     big_message = libbalsa_smtp_server_get_big_message(smtp_server);
     if (big_message > 0) {
@@ -1166,14 +1166,14 @@ message_add_references(LibBalsaMessage *message,
             }
             g_string_append_printf(str, "<%s>", (gchar *) list->data);
         } while ((list = list->next) != NULL);
-        g_mime_object_set_header(GMIME_OBJECT(msg), "References", str->str, NULL);
+        g_mime_object_set_header(GMIME_OBJECT(msg), "References", str->str);
         g_string_free(str, TRUE);
     }
 
     list = libbalsa_message_get_in_reply_to(message);
     if (list != NULL) {
         /* There's no specific header function for In-Reply-To */
-        g_mime_object_set_header(GMIME_OBJECT(msg), "In-Reply-To", list->data, NULL);
+        g_mime_object_set_header(GMIME_OBJECT(msg), "In-Reply-To", list->data);
     }
 }
 
@@ -1220,6 +1220,24 @@ parse_content_type(const char *content_type)
 }
 
 
+/* get_tz_offset() returns tz offset in RFC 5322 format ([-]hhmm) */
+static gint
+get_tz_offset(time_t t)
+{
+    GTimeZone *local_tz;
+    gint interval;
+    gint32 offset;
+    gint hours;
+
+    local_tz = g_time_zone_new_local();
+    interval = g_time_zone_find_interval(local_tz, G_TIME_TYPE_UNIVERSAL, t);
+    offset = g_time_zone_get_offset(local_tz, interval);
+    g_time_zone_unref(local_tz);
+    hours = offset / 3600;
+    return (hours * 100) + ((offset - (hours * 3600)) / 60);
+}
+
+
 static LibBalsaMsgCreateResult
 libbalsa_message_create_mime_message(LibBalsaMessage *message,
                                      gboolean         flow,
@@ -1230,6 +1248,7 @@ libbalsa_message_create_mime_message(LibBalsaMessage *message,
     GMimeMessage *mime_message;
     LibBalsaMessageBody *body;
     LibBalsaMessageHeaders *headers;
+    InternetAddressList *ia_list;
     gchar *tmp;
     GList *list;
     gboolean attach_pubkey = FALSE;
@@ -1237,7 +1256,6 @@ libbalsa_message_create_mime_message(LibBalsaMessage *message,
 #ifdef ENABLE_AUTOCRYPT
     LibBalsaIdentity *identity;
 #endif /* ENABLE_AUTOCRYPT */
-    GDateTime *datetime;
 
     /* attach the public key only if we send the message, not if we just postpone it */
     if (!postponing &&
@@ -1269,8 +1287,7 @@ libbalsa_message_create_mime_message(LibBalsaMessage *message,
             if (body->attach_mode == LIBBALSA_ATTACH_AS_EXTBODY) {
                 GMimeContentType *content_type =
                     g_mime_content_type_new("message", "external-body");
-                mime_part = g_mime_object_new_type(libbalsa_parser_options(),
-                                                   "message", "external-body");
+                mime_part = g_mime_object_new_type("message", "external-body");
                 g_mime_object_set_content_type(mime_part, content_type);
                 g_mime_part_set_content_encoding(GMIME_PART(mime_part),
                                                  GMIME_CONTENT_ENCODING_7BIT);
@@ -1313,9 +1330,8 @@ libbalsa_message_create_mime_message(LibBalsaMessage *message,
                     return LIBBALSA_MESSAGE_CREATE_ERROR;
                 }
                 parser = g_mime_parser_new_with_stream(stream);
-                g_mime_parser_set_format(parser, GMIME_FORMAT_MESSAGE);
                 g_object_unref(stream);
-                mime_msg = g_mime_parser_construct_message(parser, libbalsa_parser_options());
+                mime_msg = g_mime_parser_construct_message(parser);
                 g_object_unref(parser);
                 mime_part =
                     GMIME_OBJECT(g_mime_message_part_new_with_message
@@ -1384,7 +1400,7 @@ libbalsa_message_create_mime_message(LibBalsaMessage *message,
                 content = g_mime_data_wrapper_new_with_stream(stream,
                                                               GMIME_CONTENT_ENCODING_DEFAULT);
                 g_object_unref(stream);
-                g_mime_part_set_content(GMIME_PART(mime_part),
+                g_mime_part_set_content_object(GMIME_PART(mime_part),
                                                content);
                 g_object_unref(content);
             }
@@ -1467,56 +1483,54 @@ libbalsa_message_create_mime_message(LibBalsaMessage *message,
     message_add_references(message, mime_message);
 
     headers = libbalsa_message_get_headers(message);
-
     if (headers->from != NULL) {
-        InternetAddressList *from;
-
-        from = g_mime_message_get_from(mime_message);
-        internet_address_list_append(from, headers->from);
+        tmp = internet_address_list_to_string(headers->from, TRUE);
+        if (tmp != NULL) {
+            g_mime_message_set_sender(mime_message, tmp);
+            g_free(tmp);
+        }
     }
-
     if (headers->reply_to != NULL) {
-        InternetAddressList *reply_to;
-
-        reply_to = g_mime_message_get_reply_to(mime_message);
-        internet_address_list_append(reply_to, headers->reply_to);
+        tmp = internet_address_list_to_string(headers->reply_to, TRUE);
+        if (tmp != NULL) {
+            g_mime_message_set_reply_to(mime_message, tmp);
+            g_free(tmp);
+        }
     }
 
     if (LIBBALSA_MESSAGE_GET_SUBJECT(message)) {
         g_mime_message_set_subject(mime_message,
-                                   LIBBALSA_MESSAGE_GET_SUBJECT(message), NULL);
+                                   LIBBALSA_MESSAGE_GET_SUBJECT(message));
     }
 
-    datetime = g_date_time_new_from_unix_local(headers->date);
-    g_mime_message_set_date(mime_message, datetime);
-    g_date_time_unref(datetime);
+    g_mime_message_set_date(mime_message, headers->date, get_tz_offset(headers->date));
 
-    if (headers->to_list != NULL) {
-        InternetAddressList *addresses =
-            g_mime_message_get_addresses(mime_message,
-                                          GMIME_ADDRESS_TYPE_TO);
-        internet_address_list_append(addresses, headers->to_list);
+    if ((ia_list = headers->to_list) != NULL) {
+        InternetAddressList *recipients =
+            g_mime_message_get_recipients(mime_message,
+                                          GMIME_RECIPIENT_TYPE_TO);
+        internet_address_list_append(recipients, ia_list);
     }
 
-    if (headers->cc_list != NULL) {
-        InternetAddressList *addresses =
-            g_mime_message_get_addresses(mime_message,
-                                          GMIME_ADDRESS_TYPE_CC);
-        internet_address_list_append(addresses, headers->cc_list);
+    if ((ia_list = headers->cc_list) != NULL) {
+        InternetAddressList *recipients =
+            g_mime_message_get_recipients(mime_message,
+                                          GMIME_RECIPIENT_TYPE_CC);
+        internet_address_list_append(recipients, ia_list);
     }
 
-    if (headers->bcc_list != NULL) {
-        InternetAddressList *addresses =
-            g_mime_message_get_addresses(mime_message,
-                                          GMIME_ADDRESS_TYPE_BCC);
-        internet_address_list_append(addresses, headers->bcc_list);
+    if ((ia_list = headers->bcc_list) != NULL) {
+        InternetAddressList *recipients =
+            g_mime_message_get_recipients(mime_message,
+                                          GMIME_RECIPIENT_TYPE_BCC);
+        internet_address_list_append(recipients, ia_list);
     }
 
     if (headers->dispnotify_to != NULL) {
-        tmp = internet_address_list_to_string(headers->dispnotify_to, NULL, TRUE);
+        tmp = internet_address_list_to_string(headers->dispnotify_to, TRUE);
         if (tmp != NULL) {
             g_mime_object_append_header(GMIME_OBJECT(mime_message),
-                                        "Disposition-Notification-To", tmp, NULL);
+                                        "Disposition-Notification-To", tmp);
             g_free(tmp);
         }
     }
@@ -1524,14 +1538,14 @@ libbalsa_message_create_mime_message(LibBalsaMessage *message,
     for (list = headers->user_hdrs; list; list = list->next) {
         gchar **pair = list->data;
         g_strchug(pair[1]);
-        g_mime_object_append_header(GMIME_OBJECT(mime_message), pair[0], pair[1], NULL);
+        g_mime_object_append_header(GMIME_OBJECT(mime_message), pair[0], pair[1]);
 #if DEBUG_USER_HEADERS
         printf("adding header '%s:%s'\n", pair[0], pair[1]);
 #endif
     }
 
     tmp = g_strdup_printf("Balsa %s", VERSION);
-    g_mime_object_append_header(GMIME_OBJECT(mime_message), "X-Mailer", tmp, NULL);
+    g_mime_object_append_header(GMIME_OBJECT(mime_message), "X-Mailer", tmp);
     g_free(tmp);
 
 #ifdef ENABLE_AUTOCRYPT
@@ -1544,7 +1558,7 @@ libbalsa_message_create_mime_message(LibBalsaMessage *message,
                g_object_unref(mime_message);
                return LIBBALSA_MESSAGE_CREATE_ERROR;
        }
-       g_mime_object_append_header(GMIME_OBJECT(mime_message), "Autocrypt", tmp, NULL);
+       g_mime_object_append_header(GMIME_OBJECT(mime_message), "Autocrypt", tmp);
        g_free(tmp);
     }
 #endif
@@ -1581,8 +1595,8 @@ libbalsa_message_postpone(LibBalsaMessage *message,
         gint i;
 
         for (i = 0; extra_headers[i] && extra_headers[i + 1]; i += 2) {
-            g_mime_object_set_header(GMIME_OBJECT(libbalsa_message_get_mime_message(message)),
-                                     extra_headers[i], extra_headers[i + 1], NULL);
+            g_mime_object_set_header(GMIME_OBJECT(libbalsa_message_get_mime_message(message)), 
extra_headers[i],
+                                     extra_headers[i + 1]);
         }
     }
 
@@ -1710,7 +1724,7 @@ libbalsa_fill_msg_queue_item_from_queu(LibBalsaMessage  *message,
 
         msg_stream = g_mime_stream_mem_new();
         libbalsa_mailbox_lock_store(mailbox);
-        g_mime_object_write_to_stream(GMIME_OBJECT(libbalsa_message_get_mime_message(message)), NULL, 
msg_stream);
+        g_mime_object_write_to_stream(GMIME_OBJECT(libbalsa_message_get_mime_message(message)), msg_stream);
         libbalsa_mailbox_unlock_store(mailbox);
         g_mime_stream_reset(msg_stream);
     } else {
@@ -1728,13 +1742,8 @@ libbalsa_fill_msg_queue_item_from_queu(LibBalsaMessage  *message,
         g_mime_stream_filter_add(GMIME_STREAM_FILTER(filter_stream), filter);
         g_object_unref(filter);
 
-        /* add CRLF */
-        filter = g_mime_filter_unix2dos_new(FALSE);
-        g_mime_stream_filter_add(GMIME_STREAM_FILTER(filter_stream), filter);
-        g_object_unref(filter);
-
-        /* encode dot */
-        filter = g_mime_filter_smtp_data_new();
+        /* add CRLF, encode dot */
+        filter = g_mime_filter_crlf_new(TRUE, TRUE);
         g_mime_stream_filter_add(GMIME_STREAM_FILTER(filter_stream), filter);
         g_object_unref(filter);
 
@@ -1818,7 +1827,7 @@ lb_create_pubkey_part(LibBalsaMessage  *message,
            wrapper = g_mime_data_wrapper_new();
            g_mime_data_wrapper_set_stream(wrapper, stream);
            g_object_unref(stream);
-           g_mime_part_set_content(mime_part, wrapper);
+           g_mime_part_set_content_object(mime_part, wrapper);
            g_object_unref(wrapper);
        }
 
diff --git a/meson.build b/meson.build
index 8848339f7..48545e3aa 100644
--- a/meson.build
+++ b/meson.build
@@ -1,5 +1,5 @@
 project('balsa', 'c',
-        version         : '2.6.0',
+        version         : '2.5.10',
         meson_version   : '>= 0.50.0',
         default_options : ['sysconfdir=/etc', 'optimization=2'])
 
@@ -130,7 +130,7 @@ conf.set('TOOLKIT_CATEGORIES', TOOLKIT_CATEGORIES)
 # Dependencies for balsa and balsa_ab:
 glib_dep    = dependency('glib-2.0', version : '>= 2.48.0')
 gtk_dep     = dependency('gtk+-3.0', version : '>= 3.18.0')
-gmime_dep   = dependency('gmime-3.0', version : '>= 3.2.6')
+gmime_dep   = dependency('gmime-2.6')
 gio_dep     = dependency('gio-2.0')
 gthread_dep = dependency('gthread-2.0')
 gnutls_dep  = dependency('gnutls', version : '>= 3.0')
diff --git a/src/ab-main.c b/src/ab-main.c
index a74b2929a..752bfab11 100644
--- a/src/ab-main.c
+++ b/src/ab-main.c
@@ -462,7 +462,7 @@ file_delete_activated(GSimpleAction * action,
     if (!list)
         return;
 
-    contacts_app.address_book = address_book;
+    contacts_app.address_book = list->data;
     set_address_book_menu_items();
 }
 
@@ -1116,8 +1116,7 @@ main(int argc, char *argv[])
 
     bab_init();
     balsa_ab_setup_libbalsa_notification((GApplication *) application);
-    g_mime_init();
-    libbalsa_parser_options_init();
+    g_mime_init(GMIME_ENABLE_RFC2047_WORKAROUNDS);
 
     /* load address book data */
     libbalsa_conf_push_group("Globals");
diff --git a/src/balsa-message.c b/src/balsa-message.c
index 00238a784..d496b9fcd 100644
--- a/src/balsa-message.c
+++ b/src/balsa-message.c
@@ -1050,9 +1050,9 @@ balsa_message_sender_to_gchar(InternetAddressList * list, gint which)
     if (!list)
        return g_strdup(_("(No sender)"));
     if (which < 0)
-       return internet_address_list_to_string(list, NULL, FALSE);
+       return internet_address_list_to_string(list, FALSE);
     ia = internet_address_list_get_address (list, which);
-    return internet_address_to_string(ia, NULL, FALSE);
+    return internet_address_to_string(ia, FALSE);
 }
 
 static void
@@ -2113,7 +2113,7 @@ add_multipart_mixed(BalsaMessage * balsa_message, LibBalsaMessageBody * body,
         retval = add_body(balsa_message, body, container);
         for (body = body->next; body; body = body->next) {
            GMimeContentType *type =
-               g_mime_content_type_parse(libbalsa_parser_options(), body->content_type);
+               g_mime_content_type_new_from_string(body->content_type);
 
             if (libbalsa_message_body_is_inline(body) ||
                balsa_message->force_inline ||
@@ -2141,7 +2141,7 @@ add_multipart(BalsaMessage *balsa_message, LibBalsaMessageBody *body,
     if (!body->parts)
        return body;
 
-    type = g_mime_content_type_parse(libbalsa_parser_options(), body->content_type);
+    type=g_mime_content_type_new_from_string(body->content_type);
 
     if (g_mime_content_type_is_type(type, "multipart", "related")) {
         /* add the compound object root part */
@@ -2432,9 +2432,9 @@ handle_mdn_request(GtkWindow *parent,
     if (action == BALSA_MDN_REPLY_ASKME) {
         gchar *sender;
         gchar *reply_to;
-        sender = from ? internet_address_to_string(from, NULL, FALSE) : NULL;
+        sender = from ? internet_address_to_string (from, FALSE) : NULL;
         reply_to =
-            internet_address_list_to_string (headers->dispnotify_to, NULL,
+            internet_address_list_to_string (headers->dispnotify_to,
                                             FALSE);
         gtk_widget_show_all (create_mdn_dialog (parent, sender, reply_to, mdn,
                                                 mdn_ident));
@@ -2496,7 +2496,7 @@ static LibBalsaMessage *create_mdn_reply (const LibBalsaIdentity *mdn_ident,
     /* the first part of the body is an informational note */
     body = libbalsa_message_body_new(message);
     date = libbalsa_message_date_to_utf8(for_msg, balsa_app.date_string);
-    dummy = internet_address_list_to_string(for_msg_headers->to_list, NULL, FALSE);
+    dummy = internet_address_list_to_string(for_msg_headers->to_list, FALSE);
     body->buffer = g_strdup_printf(
         "The message sent on %s to %s with subject “%s” has been displayed.\n"
         "There is no guarantee that the message has been read or understood.\n\n",
diff --git a/src/balsa-mime-widget-message.c b/src/balsa-mime-widget-message.c
index e6a166e1a..12cda123c 100644
--- a/src/balsa-mime-widget-message.c
+++ b/src/balsa-mime-widget-message.c
@@ -360,7 +360,7 @@ extbody_send_mail(GtkWidget * button, LibBalsaMessageBody * mime_body)
     }
 
     data = libbalsa_message_body_get_parameter(mime_body, "server");
-    headers->to_list = internet_address_list_parse(libbalsa_parser_options(), data);
+    headers->to_list = internet_address_list_parse_string(data);
     g_free(data);
 
     /* the original body my have some data to be returned as commands... */
@@ -685,7 +685,7 @@ add_header_address_list(BalsaMessage * bm, GtkGrid * grid,
          libbalsa_find_word(header, balsa_app.selected_headers)))
        return;
 
-    value = internet_address_list_to_string(list, NULL, FALSE);
+    value = internet_address_list_to_string(list, FALSE);
 
     add_header_gchar(grid, header, label, value, show_all_headers);
 
@@ -749,14 +749,14 @@ bmw_message_set_headers_d(BalsaMessage           * bm,
 
     if (headers->from) {
        gchar *from =
-           internet_address_list_to_string(headers->from, NULL, FALSE);
+           internet_address_list_to_string(headers->from, FALSE);
        add_header_gchar(grid, "from", _("From:"), from, show_all_headers);
        g_free(from);
     }
 
     if (headers->reply_to) {
        gchar *reply_to =
-           internet_address_list_to_string(headers->reply_to, NULL, FALSE);
+           internet_address_list_to_string(headers->reply_to, FALSE);
        add_header_gchar(grid, "reply-to", _("Reply-To:"), reply_to,
                          show_all_headers);
        g_free(reply_to);
@@ -776,7 +776,7 @@ bmw_message_set_headers_d(BalsaMessage           * bm,
 
     if (headers->dispnotify_to) {
        gchar *mdn_to =
-           internet_address_list_to_string(headers->dispnotify_to, NULL, FALSE);
+           internet_address_list_to_string(headers->dispnotify_to, FALSE);
        add_header_gchar(grid, "disposition-notification-to",
                         _("Disposition-Notification-To:"), mdn_to,
                          show_all_headers);
diff --git a/src/balsa-mime-widget-text.c b/src/balsa-mime-widget-text.c
index ef4f6feb5..8cbee2fae 100644
--- a/src/balsa-mime-widget-text.c
+++ b/src/balsa-mime-widget-text.c
@@ -1139,8 +1139,7 @@ balsa_gtk_html_popup(GtkWidget * html, BalsaMessage * bm)
                                  GTK_WIDGET(bm),
                                  GDK_GRAVITY_CENTER, GDK_GRAVITY_CENTER,
                                  NULL);
-    if (current_event != NULL)
-        gdk_event_free(current_event);
+    g_clear_object(&current_event);
 
     return TRUE;
 }
diff --git a/src/balsa-mime-widget-vcalendar.c b/src/balsa-mime-widget-vcalendar.c
index 44d7120d2..924092b1a 100644
--- a/src/balsa-mime-widget-vcalendar.c
+++ b/src/balsa-mime-widget-vcalendar.c
@@ -254,7 +254,7 @@ balsa_vevent_widget(LibBalsaVEvent *event, LibBalsaVCal *vcal, gboolean may_repl
 
        /* add the callback data to the event object */
        g_object_set_data_full(G_OBJECT(event), "ev:sender",
-                              internet_address_to_string(sender, NULL, FALSE),
+                              internet_address_to_string(sender, FALSE),
                               (GDestroyNotify) g_free);
         g_object_set_data_full(G_OBJECT(event), "ev:ident",
                                g_object_ref(vevent_ident),
@@ -354,7 +354,7 @@ vevent_reply(GObject * button, GtkWidget * box)
     headers = libbalsa_message_get_headers(message);
     headers->from = internet_address_list_new();
     internet_address_list_add(headers->from, ia);
-    headers->to_list = internet_address_list_parse(libbalsa_parser_options(), rcpt);
+    headers->to_list = internet_address_list_parse_string(rcpt);
     headers->date = time(NULL);
 
     /* create the message subject */
diff --git a/src/balsa-print-object-header.c b/src/balsa-print-object-header.c
index ec08a3dcb..e832c20ea 100644
--- a/src/balsa-print-object-header.c
+++ b/src/balsa-print-object-header.c
@@ -492,7 +492,7 @@ header_add_list(PangoLayout * layout, GString * header_buf,
          balsa_app.shown_headers == HEADERS_ALL ||
          libbalsa_find_word(field_id, balsa_app.selected_headers)) ||
         !values ||
-        !(_value = internet_address_list_to_string(values, NULL, FALSE)))
+        !(_value = internet_address_list_to_string(values, FALSE)))
        return;
 
     p_width = p_string_width_from_layout(layout, label);
diff --git a/src/main-window.c b/src/main-window.c
index 05b6cf404..b8a98fc2a 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -3201,11 +3201,6 @@ balsa_window_dispose(GObject * object)
         priv->open_mbnode_info_array = NULL;
     }
 
-    if (priv->activity_messages != NULL) {
-        g_slist_free_full(priv->activity_messages, g_free);
-        priv->activity_messages = NULL;
-    }
-
     balsa_app.in_destruction = TRUE;
     G_OBJECT_CLASS(balsa_window_parent_class)->dispose(object);
 
@@ -4631,7 +4626,7 @@ balsa_window_decrease_activity(BalsaWindow * window, const gchar * message)
     const gchar *new_message = NULL;
     gboolean clear_fraction = FALSE;
 
-    if (priv->progress_bar == NULL || priv->activity_messages == NULL)
+    if (priv->progress_bar == NULL)
         return;
 
     link = g_slist_find_custom(priv->activity_messages, message,
diff --git a/src/message-window.c b/src/message-window.c
index 909641b65..dacd08602 100644
--- a/src/message-window.c
+++ b/src/message-window.c
@@ -750,7 +750,7 @@ mw_select_part_cb(BalsaMessage * bm, gpointer data)
         LibBalsaMessage *message = balsa_message_get_message(bm);
 
         if (message != NULL) {
-            from = internet_address_list_to_string(libbalsa_message_get_headers(message)->from, NULL,
+            from = internet_address_list_to_string(libbalsa_message_get_headers(message)->from,
                                                    FALSE);
             title = g_strdup_printf(_("Message from %s: %s"), from,
                                     LIBBALSA_MESSAGE_GET_SUBJECT(message));
diff --git a/src/print-gtk.c b/src/print-gtk.c
index 939053ac8..847eb5282 100644
--- a/src/print-gtk.c
+++ b/src/print-gtk.c
@@ -348,7 +348,7 @@ begin_print(GtkPrintOperation * operation, GtkPrintContext * context,
 
     from_list = libbalsa_message_get_headers(pdata->message)->from;
     if (from_list != NULL) {
-       gchar *from = internet_address_list_to_string(from_list, NULL, FALSE);
+       gchar *from = internet_address_list_to_string(from_list, FALSE);
 
        libbalsa_utf8_sanitize(&from, balsa_app.convert_unknown_8bit,
                               NULL);
diff --git a/src/sendmsg-window.c b/src/sendmsg-window.c
index 75db6f431..8d5ab0fb8 100644
--- a/src/sendmsg-window.c
+++ b/src/sendmsg-window.c
@@ -478,7 +478,7 @@ delete_handler(BalsaSendmsg * bsmsg)
     if (ia) {
         tmp = ia->name;
         if (!tmp || !*tmp)
-            tmp = free_me = internet_address_to_string(ia, NULL, FALSE);
+            tmp = free_me = internet_address_to_string(ia, FALSE);
     }
     if (!tmp || !*tmp)
         tmp = _("(No name)");
@@ -814,7 +814,7 @@ sw_edit_activated(GSimpleAction * action,
             InternetAddressList *list =
                 libbalsa_address_view_get_list(bsmsg->recipient_view,
                                                address_types[type]);
-            gchar *addr_string = internet_address_list_to_string(list, NULL, FALSE);
+            gchar *addr_string = internet_address_list_to_string(list, FALSE);
             g_object_unref(list);
             fprintf(tmp, "%s %s\n", _(address_types[type]), addr_string);
             g_free(addr_string);
@@ -1096,7 +1096,7 @@ update_bsmsg_identity(BalsaSendmsg* bsmsg, LibBalsaIdentity* ident)
         bcc_list =
             libbalsa_address_view_get_list(bsmsg->recipient_view, "BCC:");
 
-        ident_list = internet_address_list_parse(libbalsa_parser_options(), addr);
+        ident_list = internet_address_list_parse_string(addr);
         if (ident_list) {
             /* Remove any Bcc addresses that came from the old identity
              * from the list. */
@@ -1126,7 +1126,7 @@ update_bsmsg_identity(BalsaSendmsg* bsmsg, LibBalsaIdentity* ident)
 
         /* Add the new Bcc addresses, if any: */
         addr = libbalsa_identity_get_bcc(ident);
-        ident_list = internet_address_list_parse(libbalsa_parser_options(), addr);
+        ident_list = internet_address_list_parse_string(addr);
         if (ident_list) {
             internet_address_list_append(bcc_list, ident_list);
             g_object_unref(ident_list);
@@ -1630,9 +1630,9 @@ get_fwd_mail_headers(const gchar *mailfile)
     }
 
     /* parse the file */
-    parser = g_mime_parser_new_with_stream(stream);
-    g_mime_parser_set_format(parser, GMIME_FORMAT_MESSAGE);
-    message = g_mime_parser_construct_message (parser, libbalsa_parser_options());
+    parser = g_mime_parser_new();
+    g_mime_parser_init_with_stream(parser, stream);
+    message = g_mime_parser_construct_message (parser);
     g_object_unref (parser);
     g_object_unref(stream);
     close(fd);
@@ -1646,7 +1646,7 @@ get_fwd_mail_headers(const gchar *mailfile)
        if (!subject)
            headers->subject = g_strdup(_("(no subject)"));
        else
-           headers->subject = g_mime_utils_header_decode_text(libbalsa_parser_options(), subject);
+           headers->subject = g_mime_utils_header_decode_text(subject);
     }
     libbalsa_utf8_sanitize(&headers->subject,
                           balsa_app.convert_unknown_8bit,
@@ -1733,7 +1733,7 @@ add_attachment(BalsaSendmsg * bsmsg, const gchar *filename,
            utf8name = g_strdup(_("forwarded message"));
        else {
             gchar *tmp =
-                internet_address_list_to_string(attach_data->headers->from, NULL,
+                internet_address_list_to_string(attach_data->headers->from,
                                                 FALSE);
            utf8name = g_strdup_printf(_("Message from %s, subject: “%s”"),
                                       tmp,
@@ -1811,12 +1811,6 @@ add_attachment(BalsaSendmsg * bsmsg, const gchar *filename,
                              menu_item);
     }
 
-    if (can_inline || !is_a_temp_file) {
-        /* Need a separator */
-        menu_item = gtk_separator_menu_item_new();
-        gtk_menu_shell_append(GTK_MENU_SHELL(attach_data->popup_menu), menu_item);
-    }
-
     /* an attachment can be removed */
     menu_item =
        gtk_menu_item_new_with_label(_("Remove"));
@@ -1826,10 +1820,6 @@ add_attachment(BalsaSendmsg * bsmsg, const gchar *filename,
     gtk_menu_shell_append(GTK_MENU_SHELL(attach_data->popup_menu),
                          menu_item);
 
-    /* Insert another separator */
-    menu_item = gtk_separator_menu_item_new();
-    gtk_menu_shell_append(GTK_MENU_SHELL(attach_data->popup_menu), menu_item);
-
     /* add the usual vfs menu so the user can inspect what (s)he actually
        attached... (only for non-message attachments) */
     if (!is_fwd_message)
@@ -3607,7 +3597,7 @@ quote_body(BalsaSendmsg * bsmsg, LibBalsaMessageHeaders *headers,
 
        if (headers->from) {
            gchar *from =
-               internet_address_list_to_string(headers->from, NULL,
+               internet_address_list_to_string(headers->from,
                                                FALSE);
            g_string_append_printf(body, "%s %s\n", _("From:"), from);
            g_free(from);
@@ -3615,7 +3605,7 @@ quote_body(BalsaSendmsg * bsmsg, LibBalsaMessageHeaders *headers,
 
        if (internet_address_list_length(headers->to_list) > 0) {
            gchar *to_list =
-               internet_address_list_to_string(headers->to_list, NULL,
+               internet_address_list_to_string(headers->to_list,
                                                FALSE);
            g_string_append_printf(body, "%s %s\n", _("To:"), to_list);
            g_free(to_list);
@@ -3623,7 +3613,7 @@ quote_body(BalsaSendmsg * bsmsg, LibBalsaMessageHeaders *headers,
 
        if (internet_address_list_length(headers->cc_list) > 0) {
            gchar *cc_list =
-               internet_address_list_to_string(headers->cc_list, NULL,
+               internet_address_list_to_string(headers->cc_list,
                                                FALSE);
            g_string_append_printf(body, "%s %s\n", _("CC:"), cc_list);
            g_free(cc_list);
@@ -6675,7 +6665,7 @@ sendmsg_window_set_title(BalsaSendmsg * bsmsg)
     }
 
     list = libbalsa_address_view_get_list(bsmsg->recipient_view, "To:");
-    to_string = internet_address_list_to_string(list, NULL, FALSE);
+    to_string = internet_address_list_to_string(list, FALSE);
     g_object_unref(list);
 
     title = g_strdup_printf(title_format, to_string ? to_string : "",
diff --git a/src/store-address.c b/src/store-address.c
index 257a8ce13..37f240bac 100644
--- a/src/store-address.c
+++ b/src/store-address.c
@@ -376,7 +376,7 @@ store_address_add_address(StoreAddressInfo * info,
     entries = g_new(GtkWidget *, NUM_FIELDS);
     info->entries_list = g_list_append(info->entries_list, entries);
 
-    text = internet_address_to_string(ia, NULL, FALSE);
+    text = internet_address_to_string(ia, FALSE);
     address = libbalsa_address_new();
     libbalsa_address_set_full_name(address,
                                    ia->name != NULL ? ia->name :


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