diff --git a/camel/camel-network-service.c b/camel/camel-network-service.c
index c6f5377..9a5f20b 100644
--- a/camel/camel-network-service.c
+++ b/camel/camel-network-service.c
@@ -92,7 +92,7 @@ network_service_connect_sync (CamelNetworkService *service,
 			g_return_val_if_reached (NULL);
 	}
 
-	camel_session_get_socks_proxy (session, &socks_host, &socks_port);
+	camel_session_get_socks_proxy (session, url->host, &socks_host, &socks_port);
 
 	if (socks_host != NULL) {
 		camel_tcp_stream_set_socks_proxy (
diff --git a/camel/camel-session.c b/camel/camel-session.c
index e98bae83..bfa5e18 100644
--- a/camel/camel-session.c
+++ b/camel/camel-session.c
@@ -71,9 +71,6 @@ struct _CamelSessionPrivate {
 
 	GMainContext *context;
 
-	gchar *socks_proxy_host;
-	gint socks_proxy_port;
-
 	guint check_junk        : 1;
 	guint network_available : 1;
 	guint online            : 1;
@@ -1369,56 +1366,33 @@ camel_session_unlock (CamelSession *session,
 }
 
 /**
- * camel_session_set_socks_proxy:
- * @session: A #CamelSession
- * @socks_host: Hostname of the SOCKS proxy, or %NULL for none.
- * @socks_port: Port number of the SOCKS proxy
- *
- * Sets a SOCKS proxy that will be used throughout the @session for
- * TCP connections.
- *
- * Since: 2.32
- */
-void
-camel_session_set_socks_proxy (CamelSession *session,
-                               const gchar *socks_host,
-                               gint socks_port)
-{
-	g_return_if_fail (CAMEL_IS_SESSION (session));
-
-	if (session->priv->socks_proxy_host)
-		g_free (session->priv->socks_proxy_host);
-
-	if (socks_host && socks_host[0] != '\0') {
-		session->priv->socks_proxy_host = g_strdup (socks_host);
-		session->priv->socks_proxy_port = socks_port;
-	} else {
-		session->priv->socks_proxy_host = NULL;
-		session->priv->socks_proxy_port = 0;
-	}
-}
-
-/**
  * camel_session_get_socks_proxy:
  * @session: A #CamelSession
+ * @for_host: Host name to which the connection will be requested
  * @host_ret: Location to return the SOCKS proxy hostname
  * @port_ret: Location to return the SOCKS proxy port
  *
  * Queries the SOCKS proxy that is configured for a @session.  This will
- * put %NULL in @hosts_ret if there is no proxy configured.
+ * put %NULL in @hosts_ret if there is no proxy configured or when
+ * the @for_host is listed in proxy ignore list.
  *
  * Since: 2.32
  */
 void
 camel_session_get_socks_proxy (CamelSession *session,
+			       const gchar *for_host,
                                gchar **host_ret,
                                gint *port_ret)
 {
+	CamelSessionClass *klass;
+
 	g_return_if_fail (CAMEL_IS_SESSION (session));
+	g_return_if_fail (for_host != NULL);
 	g_return_if_fail (host_ret != NULL);
 	g_return_if_fail (port_ret != NULL);
 
-	*host_ret = g_strdup (session->priv->socks_proxy_host);
-	*port_ret = session->priv->socks_proxy_port;
-}
+	klass = CAMEL_SESSION_GET_CLASS (session);
+	g_return_if_fail (klass->get_socks_proxy != NULL);
 
+	klass->get_socks_proxy (session, for_host, host_ret, port_ret);
+}
diff --git a/camel/camel-session.h b/camel/camel-session.h
index 984097b..26861b2 100644
--- a/camel/camel-session.h
+++ b/camel/camel-session.h
@@ -135,6 +135,10 @@ struct _CamelSessionClass {
 						 CamelMimeMessage *message,
 						 const gchar *address,
 						 GError **error);
+	void		(*get_socks_proxy)	(CamelSession *session,
+						 const gchar *for_host,
+						 gchar **host_ret,
+						 gint *port_ret);
 
 	/* Signals */
 	void		(*job_started)		(CamelSession *session,
@@ -148,10 +152,8 @@ GType		camel_session_get_type		(void);
 const gchar *	camel_session_get_user_data_dir	(CamelSession *session);
 const gchar *	camel_session_get_user_cache_dir
 						(CamelSession *session);
-void            camel_session_set_socks_proxy   (CamelSession *session,
-						 const gchar *socks_host,
-						 gint socks_port);
 void            camel_session_get_socks_proxy   (CamelSession *session,
+						 const gchar *for_host,
 						 gchar **host_ret,
 						 gint *port_ret);
 CamelService *	camel_session_add_service	(CamelSession *session,
diff --git a/libedataserver/e-proxy.c b/libedataserver/e-proxy.c
index 83260be..c52b168 100644
--- a/libedataserver/e-proxy.c
+++ b/libedataserver/e-proxy.c
@@ -92,7 +92,7 @@ typedef enum {
 } EProxyKey;
 
 struct _EProxyPrivate {
-	SoupURI *uri_http, *uri_https;
+	SoupURI *uri_http, *uri_https, *uri_socks;
 	guint notify_id_evo; /* conxn id of gconf_client_notify_add  */
 	GSList * ign_hosts;	/* List of hostnames. (Strings)		*/
 	GSList * ign_addrs;	/* List of hostaddrs. (ProxyHostAddrs)	*/
@@ -436,6 +436,14 @@ ep_need_proxy_https (EProxy *proxy,
 }
 
 static gboolean
+ep_need_proxy_socks (EProxy *proxy,
+                     const gchar *host)
+{
+	/* Can we share ignore list from HTTP at all? */
+	return !ep_is_in_ignored (proxy, host);
+}
+
+static gboolean
 ep_manipulate_ipv4 (ProxyHostAddr *host_addr,
                     struct in_addr *addr_in,
                     gchar *netmask)
@@ -582,10 +590,12 @@ ep_parse_ignore_host (gpointer data,
 							&((struct sockaddr_in6 *) so_addr)->sin6_addr,
 							netmask);
 
-		if (!has_error)
+		if (!has_error) {
 			priv->ign_addrs = g_slist_append (priv->ign_addrs, host_addr);
-
-		g_free (hostname);
+			priv->ign_hosts = g_slist_append (priv->ign_hosts, hostname);
+		} else {
+			g_free (hostname);
+		}
 	} else {
 		d(g_print ("Unable to resolve %s\n", hostname));
 		priv->ign_hosts = g_slist_append (priv->ign_hosts, hostname);
@@ -674,7 +684,7 @@ static void
 ep_set_proxy (EProxy *proxy,
               gboolean regen_ign_host_list)
 {
-	gchar *proxy_server, *uri_http = NULL, *uri_https = NULL;
+	gchar *proxy_server, *uri_http = NULL, *uri_https = NULL, *uri_socks = NULL;
 	gint proxy_port, old_type;
 	EProxyPrivate * priv = proxy->priv;
 	GSList *ignore;
@@ -700,6 +710,7 @@ ep_set_proxy (EProxy *proxy,
 	if (!priv->use_proxy || priv->type == PROXY_TYPE_NO_PROXY || !sys_manual) {
 		changed = ep_change_uri (&priv->uri_http, NULL) || changed;
 		changed = ep_change_uri (&priv->uri_https, NULL) || changed;
+		changed = ep_change_uri (&priv->uri_socks, NULL) || changed;
 		goto emit_signal;
 	}
 
@@ -727,6 +738,18 @@ ep_set_proxy (EProxy *proxy,
 	g_free (proxy_server);
 	d(g_print ("ep_set_proxy: uri_https: %s\n", uri_https));
 
+	proxy_server = ep_read_key_string (proxy, E_PROXY_KEY_SOCKS_HOST, client);
+	proxy_port = ep_read_key_int (proxy, E_PROXY_KEY_SOCKS_PORT, client);
+	if (proxy_server != NULL && *proxy_server && !g_ascii_isspace (*proxy_server)) {
+		if (proxy_port > 0)
+			uri_socks = g_strdup_printf ("socks://%s:%d", proxy_server, proxy_port);
+		else
+			uri_socks = g_strdup_printf ("socks://%s", proxy_server);
+	} else
+		uri_socks = NULL;
+	g_free (proxy_server);
+	d(g_print ("ep_set_proxy: uri_socks: %s\n", uri_socks));
+
 	if (regen_ign_host_list) {
 		if (priv->ign_hosts) {
 			g_slist_foreach (priv->ign_hosts, (GFunc) g_free, NULL);
@@ -772,14 +795,16 @@ ep_set_proxy (EProxy *proxy,
 
 	changed = ep_change_uri (&priv->uri_http, uri_http) || changed;
 	changed = ep_change_uri (&priv->uri_https, uri_https) || changed;
+	changed = ep_change_uri (&priv->uri_socks, uri_socks) || changed;
 
  emit_signal:
-	d(g_print ("%s: changed:%d uri_http: %s; uri_https: %s\n", G_STRFUNC, changed ? 1 : 0, uri_http ? uri_http : "[null]", uri_https ? uri_https : "[null]"));
+	d(g_print ("%s: changed:%d uri_http: %s; uri_https: %s; uri_socks: %s\n", G_STRFUNC, changed ? 1 : 0, uri_http ? uri_http : "[null]", uri_https ? uri_https : "[null]", uri_socks ? uri_socks : "[null]"));
 	if (changed)
 		g_signal_emit (proxy, signals[CHANGED], 0);
 
 	g_free (uri_http);
 	g_free (uri_https);
+	g_free (uri_socks);
 	g_object_unref (client);
 }
 
@@ -800,7 +825,7 @@ ep_setting_changed (GConfClient *client,
 	key = gconf_entry_get_key (entry);
 
 	if (g_str_equal (key, KEY_GCONF_EVO_PROXY_TYPE)) {
-		ep_set_proxy (user_data, FALSE);
+		ep_set_proxy (user_data, TRUE);
 		d(g_print ("e-proxy.c:ep_settings_changed: proxy type changed\n"));
 	} else if (priv->type == PROXY_TYPE_SYSTEM) {
 		return;
@@ -829,8 +854,11 @@ ep_setting_changed (GConfClient *client,
 		ep_set_proxy (proxy, FALSE);
 		d(g_print ("e-proxy.c:ep_settings_changed: https\n"));
 	} else if (g_str_equal (key, KEY_GCONF_EVO_SOCKS_HOST) ||
-		   g_str_equal (key, KEY_GCONF_EVO_SOCKS_PORT) ||
-		   g_str_equal (key, KEY_GCONF_EVO_AUTOCONFIG_URL)) {
+		   g_str_equal (key, KEY_GCONF_EVO_SOCKS_PORT)) {
+
+		ep_set_proxy (proxy, FALSE);
+		d(g_print ("e-proxy.c:ep_settings_changed: socks\n"));
+	} else if (g_str_equal (key, KEY_GCONF_EVO_AUTOCONFIG_URL)) {
 
 		/* ep_set_proxy (proxy, FALSE); */
 		d(g_print ("e-proxy.c:ep_settings_changed: socks/autoconf-url changed\n"));
@@ -924,6 +952,9 @@ e_proxy_dispose (GObject *object)
 	if (priv->uri_https)
 		soup_uri_free (priv->uri_https);
 
+	if (priv->uri_socks)
+		soup_uri_free (priv->uri_socks);
+
 	g_slist_foreach (priv->ign_hosts, (GFunc) g_free, NULL);
 	g_slist_free (priv->ign_hosts);
 
@@ -1045,10 +1076,16 @@ e_proxy_peek_uri_for (EProxy *proxy,
 	if (soup_uri == NULL)
 		return NULL;
 
+	if (soup_uri->scheme == SOUP_URI_SCHEME_HTTP)
+		return proxy->priv->uri_http;
+
 	if (soup_uri->scheme == SOUP_URI_SCHEME_HTTPS)
 		return proxy->priv->uri_https;
 
-	return proxy->priv->uri_http;
+	if (soup_uri->scheme && g_ascii_strcasecmp (soup_uri->scheme, "socks") == 0)
+		return proxy->priv->uri_socks;
+
+	return NULL;
 }
 
 /**
@@ -1075,10 +1112,12 @@ e_proxy_require_proxy_for_uri (EProxy *proxy,
 	if (soup_uri == NULL)
 		return FALSE;
 
-	if (soup_uri->scheme == SOUP_URI_SCHEME_HTTPS)
-		need_proxy = ep_need_proxy_https (proxy, soup_uri->host);
-	else
+	if (soup_uri->scheme == SOUP_URI_SCHEME_HTTP)
 		need_proxy = ep_need_proxy_http (proxy, soup_uri->host);
+	else if (soup_uri->scheme == SOUP_URI_SCHEME_HTTPS)
+		need_proxy = ep_need_proxy_https (proxy, soup_uri->host);
+	else if (soup_uri->scheme && g_ascii_strcasecmp (soup_uri->scheme, "socks") == 0)
+		need_proxy = ep_need_proxy_socks (proxy, soup_uri->host);
 
 	soup_uri_free (soup_uri);
 
