[balsa/gtk3] Enable the request of DSNs (Albrecht Dre ß)



commit 6ac2ffe7c61ca39ff6bd863ae11d148cccd62246
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Fri Feb 27 16:41:04 2015 -0500

    Enable the request of DSNs (Albrecht Dreß)
    
        * libbalsa/identity.[hc]: define default DSN setting, load and store it
        * libbalsa/identity.c, src/balsa-index.c, src/filter-edit-callbacks.c:
        fix clang nagging about a misplaced 'static const' qualifier
        * libbalsa/message.h: add request dsn flag
        * libbalsa/send.c: instruct libesmtp to request the DSN
        * libbalsa/send.c: pass const parameter as const
        * src/balsa-icons.c: add braces around macro
        * src/balsa-index.c: fix clang nagging
        * src/filter-edit-callbacks.c: ditto
        * src/sendmsg-window.[hc]: add GUI stuff for requesting the DSN
            * ui/sendmsg-window.ui: ditto

 ChangeLog                   |   13 ++++++++++++
 libbalsa/identity.c         |   14 +++++++++++-
 libbalsa/identity.h         |    1 +
 libbalsa/message.h          |    3 ++
 libbalsa/send.c             |   46 +++++++++++++++++++++++++++++++-----------
 src/balsa-icons.c           |    6 +++-
 src/balsa-index.c           |    2 +-
 src/filter-edit-callbacks.c |    2 +-
 src/sendmsg-window.c        |   28 ++++++++++++++++++++++---
 src/sendmsg-window.h        |    3 +-
 ui/sendmsg-window.ui        |    5 ++++
 11 files changed, 100 insertions(+), 23 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 175ca5d..43c0dde 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2015-02-27  Albrecht Dreß
+
+       Enable the request of Delivery Status Notifications
+
+       * libbalsa/identity.[hc]: define default DSN setting, load and store it
+       * libbalsa/identity.c, src/balsa-index.c, src/filter-edit-callbacks.c:
+       fix clang nagging about a misplaced 'static const' qualifier
+       * libbalsa/message.h: add request dsn flag
+       * libbalsa/send.c: instruct libesmtp to request the DSN
+       * libbalsa/send.c: pass const parameter as const
+       * src/balsa-icons.c: add braces around macro
+       * src/sendmsg-window.[hc]: add GUI stuff for requesting the DSN
+
 2015-02-23  Peter Bloomfield  <pbloomfield bellsouth net>
 
        Actually change spell-checking language
diff --git a/libbalsa/identity.c b/libbalsa/identity.c
index 3eb4752..e7cdd6c 100644
--- a/libbalsa/identity.c
+++ b/libbalsa/identity.c
@@ -117,6 +117,7 @@ libbalsa_identity_init(LibBalsaIdentity* ident)
     ident->crypt_protocol = LIBBALSA_PROTECT_OPENPGP;
     ident->force_key_id = NULL;
     ident->request_mdn = FALSE;
+    ident->request_dsn = FALSE;
     /*
     ident->face = NULL;
     ident->x_face = NULL;
@@ -945,13 +946,13 @@ append_ident_notebook_page(GtkNotebook *notebook, guint rows,
  * Put the required GtkEntries, Labels, and Checkbuttons in the dialog
  * for creating/editing identities.
  */
