diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2011-11-23 03:52:33 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2011-11-23 03:52:33 +0800 |
commit | 00e495279937c6495d6fab99fe7f89583859ecd1 (patch) | |
tree | 34b9779e6406e44a646bd8bf65a66dc55654f51a /modules | |
parent | 0c83b9b25d967ce6d6793ef851e86bc272a2f129 (diff) | |
parent | f3abed7ac2c6099dbf5fd3e7c2483b6d75a637b5 (diff) | |
download | gsoc2013-evolution-00e495279937c6495d6fab99fe7f89583859ecd1.tar gsoc2013-evolution-00e495279937c6495d6fab99fe7f89583859ecd1.tar.gz gsoc2013-evolution-00e495279937c6495d6fab99fe7f89583859ecd1.tar.bz2 gsoc2013-evolution-00e495279937c6495d6fab99fe7f89583859ecd1.tar.lz gsoc2013-evolution-00e495279937c6495d6fab99fe7f89583859ecd1.tar.xz gsoc2013-evolution-00e495279937c6495d6fab99fe7f89583859ecd1.tar.zst gsoc2013-evolution-00e495279937c6495d6fab99fe7f89583859ecd1.zip |
Merge branch 'master' into wip/gsettings
Conflicts:
mail/e-mail-paned-view.c
Diffstat (limited to 'modules')
-rw-r--r-- | modules/Makefile.am | 1 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-content.c | 114 | ||||
-rw-r--r-- | modules/mdn/Makefile.am | 36 | ||||
-rw-r--r-- | modules/mdn/evolution-mdn.c | 569 | ||||
-rw-r--r-- | modules/mdn/evolution-mdn.error.xml | 9 | ||||
-rw-r--r-- | modules/offline-alert/evolution-offline-alert.error.xml | 2 |
6 files changed, 666 insertions, 65 deletions
diff --git a/modules/Makefile.am b/modules/Makefile.am index dd363d27a3..ee3cdfdb1a 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -29,6 +29,7 @@ SUBDIRS = \ mail \ composer-autosave \ mailto-handler \ + mdn \ offline-alert \ plugin-lib \ plugin-manager \ diff --git a/modules/mail/e-mail-shell-content.c b/modules/mail/e-mail-shell-content.c index 7918930736..e3b9f1f5ff 100644 --- a/modules/mail/e-mail-shell-content.c +++ b/modules/mail/e-mail-shell-content.c @@ -46,6 +46,10 @@ #include "e-mail-shell-backend.h" #include "e-mail-shell-view-actions.h" +#define E_MAIL_SHELL_CONTENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContentPrivate)) + struct _EMailShellContentPrivate { EMailView *mail_view; }; @@ -153,7 +157,7 @@ mail_shell_content_dispose (GObject *object) { EMailShellContentPrivate *priv; - priv = E_MAIL_SHELL_CONTENT (object)->priv; + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (object); if (priv->mail_view != NULL) { g_object_unref (priv->mail_view); @@ -173,7 +177,7 @@ mail_shell_content_constructed (GObject *object) GtkWidget *container; GtkWidget *widget; - priv = E_MAIL_SHELL_CONTENT (object)->priv; + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (object); /* Chain up to parent's constructed () method. */ G_OBJECT_CLASS (parent_class)->constructed (object); @@ -209,14 +213,14 @@ mail_shell_content_constructed (GObject *object) static guint32 mail_shell_content_check_state (EShellContent *shell_content) { - EMailShellContentPrivate *priv; + EMailShellContent *mail_shell_content; EMailReader *reader; - priv = E_MAIL_SHELL_CONTENT (shell_content)->priv; + mail_shell_content = E_MAIL_SHELL_CONTENT (shell_content); /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ - reader = E_MAIL_READER (priv->mail_view); + reader = E_MAIL_READER (mail_shell_content->priv->mail_view); return e_mail_reader_check_state (reader); } @@ -224,13 +228,13 @@ mail_shell_content_check_state (EShellContent *shell_content) static void mail_shell_content_focus_search_results (EShellContent *shell_content) { - EMailShellContentPrivate *priv; + EMailShellContent *mail_shell_content; GtkWidget *message_list; EMailReader *reader; - priv = E_MAIL_SHELL_CONTENT (shell_content)->priv; + mail_shell_content = E_MAIL_SHELL_CONTENT (shell_content); - reader = E_MAIL_READER (priv->mail_view); + reader = E_MAIL_READER (mail_shell_content->priv->mail_view); message_list = e_mail_reader_get_message_list (reader); gtk_widget_grab_focus (message_list); @@ -239,13 +243,13 @@ mail_shell_content_focus_search_results (EShellContent *shell_content) static guint mail_shell_content_open_selected_mail (EMailReader *reader) { - EMailShellContentPrivate *priv; + EMailShellContent *mail_shell_content; - priv = E_MAIL_SHELL_CONTENT (reader)->priv; + mail_shell_content = E_MAIL_SHELL_CONTENT (reader); /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ - reader = E_MAIL_READER (priv->mail_view); + reader = E_MAIL_READER (mail_shell_content->priv->mail_view); return e_mail_reader_open_selected_mail (reader); } @@ -277,30 +281,16 @@ mail_shell_content_get_action_group (EMailReader *reader, return e_shell_window_get_action_group (shell_window, group_name); } -static EAlertSink * -mail_shell_content_get_alert_sink (EMailReader *reader) -{ - EMailShellContentPrivate *priv; - - priv = E_MAIL_SHELL_CONTENT (reader)->priv; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (priv->mail_view); - - return e_mail_reader_get_alert_sink (reader); -} - static EMailBackend * mail_shell_content_get_backend (EMailReader *reader) { - EMailShellContentPrivate *priv; + EMailShellContent *mail_shell_content; - priv = E_MAIL_SHELL_CONTENT (reader)->priv; + mail_shell_content = E_MAIL_SHELL_CONTENT (reader); /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ - reader = E_MAIL_READER (priv->mail_view); + reader = E_MAIL_READER (mail_shell_content->priv->mail_view); return e_mail_reader_get_backend (reader); } @@ -308,13 +298,13 @@ mail_shell_content_get_backend (EMailReader *reader) static EMFormatHTML * mail_shell_content_get_formatter (EMailReader *reader) { - EMailShellContentPrivate *priv; + EMailShellContent *mail_shell_content; - priv = E_MAIL_SHELL_CONTENT (reader)->priv; + mail_shell_content = E_MAIL_SHELL_CONTENT (reader); /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ - reader = E_MAIL_READER (priv->mail_view); + reader = E_MAIL_READER (mail_shell_content->priv->mail_view); return e_mail_reader_get_formatter (reader); } @@ -322,13 +312,13 @@ mail_shell_content_get_formatter (EMailReader *reader) static gboolean mail_shell_content_get_hide_deleted (EMailReader *reader) { - EMailShellContentPrivate *priv; + EMailShellContent *mail_shell_content; - priv = E_MAIL_SHELL_CONTENT (reader)->priv; + mail_shell_content = E_MAIL_SHELL_CONTENT (reader); /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ - reader = E_MAIL_READER (priv->mail_view); + reader = E_MAIL_READER (mail_shell_content->priv->mail_view); return e_mail_reader_get_hide_deleted (reader); } @@ -336,13 +326,13 @@ mail_shell_content_get_hide_deleted (EMailReader *reader) static GtkWidget * mail_shell_content_get_message_list (EMailReader *reader) { - EMailShellContentPrivate *priv; + EMailShellContent *mail_shell_content; - priv = E_MAIL_SHELL_CONTENT (reader)->priv; + mail_shell_content = E_MAIL_SHELL_CONTENT (reader); /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ - reader = E_MAIL_READER (priv->mail_view); + reader = E_MAIL_READER (mail_shell_content->priv->mail_view); return e_mail_reader_get_message_list (reader); } @@ -350,58 +340,58 @@ mail_shell_content_get_message_list (EMailReader *reader) static GtkMenu * mail_shell_content_get_popup_menu (EMailReader *reader) { - EMailShellContentPrivate *priv; + EMailShellContent *mail_shell_content; - priv = E_MAIL_SHELL_CONTENT (reader)->priv; + mail_shell_content = E_MAIL_SHELL_CONTENT (reader); /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ - reader = E_MAIL_READER (priv->mail_view); + reader = E_MAIL_READER (mail_shell_content->priv->mail_view); return e_mail_reader_get_popup_menu (reader); } -static GtkWindow * -mail_shell_content_get_window (EMailReader *reader) +static EPreviewPane * +mail_shell_content_get_preview_pane (EMailReader *reader) { - EMailShellContentPrivate *priv; + EMailShellContent *mail_shell_content; - priv = E_MAIL_SHELL_CONTENT (reader)->priv; + mail_shell_content = E_MAIL_SHELL_CONTENT (reader); /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ - reader = E_MAIL_READER (priv->mail_view); + reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - return e_mail_reader_get_window (reader); + return e_mail_reader_get_preview_pane (reader); } -static void -mail_shell_content_set_folder (EMailReader *reader, - CamelFolder *folder) +static GtkWindow * +mail_shell_content_get_window (EMailReader *reader) { - EMailShellContentPrivate *priv; + EMailShellContent *mail_shell_content; - priv = E_MAIL_SHELL_CONTENT (reader)->priv; + mail_shell_content = E_MAIL_SHELL_CONTENT (reader); /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ - reader = E_MAIL_READER (priv->mail_view); + reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - return e_mail_reader_set_folder (reader, folder); + return e_mail_reader_get_window (reader); } static void -mail_shell_content_show_search_bar (EMailReader *reader) +mail_shell_content_set_folder (EMailReader *reader, + CamelFolder *folder) { - EMailShellContentPrivate *priv; + EMailShellContent *mail_shell_content; - priv = E_MAIL_SHELL_CONTENT (reader)->priv; + mail_shell_content = E_MAIL_SHELL_CONTENT (reader); /* Forward this to our internal EMailView, which * also implements the EMailReader interface. */ - reader = E_MAIL_READER (priv->mail_view); + reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - e_mail_reader_show_search_bar (reader); + return e_mail_reader_set_folder (reader, folder); } static void @@ -456,9 +446,8 @@ mail_shell_content_class_init (EMailShellContentClass *class) static void mail_shell_content_init (EMailShellContent *mail_shell_content) { - mail_shell_content->priv = G_TYPE_INSTANCE_GET_PRIVATE ( - mail_shell_content, E_TYPE_MAIL_SHELL_CONTENT, - EMailShellContentPrivate); + mail_shell_content->priv = + E_MAIL_SHELL_CONTENT_GET_PRIVATE (mail_shell_content); /* Postpone widget construction until we have a shell view. */ } @@ -473,15 +462,14 @@ static void mail_shell_content_reader_init (EMailReaderInterface *interface) { interface->get_action_group = mail_shell_content_get_action_group; - interface->get_alert_sink = mail_shell_content_get_alert_sink; interface->get_backend = mail_shell_content_get_backend; interface->get_formatter = mail_shell_content_get_formatter; interface->get_hide_deleted = mail_shell_content_get_hide_deleted; interface->get_message_list = mail_shell_content_get_message_list; interface->get_popup_menu = mail_shell_content_get_popup_menu; + interface->get_preview_pane = mail_shell_content_get_preview_pane; interface->get_window = mail_shell_content_get_window; interface->set_folder = mail_shell_content_set_folder; - interface->show_search_bar = mail_shell_content_show_search_bar; interface->open_selected_mail = mail_shell_content_open_selected_mail; } diff --git a/modules/mdn/Makefile.am b/modules/mdn/Makefile.am new file mode 100644 index 0000000000..16976b54c1 --- /dev/null +++ b/modules/mdn/Makefile.am @@ -0,0 +1,36 @@ +module_LTLIBRARIES = libevolution-module-mdn.la + +libevolution_module_mdn_la_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/widgets \ + -DG_LOG_DOMAIN=\"evolution-mdn\" \ + $(EVOLUTION_DATA_SERVER_CFLAGS) \ + $(GNOME_PLATFORM_CFLAGS) \ + $(GTKHTML_CFLAGS) + +libevolution_module_mdn_la_SOURCES = \ + evolution-mdn.c + +libevolution_module_mdn_la_LIBADD = \ + $(top_builddir)/mail/libevolution-mail.la \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/shell/libeshell.la \ + $(EVOLUTION_DATA_SERVER_LIBS) \ + $(GNOME_PLATFORM_LIBS) \ + $(GTKHTML_LIBS) + +libevolution_module_mdn_la_LDFLAGS = \ + -module -avoid-version $(NO_UNDEFINED) + +error_DATA = evolution-mdn.error +errordir = $(privdatadir)/errors +@EVO_PLUGIN_RULE@ + +BUILT_SOURCES = $(error_DATA) + +CLEANFILES = $(BUILT_SOURCES) + +EXTRA_DIST = evolution-mdn.error.xml + +-include $(top_srcdir)/git.mk diff --git a/modules/mdn/evolution-mdn.c b/modules/mdn/evolution-mdn.c new file mode 100644 index 0000000000..4311ab73bf --- /dev/null +++ b/modules/mdn/evolution-mdn.c @@ -0,0 +1,569 @@ +/* + * evolution-mdn.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + */ + +#include <config.h> +#include <string.h> +#include <glib/gi18n-lib.h> + +#include <libebackend/e-extension.h> + +#include <e-util/e-alert-dialog.h> +#include <e-util/e-account-utils.h> + +#include <mail/em-utils.h> +#include <mail/e-mail-local.h> +#include <mail/e-mail-reader.h> +#include <mail/mail-send-recv.h> +#include <mail/em-composer-utils.h> +#include <mail/e-mail-folder-utils.h> + +#define MDN_USER_FLAG "receipt-handled" + +typedef EExtension EMdn; +typedef EExtensionClass EMdnClass; + +typedef struct _MdnContext MdnContext; + +struct _MdnContext { + EAccount *account; + EMailReader *reader; + CamelFolder *folder; + CamelMessageInfo *info; + CamelMimeMessage *message; + gchar *notify_to; +}; + +typedef enum { + MDN_ACTION_MODE_MANUAL, + MDN_ACTION_MODE_AUTOMATIC +} MdnActionMode; + +typedef enum { + MDN_SENDING_MODE_MANUAL, + MDN_SENDING_MODE_AUTOMATIC +} MdnSendingMode; + +/* Module Entry Points */ +void e_module_load (GTypeModule *type_module); +void e_module_unload (GTypeModule *type_module); + +/* Forward Declarations */ +GType e_mdn_get_type (void); + +G_DEFINE_DYNAMIC_TYPE (EMdn, e_mdn, E_TYPE_EXTENSION) + +static void +mdn_context_free (MdnContext *context) +{ + if (context->info != NULL) + camel_folder_free_message_info ( + context->folder, context->info); + + g_object_unref (context->account); + g_object_unref (context->reader); + g_object_unref (context->folder); + g_object_unref (context->message); + + g_free (context->notify_to); + + g_slice_free (MdnContext, context); +} + +static void +mdn_submit_alert (EMailReader *reader, + EAlert *alert) +{ + EPreviewPane *preview_pane; + + /* Make sure alerts are shown in the preview pane and not + * wherever e_mail_reader_get_alert_sink() might show it. */ + preview_pane = e_mail_reader_get_preview_pane (reader); + e_alert_sink_submit_alert (E_ALERT_SINK (preview_pane), alert); +} + +static gchar * +mdn_get_notify_to (CamelMimeMessage *message) +{ + CamelMedium *medium; + const gchar *address; + const gchar *header_name; + + medium = CAMEL_MEDIUM (message); + header_name = "Disposition-Notification-To"; + address = camel_medium_get_header (medium, header_name); + + /* TODO Should probably decode/format the address, + * since it could be in RFC 2047 format. */ + if (address != NULL) + while (camel_mime_is_lwsp (*address)) + address++; + + return g_strdup (address); +} + +static gchar * +mdn_get_disposition (MdnActionMode action_mode, + MdnSendingMode sending_mode) +{ + GString *string; + + string = g_string_sized_new (64); + + switch (action_mode) { + case MDN_ACTION_MODE_MANUAL: + g_string_append (string, "manual-action"); + break; + case MDN_ACTION_MODE_AUTOMATIC: + g_string_append (string, "automatic-action"); + break; + default: + g_warn_if_reached (); + } + + g_string_append_c (string, '/'); + + switch (sending_mode) { + case MDN_SENDING_MODE_MANUAL: + g_string_append (string, "MDN-sent-manually"); + break; + case MDN_SENDING_MODE_AUTOMATIC: + g_string_append (string, "MDN-sent-automatically"); + break; + default: + g_warn_if_reached (); + } + + g_string_append (string, ";displayed"); + + return g_string_free (string, FALSE); +} + +static void +mdn_receipt_done (CamelFolder *folder, + GAsyncResult *result, + EMailBackend *backend) +{ + /* FIXME Poor error handling. */ + if (e_mail_folder_append_message_finish (folder, result, NULL, NULL)) + mail_send (backend); + + g_object_unref (backend); +} + +static void +mdn_notify_sender (EAccount *account, + EMailReader *reader, + CamelFolder *folder, + CamelMimeMessage *message, + CamelMessageInfo *info, + const gchar *notify_to, + MdnActionMode action_mode, + MdnSendingMode sending_mode) +{ + /* See RFC 3798 for a description of message receipts. */ + + CamelMimeMessage *receipt; + CamelMultipart *body; + CamelMimePart *part; + CamelMedium *medium; + CamelDataWrapper *receipt_text, *receipt_data; + CamelContentType *type; + CamelInternetAddress *address; + CamelStream *stream; + CamelFolder *out_folder; + CamelMessageInfo *receipt_info; + EMailBackend *backend; + const gchar *message_id; + const gchar *message_date; + const gchar *message_subject; + gchar *fake_msgid; + gchar *hostname; + gchar *self_address; + gchar *receipt_subject; + gchar *transport_uid; + gchar *disposition; + gchar *recipient; + gchar *content; + gchar *ua; + + backend = e_mail_reader_get_backend (reader); + + /* Tag the message immediately even though we haven't actually sent + * the read receipt yet. Not a big deal if we fail to send it, and + * we don't want to keep badgering the user about it. */ + camel_message_info_set_user_flag (info, MDN_USER_FLAG, TRUE); + + receipt = camel_mime_message_new (); + body = camel_multipart_new (); + + medium = CAMEL_MEDIUM (message); + message_id = camel_medium_get_header (medium, "Message-ID"); + message_date = camel_medium_get_header (medium, "Date"); + message_subject = camel_mime_message_get_subject (message); + + if (message_id == NULL) + message_id = ""; + + if (message_date == NULL) + message_date = ""; + + /* Collect information for the receipt. */ + + /* We use camel_header_msgid_generate() to get a canonical + * hostname, then skip the part leading to '@' */ + fake_msgid = camel_header_msgid_generate (); + hostname = strchr (fake_msgid, '@'); + hostname++; + + self_address = account->id->address; + + /* Create toplevel container. */ + camel_data_wrapper_set_mime_type ( + CAMEL_DATA_WRAPPER (body), + "multipart/report;" + "report-type=\"disposition-notification\""); + camel_multipart_set_boundary (body, NULL); + + /* Create textual receipt. */ + + receipt_text = camel_data_wrapper_new (); + + type = camel_content_type_new ("text", "plain"); + camel_content_type_set_param (type, "format", "flowed"); + camel_content_type_set_param (type, "charset", "UTF-8"); + camel_data_wrapper_set_mime_type_field (receipt_text, type); + camel_content_type_unref (type); + + content = g_strdup_printf ( + /* Translators: First %s is an email address, second %s + * is the subject of the email, third %s is the date. */ + _("Your message to %s about \"%s\" on %s has been read."), + self_address, message_subject, message_date); + stream = camel_stream_mem_new (); + camel_stream_write_string (stream, content, NULL, NULL); + camel_data_wrapper_construct_from_stream_sync ( + receipt_text, stream, NULL, NULL); + g_object_unref (stream); + g_free (content); + + part = camel_mime_part_new (); + camel_medium_set_content (CAMEL_MEDIUM (part), receipt_text); + camel_mime_part_set_encoding ( + part, CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE); + camel_multipart_add_part (body, part); + g_object_unref (part); + + g_object_unref (receipt_text); + + /* Create the machine-readable receipt. */ + + receipt_data = camel_data_wrapper_new (); + + ua = g_strdup_printf ( + "%s; %s", hostname, "Evolution " + VERSION SUB_VERSION " " VERSION_COMMENT); + recipient = g_strdup_printf ("rfc822; %s", self_address); + disposition = mdn_get_disposition (action_mode, sending_mode); + + type = camel_content_type_new ("message", "disposition-notification"); + camel_data_wrapper_set_mime_type_field (receipt_data, type); + camel_content_type_unref (type); + + content = g_strdup_printf ( + "Reporting-UA: %s\n" + "Final-Recipient: %s\n" + "Original-Message-ID: %s\n" + "Disposition: %s\n", + ua, recipient, message_id, disposition); + stream = camel_stream_mem_new (); + camel_stream_write_string (stream, content, NULL, NULL); + camel_data_wrapper_construct_from_stream_sync ( + receipt_data, stream, NULL, NULL); + g_object_unref (stream); + g_free (content); + + g_free (ua); + g_free (recipient); + g_free (fake_msgid); + g_free (disposition); + + part = camel_mime_part_new (); + camel_medium_set_content (CAMEL_MEDIUM (part), receipt_data); + camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_7BIT); + camel_multipart_add_part (body, part); + g_object_unref (part); + + g_object_unref (receipt_data); + + /* Finish creating the message. */ + + camel_medium_set_content ( + CAMEL_MEDIUM (receipt), CAMEL_DATA_WRAPPER (body)); + g_object_unref (body); + + receipt_subject = g_strdup_printf ( + /* Translators: %s is the subject of the email message. */ + _("Delivery Notification for \"%s\""), message_subject); + camel_mime_message_set_subject (receipt, receipt_subject); + g_free (receipt_subject); + + address = camel_internet_address_new (); + camel_address_decode (CAMEL_ADDRESS (address), self_address); + camel_mime_message_set_from (receipt, address); + g_object_unref (address); + + address = camel_internet_address_new (); + camel_address_decode (CAMEL_ADDRESS (address), notify_to); + camel_mime_message_set_recipients ( + receipt, CAMEL_RECIPIENT_TYPE_TO, address); + g_object_unref (address); + + transport_uid = g_strconcat ( + account->uid, "-transport", NULL); + + camel_medium_set_header ( + CAMEL_MEDIUM (receipt), + "Return-Path", "<>"); + camel_medium_set_header ( + CAMEL_MEDIUM (receipt), + "X-Evolution-Account", + account->uid); + camel_medium_set_header ( + CAMEL_MEDIUM (receipt), + "X-Evolution-Transport", + transport_uid); + camel_medium_set_header ( + CAMEL_MEDIUM (receipt), + "X-Evolution-Fcc", + account->sent_folder_uri); + + /* RFC 3834, Section 5 describes this header. */ + camel_medium_set_header ( + CAMEL_MEDIUM (receipt), + "Auto-Submitted", "auto-replied"); + + g_free (transport_uid); + + /* Send the receipt. */ + receipt_info = camel_message_info_new (NULL); + out_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX); + camel_message_info_set_flags ( + receipt_info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); + + /* FIXME Pass a GCancellable. */ + e_mail_folder_append_message ( + out_folder, receipt, receipt_info, G_PRIORITY_DEFAULT, + NULL, (GAsyncReadyCallback) mdn_receipt_done, + g_object_ref (backend)); + + camel_message_info_free (receipt_info); +} + +static void +mdn_notify_action_cb (GtkAction *action, + MdnContext *context) +{ + mdn_notify_sender ( + context->account, + context->reader, + context->folder, + context->message, + context->info, + context->notify_to, + MDN_ACTION_MODE_MANUAL, + MDN_SENDING_MODE_MANUAL); + + /* Make sure the newly-added user flag gets saved. */ + camel_folder_free_message_info (context->folder, context->info); + context->info = NULL; +} + +static void +mdn_message_loaded_cb (EMailReader *reader, + const gchar *message_uid, + CamelMimeMessage *message, + EMdn *extension) +{ + EAlert *alert; + EAccount *account; + CamelFolder *folder; + CamelMessageInfo *info; + gchar *notify_to = NULL; + + folder = e_mail_reader_get_folder (reader); + + info = camel_folder_get_message_info (folder, message_uid); + if (info == NULL) + return; + + if (camel_message_info_user_flag (info, MDN_USER_FLAG)) { + alert = e_alert_new ("mdn:sender-notified", NULL); + mdn_submit_alert (reader, alert); + g_object_unref (alert); + goto exit; + } + + notify_to = mdn_get_notify_to (message); + if (notify_to == NULL) + goto exit; + + account = em_utils_guess_account_with_recipients (message, folder); + if (account == NULL) + goto exit; + + if (account->receipt_policy == E_ACCOUNT_RECEIPT_ASK) { + MdnContext *context; + GtkAction *action; + gchar *tooltip; + + context = g_slice_new0 (MdnContext); + context->account = g_object_ref (account); + context->reader = g_object_ref (reader); + context->folder = g_object_ref (folder); + context->message = g_object_ref (message); + context->info = camel_message_info_ref (info); + + context->notify_to = notify_to; + notify_to = NULL; + + tooltip = g_strdup_printf ( + _("Send a read receipt to '%s'"), + context->notify_to); + + action = gtk_action_new ( + "notify-sender", /* name doesn't matter */ + _("_Notify Sender"), + tooltip, NULL); + + g_signal_connect_data ( + action, "activate", + G_CALLBACK (mdn_notify_action_cb), + context, + (GClosureNotify) mdn_context_free, + (GConnectFlags) 0); + + alert = e_alert_new ("mdn:notify-sender", NULL); + e_alert_add_action (alert, action, GTK_RESPONSE_APPLY); + mdn_submit_alert (reader, alert); + g_object_unref (alert); + + g_object_unref (action); + g_free (tooltip); + } + +exit: + camel_folder_free_message_info (folder, info); + g_free (notify_to); +} + +static void +mdn_message_seen_cb (EMailReader *reader, + const gchar *message_uid, + CamelMimeMessage *message, + EMdn *extension) +{ + EAccount *account; + CamelFolder *folder; + CamelMessageInfo *info; + gchar *notify_to = NULL; + + folder = e_mail_reader_get_folder (reader); + + info = camel_folder_get_message_info (folder, message_uid); + if (info == NULL) + return; + + if (camel_message_info_user_flag (info, MDN_USER_FLAG)) + goto exit; + + notify_to = mdn_get_notify_to (message); + if (notify_to == NULL) + goto exit; + + account = em_utils_guess_account_with_recipients (message, folder); + if (account == NULL) + goto exit; + + if (account->receipt_policy == E_ACCOUNT_RECEIPT_ALWAYS) + mdn_notify_sender ( + account, reader, folder, + message, info, notify_to, + MDN_ACTION_MODE_AUTOMATIC, + MDN_SENDING_MODE_AUTOMATIC); + +exit: + camel_folder_free_message_info (folder, info); + g_free (notify_to); +} + +static void +mdn_constructed (GObject *object) +{ + EExtension *extension; + EExtensible *extensible; + + extension = E_EXTENSION (object); + extensible = e_extension_get_extensible (extension); + g_return_if_fail (E_IS_MAIL_READER (extensible)); + + g_signal_connect ( + extensible, "message-loaded", + G_CALLBACK (mdn_message_loaded_cb), extension); + + g_signal_connect ( + extensible, "message-seen", + G_CALLBACK (mdn_message_seen_cb), extension); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_mdn_parent_class)->constructed (object); +} + +static void +e_mdn_class_init (EMdnClass *class) +{ + GObjectClass *object_class; + EExtensionClass *extension_class; + + object_class = G_OBJECT_CLASS (class); + object_class->constructed = mdn_constructed; + + extension_class = E_EXTENSION_CLASS (class); + extension_class->extensible_type = E_TYPE_MAIL_READER; +} + +static void +e_mdn_class_finalize (EMdnClass *class) +{ +} + +static void +e_mdn_init (EMdn *extension) +{ +} + +G_MODULE_EXPORT void +e_module_load (GTypeModule *type_module) +{ + e_mdn_register_type (type_module); +} + +G_MODULE_EXPORT void +e_module_unload (GTypeModule *type_module) +{ +} + diff --git a/modules/mdn/evolution-mdn.error.xml b/modules/mdn/evolution-mdn.error.xml new file mode 100644 index 0000000000..4607d5be7a --- /dev/null +++ b/modules/mdn/evolution-mdn.error.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<error-list domain="mdn"> + <error id="notify-sender" type="question"> + <_primary>Sender wants to be notified when you have read this message.</_primary> + </error> + <error id="sender-notified" type="info"> + <_primary>Sender has been notified that you have read this message.</_primary> + </error> +</error-list> diff --git a/modules/offline-alert/evolution-offline-alert.error.xml b/modules/offline-alert/evolution-offline-alert.error.xml index a6362da42e..782ee8d635 100644 --- a/modules/offline-alert/evolution-offline-alert.error.xml +++ b/modules/offline-alert/evolution-offline-alert.error.xml @@ -3,11 +3,9 @@ <error id="offline" type="info"> <_primary>Evolution is currently offline.</_primary> <_secondary>Click 'Work Online' to return to online mode.</_secondary> - <button _label="_Dismiss" response="GTK_RESPONSE_OK"/> </error> <error id="no-network" type="info"> <_primary>Evolution is currently offline due to a network outage.</_primary> <_secondary>Evolution will return to online mode once a network connection is established.</_secondary> - <button _label="_Dismiss" response="GTK_RESPONSE_OK"/> </error> </error-list> |