diff options
Diffstat (limited to 'shell/e-convert-local-mail.c')
-rw-r--r-- | shell/e-convert-local-mail.c | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/shell/e-convert-local-mail.c b/shell/e-convert-local-mail.c new file mode 100644 index 0000000000..c36a036749 --- /dev/null +++ b/shell/e-convert-local-mail.c @@ -0,0 +1,315 @@ +/* + * e-convert-local-mail.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 <glib/gstdio.h> +#include <camel/camel.h> + +#include <shell/e-shell.h> +#include <libevolution-utils/e-alert-dialog.h> + +/* Forward Declarations */ +void e_convert_local_mail (EShell *shell); + +static gboolean +mail_to_maildir_migration_needed (const gchar *mail_data_dir) +{ + gchar *local_store; + gchar *local_outbox; + gboolean migration_needed = FALSE; + + local_store = g_build_filename (mail_data_dir, "local", NULL); + local_outbox = g_build_filename (local_store, ".Outbox", NULL); + + /* If this is a fresh install (no local store exists yet) + * then obviously there's nothing to migrate to Maildir. */ + if (!g_file_test (local_store, G_FILE_TEST_IS_DIR)) + migration_needed = FALSE; + + /* Look for a Maildir Outbox folder. */ + else if (!g_file_test (local_outbox, G_FILE_TEST_IS_DIR)) + migration_needed = TRUE; + + g_free (local_store); + g_free (local_outbox); + + return migration_needed; +} + +/* Folder names with '.' are converted to '_' */ +static gchar * +sanitize_maildir_folder_name (gchar *folder_name) +{ + gchar *maildir_folder_name; + + maildir_folder_name = g_strdup (folder_name); + g_strdelimit (maildir_folder_name, ".", '_'); + + return maildir_folder_name; +} + +static void +copy_folder (CamelStore *mail_store, + CamelStore *maildir_store, + const gchar *mail_fname, + const gchar *maildir_fname) +{ + CamelFolder *fromfolder, *tofolder; + GPtrArray *uids; + + fromfolder = camel_store_get_folder_sync ( + mail_store, mail_fname, 0, NULL, NULL); + if (fromfolder == NULL) { + g_warning ("Cannot find mail folder %s \n", mail_fname); + return; + } + + tofolder = camel_store_get_folder_sync ( + maildir_store, maildir_fname, + CAMEL_STORE_FOLDER_CREATE, NULL, NULL); + if (tofolder == NULL) { + g_warning ("Cannot create maildir folder %s \n", maildir_fname); + g_object_unref (fromfolder); + return; + } + + uids = camel_folder_get_uids (fromfolder); + camel_folder_transfer_messages_to_sync ( + fromfolder, uids, tofolder, FALSE, NULL, NULL, NULL); + camel_folder_free_uids (fromfolder, uids); + + g_object_unref (fromfolder); + g_object_unref (tofolder); +} + +static void +copy_folders (CamelStore *mail_store, + CamelStore *maildir_store, + CamelFolderInfo *fi, + CamelSession *session) +{ + if (fi) { + if (!g_str_has_prefix (fi->full_name, ".#evolution")) { + gchar *maildir_folder_name; + + /* sanitize folder names and copy folders */ + maildir_folder_name = sanitize_maildir_folder_name (fi->full_name); + copy_folder ( + mail_store, maildir_store, + fi->full_name, maildir_folder_name); + g_free (maildir_folder_name); + } + + if (fi->child) + copy_folders (mail_store, maildir_store, fi->child, session); + + copy_folders (mail_store, maildir_store, fi->next, session); + } +} + +struct MigrateStore { + CamelSession *session; + CamelStore *mail_store; + CamelStore *maildir_store; + gboolean complete; +}; + +static void +migrate_stores (struct MigrateStore *ms) +{ + CamelFolderInfo *mail_fi; + CamelStore *mail_store = ms->mail_store; + CamelStore *maildir_store = ms->maildir_store; + + mail_fi = camel_store_get_folder_info_sync ( + mail_store, NULL, + CAMEL_STORE_FOLDER_INFO_RECURSIVE | + CAMEL_STORE_FOLDER_INFO_FAST | + CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, + NULL, NULL); + + /* FIXME progres dialog */ + copy_folders (mail_store, maildir_store, mail_fi, ms->session); + ms->complete = TRUE; +} + +static void +rename_mail_dir (ESource *mbox_source, + const gchar *mail_data_dir) +{ + gchar *old_mail_dir; + gchar *new_mail_dir; + gboolean need_rename; + const gchar *mbox_uid; + + mbox_uid = e_source_get_uid (mbox_source); + + old_mail_dir = g_build_filename (mail_data_dir, "local", NULL); + new_mail_dir = g_build_filename (mail_data_dir, mbox_uid, NULL); + + /* Rename if old directory exists and new directory does not. */ + need_rename = + g_file_test (old_mail_dir, G_FILE_TEST_EXISTS) && + !g_file_test (new_mail_dir, G_FILE_TEST_EXISTS); + + if (need_rename) + g_rename (old_mail_dir, new_mail_dir); + + g_free (old_mail_dir); + g_free (new_mail_dir); +} + +static gboolean +migrate_mail_to_maildir (EShell *shell, + CamelSession *session, + ESource *mbox_source) +{ + ESourceRegistry *registry; + ESourceExtension *extension; + const gchar *extension_name; + CamelService *mail_service; + CamelService *maildir_service; + CamelStore *mail_store; + CamelStore *maildir_store; + CamelSettings *settings; + const gchar *data_dir; + const gchar *mbox_uid; + gchar *path; + struct MigrateStore ms; + GError *error = NULL; + + registry = e_shell_get_registry (shell); + + data_dir = camel_session_get_user_data_dir (session); + + mbox_uid = e_source_get_uid (mbox_source); + e_source_set_display_name (mbox_source, "local_mbox"); + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + extension = e_source_get_extension (mbox_source, extension_name); + + e_source_backend_set_backend_name ( + E_SOURCE_BACKEND (extension), "mbox"); + + extension_name = e_source_camel_get_extension_name ("mbox"); + extension = e_source_get_extension (mbox_source, extension_name); + settings = e_source_camel_get_settings (E_SOURCE_CAMEL (extension)); + + path = g_build_filename (data_dir, mbox_uid, NULL); + g_object_set (settings, "path", path, NULL); + g_free (path); + + e_source_registry_commit_source_sync ( + registry, mbox_source, NULL, &error); + + if (error == NULL) + mail_service = camel_session_add_service ( + session, mbox_uid, "mbox", + CAMEL_PROVIDER_STORE, &error); + + if (error == NULL) + maildir_service = camel_session_add_service ( + session, "local", "maildir", + CAMEL_PROVIDER_STORE, &error); + + if (error != NULL) { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + return FALSE; + } + + camel_service_set_settings (mail_service, settings); + + settings = camel_service_get_settings (maildir_service); + path = g_build_filename (data_dir, "local", NULL); + g_object_set (settings, "path", path, NULL); + g_mkdir (path, 0700); + g_free (path); + + mail_store = CAMEL_STORE (mail_service); + maildir_store = CAMEL_STORE (maildir_service); + + ms.mail_store = mail_store; + ms.maildir_store = maildir_store; + ms.session = session; + ms.complete = FALSE; + + g_thread_create ((GThreadFunc) migrate_stores, &ms, TRUE, NULL); + while (!ms.complete) + g_main_context_iteration (NULL, TRUE); + + return TRUE; +} + +void +e_convert_local_mail (EShell *shell) +{ + CamelSession *session; + ESource *mbox_source; + const gchar *user_data_dir; + const gchar *user_cache_dir; + gchar *mail_data_dir; + gchar *mail_cache_dir; + gchar *local_store; + gint response; + + user_data_dir = e_get_user_data_dir (); + user_cache_dir = e_get_user_cache_dir (); + + mail_data_dir = g_build_filename (user_data_dir, "mail", NULL); + mail_cache_dir = g_build_filename (user_cache_dir, "mail", NULL); + + if (!mail_to_maildir_migration_needed (mail_data_dir)) + goto exit; + + response = e_alert_run_dialog_for_args ( + e_shell_get_active_window (NULL), + "mail:ask-migrate-store", NULL); + + if (response == GTK_RESPONSE_CANCEL) + exit (EXIT_SUCCESS); + + mbox_source = e_source_new (NULL, NULL, NULL); + + rename_mail_dir (mbox_source, mail_data_dir); + + local_store = g_build_filename (mail_data_dir, "local", NULL); + + if (!g_file_test (local_store, G_FILE_TEST_EXISTS)) + g_mkdir_with_parents (local_store, 0700); + + g_free (local_store); + + session = g_object_new ( + CAMEL_TYPE_SESSION, + "online", FALSE, + "user-data-dir", mail_data_dir, + "user-cache-dir", mail_cache_dir, + NULL); + + migrate_mail_to_maildir (shell, session, mbox_source); + + g_object_unref (session); + + g_object_unref (mbox_source); + +exit: + g_free (mail_data_dir); + g_free (mail_cache_dir); +} |