-struct {
+static const struct {
     const gchar *mnemonic;
     const gchar *path_key;
     const gchar *box_key;
     const gchar *basename;
     const gchar *info;
-} static const path_info[] = {
+} path_info[] = {
         /* Translators: please do not translate Face. */
     {N_("_Face Path"),
      "identity-facepath",
@@ -1013,6 +1014,10 @@ setup_ident_frame(GtkDialog * dialog, gboolean createp, gpointer tree)
                                  _("send messages in both plain text and _HTML format"),
                                  "identity-sendmpalternative", TRUE);
     ident_dialog_add_checkbutton(grid, row++, dialog,
+                                 _("request positive (successful)"
+                                   " _Delivery Status Notification by default"),
+                                 "identity-requestdsn", TRUE);
+    ident_dialog_add_checkbutton(grid, row++, dialog,
                                  _("request _Message Disposition Notification by default"),
                                  "identity-requestmdn", TRUE);
     ident_dialog_add_file_chooser_button(grid, row++, dialog,
@@ -1492,6 +1497,7 @@ ident_dialog_update(GObject * dlg)
     g_free(id->x_face);
     id->x_face          = ident_dialog_get_path(dlg, "identity-xfacepath");
     id->request_mdn     = ident_dialog_get_bool(dlg, "identity-requestmdn");
+    id->request_dsn     = ident_dialog_get_bool(dlg, "identity-requestdsn");
 
     id->gpg_sign        = ident_dialog_get_bool(dlg, "identity-gpgsign");
     id->gpg_encrypt     = ident_dialog_get_bool(dlg, "identity-gpgencrypt");
@@ -1876,6 +1882,8 @@ display_frame_update(GObject * dialog, LibBalsaIdentity* ident)
                            ident->x_face, TRUE);
     display_frame_set_boolean(dialog, "identity-requestmdn",
                               ident->request_mdn);
+    display_frame_set_boolean(dialog, "identity-requestdsn",
+                              ident->request_dsn);
 
     display_frame_set_boolean(dialog, "identity-gpgsign",
                               ident->gpg_sign);
@@ -1981,6 +1989,7 @@ libbalsa_identity_new_config(const gchar* name)
     ident->face = libbalsa_conf_get_string("FacePath");
     ident->x_face = libbalsa_conf_get_string("XFacePath");
     ident->request_mdn = libbalsa_conf_get_bool("RequestMDN");
+    ident->request_dsn = libbalsa_conf_get_bool("RequestDSN");
 
     ident->gpg_sign = libbalsa_conf_get_bool("GpgSign");
     ident->gpg_encrypt = libbalsa_conf_get_bool("GpgEncrypt");
@@ -2027,6 +2036,7 @@ libbalsa_identity_save(LibBalsaIdentity* ident, const gchar* group)
     if (ident->x_face)
         libbalsa_conf_set_string("XFacePath", ident->x_face);
     libbalsa_conf_set_bool("RequestMDN", ident->request_mdn);
+    libbalsa_conf_set_bool("RequestDSN", ident->request_dsn);
 
     libbalsa_conf_set_bool("GpgSign", ident->gpg_sign);
     libbalsa_conf_set_bool("GpgEncrypt", ident->gpg_encrypt);
diff --git a/libbalsa/identity.h b/libbalsa/identity.h
index 57134b3..f0bae34 100644
--- a/libbalsa/identity.h
+++ b/libbalsa/identity.h
@@ -79,6 +79,7 @@ extern "C"
         gchar *face;
         gchar *x_face;
        gboolean request_mdn;
+       gboolean request_dsn;
 
        gboolean gpg_sign;
        gboolean gpg_encrypt;
diff --git a/libbalsa/message.h b/libbalsa/message.h
index 8a69c12..b9e82ec 100644
--- a/libbalsa/message.h
+++ b/libbalsa/message.h
@@ -212,6 +212,9 @@ struct _LibBalsaMessage {
     gchar * force_key_id;
 #endif
 
+    /* request a DSN (sending) */
+    gboolean request_dsn;
+
     /* a forced multipart subtype or NULL for mixed; used only for
      * sending */
     gchar *subtype;
diff --git a/libbalsa/send.c b/libbalsa/send.c
index 93b36fb..def8cb5 100644
--- a/libbalsa/send.c
+++ b/libbalsa/send.c
@@ -476,6 +476,8 @@ libbalsa_message_queue(LibBalsaMessage * message, LibBalsaMailbox * outbox,
     if (fccbox)
         g_mime_object_set_header(GMIME_OBJECT(message->mime_msg), "X-Balsa-Fcc",
                                   fccbox->url);
+    g_mime_object_set_header(GMIME_OBJECT(message->mime_msg), "X-Balsa-DSN",
+                            message->request_dsn ? "1" : "0");
 #if ENABLE_ESMTP
     g_mime_object_set_header(GMIME_OBJECT(message->mime_msg), "X-Balsa-SmtpServer",
                              libbalsa_smtp_server_get_name(smtp_server));
@@ -600,7 +602,8 @@ libbalsa_message_cb (void **buf, int *len, void *arg)
 
 static void
 add_recipients(smtp_message_t message,
-               InternetAddressList * recipient_list)
+               InternetAddressList * recipient_list,
+               gboolean request_dsn)
 {
     const InternetAddress *ia;
     int i;
@@ -611,14 +614,24 @@ add_recipients(smtp_message_t message,
     for (i = 0; i < internet_address_list_length (recipient_list); i++) {
         ia = internet_address_list_get_address (recipient_list, i);
 
-       if (INTERNET_ADDRESS_IS_MAILBOX (ia))
-           smtp_add_recipient (message, INTERNET_ADDRESS_MAILBOX (ia)->addr);
-       else
-           add_recipients(message, INTERNET_ADDRESS_GROUP (ia)->members);
+       if (INTERNET_ADDRESS_IS_MAILBOX (ia)) {
+           smtp_recipient_t recipient;
+
+            recipient =
+                smtp_add_recipient(message,
+                                   INTERNET_ADDRESS_MAILBOX(ia)->addr);
+           if (request_dsn) {
+                smtp_dsn_set_notify(recipient,
+                                    Notify_SUCCESS | Notify_FAILURE |
+                                    Notify_DELAY);
 
-            /* XXX  - this is where to add DSN requests.  It would be
-               cool if LibBalsaAddress could contain DSN options
-               for a particular recipient. */
+               /* XXX  - It would be cool if LibBalsaAddress could contain DSN options
+                  for a particular recipient.  For the time being, just use a switch */
+           }
+       } else {
+            add_recipients(message, INTERNET_ADDRESS_GROUP(ia)->members,
+                           request_dsn);
+       }
     }
 }
 
@@ -707,6 +720,8 @@ lbs_process_queue(LibBalsaMailbox * outbox, LibBalsaFccboxFinder finder,
             g_object_unref(msg);
             continue;
         }
+        msg->request_dsn =
+               (atoi(libbalsa_message_get_user_header(msg, "X-Balsa-DSN")) != 0);
 
        new_message = msg_queue_item_new(finder);
         created = libbalsa_fill_msg_queue_item_from_queu(msg, new_message);
@@ -779,6 +794,11 @@ lbs_process_queue(LibBalsaMailbox * outbox, LibBalsaFccboxFinder finder,
            /* Add this after the Bcc: copy. */
            message = smtp_add_message (session);
 
+           if (msg->request_dsn) {
+               smtp_dsn_set_ret(message, Ret_HDRS);
+               smtp_dsn_set_envid(message, msg->message_id);
+           }
+
             /* The main copy must not contain a Bcc: header, unless the
              * message has no To: recipients and no Cc: recipients, and
              * exactly one Bcc: recipient: */
@@ -859,11 +879,11 @@ lbs_process_queue(LibBalsaMailbox * outbox, LibBalsaFccboxFinder finder,
               the Bcc recipient list, when it has more than one address.
               The bcc copy gets the single Bcc recipient.  */
 
-            add_recipients(message, msg->headers->to_list);
-            add_recipients(message, msg->headers->cc_list);
+            add_recipients(message, msg->headers->to_list, msg->request_dsn);
+            add_recipients(message, msg->headers->cc_list, msg->request_dsn);
 
             add_recipients(bcc_message ? bcc_message : message, 
-                           msg->headers->bcc_list);
+                           msg->headers->bcc_list, msg->request_dsn);
 
            /* Prohibit status headers. */
            smtp_set_header_option(message, "Status", Hdr_PROHIBIT, 1);
@@ -1618,7 +1638,7 @@ balsa_send_message_real(SendMessageInfo* info)
 
 
 static void
-message_add_references(LibBalsaMessage * message, GMimeMessage * msg)
+message_add_references(const LibBalsaMessage * message, GMimeMessage * msg)
 {
     /* If the message has references set, add them to the envelope */
     if (message->references != NULL) {
@@ -2088,6 +2108,8 @@ libbalsa_fill_msg_queue_item_from_queu(LibBalsaMessage * message,
                                     "X-Balsa-Fcc");
         g_mime_object_remove_header(GMIME_OBJECT(message->mime_msg),
                                     "X-Balsa-SmtpServer");
+        g_mime_object_remove_header(GMIME_OBJECT(message->mime_msg),
+                                    "X-Balsa-DSN");
        mqi->stream = g_mime_stream_mem_new();
         libbalsa_mailbox_lock_store(message->mailbox);
        g_mime_object_write_to_stream(GMIME_OBJECT(message->mime_msg),
diff --git a/src/balsa-icons.c b/src/balsa-icons.c
index 9cfafc0..2d87d9c 100644
--- a/src/balsa-icons.c
+++ b/src/balsa-icons.c
@@ -88,8 +88,9 @@ load_balsa_pixmap(GtkIconTheme *icon_theme, const balsa_pixmap_t *bpixmap)
            BICONS_ERR("icon %s unknown, no fallback", bpixmap->stock_id);
            use_id = "image-missing";
        }
-    } else
+    } else {
        use_id = bpixmap->stock_id;
+    }
 
     BICONS_LOG("\tuse_id %s", use_id);
     g_hash_table_insert(balsa_icon_table, g_strdup(bpixmap->name),
@@ -242,8 +243,9 @@ balsa_register_pixbufs(GtkWidget * widget)
             g_print("%s %s size %d err %s\n", __func__, use_id,
                     width, err->message);
             g_clear_error(&err);
-        } else
+        } else {
             icons[i].set_icon(pixbuf);
+        }
     }
 }
 
diff --git a/src/balsa-index.c b/src/balsa-index.c
index 28f8a0c..a732771 100644
--- a/src/balsa-index.c
+++ b/src/balsa-index.c
@@ -1807,7 +1807,7 @@ mru_menu_cb(const gchar * url, BalsaIndex * index)
 static GtkWidget *
 bndx_popup_menu_create(BalsaIndex * index)
 {
-    const static struct {       /* this is a invariable part of */
+    static const struct {       /* this is a invariable part of */
         const char *icon, *label;       /* the context message menu.    */
         GCallback func;
     } entries[] = {
diff --git a/src/filter-edit-callbacks.c b/src/filter-edit-callbacks.c
index d2f6a3d..5ceb834 100644
--- a/src/filter-edit-callbacks.c
+++ b/src/filter-edit-callbacks.c
@@ -1698,7 +1698,7 @@ change_filter_name(gchar * old_name,gchar * new_name)
 void
 fe_new_pressed(GtkWidget * widget, gpointer data)
 {
-    const static char FLT_NAME_TEMPLATE[] = N_("New filter");
+    static const char FLT_NAME_TEMPLATE[] = N_("New filter");
     gint filter_number;
     LibBalsaFilter* fil;
     guint len = strlen(_(FLT_NAME_TEMPLATE))+4;
diff --git a/src/sendmsg-window.c b/src/sendmsg-window.c
index 961c6ac..5f46be6 100644
--- a/src/sendmsg-window.c
+++ b/src/sendmsg-window.c
@@ -1317,6 +1317,7 @@ update_bsmsg_identity(BalsaSendmsg* bsmsg, LibBalsaIdentity* ident)
     libbalsa_address_view_set_domain(bsmsg->recipient_view, ident->domain);
 
     sw_action_set_active(bsmsg, "request-mdn", ident->request_mdn);
+    sw_action_set_active(bsmsg, "request-dsn", ident->request_dsn);
 }
 
 
@@ -4913,8 +4914,9 @@ bsmsg2message(BalsaSendmsg * bsmsg)
         libbalsa_address_view_get_list(bsmsg->replyto_view, "Reply To:");
 #endif
 
-    if (bsmsg->req_dispnotify)
+    if (bsmsg->req_mdn)
        libbalsa_message_set_dispnotify(message, ident->ia);
+    message->request_dsn = bsmsg->req_dsn;
 
     sw_set_header_from_path(message, "Face", ident->face,
             /* Translators: please do not translate Face. */
@@ -5418,7 +5420,9 @@ message_postpone(BalsaSendmsg * bsmsg)
         g_ptr_array_add(headers, g_strdup(bsmsg->fcc_url));
     }
     g_ptr_array_add(headers, g_strdup("X-Balsa-MDN"));
-    g_ptr_array_add(headers, g_strdup_printf("%d", bsmsg->req_dispnotify));
+    g_ptr_array_add(headers, g_strdup_printf("%d", bsmsg->req_mdn));
+    g_ptr_array_add(headers, g_strdup("X-Balsa-DSN"));
+    g_ptr_array_add(headers, g_strdup_printf("%d", bsmsg->req_dsn));
 #ifdef HAVE_GPGME
     g_ptr_array_add(headers, g_strdup("X-Balsa-Crypto"));
     g_ptr_array_add(headers, g_strdup_printf("%d", bsmsg->gpg_mode));
@@ -6018,7 +6022,17 @@ sw_request_mdn_change_state(GSimpleAction * action, GVariant * state, gpointer d
 {
     BalsaSendmsg *bsmsg = data;
 
-    bsmsg->req_dispnotify = g_variant_get_boolean(state);
+    bsmsg->req_mdn = g_variant_get_boolean(state);
+
+    g_simple_action_set_state(action, state);
+}
+
+static void
+sw_request_dsn_change_state(GSimpleAction * action, GVariant * state, gpointer data)
+{
+    BalsaSendmsg *bsmsg = data;
+
+    bsmsg->req_dsn = g_variant_get_boolean(state);
 
     g_simple_action_set_state(action, state);
 }
@@ -6674,6 +6688,8 @@ static GActionEntry win_entries[] = {
                          sw_fcc_change_state            },
     {"request-mdn",      libbalsa_toggle_activated, NULL, "false",
                          sw_request_mdn_change_state    },
+    {"request-dsn",      libbalsa_toggle_activated, NULL, "false",
+                         sw_request_dsn_change_state    },
     {"flowed",           libbalsa_toggle_activated, NULL, "false",
                          sw_flowed_change_state         },
     {"send-html",        libbalsa_toggle_activated, NULL, "false",
@@ -6819,7 +6835,8 @@ sendmsg_window_new()
 #endif                          /* HAVE_GTKSOURCEVIEW */
 
     /* set options */
-    bsmsg->req_dispnotify = FALSE;
+    bsmsg->req_mdn = FALSE;
+    bsmsg->req_dsn = FALSE;
 
     sw_action_set_active(bsmsg, "flowed", bsmsg->flow);
     sw_action_set_active(bsmsg, "send-html", bsmsg->ident->send_mp_alternative);
@@ -7074,6 +7091,9 @@ sendmsg_window_continue(LibBalsaMailbox * mailbox, guint msgno)
          libbalsa_message_get_user_header(message, "X-Balsa-MDN")))
         sw_action_set_active(bsmsg, "request-mdn", atoi(postpone_hdr) != 0);
     if ((postpone_hdr =
+         libbalsa_message_get_user_header(message, "X-Balsa-DSN")))
+        sw_action_set_active(bsmsg, "request-dsn", atoi(postpone_hdr) != 0);
+    if ((postpone_hdr =
          libbalsa_message_get_user_header(message, "X-Balsa-Lang"))) {
         GtkWidget *langs =
             gtk_menu_item_get_submenu(GTK_MENU_ITEM
diff --git a/src/sendmsg-window.h b/src/sendmsg-window.h
index f9b2223..78e75f6 100644
--- a/src/sendmsg-window.h
+++ b/src/sendmsg-window.h
@@ -98,7 +98,8 @@ extern "C" {
         gulong identities_changed_id;
        gboolean flow;          /* send format=flowed */ 
        gboolean send_mp_alt;   /* send multipart/alternative (plain and html) */ 
-       gboolean req_dispnotify; /* send a MDN */ 
+       gboolean req_mdn;        /* send a MDN */
+       gboolean req_dsn;        /* send a delivery status notification */
        gboolean quit_on_close; /* quit balsa after the compose window */
                                /* is closed.                          */
 #ifdef HAVE_GPGME
diff --git a/ui/sendmsg-window.ui b/ui/sendmsg-window.ui
index b6f4e65..fc4461d 100644
--- a/ui/sendmsg-window.ui
+++ b/ui/sendmsg-window.ui
@@ -206,6 +206,11 @@
         </item>
         <item>
           <attribute name='label'
+            translatable='yes'>_Request Delivery Status Notification</attribute>
+          <attribute name='action'>win.request-dsn</attribute>
+        </item>
+        <item>
+          <attribute name='label'
             translatable='yes'>_Format = Flowed</attribute>
           <attribute name='action'>win.flowed</attribute>
         </item>


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