static gchar * pop3_store_get_name (CamelService *service, gboolean brief) { CamelNetworkSettings *network_settings; CamelSettings *settings; gchar *host; gchar *user; gchar *name; settings = camel_service_ref_settings (service); network_settings = CAMEL_NETWORK_SETTINGS (settings); host = camel_network_settings_dup_host (network_settings); user = camel_network_settings_dup_user (network_settings); g_object_unref (settings); if (brief) name = g_strdup_printf ( _("POP3 server %s"), host); else name = g_strdup_printf ( _("POP3 server for %s on %s"), user, host); g_free (host); g_free (user); return name; }
static gchar * smtp_transport_get_name (CamelService *service, gboolean brief) { CamelNetworkSettings *network_settings; CamelSettings *settings; gchar *host; gchar *name; settings = camel_service_ref_settings (service); network_settings = CAMEL_NETWORK_SETTINGS (settings); host = camel_network_settings_dup_host (network_settings); g_object_unref (settings); if (brief) name = g_strdup_printf ( _("SMTP server %s"), host); else name = g_strdup_printf ( _("SMTP mail delivery via %s"), host); g_free (host); return name; }
static gchar * ews_transport_get_name (CamelService *service, gboolean brief) { CamelSettings *settings; gchar *host; gchar *name; settings = camel_service_ref_settings (service); host = camel_ews_utils_get_host_name (settings); g_object_unref (settings); if (brief) name = g_strdup_printf ( _("Exchange server %s"), host); else name = g_strdup_printf ( _("Exchange mail delivery via %s"), host); g_free (host); return name; }
static gboolean ews_transport_connect_sync (CamelService *service, GCancellable *cancellable, GError **error) { EEwsConnection *connection; CamelSession *session; CamelSettings *settings; gchar *auth_mech; gboolean success; /* Chain up to parent's method. */ if (!CAMEL_SERVICE_CLASS (camel_ews_transport_parent_class)->connect_sync (service, cancellable, error)) return FALSE; if (camel_service_get_connection_status (service) == CAMEL_SERVICE_DISCONNECTED) return FALSE; connection = ews_transport_ref_connection (CAMEL_EWS_TRANSPORT (service)); if (connection) { g_object_unref (connection); return TRUE; } session = camel_service_ref_session (service); settings = camel_service_ref_settings (service); /* Try running an operation that requires authentication * to make sure we have valid credentials available. */ auth_mech = camel_network_settings_dup_auth_mechanism (CAMEL_NETWORK_SETTINGS (settings)); success = camel_session_authenticate_sync (session, service, auth_mech ? auth_mech : "NTLM", cancellable, error); g_free (auth_mech); g_object_unref (session); g_object_unref (settings); return success; }
static void smtp_debug_print_server_name (CamelService *service, const gchar *what) { CamelNetworkSettings *network_settings; CamelSettings *settings; gchar *host; gint port; if (d(1) + 0 == 0) return; settings = camel_service_ref_settings (service); network_settings = CAMEL_NETWORK_SETTINGS (settings); host = camel_network_settings_dup_host (network_settings); port = camel_network_settings_get_port (network_settings); g_object_unref (settings); fprintf (stderr, "[SMTP] %s server %s:%d from account %s\r\n", what, host, port, camel_service_get_uid (service)); g_free (host); }
static CamelAuthenticationResult pop3_store_authenticate_sync (CamelService *service, const gchar *mechanism, GCancellable *cancellable, GError **error) { CamelPOP3Store *store = CAMEL_POP3_STORE (service); CamelNetworkSettings *network_settings; CamelAuthenticationResult result; CamelSettings *settings; CamelPOP3Command *pcu = NULL; CamelPOP3Command *pcp = NULL; CamelPOP3Engine *pop3_engine; const gchar *password; gchar *host; gchar *user; gint status; password = camel_service_get_password (service); settings = camel_service_ref_settings (service); network_settings = CAMEL_NETWORK_SETTINGS (settings); host = camel_network_settings_dup_host (network_settings); user = camel_network_settings_dup_user (network_settings); g_object_unref (settings); pop3_engine = camel_pop3_store_ref_engine (store); if (!pop3_engine) { g_set_error_literal ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE, _("You must be working online to complete this operation")); result = CAMEL_AUTHENTICATION_ERROR; goto exit; } if (mechanism == NULL) { if (password == NULL) { g_set_error_literal ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("Authentication password not available")); result = CAMEL_AUTHENTICATION_ERROR; goto exit; } /* pop engine will take care of pipelining ability */ pcu = camel_pop3_engine_command_new ( pop3_engine, 0, NULL, NULL, cancellable, error, "USER %s\r\n", user); pcp = camel_pop3_engine_command_new ( pop3_engine, 0, NULL, NULL, cancellable, error, "PASS %s\r\n", password); } else if (strcmp (mechanism, "+APOP") == 0 && pop3_engine->apop) { gchar *secret, *md5asc, *d; if (password == NULL) { g_set_error_literal ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("Authentication password not available")); result = CAMEL_AUTHENTICATION_ERROR; goto exit; } d = pop3_engine->apop; while (*d != '\0') { if (!isascii ((gint) * d)) { /* Translators: Do not translate APOP. */ g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_URL_INVALID, _("Unable to connect to POP server %s: " "Invalid APOP ID received. Impersonation " "attack suspected. Please contact your admin."), host); result = CAMEL_AUTHENTICATION_ERROR; goto exit; } d++; } secret = g_alloca ( strlen (pop3_engine->apop) + strlen (password) + 1); sprintf (secret, "%s%s", pop3_engine->apop, password); md5asc = g_compute_checksum_for_string ( G_CHECKSUM_MD5, secret, -1); pcp = camel_pop3_engine_command_new ( pop3_engine, 0, NULL, NULL, cancellable, error, "APOP %s %s\r\n", user, md5asc); g_free (md5asc); } else { GList *link; link = pop3_engine->auth; while (link != NULL) { CamelServiceAuthType *auth = link->data; if (g_strcmp0 (auth->authproto, mechanism) == 0) { result = try_sasl ( store, mechanism, cancellable, error); goto exit; } link = g_list_next (link); } g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("No support for %s authentication"), mechanism); result = CAMEL_AUTHENTICATION_ERROR; goto exit; } while ((status = camel_pop3_engine_iterate (pop3_engine, pcp, cancellable, error)) > 0) ; if (status == -1) { g_prefix_error ( error, _("Unable to connect to POP server %s.\n" "Error sending password: "******": " separator. */ _("Unable to connect to POP server %s.\n" "Error sending username%s"), host, (tmp != NULL) ? tmp : ""); g_free (tmp); result = CAMEL_AUTHENTICATION_ERROR; } else if (pcp->state != CAMEL_POP3_COMMAND_OK) { result = CAMEL_AUTHENTICATION_REJECTED; } else { result = CAMEL_AUTHENTICATION_ACCEPTED; } camel_pop3_engine_command_free (pop3_engine, pcp); if (pcu != NULL) camel_pop3_engine_command_free (pop3_engine, pcu); exit: g_free (host); g_free (user); g_clear_object (&pop3_engine); return result; }
static gboolean pop3_store_connect_sync (CamelService *service, GCancellable *cancellable, GError **error) { CamelPOP3Store *store = (CamelPOP3Store *) service; CamelPOP3Engine *pop3_engine; CamelSettings *settings; CamelSession *session; const gchar *user_data_dir; gboolean success = TRUE; gchar *mechanism; session = camel_service_ref_session (service); user_data_dir = camel_service_get_user_data_dir (service); settings = camel_service_ref_settings (service); mechanism = camel_network_settings_dup_auth_mechanism ( CAMEL_NETWORK_SETTINGS (settings)); g_object_unref (settings); if (!camel_session_get_online (session)) { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE, _("You must be working online to complete this operation")); success = FALSE; goto exit; } g_mutex_lock (&store->priv->property_lock); if (store->priv->cache == NULL) { CamelDataCache *cache; cache = camel_data_cache_new (user_data_dir, error); if (cache != NULL) { /* Ensure cache will never expire, otherwise * it causes redownload of messages. */ camel_data_cache_set_expire_age (cache, -1); camel_data_cache_set_expire_access (cache, -1); store->priv->cache = g_object_ref (cache); g_object_unref (cache); } } g_mutex_unlock (&store->priv->property_lock); success = connect_to_server (service, cancellable, error); if (!success) goto exit; success = camel_session_authenticate_sync ( session, service, mechanism, cancellable, error); if (!success) goto exit; /* Now that we are in the TRANSACTION state, * try regetting the capabilities */ pop3_engine = camel_pop3_store_ref_engine (store); if (pop3_engine) { pop3_engine->state = CAMEL_POP3_ENGINE_TRANSACTION; if (!camel_pop3_engine_reget_capabilities (pop3_engine, cancellable, error)) success = FALSE; g_clear_object (&pop3_engine); } else { g_set_error_literal ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE, _("You must be working online to complete this operation")); success = FALSE; } exit: g_free (mechanism); g_object_unref (session); if (!success) { /* to not leak possible connection to the server */ g_mutex_lock (&store->priv->property_lock); g_clear_object (&store->priv->engine); g_mutex_unlock (&store->priv->property_lock); } return success; }
static CamelAuthenticationResult try_sasl (CamelPOP3Store *store, const gchar *mechanism, GCancellable *cancellable, GError **error) { CamelPOP3Engine *pop3_engine; CamelPOP3Stream *pop3_stream; CamelNetworkSettings *network_settings; CamelAuthenticationResult result; CamelSettings *settings; CamelService *service; guchar *line, *resp; CamelSasl *sasl = NULL; gchar *string; gchar *host; guint len; gint ret; service = CAMEL_SERVICE (store); settings = camel_service_ref_settings (service); network_settings = CAMEL_NETWORK_SETTINGS (settings); host = camel_network_settings_dup_host (network_settings); g_object_unref (settings); pop3_engine = camel_pop3_store_ref_engine (store); if (!pop3_engine) { g_set_error_literal ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE, _("You must be working online to complete this operation")); result = CAMEL_AUTHENTICATION_ERROR; goto exit; } pop3_stream = pop3_engine->stream; sasl = camel_sasl_new ("pop", mechanism, service); if (sasl == NULL) { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_URL_INVALID, _("No support for %s authentication"), mechanism); result = CAMEL_AUTHENTICATION_ERROR; goto exit; } string = g_strdup_printf ("AUTH %s\r\n", mechanism); ret = camel_stream_write_string ( CAMEL_STREAM (pop3_stream), string, cancellable, error); g_free (string); if (ret == -1) goto ioerror; while (1) { GError *local_error = NULL; if (camel_pop3_stream_line (pop3_stream, &line, &len, cancellable, error) == -1) goto ioerror; if (strncmp ((gchar *) line, "+OK", 3) == 0) { result = CAMEL_AUTHENTICATION_ACCEPTED; break; } if (strncmp ((gchar *) line, "-ERR", 4) == 0) { result = CAMEL_AUTHENTICATION_REJECTED; break; } /* If we dont get continuation, or the sasl object's run out * of work, or we dont get a challenge, its a protocol error, * so fail, and try reset the server. */ if (strncmp ((gchar *) line, "+ ", 2) != 0 || camel_sasl_get_authenticated (sasl) || (resp = (guchar *) camel_sasl_challenge_base64_sync (sasl, (const gchar *) line + 2, cancellable, &local_error)) == NULL) { camel_stream_write_string ( CAMEL_STREAM (pop3_stream), "*\r\n", cancellable, NULL); camel_pop3_stream_line (pop3_stream, &line, &len, cancellable, NULL); if (local_error) { g_propagate_error (error, local_error); local_error = NULL; goto ioerror; } g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("Cannot login to POP server %s: " "SASL Protocol error"), host); result = CAMEL_AUTHENTICATION_ERROR; goto exit; } string = g_strdup_printf ("%s\r\n", resp); ret = camel_stream_write_string ( CAMEL_STREAM (pop3_stream), string, cancellable, error); g_free (string); g_free (resp); if (ret == -1) goto ioerror; } goto exit; ioerror: g_prefix_error ( error, _("Failed to authenticate on POP server %s: "), host); result = CAMEL_AUTHENTICATION_ERROR; exit: if (sasl != NULL) g_object_unref (sasl); g_free (host); g_clear_object (&pop3_engine); return result; }
static gboolean connect_to_server (CamelService *service, GCancellable *cancellable, GError **error) { CamelPOP3Store *store = CAMEL_POP3_STORE (service); CamelNetworkSettings *network_settings; CamelNetworkSecurityMethod method; CamelSettings *settings; CamelStream *tcp_stream; CamelPOP3Engine *pop3_engine = NULL; CamelPOP3Command *pc; gboolean disable_extensions; gboolean success = TRUE; gchar *host; guint32 flags = 0; gint ret; GError *local_error = NULL; settings = camel_service_ref_settings (service); network_settings = CAMEL_NETWORK_SETTINGS (settings); host = camel_network_settings_dup_host (network_settings); method = camel_network_settings_get_security_method (network_settings); disable_extensions = camel_pop3_settings_get_disable_extensions ( CAMEL_POP3_SETTINGS (settings)); g_object_unref (settings); tcp_stream = camel_network_service_connect_sync ( CAMEL_NETWORK_SERVICE (service), cancellable, error); if (tcp_stream == NULL) { success = FALSE; goto exit; } /* parent class connect initialization */ if (CAMEL_SERVICE_CLASS (camel_pop3_store_parent_class)-> connect_sync (service, cancellable, error) == FALSE) { g_object_unref (tcp_stream); success = FALSE; goto exit; } if (disable_extensions) flags |= CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS; if (!(pop3_engine = camel_pop3_engine_new (tcp_stream, flags, cancellable, &local_error)) || local_error != NULL) { if (local_error) g_propagate_error (error, local_error); else g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Failed to read a valid greeting from POP server %s"), host); g_object_unref (tcp_stream); success = FALSE; goto exit; } if (method != CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT) { g_object_unref (tcp_stream); goto exit; } if (!(pop3_engine->capa & CAMEL_POP3_CAP_STLS)) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Failed to connect to POP server %s in secure mode: %s"), host, _("STLS not supported by server")); goto stls_exception; } pc = camel_pop3_engine_command_new ( pop3_engine, 0, NULL, NULL, cancellable, error, "STLS\r\n"); while (camel_pop3_engine_iterate (pop3_engine, NULL, cancellable, NULL) > 0) ; ret = pc->state == CAMEL_POP3_COMMAND_OK; camel_pop3_engine_command_free (pop3_engine, pc); if (ret == FALSE) { gchar *tmp; tmp = get_valid_utf8_error ((gchar *) pop3_engine->line); g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, /* Translators: Last %s is an optional * explanation beginning with ": " separator. */ _("Failed to connect to POP server %s in secure mode%s"), host, (tmp != NULL) ? tmp : ""); g_free (tmp); goto stls_exception; } /* Okay, now toggle SSL/TLS mode */ ret = camel_tcp_stream_ssl_enable_ssl ( CAMEL_TCP_STREAM_SSL (tcp_stream), cancellable, error); if (ret == -1) { g_prefix_error ( error, _("Failed to connect to POP server %s in secure mode: "), host); goto stls_exception; } g_object_unref (tcp_stream); /* rfc2595, section 4 states that after a successful STLS * command, the client MUST discard prior CAPA responses */ if (!camel_pop3_engine_reget_capabilities (pop3_engine, cancellable, error)) goto exception; goto exit; stls_exception: /* As soon as we send a STLS command, all hope * is lost of a clean QUIT if problems arise. */ /* if (clean_quit) { / * try to disconnect cleanly * / pc = camel_pop3_engine_command_new ( pop3_engine, 0, NULL, NULL, cancellable, NULL, "QUIT\r\n"); while (camel_pop3_engine_iterate (pop3_engine, NULL, cancellable, NULL) > 0) ; camel_pop3_engine_command_free (pop3_engine, pc); }*/ exception: g_object_unref (tcp_stream); g_clear_object (&pop3_engine); success = FALSE; exit: g_free (host); g_mutex_lock (&store->priv->property_lock); if (pop3_engine != NULL) store->priv->engine = g_object_ref (pop3_engine); g_mutex_unlock (&store->priv->property_lock); g_clear_object (&pop3_engine); return success; }
static gboolean ews_send_to_sync (CamelTransport *transport, CamelMimeMessage *message, CamelAddress *from, CamelAddress *recipients, gboolean *out_sent_message_saved, GCancellable *cancellable, GError **error) { CamelNetworkSettings *network_settings; CamelEwsSettings *ews_settings; CamelInternetAddress *used_from; CamelSettings *settings; CamelService *service; EEwsConnection *cnc; EwsFolderId *folder_id = NULL; gchar *ews_email; gchar *host_url; gchar *user; gboolean success = FALSE; service = CAMEL_SERVICE (transport); settings = camel_service_ref_settings (service); ews_settings = CAMEL_EWS_SETTINGS (settings); ews_email = camel_ews_settings_dup_email (ews_settings); host_url = camel_ews_settings_dup_hosturl (ews_settings); network_settings = CAMEL_NETWORK_SETTINGS (settings); user = camel_network_settings_dup_user (network_settings); g_object_unref (settings); if (CAMEL_IS_INTERNET_ADDRESS (from)) used_from = CAMEL_INTERNET_ADDRESS (from); else used_from = camel_mime_message_get_from (message); if (!used_from || camel_address_length (CAMEL_ADDRESS (used_from)) == 0) { g_set_error_literal ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot send message with no From address")); goto exit; } else if (camel_address_length (CAMEL_ADDRESS (used_from)) > 1) { g_set_error_literal ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Exchange server cannot send message with " "multiple From addresses")); goto exit; } else { const gchar *used_email = NULL; if (!camel_internet_address_get (used_from, 0, NULL, &used_email)) { g_set_error_literal ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Failed to read From address")); goto exit; } } cnc = ews_transport_ref_connection (CAMEL_EWS_TRANSPORT (service)); if (!cnc) { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_NOT_CONNECTED, _("Service not connected")); goto exit; } if (ews_transport_can_server_side_sent_folder (service, &folder_id, cancellable)) { if (out_sent_message_saved) *out_sent_message_saved = TRUE; } success = camel_ews_utils_create_mime_message ( cnc, folder_id ? "SendAndSaveCopy" : "SendOnly", folder_id, message, NULL, from, recipients, NULL, NULL, cancellable, error); g_object_unref (cnc); e_ews_folder_id_free (folder_id); exit: g_free (ews_email); g_free (host_url); g_free (user); return success; }
static CamelAuthenticationResult ews_transport_authenticate_sync (CamelService *service, const gchar *mechanism, GCancellable *cancellable, GError **error) { CamelAuthenticationResult result; CamelEwsTransport *ews_transport; CamelSettings *settings; CamelEwsSettings *ews_settings; EEwsConnection *connection; const gchar *password; gchar *hosturl, *new_sync_state = NULL; GSList *folders_created = NULL; GSList *folders_updated = NULL; GSList *folders_deleted = NULL; gboolean includes_last_folder = FALSE; GError *local_error = NULL; ews_transport = CAMEL_EWS_TRANSPORT (service); password = camel_service_get_password (service); settings = camel_service_ref_settings (service); ews_settings = CAMEL_EWS_SETTINGS (settings); hosturl = camel_ews_settings_dup_hosturl (ews_settings); connection = e_ews_connection_new (hosturl, ews_settings); e_ews_connection_set_password (connection, password); g_free (hosturl); g_object_unref (settings); e_binding_bind_property ( service, "proxy-resolver", connection, "proxy-resolver", G_BINDING_SYNC_CREATE); /* XXX We need to run some operation that requires authentication * but does not change any server-side state, so we can check * the error status and determine if our password is valid. * David suggested e_ews_connection_sync_folder_hierarchy(), * since we have to do that eventually anyway. */ e_ews_connection_sync_folder_hierarchy_sync (connection, EWS_PRIORITY_MEDIUM, NULL, &new_sync_state, &includes_last_folder, &folders_created, &folders_updated, &folders_deleted, cancellable, &local_error); g_slist_free_full (folders_created, g_object_unref); g_slist_free_full (folders_updated, g_object_unref); g_slist_free_full (folders_deleted, g_free); g_free (new_sync_state); if (g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_UNAVAILABLE)) { local_error->domain = CAMEL_SERVICE_ERROR; local_error->code = CAMEL_SERVICE_ERROR_UNAVAILABLE; } if (!local_error) { g_mutex_lock (&ews_transport->priv->connection_lock); g_clear_object (&ews_transport->priv->connection); ews_transport->priv->connection = g_object_ref (connection); g_mutex_unlock (&ews_transport->priv->connection_lock); } else { g_mutex_lock (&ews_transport->priv->connection_lock); g_clear_object (&ews_transport->priv->connection); g_mutex_unlock (&ews_transport->priv->connection_lock); } if (!local_error) { result = CAMEL_AUTHENTICATION_ACCEPTED; } else if (g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_AUTHENTICATION_FAILED)) { g_clear_error (&local_error); result = CAMEL_AUTHENTICATION_REJECTED; } else { g_propagate_error (error, local_error); result = CAMEL_AUTHENTICATION_ERROR; } g_object_unref (connection); return result; }
gchar * mail_tool_do_movemail (CamelStore *store, GError **error) { #ifndef G_OS_WIN32 CamelService *service; CamelProvider *provider; CamelSettings *settings; gchar *src_path; gchar *dest_path; struct stat sb; gboolean success; g_return_val_if_fail (CAMEL_IS_STORE (store), NULL); service = CAMEL_SERVICE (store); provider = camel_service_get_provider (service); g_return_val_if_fail (provider != NULL, NULL); if (g_strcmp0 (provider->protocol, "mbox") != 0) { /* This is really only an internal error anyway */ g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_URL_INVALID, _("Trying to movemail a non-mbox source '%s'"), camel_service_get_uid (CAMEL_SERVICE (store))); return NULL; } settings = camel_service_ref_settings (service); src_path = camel_local_settings_dup_path ( CAMEL_LOCAL_SETTINGS (settings)); g_object_unref (settings); /* Set up our destination. */ dest_path = mail_tool_get_local_movemail_path (store, error); if (dest_path == NULL) return NULL; /* Movemail from source to dest_path */ success = camel_movemail (src_path, dest_path, error) != -1; g_free (src_path); if (g_stat (dest_path, &sb) < 0 || sb.st_size == 0) { g_unlink (dest_path); /* Clean up the movemail.foo file. */ g_free (dest_path); return NULL; } if (!success) { g_free (dest_path); return NULL; } return dest_path; #else /* Unclear yet whether camel-movemail etc makes any sense on * Win32, at least it is not ported yet. */ g_warning ("%s: Not implemented", __FUNCTION__); return NULL; #endif }
static gchar * format_service_name (CamelService *service) { CamelProvider *provider; CamelSettings *settings; gchar *service_name = NULL; const gchar *display_name; gchar *pretty_url = NULL; gchar *host = NULL; gchar *path = NULL; gchar *user = NULL; gchar *cp; gboolean have_host = FALSE; gboolean have_path = FALSE; gboolean have_user = FALSE; provider = camel_service_get_provider (service); display_name = camel_service_get_display_name (service); settings = camel_service_ref_settings (service); if (CAMEL_IS_NETWORK_SETTINGS (settings)) { host = camel_network_settings_dup_host ( CAMEL_NETWORK_SETTINGS (settings)); have_host = (host != NULL) && (*host != '\0'); user = camel_network_settings_dup_user ( CAMEL_NETWORK_SETTINGS (settings)); have_user = (user != NULL) && (*user != '\0'); } if (CAMEL_IS_LOCAL_SETTINGS (settings)) { path = camel_local_settings_dup_path ( CAMEL_LOCAL_SETTINGS (settings)); have_path = (path != NULL) && (*path != '\0'); } g_object_unref (settings); /* Shorten user names with '@', since multiple '@' in a * 'user@host' label look weird. This is just supposed * to be a hint anyway so it doesn't matter if it's not * strictly correct. */ if (have_user && (cp = strchr (user, '@')) != NULL) *cp = '\0'; g_return_val_if_fail (provider != NULL, NULL); /* This should never happen, but if the service has no * display name, fall back to the generic service name. */ if (display_name == NULL || *display_name == '\0') { service_name = camel_service_get_name (service, TRUE); display_name = service_name; } if (have_host && have_user) { pretty_url = g_markup_printf_escaped ( "<b>%s</b> <small>(%s@%s)</small>", display_name, user, host); } else if (have_host) { pretty_url = g_markup_printf_escaped ( "<b>%s</b> <small>(%s)</small>", display_name, host); } else if (have_path) { pretty_url = g_markup_printf_escaped ( "<b>%s</b> <small>(%s)</small>", display_name, path); } else { pretty_url = g_markup_printf_escaped ( "<b>%s</b>", display_name); } g_free (service_name); g_free (host); g_free (path); g_free (user); return pretty_url; }
} if (provider->object_types[CAMEL_PROVIDER_TRANSPORT]) return SEND_SEND; return SEND_INVALID; } static gboolean get_keep_on_server (CamelService *service) { GObjectClass *class; CamelSettings *settings; gboolean keep_on_server = FALSE; settings = camel_service_ref_settings (service); class = G_OBJECT_GET_CLASS (settings); /* XXX This is a POP3-specific setting. */ if (g_object_class_find_property (class, "keep-on-server") != NULL) g_object_get ( settings, "keep-on-server", &keep_on_server, NULL); g_object_unref (settings); return keep_on_server; } static struct _send_data * build_dialog (GtkWindow *parent,
static gboolean smtp_transport_connect_sync (CamelService *service, GCancellable *cancellable, GError **error) { CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); CamelNetworkSettings *network_settings; CamelSettings *settings; gchar *host; gchar *mechanism; gboolean auth_required; gboolean success = TRUE; /* Chain up to parent's method. */ if (!CAMEL_SERVICE_CLASS (camel_smtp_transport_parent_class)->connect_sync (service, cancellable, error)) return FALSE; smtp_debug_print_server_name (service, "Connecting to"); settings = camel_service_ref_settings (service); network_settings = CAMEL_NETWORK_SETTINGS (settings); host = camel_network_settings_dup_host (network_settings); mechanism = camel_network_settings_dup_auth_mechanism (network_settings); g_object_unref (settings); /* We (probably) need to check popb4smtp before we connect ... */ if (g_strcmp0 (mechanism, "POPB4SMTP") == 0) { GByteArray *chal; CamelSasl *sasl; sasl = camel_sasl_new ("smtp", "POPB4SMTP", service); chal = camel_sasl_challenge_sync (sasl, NULL, cancellable, error); if (chal != NULL) g_byte_array_free (chal, TRUE); if (camel_sasl_get_authenticated (sasl)) success = connect_to_server ( service, cancellable, error); else success = FALSE; g_object_unref (sasl); goto exit; } success = connect_to_server (service, cancellable, error); if (!success) return FALSE; /* check to see if AUTH is required, if so...then AUTH ourselves */ auth_required = (mechanism != NULL) && (transport->authtypes != NULL) && (g_hash_table_size (transport->authtypes) > 0) && (transport->flags & CAMEL_SMTP_TRANSPORT_IS_ESMTP); if (auth_required) { CamelSession *session; session = camel_service_ref_session (service); if (g_hash_table_lookup (transport->authtypes, mechanism)) { success = camel_session_authenticate_sync ( session, service, mechanism, cancellable, error); } else { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("SMTP server %s does not support %s " "authentication"), host, mechanism); success = FALSE; } g_object_unref (session); if (!success) transport->connected = FALSE; } exit: g_free (host); g_free (mechanism); return success; }
static gboolean migrate_mbox_to_maildir (EShell *shell, CamelSession *session, ESource *mbox_source) { ESourceRegistry *registry; ESourceExtension *extension; const gchar *extension_name; CamelService *mbox_service = NULL; CamelService *maildir_service = NULL; CamelSettings *settings; const gchar *data_dir; const gchar *mbox_uid; gchar *path; struct MigrateStore ms; GThread *thread; 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) mbox_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) { if (mbox_service != NULL) g_object_unref (mbox_service); if (maildir_service != NULL) g_object_unref (maildir_service); g_warning ("%s: %s", G_STRFUNC, error->message); g_error_free (error); return FALSE; } g_return_val_if_fail (CAMEL_IS_STORE (mbox_service), FALSE); g_return_val_if_fail (CAMEL_IS_STORE (maildir_service), FALSE); camel_service_set_settings (mbox_service, settings); settings = camel_service_ref_settings (maildir_service); path = g_build_filename (data_dir, "local", NULL); g_object_set (settings, "path", path, NULL); if (g_mkdir (path, 0700) == -1) g_warning ( "%s: Failed to make directory '%s': %s", G_STRFUNC, path, g_strerror (errno)); g_free (path); g_object_unref (settings); ms.mail_store = CAMEL_STORE (mbox_service); ms.maildir_store = CAMEL_STORE (maildir_service); ms.session = session; ms.complete = FALSE; thread = g_thread_new (NULL, (GThreadFunc) migrate_stores, &ms); /* coverity[loop_condition] */ while (!ms.complete) g_main_context_iteration (NULL, TRUE); g_object_unref (mbox_service); g_object_unref (maildir_service); g_thread_unref (thread); return TRUE; }
static gboolean sendmail_send_to_sync (CamelTransport *transport, CamelMimeMessage *message, CamelAddress *from, CamelAddress *recipients, gboolean *out_sent_message_saved, GCancellable *cancellable, GError **error) { CamelHeaderRaw *header, *savedbcc, *n, *tail; const gchar *from_addr, *addr; GPtrArray *argv_arr; gint i, len, fd[2], nullfd, wstat; CamelStream *filter; CamelMimeFilter *crlf; sigset_t mask, omask; CamelStream *out; CamelSendmailSettings *settings; const gchar *binary = SENDMAIL_PATH; gchar *custom_binary = NULL, *custom_args = NULL; gboolean success; pid_t pid; success = camel_internet_address_get ( CAMEL_INTERNET_ADDRESS (from), 0, NULL, &from_addr); if (!success) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Failed to read From address")); return FALSE; } settings = CAMEL_SENDMAIL_SETTINGS (camel_service_ref_settings (CAMEL_SERVICE (transport))); if (!camel_sendmail_settings_get_send_in_offline (settings)) { CamelSession *session; gboolean is_online; session = camel_service_ref_session (CAMEL_SERVICE (transport)); is_online = session && camel_session_get_online (session); g_clear_object (&session); if (!is_online) { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE, _("Message send in offline mode is disabled")); return FALSE; } } if (camel_sendmail_settings_get_use_custom_binary (settings)) { custom_binary = camel_sendmail_settings_dup_custom_binary (settings); if (custom_binary && *custom_binary) binary = custom_binary; } if (camel_sendmail_settings_get_use_custom_args (settings)) { custom_args = camel_sendmail_settings_dup_custom_args (settings); /* means no arguments used */ if (!custom_args) custom_args = g_strdup (""); } g_object_unref (settings); len = camel_address_length (recipients); for (i = 0; i < len; i++) { success = camel_internet_address_get ( CAMEL_INTERNET_ADDRESS (recipients), i, NULL, &addr); if (!success) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Could not parse recipient list")); g_free (custom_binary); g_free (custom_args); return FALSE; } } argv_arr = parse_sendmail_args ( binary, custom_args ? custom_args : "-i -f %F -- %R", from_addr, recipients); if (!argv_arr) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Could not parse arguments")); g_free (custom_binary); g_free (custom_args); return FALSE; } /* unlink the bcc headers */ savedbcc = NULL; tail = (CamelHeaderRaw *) &savedbcc; header = (CamelHeaderRaw *) &CAMEL_MIME_PART (message)->headers; n = header->next; while (n != NULL) { if (!g_ascii_strcasecmp (n->name, "Bcc")) { header->next = n->next; tail->next = n; n->next = NULL; tail = n; } else { header = n; } n = header->next; } if (pipe (fd) == -1) { g_set_error ( error, G_IO_ERROR, g_io_error_from_errno (errno), _("Could not create pipe to '%s': %s: " "mail not sent"), binary, g_strerror (errno)); /* restore the bcc headers */ header->next = savedbcc; g_free (custom_binary); g_free (custom_args); g_ptr_array_free (argv_arr, TRUE); return FALSE; } /* Block SIGCHLD so the calling application doesn't notice * sendmail exiting before we do. */ sigemptyset (&mask); sigaddset (&mask, SIGCHLD); sigprocmask (SIG_BLOCK, &mask, &omask); pid = fork (); switch (pid) { case -1: g_set_error ( error, G_IO_ERROR, g_io_error_from_errno (errno), _("Could not fork '%s': %s: " "mail not sent"), binary, g_strerror (errno)); close (fd[0]); close (fd[1]); sigprocmask (SIG_SETMASK, &omask, NULL); /* restore the bcc headers */ header->next = savedbcc; g_free (custom_binary); g_free (custom_args); g_ptr_array_free (argv_arr, TRUE); return FALSE; case 0: /* Child process */ nullfd = open ("/dev/null", O_RDWR); dup2 (fd[0], STDIN_FILENO); if (nullfd != -1) { /*dup2 (nullfd, STDOUT_FILENO); dup2 (nullfd, STDERR_FILENO);*/ close (nullfd); } close (fd[1]); execv (binary, (gchar **) argv_arr->pdata); _exit (255); } g_ptr_array_free (argv_arr, TRUE); /* Parent process. Write the message out. */ close (fd[0]); out = camel_stream_fs_new_with_fd (fd[1]); /* XXX Workaround for lame sendmail implementations * that can't handle CRLF eoln sequences. */ filter = camel_stream_filter_new (out); crlf = camel_mime_filter_crlf_new ( CAMEL_MIME_FILTER_CRLF_DECODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); camel_stream_filter_add (CAMEL_STREAM_FILTER (filter), crlf); g_object_unref (crlf); g_object_unref (out); out = (CamelStream *) filter; if (camel_data_wrapper_write_to_stream_sync ( CAMEL_DATA_WRAPPER (message), out, cancellable, error) == -1 || camel_stream_close (out, cancellable, error) == -1) { g_object_unref (out); g_prefix_error (error, _("Could not send message: ")); /* Wait for sendmail to exit. */ while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR) ; sigprocmask (SIG_SETMASK, &omask, NULL); /* restore the bcc headers */ header->next = savedbcc; g_free (custom_binary); g_free (custom_args); return FALSE; } g_object_unref (out); /* Wait for sendmail to exit. */ while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR) ; sigprocmask (SIG_SETMASK, &omask, NULL); /* restore the bcc headers */ header->next = savedbcc; if (!WIFEXITED (wstat)) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("'%s' exited with signal %s: mail not sent."), binary, g_strsignal (WTERMSIG (wstat))); g_free (custom_binary); g_free (custom_args); return FALSE; } else if (WEXITSTATUS (wstat) != 0) { if (WEXITSTATUS (wstat) == 255) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Could not execute '%s': mail not sent."), binary); } else { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("'%s' exited with status %d: " "mail not sent."), binary, WEXITSTATUS (wstat)); } g_free (custom_binary); g_free (custom_args); return FALSE; } g_free (custom_binary); g_free (custom_args); return TRUE; }
static gboolean connect_to_server (CamelService *service, GCancellable *cancellable, GError **error) { CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); CamelNetworkSettings *network_settings; CamelNetworkSecurityMethod method; CamelSettings *settings; CamelStream *stream; GIOStream *base_stream; GIOStream *tls_stream; gchar *respbuf = NULL; gboolean success = TRUE; gchar *host; if (!CAMEL_SERVICE_CLASS (camel_smtp_transport_parent_class)-> connect_sync (service, cancellable, error)) return FALSE; /* set some smtp transport defaults */ transport->flags = 0; transport->authtypes = NULL; settings = camel_service_ref_settings (service); network_settings = CAMEL_NETWORK_SETTINGS (settings); host = camel_network_settings_dup_host (network_settings); method = camel_network_settings_get_security_method (network_settings); g_object_unref (settings); base_stream = camel_network_service_connect_sync ( CAMEL_NETWORK_SERVICE (service), cancellable, error); if (base_stream != NULL) { /* get the localaddr - needed later by smtp_helo */ transport->local_address = g_socket_connection_get_local_address ( G_SOCKET_CONNECTION (base_stream), NULL); stream = camel_stream_new (base_stream); g_object_unref (base_stream); } else { success = FALSE; goto exit; } transport->connected = TRUE; transport->ostream = stream; transport->istream = camel_stream_buffer_new ( stream, CAMEL_STREAM_BUFFER_READ); /* Read the greeting, note whether the server is ESMTP or not. */ do { /* Check for "220" */ g_free (respbuf); respbuf = camel_stream_buffer_read_line ( CAMEL_STREAM_BUFFER (transport->istream), cancellable, error); d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)")); if (respbuf == NULL) { g_prefix_error (error, _("Welcome response error: ")); transport->connected = FALSE; success = FALSE; goto exit; } if (strncmp (respbuf, "220", 3)) { smtp_set_error ( transport, respbuf, cancellable, error); g_prefix_error (error, _("Welcome response error: ")); g_free (respbuf); success = FALSE; goto exit; } } while (*(respbuf+3) == '-'); /* if we got "220-" then loop again */ g_free (respbuf); /* Try sending EHLO */ transport->flags |= CAMEL_SMTP_TRANSPORT_IS_ESMTP; if (!smtp_helo (transport, cancellable, error)) { if (!transport->connected) { success = FALSE; goto exit; } /* Fall back to HELO */ g_clear_error (error); transport->flags &= ~CAMEL_SMTP_TRANSPORT_IS_ESMTP; if (!smtp_helo (transport, cancellable, error)) { success = FALSE; goto exit; } } /* Clear any EHLO/HELO exception and assume that * any SMTP errors encountered were non-fatal. */ g_clear_error (error); if (method != CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT) goto exit; /* we're done */ if (!(transport->flags & CAMEL_SMTP_TRANSPORT_STARTTLS)) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Failed to connect to SMTP server %s in secure mode: %s"), host, _("STARTTLS not supported")); success = FALSE; goto exit; } d (fprintf (stderr, "[SMTP] sending: STARTTLS\r\n")); if (camel_stream_write ( stream, "STARTTLS\r\n", 10, cancellable, error) == -1) { g_prefix_error (error, _("STARTTLS command failed: ")); success = FALSE; goto exit; } respbuf = NULL; do { /* Check for "220 Ready for TLS" */ g_free (respbuf); respbuf = camel_stream_buffer_read_line ( CAMEL_STREAM_BUFFER (transport->istream), cancellable, error); d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)")); if (respbuf == NULL) { g_prefix_error (error, _("STARTTLS command failed: ")); transport->connected = FALSE; success = FALSE; goto exit; } if (strncmp (respbuf, "220", 3) != 0) { smtp_set_error ( transport, respbuf, cancellable, error); g_prefix_error (error, _("STARTTLS command failed: ")); g_free (respbuf); success = FALSE; goto exit; } } while (*(respbuf+3) == '-'); /* if we got "220-" then loop again */ /* Okay, now toggle SSL/TLS mode */ base_stream = camel_stream_ref_base_stream (stream); tls_stream = camel_network_service_starttls ( CAMEL_NETWORK_SERVICE (service), base_stream, error); g_object_unref (base_stream); if (tls_stream != NULL) { camel_stream_set_base_stream (stream, tls_stream); g_object_unref (tls_stream); } else { g_prefix_error ( error, _("Failed to connect to SMTP server %s in secure mode: "), host); success = FALSE; goto exit; } /* We are supposed to re-EHLO after a successful STARTTLS to * re-fetch any supported extensions. */ if (!smtp_helo (transport, cancellable, error)) { success = FALSE; } exit: g_free (host); if (!success) { transport->connected = FALSE; g_clear_object (&transport->istream); g_clear_object (&transport->ostream); } return success; }