void e_mail_store_remove_by_account (EMailBackend *backend, EAccount *account) { EMailSession *session; CamelService *service; CamelProvider *provider; const gchar *uid; g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (E_IS_ACCOUNT (account)); uid = account->uid; session = e_mail_backend_get_session (backend); service = camel_session_get_service (CAMEL_SESSION (session), uid); g_return_if_fail (CAMEL_IS_STORE (service)); provider = camel_service_get_provider (service); g_return_if_fail (provider != NULL); if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE)) return; e_mail_store_remove (backend, CAMEL_STORE (service)); }
static void mail_store_add (EMailBackend *backend, CamelStore *store, AddStoreCallback callback) { EMailSession *session; EMFolderTreeModel *default_model; MailFolderCache *folder_cache; StoreInfo *store_info; g_return_if_fail (store_table != NULL); g_return_if_fail (store != NULL); g_return_if_fail (CAMEL_IS_STORE (store)); session = e_mail_backend_get_session (backend); default_model = em_folder_tree_model_get_default (); folder_cache = e_mail_session_get_folder_cache (session); store_info = store_info_new (store); store_info->callback = callback; g_hash_table_insert (store_table, store, store_info); if (special_mail_store_is_enabled (store)) em_folder_tree_model_add_store (default_model, store); mail_folder_cache_note_store ( folder_cache, CAMEL_SESSION (session), store, NULL, mail_store_note_store_cb, store_info_ref (store_info)); }
static gchar * vfolder_adduri_desc (struct _adduri_msg *m) { CamelStore *store; CamelService *service; EMailSession *session; const gchar *display_name; gchar *folder_name; gchar *description; gboolean success; session = e_mail_backend_get_session (m->backend); success = e_mail_folder_uri_parse ( CAMEL_SESSION (session), m->uri, &store, &folder_name, NULL); if (!success) return NULL; service = CAMEL_SERVICE (store); display_name = camel_service_get_display_name (service); description = g_strdup_printf ( _("Updating Search Folders for '%s' : %s"), display_name, folder_name); g_object_unref (store); g_free (folder_name); return description; }
void e_mail_store_foreach (EMailBackend *backend, GFunc func, gpointer user_data) { EMailSession *session; GList *list, *link; /* XXX This is a silly convenience function. * Could probably just get rid of it. */ g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (func != NULL); session = e_mail_backend_get_session (backend); list = camel_session_list_services (CAMEL_SESSION (session)); for (link = list; link != NULL; link = g_list_next (link)) { CamelService *service = CAMEL_SERVICE (link->data); if (CAMEL_IS_STORE (service)) func (service, user_data); } g_list_free (list); }
static void send_receive (EMailSession *session, gboolean allow_send) { CamelFolder *local_outbox; struct _send_data *data; GList *scan; if (send_data) /* Send Receive is already in progress */ return; if (!camel_session_get_online (CAMEL_SESSION (session))) return; local_outbox = e_mail_session_get_local_folder ( session, E_MAIL_LOCAL_FOLDER_OUTBOX); data = build_infra (session, allow_send); for (scan = data->infos; scan != NULL; scan = scan->next) { struct _send_info *info = scan->data; if (!CAMEL_IS_SERVICE (info->service)) continue; switch (info->type) { case SEND_RECEIVE: mail_fetch_mail ( CAMEL_STORE (info->service), CAMEL_FETCH_OLD_MESSAGES, -1, E_FILTER_SOURCE_INCOMING, mail_provider_fetch_lock, mail_provider_fetch_unlock, mail_provider_fetch_inbox_folder, info->cancellable, receive_get_folder, info, receive_status, info, receive_done, info); break; case SEND_SEND: /* todo, store the folder in info? */ mail_send_queue ( session, local_outbox, CAMEL_TRANSPORT (info->service), E_FILTER_SOURCE_OUTGOING, info->cancellable, receive_get_folder, info, receive_status, info, send_done, info); break; case SEND_UPDATE: receive_update_got_store ( CAMEL_STORE (info->service), info); break; default: break; } } return ; }
static gint uri_is_ignore (EMailBackend *backend, const gchar *uri) { EMailSession *session; CamelSession *camel_session; EAccountList *accounts; EAccount *account; EIterator *iter; const gchar *local_drafts_uri; const gchar *local_outbox_uri; const gchar *local_sent_uri; gint found = FALSE; local_drafts_uri = e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_DRAFTS); local_outbox_uri = e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_OUTBOX); local_sent_uri = e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_SENT); session = e_mail_backend_get_session (backend); camel_session = CAMEL_SESSION (session); if (e_mail_folder_uri_equal (camel_session, local_outbox_uri, uri)) return TRUE; if (e_mail_folder_uri_equal (camel_session, local_sent_uri, uri)) return TRUE; if (e_mail_folder_uri_equal (camel_session, local_drafts_uri, uri)) return TRUE; accounts = e_get_account_list (); iter = e_list_get_iterator (E_LIST (accounts)); while (!found && e_iterator_is_valid (iter)) { /* XXX EIterator misuses const. */ account = (EAccount *) e_iterator_get (iter); if (!found && account->sent_folder_uri != NULL) found = e_mail_folder_uri_equal ( camel_session, uri, account->sent_folder_uri); if (!found && account->drafts_folder_uri != NULL) found = e_mail_folder_uri_equal ( camel_session, uri, account->drafts_folder_uri); e_iterator_next (iter); } g_object_unref (iter); return found; }
CamelSession * camel_scalix_session_new (const char *path) { CamelSession *session; session = CAMEL_SESSION (camel_object_new (E_CAMEL_SCALIX_SESSION_TYPE)); camel_session_construct (session, path); return session; }
static CamelSession * camel_pgp_session_new (const char *path) { CamelSession *session; session = CAMEL_SESSION (camel_object_new (CAMEL_PGP_SESSION_TYPE)); camel_session_construct (session, path); return session; }
GCancellable * mail_receive_account (EMailSession *session, ESource *account) { CamelService *service; service = camel_session_ref_service ( CAMEL_SESSION (session), e_source_get_uid(account)); return mail_receive_service (service); }
static void settings_jh_headers_changed (GSettings *settings, const gchar *key, EMailSession *session) { GSList *node; GPtrArray *name, *value; gchar **strv; gint i; strv = g_settings_get_strv (settings, "junk-custom-header"); if (key) { for (i = 0, node = config->jh_header; strv[i] && node; i++, node = g_slist_next (node)) { if (g_strcmp0 (node->data, strv[i]) != 0) break; } /* both lists are read to the end, thus they are the same */ if (!node && !strv[i]) { g_strfreev (strv); return; } } g_slist_foreach (config->jh_header, (GFunc) g_free, NULL); g_slist_free (config->jh_header); config->jh_header = NULL; for (i = 0; strv[i] != NULL; i++) config->jh_header = g_slist_append (config->jh_header, g_strdup (strv[i])); g_strfreev (strv); node = config->jh_header; name = g_ptr_array_new (); value = g_ptr_array_new (); while (node && node->data) { gchar **tok = g_strsplit (node->data, "=", 2); g_ptr_array_add (name, g_strdup (tok[0])); g_ptr_array_add (value, g_strdup (tok[1])); node = node->next; g_strfreev (tok); } camel_session_set_junk_headers ( CAMEL_SESSION (session), (const gchar **) name->pdata, (const gchar **) value->pdata, name->len); g_ptr_array_foreach (name, (GFunc) g_free, NULL); g_ptr_array_foreach (value, (GFunc) g_free, NULL); g_ptr_array_free (name, TRUE); g_ptr_array_free (value, TRUE); }
static void settings_jh_check_changed (GSettings *settings, const gchar *key, EMailSession *session) { config->jh_check = g_settings_get_boolean (settings, "junk-check-custom-header"); if (!config->jh_check) { camel_session_set_junk_headers ( CAMEL_SESSION (session), NULL, NULL, 0); } else { settings_jh_headers_changed (settings, NULL, session); } }
static gboolean auto_timeout (gpointer data) { EMailSession *session; struct _auto_data *info = data; CamelService *service; const char *uid; session = info->session; uid = e_source_get_uid (info->account); service = camel_session_ref_service ( CAMEL_SESSION (session), uid); printf("Timeout for %s: %p\n", uid, service); g_return_val_if_fail (CAMEL_IS_SERVICE (service), TRUE); if (camel_session_get_online (CAMEL_SESSION (session))) mail_receive_service (service); return TRUE; }
static void gconf_jh_check_changed (GConfClient *client, guint cnxn_id, GConfEntry *entry, EMailSession *session) { config->jh_check = gconf_client_get_bool ( client, "/apps/evolution/mail/junk/check_custom_header", NULL); if (!config->jh_check) { camel_session_set_junk_headers ( CAMEL_SESSION (session), NULL, NULL, 0); } else { gconf_jh_headers_changed (client, 0, NULL, session); } }
static GList * mv_find_folder (GQueue *queue, EMailSession *session, const gchar *uri) { CamelSession *camel_session = CAMEL_SESSION (session); GList *head, *link; head = g_queue_peek_head_link (queue); for (link = head; link != NULL; link = g_list_next (link)) { if (e_mail_folder_uri_equal (camel_session, link->data, uri)) break; } return link; }
static CamelService * ref_default_transport (EMailSession *session) { ESource *source; CamelService *service; const gchar *extension_name; const gchar *uid; source = e_source_registry_ref_default_mail_identity (source_registry); if (source == NULL) return NULL; extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION; if (e_source_has_extension (source, extension_name)) { ESourceMailSubmission *extension; gchar *uid; extension = e_source_get_extension (source, extension_name); uid = e_source_mail_submission_dup_transport_uid (extension); g_object_unref (source); source = e_source_registry_ref_source (source_registry, uid); g_free (uid); } else { g_object_unref (source); source = NULL; } if (source == NULL) return NULL; uid = e_source_get_uid (source); service = camel_session_ref_service (CAMEL_SESSION (session), uid); g_object_unref (source); return service; }
static void settings_jh_headers_changed (GSettings *settings, const gchar *key, EMailSession *session) { GSList *node; GPtrArray *name, *value; gchar **strv; gint i; g_slist_foreach (config->jh_header, (GFunc) g_free, NULL); g_slist_free (config->jh_header); config->jh_header = NULL; strv = g_settings_get_strv (settings, "junk-custom-header"); for (i = 0; strv[i] != NULL; i++) config->jh_header = g_slist_append (config->jh_header, g_strdup (strv[i])); g_strfreev (strv); node = config->jh_header; name = g_ptr_array_new (); value = g_ptr_array_new (); while (node && node->data) { gchar **tok = g_strsplit (node->data, "=", 2); g_ptr_array_add (name, g_strdup (tok[0])); g_ptr_array_add (value, g_strdup (tok[1])); node = node->next; g_strfreev (tok); } camel_session_set_junk_headers ( CAMEL_SESSION (session), (const gchar **) name->pdata, (const gchar **) value->pdata, name->len); g_ptr_array_foreach (name, (GFunc) g_free, NULL); g_ptr_array_foreach (value, (GFunc) g_free, NULL); g_ptr_array_free (name, TRUE); g_ptr_array_free (value, TRUE); }
gboolean e_mail_session_unsubscribe_folder_sync (EMailSession *session, const gchar *folder_uri, GCancellable *cancellable, GError **error) { CamelStore *store = NULL; gchar *folder_name = NULL; const gchar *message; gboolean success = FALSE; g_return_val_if_fail (E_IS_MAIL_SESSION (session), FALSE); g_return_val_if_fail (folder_uri != NULL, FALSE); success = e_mail_folder_uri_parse ( CAMEL_SESSION (session), folder_uri, &store, &folder_name, error); if (!success) return FALSE; message = _("Unsubscribing from folder '%s'"); camel_operation_push_message (cancellable, message, folder_name); /* FIXME This should take our GCancellable. */ success = em_utils_connect_service_sync ( CAMEL_SERVICE (store), cancellable, error) && camel_subscribable_unsubscribe_folder_sync ( CAMEL_SUBSCRIBABLE (store), folder_name, cancellable, error); camel_operation_pop_message (cancellable); g_object_unref (store); g_free (folder_name); return success; }
/** * e_mail_session_ref_transport: * @session: an #EMailSession * @transport_uid: the UID of a mail transport * * Returns the transport #CamelService instance for @transport_uid, * verifying first that the @transport_uid is indeed a mail transport and * that the corresponding #ESource is enabled. If these checks fail, the * function returns %NULL. * * The returned #CamelService is referenced for thread-safety and must be * unreferenced with g_object_unref() when finished with it. * * Returns: a #CamelService, or %NULL **/ CamelService * e_mail_session_ref_transport (EMailSession *session, const gchar *transport_uid) { ESourceRegistry *registry; ESource *source = NULL; CamelService *transport = NULL; const gchar *extension_name; g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL); g_return_val_if_fail (transport_uid != NULL, NULL); registry = e_mail_session_get_registry (session); extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT; source = e_source_registry_ref_source (registry, transport_uid); if (source == NULL) goto exit; if (!e_source_registry_check_enabled (registry, source)) goto exit; if (!e_source_has_extension (source, extension_name)) goto exit; transport = camel_session_ref_service ( CAMEL_SESSION (session), transport_uid); /* Sanity check. */ if (transport != NULL) g_warn_if_fail (CAMEL_IS_TRANSPORT (transport)); exit: g_clear_object (&source); return transport; }
static void gconf_jh_headers_changed (GConfClient *client, guint cnxn_id, GConfEntry *entry, EMailSession *session) { GSList *node; GPtrArray *name, *value; g_slist_foreach (config->jh_header, (GFunc) g_free, NULL); g_slist_free (config->jh_header); config->jh_header = gconf_client_get_list ( client, "/apps/evolution/mail/junk/custom_header", GCONF_VALUE_STRING, NULL); node = config->jh_header; name = g_ptr_array_new (); value = g_ptr_array_new (); while (node && node->data) { gchar **tok = g_strsplit (node->data, "=", 2); g_ptr_array_add (name, g_strdup (tok[0])); g_ptr_array_add (value, g_strdup (tok[1])); node = node->next; g_strfreev (tok); } camel_session_set_junk_headers ( CAMEL_SESSION (session), (const gchar **) name->pdata, (const gchar **) value->pdata, name->len); g_ptr_array_foreach (name, (GFunc) g_free, NULL); g_ptr_array_foreach (value, (GFunc) g_free, NULL); g_ptr_array_free (name, TRUE); g_ptr_array_free (value, TRUE); }
CamelStore * e_mail_store_add_by_account (EMailBackend *backend, EAccount *account) { EMailSession *session; CamelService *service = NULL; CamelProvider *provider; CamelURL *url; gboolean skip = FALSE, transport_only; GError *error = NULL; g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL); g_return_val_if_fail (E_IS_ACCOUNT (account), NULL); session = e_mail_backend_get_session (backend); /* check whether it's transport-only accounts */ transport_only = !account->source || !account->source->url || !*account->source->url; if (transport_only) goto handle_transport; /* Load the service, but don't connect. Check its provider, * and if this belongs in the folder tree model, add it. */ provider = camel_provider_get (account->source->url, &error); if (provider == NULL) { /* In case we do not have a provider here, we handle * the special case of having multiple mail identities * eg. a dummy account having just SMTP server defined */ goto handle_transport; } service = camel_session_add_service ( CAMEL_SESSION (session), account->uid, account->source->url, CAMEL_PROVIDER_STORE, &error); camel_service_set_display_name (service, account->name); handle_transport: if (account->transport) { /* While we're at it, add the account's transport to the * CamelSession. The transport's UID is a kludge for now. * We take the EAccount's UID and tack on "-transport". */ gchar *transport_uid; GError *transport_error = NULL; transport_uid = g_strconcat ( account->uid, "-transport", NULL); camel_session_add_service ( CAMEL_SESSION (session), transport_uid, account->transport->url, CAMEL_PROVIDER_TRANSPORT, &transport_error); g_free (transport_uid); if (transport_error) { g_warning ( "%s: Failed to add transport service: %s", G_STRFUNC, transport_error->message); g_error_free (transport_error); } } if (transport_only) return NULL; if (!CAMEL_IS_STORE (service)) goto fail; /* Do not add local-delivery files, * but make them ready for later use. */ url = camel_url_new (account->source->url, NULL); if (url != NULL) { skip = em_utils_is_local_delivery_mbox_file (url); camel_url_free (url); } if (!skip && (provider->flags & CAMEL_PROVIDER_IS_STORAGE)) e_mail_store_add (backend, CAMEL_STORE (service)); return CAMEL_STORE (service); fail: /* FIXME: Show an error dialog. */ g_warning ( "Couldn't get service: %s: %s", account->name, error ? error->message : "Not a CamelStore"); if (error) g_error_free (error); return NULL; }
GCancellable * mail_send (EMailSession *session) { CamelFolder *local_outbox; CamelService *service; struct _send_info *info; struct _send_data *data; send_info_t type = SEND_INVALID; const gchar *transport_uid; ESource *account; const gchar *extension_name; account = e_source_registry_ref_default_mail_identity (source_registry); if (account == NULL) return NULL; extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION; if (e_source_has_extension (account, extension_name)) { ESourceMailSubmission *extension; gchar *uid; extension = e_source_get_extension (account, extension_name); uid = e_source_mail_submission_dup_transport_uid (extension); g_object_unref (account); account = e_source_registry_ref_source (source_registry, uid); g_free (uid); } else { g_object_unref (account); account = NULL; } if (account == NULL) return NULL; transport_uid = e_source_get_uid (account); data = setup_send_data (session); info = g_hash_table_lookup (data->active, SEND_URI_KEY); if (info != NULL) { info->again++; d(printf("send of %s still in progress\n", transport_uid)); return info->cancellable; } service = camel_session_ref_service ( CAMEL_SESSION (session), transport_uid); if (!CAMEL_IS_TRANSPORT (service)) { return NULL; } d(printf("starting non-interactive send of '%s'\n", account->transport->url)); type = get_receive_type (service); if (type == SEND_INVALID) { return NULL; } info = g_malloc0 (sizeof (*info)); info->type = SEND_SEND; info->session = g_object_ref (session); info->service = g_object_ref (service); info->keep_on_server = FALSE; info->cancellable = camel_operation_new(); info->data = data; info->state = SEND_ACTIVE; info->timeout_id = 0; d(printf("Adding new info %p\n", info)); g_hash_table_insert (data->active, g_strdup(SEND_URI_KEY), info); /* todo, store the folder in info? */ local_outbox = e_mail_session_get_local_folder ( session, E_MAIL_LOCAL_FOLDER_OUTBOX); mail_send_queue ( session, local_outbox, CAMEL_TRANSPORT (service), E_FILTER_SOURCE_OUTGOING, info->cancellable, receive_get_folder, info, receive_status, info, send_done, info); return info->cancellable; }
void e_mail_session_send_to (EMailSession *session, CamelMimeMessage *message, gint io_priority, GCancellable *cancellable, CamelFilterGetFolderFunc get_folder_func, gpointer get_folder_data, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; AsyncContext *context; CamelAddress *from; CamelAddress *recipients; CamelMedium *medium; CamelMessageInfo *info; EAccount *account = NULL; GPtrArray *post_to_uris; struct _camel_header_raw *xev; struct _camel_header_raw *header; const gchar *string; const gchar *resent_from; gchar *transport_uid = NULL; gchar *sent_folder_uri = NULL; GError *error = NULL; g_return_if_fail (E_IS_MAIL_SESSION (session)); g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message)); medium = CAMEL_MEDIUM (message); camel_medium_set_header (medium, "X-Mailer", X_MAILER); xev = mail_tool_remove_xevolution_headers (message); /* Extract directives from X-Evolution headers. */ string = camel_header_raw_find (&xev, "X-Evolution-Account", NULL); if (string != NULL) { gchar *account_uid; account_uid = g_strstrip (g_strdup (string)); account = e_get_account_by_uid (account_uid); g_free (account_uid); } if (account != NULL) { if (account->transport != NULL) { /* XXX Transport UIDs are kludgy right now. We * use the EAccount's regular UID and tack on * "-transport". Will be better soon. */ transport_uid = g_strconcat ( account->uid, "-transport", NULL); /* to reprompt password on sending if needed */ account->transport->get_password_canceled = FALSE; } sent_folder_uri = g_strdup (account->sent_folder_uri); } string = camel_header_raw_find (&xev, "X-Evolution-Fcc", NULL); if (sent_folder_uri == NULL && string != NULL) sent_folder_uri = g_strstrip (g_strdup (string)); string = camel_header_raw_find (&xev, "X-Evolution-Transport", NULL); if (transport_uid == NULL && string != NULL) transport_uid = g_strstrip (g_strdup (string)); post_to_uris = g_ptr_array_new (); for (header = xev; header != NULL; header = header->next) { gchar *folder_uri; if (g_strcmp0 (header->name, "X-Evolution-PostTo") != 0) continue; folder_uri = g_strstrip (g_strdup (header->value)); g_ptr_array_add (post_to_uris, folder_uri); } /* Collect sender and recipients from headers. */ from = (CamelAddress *) camel_internet_address_new (); recipients = (CamelAddress *) camel_internet_address_new (); resent_from = camel_medium_get_header (medium, "Resent-From"); if (resent_from != NULL) { const CamelInternetAddress *addr; const gchar *type; camel_address_decode (from, resent_from); type = CAMEL_RECIPIENT_TYPE_RESENT_TO; addr = camel_mime_message_get_recipients (message, type); camel_address_cat (recipients, CAMEL_ADDRESS (addr)); type = CAMEL_RECIPIENT_TYPE_RESENT_CC; addr = camel_mime_message_get_recipients (message, type); camel_address_cat (recipients, CAMEL_ADDRESS (addr)); type = CAMEL_RECIPIENT_TYPE_RESENT_BCC; addr = camel_mime_message_get_recipients (message, type); camel_address_cat (recipients, CAMEL_ADDRESS (addr)); } else { const CamelInternetAddress *addr; const gchar *type; addr = camel_mime_message_get_from (message); camel_address_copy (from, CAMEL_ADDRESS (addr)); type = CAMEL_RECIPIENT_TYPE_TO; addr = camel_mime_message_get_recipients (message, type); camel_address_cat (recipients, CAMEL_ADDRESS (addr)); type = CAMEL_RECIPIENT_TYPE_CC; addr = camel_mime_message_get_recipients (message, type); camel_address_cat (recipients, CAMEL_ADDRESS (addr)); type = CAMEL_RECIPIENT_TYPE_BCC; addr = camel_mime_message_get_recipients (message, type); camel_address_cat (recipients, CAMEL_ADDRESS (addr)); } /* Miscellaneous preparations. */ info = camel_message_info_new (NULL); camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0); /* The rest of the processing happens in a thread. */ context = g_slice_new0 (AsyncContext); context->message = g_object_ref (message); context->io_priority = io_priority; context->from = from; context->recipients = recipients; context->message = g_object_ref (message); context->info = info; context->xev = xev; context->post_to_uris = post_to_uris; context->transport_uid = transport_uid; context->sent_folder_uri = sent_folder_uri; if (G_IS_CANCELLABLE (cancellable)) context->cancellable = g_object_ref (cancellable); /* Failure here emits a runtime warning but is non-fatal. */ context->driver = camel_session_get_filter_driver ( CAMEL_SESSION (session), E_FILTER_SOURCE_OUTGOING, &error); if (context->driver != NULL && get_folder_func) camel_filter_driver_set_folder_func ( context->driver, get_folder_func, get_folder_data); if (error != NULL) { g_warn_if_fail (context->driver == NULL); g_warning ("%s", error->message); g_error_free (error); } /* This gets popped in async_context_free(). */ camel_operation_push_message ( context->cancellable, _("Sending message")); simple = g_simple_async_result_new ( G_OBJECT (session), callback, user_data, e_mail_session_send_to); g_simple_async_result_set_op_res_gpointer ( simple, context, (GDestroyNotify) async_context_free); g_simple_async_result_run_in_thread ( simple, (GSimpleAsyncThreadFunc) mail_session_send_to_thread, context->io_priority, context->cancellable); g_object_unref (simple); }
static void mail_session_send_to_thread (GSimpleAsyncResult *simple, EMailSession *session, GCancellable *cancellable) { AsyncContext *context; CamelFolder *local_sent_folder; GString *error_messages; gboolean copy_to_sent = TRUE; guint ii; GError *error = NULL; context = g_simple_async_result_get_op_res_gpointer (simple); /* Send the message to all recipients. */ if (camel_address_length (context->recipients) > 0) { CamelProvider *provider; CamelService *service; gboolean did_connect = FALSE; service = camel_session_get_service ( CAMEL_SESSION (session), context->transport_uid); if (!CAMEL_IS_TRANSPORT (service)) { g_simple_async_result_set_error (simple, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_URL_INVALID, _("Cannot get transport for account '%s'"), context->transport_uid); return; } if (camel_service_get_connection_status (service) != CAMEL_SERVICE_CONNECTED) { did_connect = TRUE; /* XXX This API does not allow for cancellation. */ if (!em_utils_connect_service_sync (service, cancellable, &error)) { g_simple_async_result_take_error (simple, error); return; } } provider = camel_service_get_provider (service); if (provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER) copy_to_sent = FALSE; camel_transport_send_to_sync ( CAMEL_TRANSPORT (service), context->message, context->from, context->recipients, cancellable, &error); if (did_connect) em_utils_disconnect_service_sync ( service, error == NULL, cancellable, error ? NULL : &error); if (error != NULL) { g_simple_async_result_take_error (simple, error); return; } } /* Post the message to requested folders. */ for (ii = 0; ii < context->post_to_uris->len; ii++) { CamelFolder *folder; const gchar *folder_uri; folder_uri = g_ptr_array_index (context->post_to_uris, ii); folder = e_mail_session_uri_to_folder_sync ( session, folder_uri, 0, cancellable, &error); if (error != NULL) { g_warn_if_fail (folder == NULL); g_simple_async_result_take_error (simple, error); return; } g_return_if_fail (CAMEL_IS_FOLDER (folder)); camel_folder_append_message_sync ( folder, context->message, context->info, NULL, cancellable, &error); g_object_unref (folder); if (error != NULL) { g_simple_async_result_take_error (simple, error); return; } } /*** Post Processing ***/ /* This accumulates error messages during post-processing. */ error_messages = g_string_sized_new (256); mail_tool_restore_xevolution_headers (context->message, context->xev); /* Run filters on the outgoing message. */ if (context->driver != NULL) { camel_filter_driver_filter_message ( context->driver, context->message, context->info, NULL, NULL, NULL, "", cancellable, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; if (error != NULL) { g_string_append_printf ( error_messages, _("Failed to apply outgoing filters: %s"), error->message); g_clear_error (&error); } } if (!copy_to_sent) goto cleanup; /* Append the sent message to a Sent folder. */ local_sent_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT); /* Try to extract a CamelFolder from the Sent folder URI. */ if (context->sent_folder_uri != NULL) { context->sent_folder = e_mail_session_uri_to_folder_sync ( session, context->sent_folder_uri, 0, cancellable, &error); if (error != NULL) { g_warn_if_fail (context->sent_folder == NULL); if (error_messages->len > 0) g_string_append (error_messages, "\n\n"); g_string_append_printf ( error_messages, _("Failed to append to %s: %s\n" "Appending to local 'Sent' folder instead."), context->sent_folder_uri, error->message); g_clear_error (&error); } } /* Fall back to the local Sent folder. */ if (context->sent_folder == NULL) context->sent_folder = g_object_ref (local_sent_folder); /* Append the message. */ camel_folder_append_message_sync ( context->sent_folder, context->message, context->info, NULL, cancellable, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; if (error == NULL) goto cleanup; /* If appending to a remote Sent folder failed, * try appending to the local Sent folder. */ if (context->sent_folder != local_sent_folder) { const gchar *description; description = camel_folder_get_description ( context->sent_folder); if (error_messages->len > 0) g_string_append (error_messages, "\n\n"); g_string_append_printf ( error_messages, _("Failed to append to %s: %s\n" "Appending to local 'Sent' folder instead."), description, error->message); g_clear_error (&error); camel_folder_append_message_sync ( local_sent_folder, context->message, context->info, NULL, cancellable, &error); } if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; /* We can't even append to the local Sent folder? * In that case just leave the message in Outbox. */ if (error != NULL) { if (error_messages->len > 0) g_string_append (error_messages, "\n\n"); g_string_append_printf ( error_messages, _("Failed to append to local 'Sent' folder: %s"), error->message); g_clear_error (&error); goto exit; } cleanup: /* The send operation was successful; ignore cleanup errors. */ /* Mark the draft message for deletion, if present. */ e_mail_session_handle_draft_headers_sync ( session, context->message, cancellable, &error); if (error != NULL) { g_warning ("%s", error->message); g_clear_error (&error); } /* Set flags on the original source message, if present. * Source message refers to the message being forwarded * or replied to. */ e_mail_session_handle_source_headers_sync ( session, context->message, cancellable, &error); if (error != NULL) { g_warning ("%s", error->message); g_clear_error (&error); } exit: /* If we were cancelled, disregard any other errors. */ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_simple_async_result_take_error (simple, error); /* Stuff the accumulated error messages in a GError. */ } else if (error_messages->len > 0) { g_simple_async_result_set_error ( simple, E_MAIL_ERROR, E_MAIL_ERROR_POST_PROCESSING, "%s", error_messages->str); } /* Synchronize the Sent folder. */ if (context->sent_folder != NULL) camel_folder_synchronize_sync ( context->sent_folder, FALSE, cancellable, NULL); g_string_free (error_messages, TRUE); }
static struct _send_data * build_infra (EMailSession *session, gboolean allow_send) { struct _send_data *data; struct _send_info *info; CamelService *transport = NULL; GList *link; GList *list = NULL; GList *accounts=NULL; transport = ref_default_transport (session); accounts = mail_get_all_accounts(); data = setup_send_data (session); link = accounts; while (link) { ESource *source; CamelService *service; const gchar *uid; source = (ESource *)link->data; if (!e_source_get_enabled(source)) { link = link->next; continue; } uid = e_source_get_uid (source); service = camel_session_ref_service ( CAMEL_SESSION (session), uid); /* see if we have an outstanding download active */ info = g_hash_table_lookup (data->active, uid); if (info == NULL) { send_info_t type = SEND_INVALID; type = get_receive_type (service); if (type == SEND_INVALID || type == SEND_SEND) { link = link->next; continue; } info = g_malloc0 (sizeof (*info)); info->type = type; info->session = g_object_ref (session); d(printf("adding source %s\n", source->url)); info->service = g_object_ref (service); info->keep_on_server = mail_get_keep_on_server (service); info->cancellable = camel_operation_new (); info->state = allow_send ? SEND_ACTIVE : SEND_COMPLETE; info->timeout_id = g_timeout_add ( STATUS_TIMEOUT, operation_status_timeout, info); g_signal_connect ( info->cancellable, "status", G_CALLBACK (operation_status), info); g_hash_table_insert ( data->active, g_strdup(uid), info); list = g_list_prepend (list, info); } else if (info->timeout_id == 0) info->timeout_id = g_timeout_add ( STATUS_TIMEOUT, operation_status_timeout, info); info->data = data; link = link->next; } g_list_free_full (accounts, (GDestroyNotify) g_object_unref); /* Skip displaying the SMTP row if we've got no outbox, * outgoing account or unsent mails. */ CamelFolder *local_outbox; local_outbox = e_mail_session_get_local_folder ( session, E_MAIL_LOCAL_FOLDER_OUTBOX); if (allow_send && local_outbox && CAMEL_IS_TRANSPORT (transport) && (camel_folder_get_message_count (local_outbox) - camel_folder_get_deleted_message_count (local_outbox)) != 0) { info = g_hash_table_lookup (data->active, SEND_URI_KEY); if (info == NULL) { info = g_malloc0 (sizeof (*info)); info->type = SEND_SEND; info->service = g_object_ref (transport); info->keep_on_server = FALSE; info->cancellable = camel_operation_new (); info->state = SEND_ACTIVE; info->timeout_id = g_timeout_add ( STATUS_TIMEOUT, operation_status_timeout, info); g_signal_connect ( info->cancellable, "status", G_CALLBACK (operation_status), info); g_hash_table_insert (data->active, g_strdup(SEND_URI_KEY), info); list = g_list_prepend (list, info); } else if (info->timeout_id == 0) info->timeout_id = g_timeout_add ( STATUS_TIMEOUT, operation_status_timeout, info); info->data = data; } data->infos = list; return data; }
/** * mail_vfolder_delete_folder: * @backend: an #EMailBackend * @store: a #CamelStore * @folder_name: a folder name * * Looks through all vfolder rules to see if @folder_name is listed as a * source for any vfolder rules. If the folder is found in the source for * any rule, it is removed and the user is alerted to the fact that the * vfolder rules have been updated. The new vfolder rules are written * to disk. * * XXX: It doesn't appear that the changes to the vfolder rules are sent * down to the camel level, however. So the actual vfolders will not change * behavior until evolution is restarted (?) * * NOTE: This function must be called from the main thread. */ static void mail_vfolder_delete_folder (EMailBackend *backend, CamelStore *store, const gchar *folder_name) { ERuleContext *rule_context; EFilterRule *rule; EMailSession *session; const gchar *source; CamelVeeFolder *vf; GString *changed; GQueue *queue; guint changed_count; gchar *uri; GList *link; g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (CAMEL_IS_STORE (store)); g_return_if_fail (folder_name != NULL); if (folder_is_spethal (store, folder_name)) return; d(printf ("Deleting uri to check: %s\n", uri)); g_return_if_fail (mail_in_main_thread ()); session = e_mail_backend_get_session (backend); uri = e_mail_folder_uri_build (store, folder_name); changed_count = 0; changed = g_string_new (""); G_LOCK (vfolder); if (context == NULL) goto done; rule_context = E_RULE_CONTEXT (context); /* see if any rules directly reference this removed uri */ rule = NULL; while ((rule = e_rule_context_next_rule (rule_context, rule, NULL))) { EMVFolderRule *vf_rule = EM_VFOLDER_RULE (rule); if (!rule->name) continue; source = NULL; while ((source = em_vfolder_rule_next_source (vf_rule, source))) { /* Remove all sources that match, ignore changed events though * because the adduri call above does the work async */ if (e_mail_folder_uri_equal (CAMEL_SESSION (session), uri, source)) { vf = g_hash_table_lookup ( vfolder_hash, rule->name); if (!vf) { g_warning ("vf is NULL for %s\n", rule->name); continue; } g_signal_handlers_disconnect_matched ( rule, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, rule_changed, vf); em_vfolder_rule_remove_source (vf_rule, source); g_signal_connect ( rule, "changed", G_CALLBACK (rule_changed), vf); if (changed_count == 0) { g_string_append (changed, rule->name); } else { if (changed_count == 1) { g_string_prepend (changed, " "); g_string_append (changed, "\n"); } g_string_append_printf ( changed, " %s\n", rule->name); } changed_count++; source = NULL; } } } done: queue = &source_folders_remote; link = mv_find_folder (queue, session, uri); if (link != NULL) { g_free (link->data); g_queue_delete_link (queue, link); } queue = &source_folders_local; link = mv_find_folder (queue, session, uri); if (link != NULL) { g_free (link->data); g_queue_delete_link (queue, link); } G_UNLOCK (vfolder); if (changed_count > 0) { const gchar *config_dir; gchar *user, *info; info = g_strdup_printf (ngettext ( /* Translators: The first %s is name of the affected * search folder(s), the second %s is the URI of the * removed folder. For more than one search folder is * each of them on a separate line, with four spaces * in front of its name, without quotes. */ "The Search Folder \"%s\" has been modified to " "account for the deleted folder\n\"%s\".", "The following Search Folders\n%s have been modified " "to account for the deleted folder\n\"%s\".", changed_count), changed->str, uri); e_mail_backend_submit_alert ( backend, "mail:vfolder-updated", info, NULL); g_free (info); config_dir = mail_session_get_config_dir (); user = g_build_filename (config_dir, "vfolders.xml", NULL); e_rule_context_save ((ERuleContext *) context, user); g_free (user); } g_string_free (changed, TRUE); g_free (uri); }
static void mail_shell_view_execute_search (EShellView *shell_view) { EMailShellViewPrivate *priv; EMailShellContent *mail_shell_content; EMailShellSidebar *mail_shell_sidebar; EShellWindow *shell_window; EShellBackend *shell_backend; EShellContent *shell_content; EShellSidebar *shell_sidebar; EShellSearchbar *searchbar; EActionComboBox *combo_box; EMailBackend *backend; EMailSession *session; ESourceRegistry *registry; EMFolderTree *folder_tree; GtkWidget *message_list; EFilterRule *rule; EMailReader *reader; EMailView *mail_view; CamelVeeFolder *search_folder; CamelFolder *folder; CamelService *service; CamelStore *store; GtkAction *action; EMailLabelListStore *label_store; GtkTreePath *path; GtkTreeIter tree_iter; GString *string; GList *list, *iter; GSList *search_strings = NULL; const gchar *text; gboolean valid; gchar *query; gchar *temp; gchar *tag; const gchar *use_tag; gint value; priv = E_MAIL_SHELL_VIEW_GET_PRIVATE (shell_view); shell_window = e_shell_view_get_shell_window (shell_view); shell_backend = e_shell_view_get_shell_backend (shell_view); shell_content = e_shell_view_get_shell_content (shell_view); shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); backend = E_MAIL_BACKEND (shell_backend); session = e_mail_backend_get_session (backend); mail_shell_content = E_MAIL_SHELL_CONTENT (shell_content); mail_view = e_mail_shell_content_get_mail_view (mail_shell_content); searchbar = e_mail_shell_content_get_searchbar (mail_shell_content); mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); reader = E_MAIL_READER (mail_view); folder = e_mail_reader_ref_folder (reader); message_list = e_mail_reader_get_message_list (reader); registry = e_mail_session_get_registry (session); label_store = e_mail_ui_session_get_label_store ( E_MAIL_UI_SESSION (session)); action = ACTION (MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN); value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); text = e_shell_searchbar_get_search_text (searchbar); if (value == MAIL_SEARCH_ADVANCED || text == NULL || *text == '\0') { if (value != MAIL_SEARCH_ADVANCED) e_shell_view_set_search_rule (shell_view, NULL); query = e_shell_view_get_search_query (shell_view); if (!query) query = g_strdup (""); goto filter; } /* Replace variables in the selected rule with the * current search text and extract a query string. */ g_return_if_fail (value >= 0 && value < MAIL_NUM_SEARCH_RULES); rule = priv->search_rules[value]; /* Set the search rule in EShellView so that "Create * Search Folder from Search" works for quick searches. */ e_shell_view_set_search_rule (shell_view, rule); for (iter = rule->parts; iter != NULL; iter = iter->next) { EFilterPart *part = iter->data; EFilterElement *element = NULL; if (strcmp (part->name, "subject") == 0) element = e_filter_part_find_element (part, "subject"); else if (strcmp (part->name, "body") == 0) element = e_filter_part_find_element (part, "word"); else if (strcmp (part->name, "sender") == 0) element = e_filter_part_find_element (part, "sender"); else if (strcmp (part->name, "to") == 0) element = e_filter_part_find_element (part, "recipient"); if (strcmp (part->name, "body") == 0) { struct _camel_search_words *words; gint ii; words = camel_search_words_split ((guchar *) text); for (ii = 0; ii < words->len; ii++) search_strings = g_slist_prepend ( search_strings, g_strdup ( words->words[ii]->word)); camel_search_words_free (words); } if (element != NULL) { EFilterInput *input = E_FILTER_INPUT (element); e_filter_input_set_value (input, text); } } string = g_string_sized_new (1024); e_filter_rule_build_code (rule, string); query = g_string_free (string, FALSE); filter: /* Apply selected filter. */ combo_box = e_shell_searchbar_get_filter_combo_box (searchbar); value = e_action_combo_box_get_current_value (combo_box); switch (value) { case MAIL_FILTER_ALL_MESSAGES: break; case MAIL_FILTER_UNREAD_MESSAGES: temp = g_strdup_printf ( "(and %s (match-all (not " "(system-flag \"Seen\"))))", query); g_free (query); query = temp; break; case MAIL_FILTER_NO_LABEL: string = g_string_sized_new (1024); g_string_append_printf ( string, "(and %s (and ", query); valid = gtk_tree_model_get_iter_first ( GTK_TREE_MODEL (label_store), &tree_iter); while (valid) { tag = e_mail_label_list_store_get_tag ( label_store, &tree_iter); use_tag = tag; if (g_str_has_prefix (use_tag, "$Label")) use_tag += 6; g_string_append_printf ( string, " (match-all (not (or " "(= (user-tag \"label\") \"%s\") " "(user-flag \"$Label%s\") " "(user-flag \"%s\"))))", use_tag, use_tag, use_tag); g_free (tag); valid = gtk_tree_model_iter_next ( GTK_TREE_MODEL (label_store), &tree_iter); } g_string_append_len (string, "))", 2); g_free (query); query = g_string_free (string, FALSE); break; case MAIL_FILTER_READ_MESSAGES: temp = g_strdup_printf ( "(and %s (match-all " "(system-flag \"Seen\")))", query); g_free (query); query = temp; break; case MAIL_FILTER_LAST_5_DAYS_MESSAGES: if (em_utils_folder_is_sent (registry, folder)) temp = g_strdup_printf ( "(and %s (match-all " "(> (get-sent-date) " "(- (get-current-date) 432000))))", query); else temp = g_strdup_printf ( "(and %s (match-all " "(> (get-received-date) " "(- (get-current-date) 432000))))", query); g_free (query); query = temp; break; case MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS: temp = g_strdup_printf ( "(and %s (match-all " "(system-flag \"Attachments\")))", query); g_free (query); query = temp; break; case MAIL_FILTER_IMPORTANT_MESSAGES: temp = g_strdup_printf ( "(and %s (match-all " "(system-flag \"Flagged\")))", query); g_free (query); query = temp; break; case MAIL_FILTER_MESSAGES_NOT_JUNK: temp = g_strdup_printf ( "(and %s (match-all (not " "(system-flag \"junk\"))))", query); g_free (query); query = temp; break; default: /* The action value also serves as a path for * the label list store. That's why we number * the label actions from zero. */ path = gtk_tree_path_new_from_indices (value, -1); gtk_tree_model_get_iter ( GTK_TREE_MODEL (label_store), &tree_iter, path); gtk_tree_path_free (path); tag = e_mail_label_list_store_get_tag ( label_store, &tree_iter); use_tag = tag; if (g_str_has_prefix (use_tag, "$Label")) use_tag += 6; temp = g_strdup_printf ( "(and %s (match-all (or " "(= (user-tag \"label\") \"%s\") " "(user-flag \"$Label%s\") " "(user-flag \"%s\"))))", query, use_tag, use_tag, use_tag); g_free (tag); g_free (query); query = temp; break; } /* Apply selected scope. */ combo_box = e_shell_searchbar_get_scope_combo_box (searchbar); value = e_action_combo_box_get_current_value (combo_box); switch (value) { case MAIL_SCOPE_CURRENT_FOLDER: goto execute; case MAIL_SCOPE_CURRENT_ACCOUNT: goto current_account; case MAIL_SCOPE_ALL_ACCOUNTS: goto all_accounts; default: g_warn_if_reached (); goto execute; } all_accounts: /* Prepare search folder for all accounts. */ /* If the search text is empty, cancel any * account-wide searches still in progress. */ text = e_shell_searchbar_get_search_text (searchbar); if (text == NULL || *text == '\0') { CamelStore *selected_store = NULL; gchar *selected_folder_name = NULL; if (priv->search_account_all != NULL) { g_object_unref (priv->search_account_all); priv->search_account_all = NULL; } if (priv->search_account_cancel != NULL) { g_cancellable_cancel (priv->search_account_cancel); g_object_unref (priv->search_account_cancel); priv->search_account_cancel = NULL; } /* Reset the message list to the current folder tree * selection. This needs to happen synchronously to * avoid search conflicts, so we can't just grab the * folder URI and let the asynchronous callbacks run * after we've already kicked off the search. */ em_folder_tree_get_selected ( folder_tree, &selected_store, &selected_folder_name); if (selected_store != NULL && selected_folder_name != NULL) { folder = camel_store_get_folder_sync ( selected_store, selected_folder_name, CAMEL_STORE_FOLDER_INFO_FAST, NULL, NULL); e_mail_reader_set_folder (reader, folder); g_object_unref (folder); } g_clear_object (&selected_store); g_free (selected_folder_name); gtk_widget_set_sensitive (GTK_WIDGET (combo_box), TRUE); goto execute; } search_folder = priv->search_account_all; /* Skip the search if we already have the results. */ if (search_folder != NULL) { const gchar *vf_query; vf_query = camel_vee_folder_get_expression (search_folder); if (g_strcmp0 (query, vf_query) == 0) goto all_accounts_setup; } /* Disable the scope combo while search is in progress. */ gtk_widget_set_sensitive (GTK_WIDGET (combo_box), FALSE); /* If we already have a search folder, reuse it. */ if (search_folder != NULL) { if (priv->search_account_cancel != NULL) { g_cancellable_cancel (priv->search_account_cancel); g_object_unref (priv->search_account_cancel); priv->search_account_cancel = NULL; } camel_vee_folder_set_expression (search_folder, query); goto all_accounts_setup; } /* Create a new search folder. */ /* FIXME Complete lack of error checking here. */ service = camel_session_ref_service ( CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID); camel_service_connect_sync (service, NULL, NULL); search_folder = (CamelVeeFolder *) camel_vee_folder_new ( CAMEL_STORE (service), _("All Account Search"), CAMEL_STORE_FOLDER_PRIVATE); priv->search_account_all = search_folder; g_object_unref (service); camel_vee_folder_set_expression (search_folder, query); all_accounts_setup: list = em_folder_tree_model_list_stores (EM_FOLDER_TREE_MODEL ( gtk_tree_view_get_model (GTK_TREE_VIEW (folder_tree)))); g_list_foreach (list, (GFunc) g_object_ref, NULL); priv->search_account_cancel = camel_operation_new (); /* This takes ownership of the stores list. */ mail_shell_view_setup_search_results_folder ( CAMEL_FOLDER (search_folder), list, priv->search_account_cancel); mail_shell_view_show_search_results_folder ( E_MAIL_SHELL_VIEW (shell_view), CAMEL_FOLDER (search_folder)); goto execute; current_account: /* Prepare search folder for current account only. */ /* If the search text is empty, cancel any * account-wide searches still in progress. */ text = e_shell_searchbar_get_search_text (searchbar); if (text == NULL || *text == '\0') { CamelStore *selected_store = NULL; gchar *selected_folder_name = NULL; if (priv->search_account_current != NULL) { g_object_unref (priv->search_account_current); priv->search_account_current = NULL; } if (priv->search_account_cancel != NULL) { g_cancellable_cancel (priv->search_account_cancel); g_object_unref (priv->search_account_cancel); priv->search_account_cancel = NULL; } /* Reset the message list to the current folder tree * selection. This needs to happen synchronously to * avoid search conflicts, so we can't just grab the * folder URI and let the asynchronous callbacks run * after we've already kicked off the search. */ em_folder_tree_get_selected ( folder_tree, &selected_store, &selected_folder_name); if (selected_store != NULL && selected_folder_name != NULL) { folder = camel_store_get_folder_sync ( selected_store, selected_folder_name, CAMEL_STORE_FOLDER_INFO_FAST, NULL, NULL); e_mail_reader_set_folder (reader, folder); g_object_unref (folder); } g_clear_object (&selected_store); g_free (selected_folder_name); gtk_widget_set_sensitive (GTK_WIDGET (combo_box), TRUE); goto execute; } search_folder = priv->search_account_current; /* Skip the search if we already have the results. */ if (search_folder != NULL) { const gchar *vf_query; vf_query = camel_vee_folder_get_expression (search_folder); if (g_strcmp0 (query, vf_query) == 0) goto current_accout_setup; } /* Disable the scope combo while search is in progress. */ gtk_widget_set_sensitive (GTK_WIDGET (combo_box), FALSE); /* If we already have a search folder, reuse it. */ if (search_folder != NULL) { if (priv->search_account_cancel != NULL) { g_cancellable_cancel (priv->search_account_cancel); g_object_unref (priv->search_account_cancel); priv->search_account_cancel = NULL; } camel_vee_folder_set_expression (search_folder, query); goto current_accout_setup; } /* Create a new search folder. */ /* FIXME Complete lack of error checking here. */ service = camel_session_ref_service ( CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID); camel_service_connect_sync (service, NULL, NULL); search_folder = (CamelVeeFolder *) camel_vee_folder_new ( CAMEL_STORE (service), _("Account Search"), CAMEL_STORE_FOLDER_PRIVATE); priv->search_account_current = search_folder; g_object_unref (service); camel_vee_folder_set_expression (search_folder, query); current_accout_setup: if (folder != NULL && folder != CAMEL_FOLDER (search_folder)) { store = camel_folder_get_parent_store (folder); if (store != NULL) g_object_ref (store); } else { store = NULL; em_folder_tree_get_selected (folder_tree, &store, NULL); } list = NULL; /* list of CamelStore-s */ if (store != NULL) list = g_list_append (NULL, store); priv->search_account_cancel = camel_operation_new (); /* This takes ownership of the stores list. */ mail_shell_view_setup_search_results_folder ( CAMEL_FOLDER (search_folder), list, priv->search_account_cancel); mail_shell_view_show_search_results_folder ( E_MAIL_SHELL_VIEW (shell_view), CAMEL_FOLDER (search_folder)); execute: /* Finally, execute the search. */ message_list_set_search (MESSAGE_LIST (message_list), query); e_mail_view_set_search_strings (mail_view, search_strings); g_slist_foreach (search_strings, (GFunc) g_free, NULL); g_slist_free (search_strings); g_free (query); g_clear_object (&folder); }
/** * mail_vfolder_add_folder: * @backend: an #EMailBackend * @store: a #CamelStore * @folder: a folder name * @remove: whether the folder should be removed or added * * Called when a new folder becomes (un)available. If @store is not a * CamelVeeStore, the folder is added/removed from the list of cached source * folders. Then each vfolder rule is checked to see if the specified folder * matches a source of the rule. It builds a list of vfolders that use (or * would use) the specified folder as a source. It then adds (or removes) * this folder to (from) those vfolders via camel_vee_folder_add/ * remove_folder() but does not modify the actual filters or write changes * to disk. * * NOTE: This function must be called from the main thread. */ static void mail_vfolder_add_folder (EMailBackend *backend, CamelStore *store, const gchar *folder_name, gint remove) { EMailSession *session; EFilterRule *rule; const gchar *source; CamelVeeFolder *vf; CamelProvider *provider; GList *folders = NULL, *link; GQueue *queue; gint remote; gint is_ignore; gchar *uri; session = e_mail_backend_get_session (backend); provider = camel_service_get_provider (CAMEL_SERVICE (store)); remote = (provider->flags & CAMEL_PROVIDER_IS_REMOTE) != 0; queue = remote ? &source_folders_remote : &source_folders_local; if (folder_is_spethal (store, folder_name)) return; g_return_if_fail (mail_in_main_thread ()); uri = e_mail_folder_uri_build (store, folder_name); is_ignore = uri_is_ignore (backend, uri); G_LOCK (vfolder); /* maintain the source folders lists for changed rules later on */ if (CAMEL_IS_VEE_STORE (store)) { is_ignore = TRUE; } else if (remove) { link = mv_find_folder (queue, session, uri); if (link != NULL) { g_free (link->data); g_queue_delete_link (queue, link); } } else if (!is_ignore) { /* we ignore drafts/sent/outbox here */ if (mv_find_folder (queue, session, uri) == NULL) g_queue_push_tail (queue, g_strdup (uri)); } if (context == NULL) goto done; rule = NULL; while ((rule = e_rule_context_next_rule ((ERuleContext *) context, rule, NULL))) { gint found = FALSE; if (!rule->name) { d(printf("invalid rule (%p): rule->name is set to NULL\n", rule)); continue; } /* Don't auto-add any sent/drafts folders etc, * they must be explictly listed as a source. */ if (rule->source && !is_ignore && ((((EMVFolderRule *) rule)->with == EM_VFOLDER_RULE_WITH_LOCAL && !remote) || (((EMVFolderRule *) rule)->with == EM_VFOLDER_RULE_WITH_REMOTE_ACTIVE && remote) || (((EMVFolderRule *) rule)->with == EM_VFOLDER_RULE_WITH_LOCAL_REMOTE_ACTIVE))) found = TRUE; source = NULL; while (!found && (source = em_vfolder_rule_next_source ( (EMVFolderRule *) rule, source))) { found = e_mail_folder_uri_equal ( CAMEL_SESSION (session), uri, source); } if (found) { vf = g_hash_table_lookup (vfolder_hash, rule->name); if (!vf) { g_warning ("vf is NULL for %s\n", rule->name); continue; } g_object_ref (vf); folders = g_list_prepend (folders, vf); } } done: G_UNLOCK (vfolder); if (folders != NULL) vfolder_adduri (backend, uri, folders, remove); g_free (uri); }
void e_mail_session_send_to (EMailSession *session, CamelMimeMessage *message, gint io_priority, GCancellable *cancellable, CamelFilterGetFolderFunc get_folder_func, gpointer get_folder_data, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; AsyncContext *context; CamelAddress *from; CamelAddress *recipients; CamelMedium *medium; CamelMessageInfo *info; CamelService *transport; GPtrArray *post_to_uris; struct _camel_header_raw *xev; struct _camel_header_raw *header; const gchar *resent_from; GError *error = NULL; g_return_if_fail (E_IS_MAIL_SESSION (session)); g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message)); medium = CAMEL_MEDIUM (message); camel_medium_set_header (medium, "X-Mailer", X_MAILER); /* Do this before removing "X-Evolution" headers. */ transport = e_mail_session_ref_transport_for_message ( session, message); xev = mail_tool_remove_xevolution_headers (message); /* Extract directives from X-Evolution headers. */ post_to_uris = g_ptr_array_new (); for (header = xev; header != NULL; header = header->next) { gchar *folder_uri; if (g_strcmp0 (header->name, "X-Evolution-PostTo") != 0) continue; folder_uri = g_strstrip (g_strdup (header->value)); g_ptr_array_add (post_to_uris, folder_uri); } /* Collect sender and recipients from headers. */ from = (CamelAddress *) camel_internet_address_new (); recipients = (CamelAddress *) camel_internet_address_new (); resent_from = camel_medium_get_header (medium, "Resent-From"); if (resent_from != NULL) { const CamelInternetAddress *addr; const gchar *type; camel_address_decode (from, resent_from); type = CAMEL_RECIPIENT_TYPE_RESENT_TO; addr = camel_mime_message_get_recipients (message, type); camel_address_cat (recipients, CAMEL_ADDRESS (addr)); type = CAMEL_RECIPIENT_TYPE_RESENT_CC; addr = camel_mime_message_get_recipients (message, type); camel_address_cat (recipients, CAMEL_ADDRESS (addr)); type = CAMEL_RECIPIENT_TYPE_RESENT_BCC; addr = camel_mime_message_get_recipients (message, type); camel_address_cat (recipients, CAMEL_ADDRESS (addr)); } else { const CamelInternetAddress *addr; const gchar *type; addr = camel_mime_message_get_from (message); camel_address_copy (from, CAMEL_ADDRESS (addr)); type = CAMEL_RECIPIENT_TYPE_TO; addr = camel_mime_message_get_recipients (message, type); camel_address_cat (recipients, CAMEL_ADDRESS (addr)); type = CAMEL_RECIPIENT_TYPE_CC; addr = camel_mime_message_get_recipients (message, type); camel_address_cat (recipients, CAMEL_ADDRESS (addr)); type = CAMEL_RECIPIENT_TYPE_BCC; addr = camel_mime_message_get_recipients (message, type); camel_address_cat (recipients, CAMEL_ADDRESS (addr)); } /* Miscellaneous preparations. */ info = camel_message_info_new_from_header ( NULL, CAMEL_MIME_PART (message)->headers); ((CamelMessageInfoBase *) info)->size = get_message_size (message, cancellable); camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0); /* expand, or remove empty, group addresses */ em_utils_expand_groups (CAMEL_INTERNET_ADDRESS (recipients)); /* The rest of the processing happens in a thread. */ context = g_slice_new0 (AsyncContext); context->message = g_object_ref (message); context->io_priority = io_priority; context->from = from; context->recipients = recipients; context->info = info; context->xev = xev; context->post_to_uris = post_to_uris; context->transport = transport; if (G_IS_CANCELLABLE (cancellable)) context->cancellable = g_object_ref (cancellable); /* Failure here emits a runtime warning but is non-fatal. */ context->driver = camel_session_get_filter_driver ( CAMEL_SESSION (session), E_FILTER_SOURCE_OUTGOING, &error); if (context->driver != NULL && get_folder_func) camel_filter_driver_set_folder_func ( context->driver, get_folder_func, get_folder_data); if (error != NULL) { g_warn_if_fail (context->driver == NULL); g_warning ("%s", error->message); g_error_free (error); } /* This gets popped in async_context_free(). */ camel_operation_push_message ( context->cancellable, _("Sending message")); simple = g_simple_async_result_new ( G_OBJECT (session), callback, user_data, e_mail_session_send_to); g_simple_async_result_set_check_cancellable (simple, cancellable); g_simple_async_result_set_op_res_gpointer ( simple, context, (GDestroyNotify) async_context_free); g_simple_async_result_run_in_thread ( simple, (GSimpleAsyncThreadFunc) mail_session_send_to_thread, context->io_priority, context->cancellable); g_object_unref (simple); }
gboolean mail_send_short_message (EGdbusSession *object, GDBusMethodInvocation *invocation, const char *account_uid, const char *text, const char **to, EMailDataSession *msession, GError **ret_error) { EAccount *account; CamelMimeMessage *message; CamelService *service; gchar *transport_uid; CamelInternetAddress *recipients; CamelMessageInfo *info; GSimpleAsyncResult *simple; SendAsyncContext *context; CamelInternetAddress *from; GCancellable *ops; EMailDataOperation *mops; char *mops_path; gchar subject[MAX_SUBJECT_LENGTH + 4]; GError *error = NULL; /* Check params. */ if (account_uid == NULL || *account_uid == 0) { error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, _("Invalid account")); goto on_error; } if (text == NULL || *text == 0) { error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, _("Text is empty")); goto on_error; } if (to == NULL || *to == 0 || **to == 0) { error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, _("No recipient")); goto on_error; } /* Get transport. */ account = e_get_account_by_uid (account_uid); if (!account) { error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, _("Invalid account %s"), account_uid); goto on_error; } transport_uid = g_strconcat (account->uid, "-transport", NULL); service = camel_session_ref_service (CAMEL_SESSION (session), transport_uid); if (!CAMEL_IS_TRANSPORT (service)) { error = g_error_new(G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, _("Invalid account %s"), account_uid); g_object_unref (account); g_free (transport_uid); goto on_error; } /* Prepare message. */ message = camel_mime_message_new (); strncpy (subject, text, MAX_SUBJECT_LENGTH + 1); if (strlen(text) > MAX_SUBJECT_LENGTH) strcpy (subject + MAX_SUBJECT_LENGTH, "..."); camel_mime_message_set_subject (message, subject); from = camel_internet_address_new (); camel_internet_address_add (from, NULL, "sms"); recipients = camel_internet_address_new (); while (*to) { camel_internet_address_add (recipients, NULL, *to); to++; } camel_mime_message_set_from (message, from); camel_mime_message_set_recipients (message, CAMEL_RECIPIENT_TYPE_TO, recipients); camel_mime_message_set_date (message, CAMEL_MESSAGE_DATE_CURRENT, 0); camel_mime_part_set_content_type (CAMEL_MIME_PART(message), "text/plain"); camel_mime_part_set_content (CAMEL_MIME_PART(message), text, strlen(text), "text/plain"); info = camel_message_info_new (NULL); camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0); /* Return the new operation */ ops = camel_operation_new (); mops = e_mail_data_operation_new ((CamelOperation *) ops); mops_path = e_mail_data_operation_register_gdbus_object (mops, g_dbus_method_invocation_get_connection(invocation), NULL); egdbus_session_complete_send_short_message (object, invocation, mops_path); /* The rest of the processing happens in a thread. */ context = g_slice_new0 (SendAsyncContext); context->message = message; context->io_priority = G_PRIORITY_DEFAULT; context->from = CAMEL_ADDRESS (from); context->recipients = CAMEL_ADDRESS (recipients); context->info = info; context->transport = service; context->sent_folder_uri = g_strdup (account->sent_folder_uri); context->cancellable = ops; context->ops_path = mops_path; context->result = g_variant_builder_new (G_VARIANT_TYPE_ARRAY); /* Failure here emits a runtime warning but is non-fatal. */ context->driver = camel_session_get_filter_driver ( CAMEL_SESSION (session), "outgoing", &error); if (error != NULL) { g_warn_if_fail (context->driver == NULL); g_warning ("%s", error->message); g_error_free (error); } /* This gets popped in async_context_free(). */ camel_operation_push_message (context->cancellable, _("Sending message")); simple = g_simple_async_result_new ( G_OBJECT (session), mail_send_short_message_completed, context, mail_send_short_message); g_simple_async_result_set_op_res_gpointer ( simple, context, (GDestroyNotify) async_context_free); g_simple_async_result_run_in_thread ( simple, (GSimpleAsyncThreadFunc) mail_send_short_to_thread, context->io_priority, context->cancellable); g_object_unref (simple); return TRUE; on_error: *ret_error = error; return FALSE; }
gint main (gint argc, gchar *argv[]) { CamelSession *session; CamelService *service; ESourceRegistry *registry; GList *list, *link; const gchar *extension_name; g_type_init (); system ("rm -rf /tmp/test-map"); camel_init ("/tmp/test-map", TRUE); e_source_camel_register_types (); session = g_object_new ( CAMEL_TYPE_SESSION, "user-data-dir", "/tmp/test-map", "user-cache-dir", "/tmp/test-map/cache", NULL); /* Browse through the ESource registry to find out the MAP account */ registry = e_source_registry_new_sync (NULL, NULL); extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; list = e_source_registry_list_sources (registry, extension_name); for (link = list; link != NULL; link = g_list_next (link)) { ESource *source = E_SOURCE (link->data); const gchar *uid; const gchar *backend_name = "INVALID"; const gchar *display_name; ESourceBackend *extension; if (!e_source_get_enabled (source)) continue; uid = e_source_get_uid (source); display_name = e_source_get_display_name (source); printf("Looking for: %s\n", display_name); extension = e_source_get_extension (source, extension_name); backend_name = e_source_backend_get_backend_name (extension); if (strcmp (backend_name, "map") == 0) { /* Lets add just map backend to the session. */ CamelFolderInfo *info; CamelFolder *folder; GPtrArray *uids; int i; GError *error=NULL; service = camel_session_add_service ( CAMEL_SESSION (session), uid, backend_name, CAMEL_PROVIDER_STORE, NULL); e_source_camel_configure_service (source, service); camel_service_connect_sync (service, NULL, NULL); info = camel_store_get_folder_info_sync ( CAMEL_STORE (service), "", 0, NULL, NULL); print_folder_info (info, 0); folder = camel_store_get_folder_sync ( CAMEL_STORE (service), "inbox", 0, NULL, NULL); camel_folder_refresh_info_sync (folder, NULL, &error); if (error) printf("Refresh info failed: %s\n", error->message); uids = camel_folder_get_uids (folder); printf("Length of messages: %p %d\n", folder, uids->len); for (i=0; i<uids->len; i++) printf("UID: %s\n", (char *)uids->pdata[i]); } } return 0; }