[balsa/79-mdn-ical-sender-fixes] fix MDN, iCalender Sender related issues, improve Sender: handling




commit 3083dff6369ad9277525e45c29afbb75b847a4a5
Author: Albrecht Dreß <albrecht dress netcologne de>
Date:   Fri Jun 3 22:08:30 2022 +0200

    fix MDN, iCalender Sender related issues, improve Sender: handling
    
    See issue #79 for a detailed description.  This patch
    - fixes checking if a MDN request is suspicious according to RFC 8098,
    - fixes sending an iCalendar reply to the ORGANIZER as requested by RFC
    5545,
    - removes the misleading _LibBalsaMessage::sender item,
    - adds the _LibBalsaMessageHeaders::sender item and fills it
    appropriately,
    - adds the Sender: header to the translatable headers for display and
    printing.
    
    Details:
    - libbalsa/mailbox_imap.c: ignore the IMAP envelope reply-to and sender
    items;
    - libbalsa/message.[ch]: remove _LibBalsaMessage::sender,
    libbalsa_message_[gs]et_sender(); add _LibBalsaMessageHeaders::sender
    and set it from gmime; do not treat Sender: as misc header
    - src/balsa-message.c: display all From: addresses in the message
    structure view; fix dealing with MDN requests according to RFC 8098
    - src/balsa-mime-widget-vcalendar.c: send iCalendar reply according to
    RFC 5545
    - src/balsa-mime-widget-message.c, src/balsa-print-object-header.c: make
    the Sender: header label translatable
    
    Signed-off-by: Albrecht Dreß <albrecht dress netcologne de>

 libbalsa/mailbox_imap.c           | 17 ++++++++--------
 libbalsa/message.c                | 37 ++++++++++------------------------
 libbalsa/message.h                |  8 +++-----
 src/balsa-message.c               | 42 ++++++++++++++++-----------------------
 src/balsa-mime-widget-message.c   |  2 ++
 src/balsa-mime-widget-vcalendar.c | 23 +++++++++++----------
 src/balsa-print-object-header.c   |  2 ++
 7 files changed, 55 insertions(+), 76 deletions(-)
---
diff --git a/libbalsa/mailbox_imap.c b/libbalsa/mailbox_imap.c
index df329ebda..19a304068 100644
--- a/libbalsa/mailbox_imap.c
+++ b/libbalsa/mailbox_imap.c
@@ -2006,6 +2006,14 @@ internet_address_new_list_from_imap_address_list(ImapAddress *list)
     return internet_address_new_list_from_imap_address(list, NULL);
 }
 
+/*
+ * Note: We ignore the "Sender" and "Reply-To" elements from the IMAP ENVELOPE response
+ * as they may not the contain the actual header values of the RFC 5322 message.  See
+ * RFC 3501:
+ *    If the Sender or Reply-To lines are absent in the [RFC-2822] header, or are present
+ *    but empty, the server sets the corresponding member of the envelope to be the same
+ *    value as the from member [...].
+ */
 static void
 lb_set_headers(LibBalsaMessageHeaders *headers, ImapEnvelope *  envelope,
                gboolean is_embedded)
