diff options
Diffstat (limited to 'plugins/mailing-list-actions/mailing-list-actions.c')
-rw-r--r-- | plugins/mailing-list-actions/mailing-list-actions.c | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/plugins/mailing-list-actions/mailing-list-actions.c b/plugins/mailing-list-actions/mailing-list-actions.c new file mode 100644 index 0000000000..e390e9dd2e --- /dev/null +++ b/plugins/mailing-list-actions/mailing-list-actions.c @@ -0,0 +1,475 @@ +/* + * 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/> + * + * + * Authors: + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * Copyright (C) 2004 Meilof Veeningen <meilof@wanadoo.nl> + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <string.h> +#include <gtk/gtk.h> +#include <glib/gi18n-lib.h> + +#include <e-util/e-util.h> + +#include <shell/e-shell-view.h> +#include <shell/e-shell-window.h> +#include <shell/e-shell-window-actions.h> + +#include <composer/e-msg-composer.h> + +#include <libemail-engine/mail-mt.h> +#include <libemail-engine/mail-ops.h> + +#include <mail/e-mail-browser.h> +#include <mail/e-mail-reader.h> +#include <mail/em-composer-utils.h> +#include <mail/em-config.h> +#include <mail/em-utils.h> +#include <mail/message-list.h> + +/* EAlert Message IDs */ +#define MESSAGE_PREFIX "org.gnome.mailing-list-actions:" +#define MESSAGE_NO_ACTION MESSAGE_PREFIX "no-action" +#define MESSAGE_NO_HEADER MESSAGE_PREFIX "no-header" +#define MESSAGE_ASK_SEND_MESSAGE MESSAGE_PREFIX "ask-send-message" +#define MESSAGE_MALFORMED_HEADER MESSAGE_PREFIX "malformed-header" +#define MESSAGE_POSTING_NOT_ALLOWED MESSAGE_PREFIX "posting-not-allowed" + +typedef enum { + EMLA_ACTION_HELP, + EMLA_ACTION_UNSUBSCRIBE, + EMLA_ACTION_SUBSCRIBE, + EMLA_ACTION_POST, + EMLA_ACTION_OWNER, + EMLA_ACTION_ARCHIVE +} EmlaAction; + +typedef struct { + /* action enumeration */ + EmlaAction action; + + /* whether the user needs to edit a mailto: + * message (e.g. for post action) */ + gboolean interactive; + + /* header representing the action */ + const gchar *header; +} EmlaActionHeader; + +const EmlaActionHeader emla_action_headers[] = { + { EMLA_ACTION_HELP, FALSE, "List-Help" }, + { EMLA_ACTION_UNSUBSCRIBE, TRUE, "List-Unsubscribe" }, + { EMLA_ACTION_SUBSCRIBE, FALSE, "List-Subscribe" }, + { EMLA_ACTION_POST, TRUE, "List-Post" }, + { EMLA_ACTION_OWNER, TRUE, "List-Owner" }, + { EMLA_ACTION_ARCHIVE, FALSE, "List-Archive" }, +}; + +gboolean mail_browser_init (GtkUIManager *ui_manager, + EMailBrowser *browser); +gboolean mail_shell_view_init (GtkUIManager *ui_manager, + EShellView *shell_view); +gint e_plugin_lib_enable (EPlugin *ep, gint enable); + +gint +e_plugin_lib_enable (EPlugin *ep, + gint enable) +{ + return 0; +} + +typedef struct _AsyncContext AsyncContext; + +struct _AsyncContext { + EActivity *activity; + EMailReader *reader; + EmlaAction action; +}; + +static void +async_context_free (AsyncContext *context) +{ + if (context->activity != NULL) + g_object_unref (context->activity); + + if (context->reader != NULL) + g_object_unref (context->reader); + + g_slice_free (AsyncContext, context); +} + +static void +emla_list_action_cb (CamelFolder *folder, + GAsyncResult *result, + AsyncContext *context) +{ + const gchar *header = NULL, *headerpos; + gchar *end, *url = NULL; + gint t; + EMsgComposer *composer; + EAlertSink *alert_sink; + CamelMimeMessage *message; + gint send_message_response; + EShell *shell; + ESource *source; + EMailBackend *backend; + ESourceRegistry *registry; + EShellBackend *shell_backend; + GtkWindow *window; + CamelStore *store; + const gchar *uid; + GError *error = NULL; + + window = e_mail_reader_get_window (context->reader); + backend = e_mail_reader_get_backend (context->reader); + alert_sink = e_activity_get_alert_sink (context->activity); + + shell_backend = E_SHELL_BACKEND (backend); + shell = e_shell_backend_get_shell (shell_backend); + + registry = e_shell_get_registry (shell); + + message = camel_folder_get_message_finish (folder, result, &error); + + if (e_activity_handle_cancellation (context->activity, error)) { + g_warn_if_fail (message == NULL); + async_context_free (context); + g_error_free (error); + return; + + } else if (error != NULL) { + g_warn_if_fail (message == NULL); + e_alert_submit ( + alert_sink, "mail:no-retrieve-message", + error->message, NULL); + async_context_free (context); + g_error_free (error); + return; + } + + g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message)); + + /* Finalize the activity here so we don't leave a + * message in the task bar while display a dialog. */ + e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED); + g_object_unref (context->activity); + context->activity = NULL; + + store = camel_folder_get_parent_store (folder); + uid = camel_service_get_uid (CAMEL_SERVICE (store)); + source = e_source_registry_ref_source (registry, uid); + + /* Reuse this to hold the mail identity UID. */ + uid = NULL; + + if (source != NULL) { + ESourceMailAccount *extension; + const gchar *extension_name; + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + extension = e_source_get_extension (source, extension_name); + uid = e_source_mail_account_get_identity_uid (extension); + } + + for (t = 0; t < G_N_ELEMENTS (emla_action_headers); t++) { + if (emla_action_headers[t].action == context->action) { + header = camel_medium_get_header ( + CAMEL_MEDIUM (message), + emla_action_headers[t].header); + if (header != NULL) + break; + } + } + + if (!header) { + /* there was no header matching the action */ + e_alert_run_dialog_for_args (window, MESSAGE_NO_HEADER, NULL); + goto exit; + } + + headerpos = header; + + if (context->action == EMLA_ACTION_POST) { + while (*headerpos == ' ') headerpos++; + if (g_ascii_strcasecmp (headerpos, "NO") == 0) { + e_alert_run_dialog_for_args ( + window, MESSAGE_POSTING_NOT_ALLOWED, NULL); + goto exit; + } + } + + /* parse the action value */ + while (*headerpos) { + /* skip whitespace */ + while (*headerpos == ' ') headerpos++; + if (*headerpos != '<' || (end = strchr (headerpos++, '>')) == NULL) { + e_alert_run_dialog_for_args ( + window, MESSAGE_MALFORMED_HEADER, + emla_action_headers[t].header, header, NULL); + goto exit; + } + + /* get URL portion */ + url = g_strndup (headerpos, end - headerpos); + + if (strncmp (url, "mailto:", 6) == 0) { + if (emla_action_headers[t].interactive) + send_message_response = GTK_RESPONSE_NO; + else + send_message_response = e_alert_run_dialog_for_args ( + window, MESSAGE_ASK_SEND_MESSAGE, + url, NULL); + + if (send_message_response == GTK_RESPONSE_YES) { + EComposerHeaderTable *table; + + /* directly send message */ + composer = e_msg_composer_new_from_url (shell, url); + table = e_msg_composer_get_header_table (composer); + + if (uid != NULL) + e_composer_header_table_set_identity_uid (table, uid); + e_msg_composer_send (composer); + } else if (send_message_response == GTK_RESPONSE_NO) { + /* show composer */ + em_utils_compose_new_message_with_mailto (shell, url, folder); + } + + goto exit; + } else { + e_show_uri (window, url); + goto exit; + } + g_free (url); + url = NULL; + headerpos = end++; + + /* ignore everything 'till next comma */ + headerpos = strchr (headerpos, ','); + if (!headerpos) + break; + headerpos++; + } + + /* if we got here, there's no valid action */ + e_alert_run_dialog_for_args (window, MESSAGE_NO_ACTION, header, NULL); + +exit: + if (source != NULL) + g_object_unref (source); + + g_object_unref (message); + g_free (url); + + async_context_free (context); +} + +static void +emla_list_action (EMailReader *reader, + EmlaAction action) +{ + EActivity *activity; + AsyncContext *context; + GCancellable *cancellable; + CamelFolder *folder; + GPtrArray *uids; + const gchar *message_uid; + + uids = e_mail_reader_get_selected_uids (reader); + g_return_if_fail (uids != NULL && uids->len == 1); + message_uid = g_ptr_array_index (uids, 0); + + activity = e_mail_reader_new_activity (reader); + cancellable = e_activity_get_cancellable (activity); + + context = g_slice_new0 (AsyncContext); + context->activity = activity; + context->reader = g_object_ref (reader); + context->action = action; + + folder = e_mail_reader_ref_folder (reader); + + camel_folder_get_message ( + folder, message_uid, G_PRIORITY_DEFAULT, + cancellable, (GAsyncReadyCallback) + emla_list_action_cb, context); + + g_clear_object (&folder); + + g_ptr_array_unref (uids); +} + +static void +action_mailing_list_archive_cb (GtkAction *action, + EMailReader *reader) +{ + emla_list_action (reader, EMLA_ACTION_ARCHIVE); +} + +static void +action_mailing_list_help_cb (GtkAction *action, + EMailReader *reader) +{ + emla_list_action (reader, EMLA_ACTION_HELP); +} + +static void +action_mailing_list_owner_cb (GtkAction *action, + EMailReader *reader) +{ + emla_list_action (reader, EMLA_ACTION_OWNER); +} + +static void +action_mailing_list_post_cb (GtkAction *action, + EMailReader *reader) +{ + emla_list_action (reader, EMLA_ACTION_POST); +} + +static void +action_mailing_list_subscribe_cb (GtkAction *action, + EMailReader *reader) +{ + emla_list_action (reader, EMLA_ACTION_SUBSCRIBE); +} + +static void +action_mailing_list_unsubscribe_cb (GtkAction *action, + EMailReader *reader) +{ + emla_list_action (reader, EMLA_ACTION_UNSUBSCRIBE); +} + +static GtkActionEntry mailing_list_entries[] = { + + { "mailing-list-archive", + NULL, + N_("Get List _Archive"), + NULL, + N_("Get an archive of the list this message belongs to"), + G_CALLBACK (action_mailing_list_archive_cb) }, + + { "mailing-list-help", + NULL, + N_("Get List _Usage Information"), + NULL, + N_("Get information about the usage of the list this message belongs to"), + G_CALLBACK (action_mailing_list_help_cb) }, + + { "mailing-list-owner", + NULL, + N_("Contact List _Owner"), + NULL, + N_("Contact the owner of the mailing list this message belongs to"), + G_CALLBACK (action_mailing_list_owner_cb) }, + + { "mailing-list-post", + NULL, + N_("_Post Message to List"), + NULL, + N_("Post a message to the mailing list this message belongs to"), + G_CALLBACK (action_mailing_list_post_cb) }, + + { "mailing-list-subscribe", + NULL, + N_("_Subscribe to List"), + NULL, + N_("Subscribe to the mailing list this message belongs to"), + G_CALLBACK (action_mailing_list_subscribe_cb) }, + + { "mailing-list-unsubscribe", + NULL, + N_("_Unsubscribe from List"), + NULL, + N_("Unsubscribe from the mailing list this message belongs to"), + G_CALLBACK (action_mailing_list_unsubscribe_cb) }, + + /*** Menus ***/ + + { "mailing-list-menu", + NULL, + N_("Mailing _List"), + NULL, + NULL, + NULL } +}; + +static void +update_actions_cb (EMailReader *reader, + guint32 state, + GtkActionGroup *action_group) +{ + gboolean sensitive; + + sensitive = (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST) != 0 + && (state & E_MAIL_READER_SELECTION_SINGLE) != 0; + gtk_action_group_set_sensitive (action_group, sensitive); +} + +static void +setup_actions (EMailReader *reader, + GtkUIManager *ui_manager) +{ + GtkActionGroup *action_group; + const gchar *domain = GETTEXT_PACKAGE; + + action_group = gtk_action_group_new ("mailing-list"); + gtk_action_group_set_translation_domain (action_group, domain); + gtk_action_group_add_actions ( + action_group, mailing_list_entries, + G_N_ELEMENTS (mailing_list_entries), reader); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + g_object_unref (action_group); + + /* GtkUIManager now owns the action group reference. + * The signal we're connecting to will only be emitted + * during the GtkUIManager's lifetime, so the action + * group will not disappear on us. */ + + g_signal_connect ( + reader, "update-actions", + G_CALLBACK (update_actions_cb), action_group); +} + +gboolean +mail_browser_init (GtkUIManager *ui_manager, + EMailBrowser *browser) +{ + setup_actions (E_MAIL_READER (browser), ui_manager); + + return TRUE; +} + +gboolean +mail_shell_view_init (GtkUIManager *ui_manager, + EShellView *shell_view) +{ + EShellContent *shell_content; + + shell_content = e_shell_view_get_shell_content (shell_view); + + setup_actions (E_MAIL_READER (shell_content), ui_manager); + + return TRUE; +} |