707 lines
18 KiB
C
707 lines
18 KiB
C
/*
|
|
* 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/libebackend.h>
|
|
|
|
#include <libemail-engine/e-mail-session-utils.h>
|
|
|
|
#include <mail/em-utils.h>
|
|
#include <mail/e-mail-reader.h>
|
|
#include <mail/mail-send-recv.h>
|
|
#include <mail/message-list.h>
|
|
#include <mail/em-composer-utils.h>
|
|
|
|
#define MDN_USER_FLAG "receipt-handled"
|
|
|
|
#define E_TYPE_MDN (e_mdn_get_type ())
|
|
#define E_MDN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_MDN, EMdn))
|
|
#define E_IS_MDN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_MDN))
|
|
|
|
typedef struct _EMdn EMdn;
|
|
typedef struct _EMdnClass EMdnClass;
|
|
|
|
struct _EMdn {
|
|
EExtension parent;
|
|
gpointer alert; /* weak pointer */
|
|
};
|
|
|
|
struct _EMdnClass {
|
|
EExtensionClass parent_class;
|
|
};
|
|
|
|
typedef struct _MdnContext MdnContext;
|
|
|
|
struct _MdnContext {
|
|
ESource *source;
|
|
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->source);
|
|
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_remove_alert (EMdn *mdn)
|
|
{
|
|
g_return_if_fail (E_IS_MDN (mdn));
|
|
|
|
if (mdn->alert != NULL)
|
|
e_alert_response (mdn->alert, GTK_RESPONSE_OK);
|
|
}
|
|
|
|
static void
|
|
mdn_submit_alert (EMdn *mdn,
|
|
EMailReader *reader,
|
|
EAlert *alert)
|
|
{
|
|
EPreviewPane *preview_pane;
|
|
|
|
g_return_if_fail (E_IS_MDN (mdn));
|
|
|
|
mdn_remove_alert (mdn);
|
|
|
|
g_return_if_fail (mdn->alert == NULL);
|
|
|
|
/* 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);
|
|
|
|
mdn->alert = alert;
|
|
g_object_add_weak_pointer (G_OBJECT (mdn->alert), &mdn->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 (EMailSession *session,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
GError *error = NULL;
|
|
|
|
e_mail_session_append_to_local_folder_finish (
|
|
session, result, NULL, &error);
|
|
|
|
if (error == NULL) {
|
|
mail_send (session);
|
|
} else {
|
|
/* FIXME Poor error handling. */
|
|
g_warning ("%s: %s", G_STRFUNC, error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
|
|
static void
|
|
mdn_notify_sender (ESource *identity_source,
|
|
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;
|
|
CamelMessageInfo *receipt_info;
|
|
EMailBackend *backend;
|
|
EMailSession *session;
|
|
ESourceExtension *extension;
|
|
const gchar *message_id;
|
|
const gchar *message_date;
|
|
const gchar *message_subject;
|
|
const gchar *extension_name;
|
|
const gchar *transport_uid;
|
|
const gchar *self_address;
|
|
const gchar *sent_folder_uri;
|
|
gchar *fake_msgid;
|
|
gchar *hostname;
|
|
gchar *receipt_subject;
|
|
gchar *disposition;
|
|
gchar *recipient;
|
|
gchar *content;
|
|
gchar *ua;
|
|
|
|
backend = e_mail_reader_get_backend (reader);
|
|
session = e_mail_backend_get_session (backend);
|
|
|
|
/* 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);
|
|
|
|
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. */
|
|
|
|
g_return_if_fail (identity_source != NULL);
|
|
|
|
extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
|
|
extension = e_source_get_extension (identity_source, extension_name);
|
|
|
|
self_address = e_source_mail_identity_get_address (
|
|
E_SOURCE_MAIL_IDENTITY (extension));
|
|
|
|
extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
|
|
extension = e_source_get_extension (identity_source, extension_name);
|
|
|
|
sent_folder_uri = e_source_mail_submission_get_sent_folder (
|
|
E_SOURCE_MAIL_SUBMISSION (extension));
|
|
|
|
transport_uid = e_source_mail_submission_get_transport_uid (
|
|
E_SOURCE_MAIL_SUBMISSION (extension));
|
|
|
|
/* 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, '@');
|
|
g_return_if_fail (hostname != NULL);
|
|
|
|
hostname++;
|
|
|
|
/* Create toplevel container. */
|
|
body = camel_multipart_new ();
|
|
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. */
|
|
|
|
receipt = camel_mime_message_new ();
|
|
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);
|
|
|
|
camel_medium_set_header (
|
|
CAMEL_MEDIUM (receipt),
|
|
"Return-Path", "<>");
|
|
camel_medium_set_header (
|
|
CAMEL_MEDIUM (receipt),
|
|
"X-Evolution-Identity",
|
|
e_source_get_uid (identity_source));
|
|
camel_medium_set_header (
|
|
CAMEL_MEDIUM (receipt),
|
|
"X-Evolution-Transport",
|
|
transport_uid);
|
|
camel_medium_set_header (
|
|
CAMEL_MEDIUM (receipt),
|
|
"X-Evolution-Fcc",
|
|
sent_folder_uri);
|
|
|
|
/* RFC 3834, Section 5 describes this header. */
|
|
camel_medium_set_header (
|
|
CAMEL_MEDIUM (receipt),
|
|
"Auto-Submitted", "auto-replied");
|
|
|
|
/* Send the receipt. */
|
|
receipt_info = camel_message_info_new (NULL);
|
|
camel_message_info_set_flags (
|
|
receipt_info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN);
|
|
|
|
/* FIXME Pass a GCancellable. */
|
|
e_mail_session_append_to_local_folder (
|
|
session, E_MAIL_LOCAL_FOLDER_OUTBOX,
|
|
receipt, receipt_info, G_PRIORITY_DEFAULT,
|
|
NULL, (GAsyncReadyCallback) mdn_receipt_done,
|
|
g_object_ref (session));
|
|
|
|
camel_message_info_free (receipt_info);
|
|
}
|
|
|
|
static void
|
|
mdn_notify_action_cb (GtkAction *action,
|
|
MdnContext *context)
|
|
{
|
|
mdn_notify_sender (
|
|
context->source,
|
|
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_mail_reader_changed_cb (EMailReader *reader,
|
|
EMdn *mdn)
|
|
{
|
|
MessageList *message_list;
|
|
|
|
g_return_if_fail (E_IS_MAIL_READER (reader));
|
|
|
|
message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
|
|
|
|
if (!message_list || message_list_selected_count (message_list) != 1)
|
|
mdn_remove_alert (mdn);
|
|
}
|
|
|
|
static void
|
|
mdn_message_loaded_cb (EMailReader *reader,
|
|
const gchar *message_uid,
|
|
CamelMimeMessage *message,
|
|
EMdn *mdn)
|
|
{
|
|
EAlert *alert;
|
|
ESource *source;
|
|
ESourceMDN *extension;
|
|
ESourceRegistry *registry;
|
|
EMailBackend *backend;
|
|
EMailSession *session;
|
|
CamelFolder *folder;
|
|
CamelMessageInfo *info;
|
|
EMdnResponsePolicy response_policy;
|
|
const gchar *extension_name;
|
|
gchar *notify_to = NULL;
|
|
|
|
backend = e_mail_reader_get_backend (reader);
|
|
session = e_mail_backend_get_session (backend);
|
|
registry = e_mail_session_get_registry (session);
|
|
|
|
folder = e_mail_reader_ref_folder (reader);
|
|
|
|
mdn_remove_alert (mdn);
|
|
|
|
info = camel_folder_get_message_info (folder, message_uid);
|
|
if (info == NULL)
|
|
goto exit;
|
|
|
|
if (camel_message_info_user_flag (info, MDN_USER_FLAG)) {
|
|
alert = e_alert_new ("mdn:sender-notified", NULL);
|
|
mdn_submit_alert (mdn, reader, alert);
|
|
g_object_unref (alert);
|
|
goto exit;
|
|
}
|
|
|
|
notify_to = mdn_get_notify_to (message);
|
|
if (notify_to == NULL)
|
|
goto exit;
|
|
|
|
/* Do not show the notice in special folders. */
|
|
|
|
if (em_utils_folder_is_drafts (registry, folder))
|
|
goto exit;
|
|
|
|
if (em_utils_folder_is_templates (registry, folder))
|
|
goto exit;
|
|
|
|
if (em_utils_folder_is_sent (registry, folder))
|
|
goto exit;
|
|
|
|
if (em_utils_folder_is_outbox (registry, folder))
|
|
goto exit;
|
|
|
|
/* This returns a new ESource reference. */
|
|
source = em_utils_guess_mail_identity_with_recipients (
|
|
registry, message, folder, message_uid);
|
|
if (source == NULL)
|
|
goto exit;
|
|
|
|
extension_name = E_SOURCE_EXTENSION_MDN;
|
|
extension = e_source_get_extension (source, extension_name);
|
|
response_policy = e_source_mdn_get_response_policy (extension);
|
|
|
|
if (response_policy == E_MDN_RESPONSE_POLICY_ASK) {
|
|
MdnContext *context;
|
|
GtkAction *action;
|
|
gchar *tooltip;
|
|
|
|
context = g_slice_new0 (MdnContext);
|
|
context->source = g_object_ref (source);
|
|
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 (mdn, reader, alert);
|
|
g_object_unref (alert);
|
|
|
|
g_object_unref (action);
|
|
g_free (tooltip);
|
|
}
|
|
|
|
g_object_unref (source);
|
|
|
|
exit:
|
|
if (info != NULL)
|
|
camel_folder_free_message_info (folder, info);
|
|
|
|
g_clear_object (&folder);
|
|
g_free (notify_to);
|
|
}
|
|
|
|
static void
|
|
mdn_message_seen_cb (EMailReader *reader,
|
|
const gchar *message_uid,
|
|
CamelMimeMessage *message)
|
|
{
|
|
ESource *source;
|
|
ESourceMDN *extension;
|
|
ESourceRegistry *registry;
|
|
EMailBackend *backend;
|
|
EMailSession *session;
|
|
CamelFolder *folder;
|
|
CamelMessageInfo *info;
|
|
EMdnResponsePolicy response_policy;
|
|
const gchar *extension_name;
|
|
gchar *notify_to = NULL;
|
|
|
|
backend = e_mail_reader_get_backend (reader);
|
|
session = e_mail_backend_get_session (backend);
|
|
registry = e_mail_session_get_registry (session);
|
|
|
|
folder = e_mail_reader_ref_folder (reader);
|
|
|
|
info = camel_folder_get_message_info (folder, message_uid);
|
|
if (info == NULL)
|
|
goto exit;
|
|
|
|
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;
|
|
|
|
/* This returns a new ESource reference. */
|
|
source = em_utils_guess_mail_identity_with_recipients (
|
|
registry, message, folder, message_uid);
|
|
if (source == NULL)
|
|
goto exit;
|
|
|
|
extension_name = E_SOURCE_EXTENSION_MDN;
|
|
extension = e_source_get_extension (source, extension_name);
|
|
response_policy = e_source_mdn_get_response_policy (extension);
|
|
|
|
if (response_policy == E_MDN_RESPONSE_POLICY_ALWAYS)
|
|
mdn_notify_sender (
|
|
source, reader, folder,
|
|
message, info, notify_to,
|
|
MDN_ACTION_MODE_AUTOMATIC,
|
|
MDN_SENDING_MODE_AUTOMATIC);
|
|
|
|
g_object_unref (source);
|
|
|
|
exit:
|
|
if (info != NULL)
|
|
camel_folder_free_message_info (folder, info);
|
|
|
|
g_clear_object (&folder);
|
|
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, "changed",
|
|
G_CALLBACK (mdn_mail_reader_changed_cb), extension);
|
|
|
|
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), NULL);
|
|
|
|
/* Chain up to parent's constructed() method. */
|
|
G_OBJECT_CLASS (e_mdn_parent_class)->constructed (object);
|
|
}
|
|
|
|
static void
|
|
mdn_dispose (GObject *object)
|
|
{
|
|
mdn_remove_alert (E_MDN (object));
|
|
|
|
/* Chain up to parent's dispose() method. */
|
|
G_OBJECT_CLASS (e_mdn_parent_class)->dispose (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;
|
|
object_class->dispose = mdn_dispose;
|
|
|
|
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)
|
|
{
|
|
}
|
|
|