@@ -2013,8 +2021,6 @@ lb_set_headers(LibBalsaMessageHeaders *headers, ImapEnvelope *  envelope,
     headers->date = envelope->date;
     headers->from =
        internet_address_new_list_from_imap_address_list(envelope->from);
-    headers->reply_to =
-        internet_address_new_list_from_imap_address_list(envelope->replyto);
     headers->to_list =
        internet_address_new_list_from_imap_address_list(envelope->to);
     headers->cc_list =
@@ -2036,7 +2042,6 @@ libbalsa_mailbox_imap_load_envelope(LibBalsaMailboxImap *mimap,
     ImapEnvelope *envelope;
     ImapMessage* imsg;
     gchar *hdr;
-    InternetAddressList *sender;
     
     g_return_val_if_fail(mimap->opened, FALSE);
     imsg = mi_get_imsg(mimap, libbalsa_message_get_msgno(message));
@@ -2058,12 +2063,6 @@ libbalsa_mailbox_imap_load_envelope(LibBalsaMailboxImap *mimap,
     envelope = imsg->envelope;
     libbalsa_message_set_subject_from_header(message, envelope->subject);
 
-    if (envelope->sender) {
-        sender = internet_address_new_list_from_imap_address_list(envelope->sender);
-               libbalsa_message_set_sender(message, sender);
-               g_object_unref(sender);
-       }
-
     libbalsa_message_set_in_reply_to_from_string(message, envelope->in_reply_to);
     if (envelope->message_id != NULL) {
         gchar *message_id = g_mime_utils_decode_message_id(envelope->message_id);
diff --git a/libbalsa/message.c b/libbalsa/message.c
index 6682d9928..9d3cef940 100644
--- a/libbalsa/message.c
+++ b/libbalsa/message.c
@@ -67,9 +67,6 @@ struct _LibBalsaMessage {
 
     GMimeMessage *mime_msg;
 
-    /* sender address */
-    InternetAddressList *sender;
-
     /* subject line; we still need it here for sending;
      * although _SET_SUBJECT might resolve it(?)
      * but we can set to to NULL unless there is no mailbox, like
@@ -140,7 +137,6 @@ libbalsa_message_init(LibBalsaMessage * message)
 {
     message->headers = g_new0(LibBalsaMessageHeaders, 1);
     message->mailbox = NULL;
-    message->sender = NULL;
     message->subj = NULL;
     message->references = NULL;
     message->in_reply_to = NULL;
@@ -190,7 +186,6 @@ libbalsa_message_dispose(GObject * object)
 {
     LibBalsaMessage *message = LIBBALSA_MESSAGE(object);
 
-    g_clear_object(&message->sender);
     g_clear_object(&message->mime_msg);
     g_clear_object(&message->ident);
 
@@ -254,6 +249,11 @@ libbalsa_message_headers_destroy(LibBalsaMessageHeaders *headers)
        headers->from = NULL;
     }
 
+    if (headers->sender) {
+       g_object_unref(headers->sender);
+       headers->sender = NULL;
+    }
+
     if (headers->to_list) {
        g_object_unref(headers->to_list);
        headers->to_list = NULL;
@@ -498,7 +498,7 @@ prepend_header_misc(GList      *res,
 {
     char lcname[28]; /* one byte longer than the longest ignored header */
     static const char ignored_headers[] =
-        "subject date from to cc bcc "
+        "subject date from sender to cc bcc "
         "message-id references in-reply-to status lines"
         "disposition-notification-to";
     unsigned i;
@@ -978,6 +978,11 @@ lb_message_headers_basic_from_gmime(LibBalsaMessageHeaders *headers,
             lb_message_address_list_ref(g_mime_message_get_from(mime_msg));
     }
 
+    if (headers->sender == NULL) {
+        headers->sender =
+            lb_message_address_list_ref(g_mime_message_get_addresses(mime_msg, GMIME_ADDRESS_TYPE_SENDER));
+    }
+
     if (headers->date == 0) {
         GDateTime *datetime;
 
@@ -1573,15 +1578,6 @@ libbalsa_message_get_has_all_headers(LibBalsaMessage *message)
 }
 
 
-InternetAddressList *
-libbalsa_message_get_sender(LibBalsaMessage *message)
-{
-    g_return_val_if_fail(LIBBALSA_IS_MESSAGE(message), 0);
-
-    return message->sender;
-}
-
-
 gboolean
 libbalsa_message_get_request_dsn(LibBalsaMessage *message)
 {
@@ -1748,17 +1744,6 @@ libbalsa_message_set_mime_message(LibBalsaMessage *message,
 }
 
 
-void
-libbalsa_message_set_sender(LibBalsaMessage     *message,
-                            InternetAddressList *sender)
-{
-    g_return_if_fail(LIBBALSA_IS_MESSAGE(message));
-    g_return_if_fail(sender == NULL || IS_INTERNET_ADDRESS_LIST(sender));
-
-    g_set_object(&message->sender, sender);
-}
-
-
 void
 libbalsa_message_set_message_id(LibBalsaMessage *message,
                                 const gchar     *message_id)
diff --git a/libbalsa/message.h b/libbalsa/message.h
index 272227941..f89b0be60 100644
--- a/libbalsa/message.h
+++ b/libbalsa/message.h
@@ -114,11 +114,12 @@ struct _LibBalsaMessageHeaders {
     gchar *subject;
 
     /* from, reply, and disposition notification addresses */
-    InternetAddressList *from;
+    InternetAddressList *from;         /* may actually be a list */
+    InternetAddressList *sender;
     InternetAddressList *reply_to;
     InternetAddressList *dispnotify_to;
 
-    /* primary, secondary, and blind recipent lists */
+    /* primary, secondary, and blind recipient lists */
     InternetAddressList *to_list;
     InternetAddressList *cc_list;
     InternetAddressList *bcc_list;
@@ -297,7 +298,6 @@ const gchar            *libbalsa_message_get_message_id(LibBalsaMessage *message
 guint                   libbalsa_message_get_msgno(LibBalsaMessage *message);
 gint64                  libbalsa_message_get_length(LibBalsaMessage *message);
 gboolean                libbalsa_message_get_has_all_headers(LibBalsaMessage *message);
-InternetAddressList    *libbalsa_message_get_sender(LibBalsaMessage *message);
 gboolean                libbalsa_message_get_request_dsn(LibBalsaMessage *message);
 GList                  *libbalsa_message_get_references(LibBalsaMessage *message);
 LibBalsaIdentity       *libbalsa_message_get_identity(LibBalsaMessage *message);
@@ -325,8 +325,6 @@ void libbalsa_message_set_length(LibBalsaMessage *message,
                                  gint64           length);
 void libbalsa_message_set_mime_message(LibBalsaMessage *message,
                                    GMimeMessage    *mime_message);
-void libbalsa_message_set_sender(LibBalsaMessage     *message,
-                                 InternetAddressList *sender);
 void libbalsa_message_set_message_id(LibBalsaMessage *message,
                                      const gchar     *message_id);
 void libbalsa_message_set_request_dsn(LibBalsaMessage *message,
diff --git a/src/balsa-message.c b/src/balsa-message.c
index fe31a2f7c..8815fd36e 100644
--- a/src/balsa-message.c
+++ b/src/balsa-message.c
@@ -1427,7 +1427,7 @@ display_part(BalsaMessage * balsa_message, LibBalsaMessageBody * body,
 
         if (strcmp(content_type, "message/rfc822") == 0 &&
             body->embhdrs) {
-            gchar *from = balsa_message_sender_to_gchar(body->embhdrs->from, 0);
+            gchar *from = balsa_message_sender_to_gchar(body->embhdrs->from, -1);
             gchar *subj = g_strdup(body->embhdrs->subject);
             libbalsa_utf8_sanitize(&from, balsa_app.convert_unknown_8bit, NULL);
             libbalsa_utf8_sanitize(&subj, balsa_app.convert_unknown_8bit, NULL);
@@ -2400,36 +2400,28 @@ handle_mdn_request(GtkWindow *parent,
                    LibBalsaMessage *message,
                    LibBalsaMessageHeaders *headers)
 {
-    gboolean suspicious;
-    InternetAddressList *use_from = NULL;
+    const gchar *return_path;
+    gboolean suspicious = TRUE;
     InternetAddressList *list;
-    InternetAddress *from, *dn;
+    InternetAddress *dn;
     BalsaMDNReply action;
     LibBalsaMessage *mdn;
     LibBalsaIdentity *mdn_ident = NULL;
     gint i, len;
 
-    /* Check if the dispnotify_to address is equal to the (in this order,
-       if present) reply_to, from or sender address. */
-    if (headers->reply_to != NULL) {
-        use_from = headers->reply_to;
-    } else if (headers->from != NULL) {
-        use_from = headers->from;
-    }
-    if (use_from == NULL) {
-        InternetAddressList *sender;
-
-        sender = libbalsa_message_get_sender(message);
-        if (sender != NULL)
-            use_from = sender;
-        else
-            use_from = NULL;
-    }
-    /* note: neither Disposition-Notification-To: nor Reply-To:, From: or
-       Sender: may be address groups */
-    from = use_from ? internet_address_list_get_address (use_from, 0) : NULL;
+    /* according to RFC 8098 sect. 2.1 a MDN request shall be considered suspicious if the Return-Path 
differs from the
+     * Disposition-Notification-To address */
+    return_path = libbalsa_message_get_user_header(message, "Return-Path");
     dn = internet_address_list_get_address(headers->dispnotify_to, 0);
-    suspicious = !libbalsa_ia_rfc2821_equal(dn, from);
+    if (return_path != NULL) {
+       InternetAddressList *return_ia;
+
+       return_ia = internet_address_list_parse(NULL, return_path);
+       if (return_ia != NULL) {
+               suspicious = !libbalsa_ia_rfc2821_equal(dn, internet_address_list_get_address(return_ia, 0));
+               g_object_unref(return_ia);
+       }
+    }
 
     /* Try to find "my" identity first in the to, then in the cc list */
     list = headers->to_list;
@@ -2485,7 +2477,7 @@ 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 = internet_address_list_to_string(headers->from, NULL, FALSE);
         reply_to =
             internet_address_list_to_string (headers->dispnotify_to, NULL,
                                             FALSE);
diff --git a/src/balsa-mime-widget-message.c b/src/balsa-mime-widget-message.c
index 2c6d6483a..33765dc44 100644
--- a/src/balsa-mime-widget-message.c
+++ b/src/balsa-mime-widget-message.c
@@ -760,6 +760,8 @@ bmw_message_set_headers_d(BalsaMessage           * bm,
                             show_all_headers);
     add_header_address_list(bm, grid, "bcc", _("BCC:"), headers->bcc_list,
                             show_all_headers);
+    add_header_address_list(bm, grid, "sender", _("Sender:"), headers->sender,
+                            show_all_headers);
 
 #if BALSA_SHOW_FCC_AS_WELL_AS_X_BALSA_FCC
     if (headers->fcc_url)
diff --git a/src/balsa-mime-widget-vcalendar.c b/src/balsa-mime-widget-vcalendar.c
index 2e8201bd0..95f7d838f 100644
--- a/src/balsa-mime-widget-vcalendar.c
+++ b/src/balsa-mime-widget-vcalendar.c
@@ -81,20 +81,15 @@ balsa_mime_widget_new_vcalendar(BalsaMessage * bm,
 
        may_reply = TRUE;
         headers = libbalsa_message_get_headers(lbm);
+
+       /* Note: usually, a VEvent reply is sent to the ORGANIZER; use the Reply-To:
+        * or From: address as fallback only if it is not specified */
        if (headers != NULL) {
            if (headers->reply_to != NULL)
                 sender = internet_address_list_get_address(headers->reply_to, 0);
            else if (headers->from != NULL)
                 sender = internet_address_list_get_address(headers->from, 0);
        }
-        if (sender == NULL) {
-            InternetAddressList *ia_list;
-
-            ia_list = libbalsa_message_get_sender(lbm);
-
-            if (ia_list != NULL)
-                sender = internet_address_list_get_address(ia_list, 0);
-        }
     }
 
     /* add events */
@@ -175,9 +170,10 @@ balsa_vevent_widget(LibBalsaVEvent *event, LibBalsaVCal *vcal, gboolean may_repl
     GtkGrid *grid;
     int row = 0;
     LibBalsaIdentity *vevent_ident = NULL;
+    gchar *answer_to_mail = NULL;
     guint attendee;
     gchar *buffer;
-       GString *all_atts = NULL;
+    GString *all_atts = NULL;
 
     grid = GTK_GRID(gtk_grid_new());
     gtk_grid_set_row_spacing(grid, 6);
@@ -224,6 +220,11 @@ balsa_vevent_widget(LibBalsaVEvent *event, LibBalsaVCal *vcal, gboolean may_repl
                     if (libbalsa_ia_rfc2821_equal(libbalsa_identity_get_address(ident),
                                                   ia)) {
                         vevent_ident = ident;
+                        if (libbalsa_vevent_organizer(event) != NULL) {
+                            answer_to_mail = libbalsa_address_to_gchar(libbalsa_vevent_organizer(event), 0);
+                        } else if (sender != NULL) {
+                            answer_to_mail = internet_address_to_string(sender, NULL, FALSE);
+                        }
                         break;
                     }
                 }
@@ -246,7 +247,7 @@ balsa_vevent_widget(LibBalsaVEvent *event, LibBalsaVCal *vcal, gboolean may_repl
 
     GRID_ATTACH_TEXT(grid, libbalsa_vevent_description(event), _("Description:"));
 
-    if (sender && vevent_ident) {
+    if (answer_to_mail != NULL) {
        GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
        GtkWidget *label;
        GtkWidget *bbox;
@@ -254,7 +255,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),
+                              answer_to_mail,
                               (GDestroyNotify) g_free);
         g_object_set_data_full(G_OBJECT(event), "ev:ident",
                                g_object_ref(vevent_ident),
diff --git a/src/balsa-print-object-header.c b/src/balsa-print-object-header.c
index ec08a3dcb..382eeca7a 100644
--- a/src/balsa-print-object-header.c
+++ b/src/balsa-print-object-header.c
@@ -149,6 +149,8 @@ balsa_print_object_header_new_real(GList * list,
                    headers->cc_list, &p_label_width, print_all_headers);
     header_add_list(test_layout, header_buf, "bcc", _("BCC:"),
                    headers->bcc_list, &p_label_width, print_all_headers);
+    header_add_list(test_layout, header_buf, "sender", _("Sender:"),
+                   headers->sender, &p_label_width, print_all_headers);
     header_add_string(test_layout, header_buf, "fcc", _("FCC:"),
                      headers->fcc_url, &p_label_width, print_all_headers);
     header_add_list(test_layout, header_buf, "disposition-notification-to",


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