diff --git a/mail/em-account-editor.c b/mail/em-account-editor.c
index 0c2e274..9e6a900 100644
--- a/mail/em-account-editor.c
+++ b/mail/em-account-editor.c
@@ -56,6 +56,7 @@
 #include "e-util/e-signature-utils.h"
 #include "e-util/e-util-private.h"
 #include "widgets/misc/e-signature-editor.h"
+#include "widgets/misc/e-portentry.h"
 
 #include "e-mail-local.h"
 #include "e-mail-session.h"
@@ -106,6 +107,8 @@ typedef struct _EMAccountEditorService {
 	GtkLabel *description;
 	GtkLabel *hostlabel;
 	GtkEntry *hostname;
+	GtkLabel *portlabel;
+	EPortEntry *port;
 	GtkLabel *userlabel;
 	GtkEntry *username;
 	GtkEntry *path;
@@ -1228,28 +1231,23 @@ smime_encrypt_key_clear (GtkWidget *w, EMAccountEditor *emae)
 #endif
 
 static void
-emae_url_set_hostport (CamelURL *url, const gchar *txt)
+emae_url_set_host (CamelURL *url, const gchar *txt)
 {
-	const gchar *port;
 	gchar *host;
 
-	/* FIXME: what if this was a raw IPv6 address? */
-	if (txt && (port = strchr (txt, ':'))) {
-		camel_url_set_port (url, atoi (port+1));
+	if (txt && *txt) {
 		host = g_strdup (txt);
-		host[port-txt] = 0;
-	} else {
-		/* "" is converted to NULL, but if we set NULL on the url,
-		   camel_url_to_string strips lots of details */
-		host = g_strdup ((txt?txt:""));
-		camel_url_set_port (url, 0);
-	}
-
-	g_strstrip (host);
-	if (txt && *txt)
+		g_strstrip (host);
 		camel_url_set_host (url, host);
+		g_free (host);
+	}
+}
 
-	g_free (host);
+static void
+emae_url_set_port (CamelURL *url, const gchar *port)
+{
+	if (port && *port)
+		camel_url_set_port (url, atoi (port));
 }
 
 /* This is used to map a funciton which will set on the url a string value.
@@ -1262,7 +1260,8 @@ struct _provider_host_info {
 };
 
 static struct _provider_host_info emae_source_host_info[] = {
-	{ CAMEL_URL_PART_HOST, emae_url_set_hostport, { G_STRUCT_OFFSET (EMAccountEditorService, hostname), G_STRUCT_OFFSET (EMAccountEditorService, hostlabel), }, },
+	{ CAMEL_URL_PART_HOST, emae_url_set_host, { G_STRUCT_OFFSET (EMAccountEditorService, hostname), G_STRUCT_OFFSET (EMAccountEditorService, hostlabel), }, },
+	{ CAMEL_URL_PART_HOST, emae_url_set_port,  { G_STRUCT_OFFSET (EMAccountEditorService, port), G_STRUCT_OFFSET (EMAccountEditorService, portlabel), }, },
 	{ CAMEL_URL_PART_USER, camel_url_set_user, { G_STRUCT_OFFSET (EMAccountEditorService, username), G_STRUCT_OFFSET (EMAccountEditorService, userlabel), } },
 	{ CAMEL_URL_PART_PATH, camel_url_set_path, { G_STRUCT_OFFSET (EMAccountEditorService, path), G_STRUCT_OFFSET (EMAccountEditorService, pathlabel), G_STRUCT_OFFSET (EMAccountEditorService, pathentry) }, },
 	{ CAMEL_URL_PART_AUTH, NULL, { 0, G_STRUCT_OFFSET (EMAccountEditorService, auth_frame), }, },
@@ -1270,7 +1269,8 @@ static struct _provider_host_info emae_source_host_info[] = {
 };
 
 static struct _provider_host_info emae_transport_host_info[] = {
-	{ CAMEL_URL_PART_HOST, emae_url_set_hostport, { G_STRUCT_OFFSET (EMAccountEditorService, hostname), G_STRUCT_OFFSET (EMAccountEditorService, hostlabel), }, },
+	{ CAMEL_URL_PART_HOST, emae_url_set_host, { G_STRUCT_OFFSET (EMAccountEditorService, hostname), G_STRUCT_OFFSET (EMAccountEditorService, hostlabel), }, },
+	{ CAMEL_URL_PART_HOST, emae_url_set_port, { G_STRUCT_OFFSET (EMAccountEditorService, port), G_STRUCT_OFFSET (EMAccountEditorService, portlabel), }, },
 	{ CAMEL_URL_PART_USER, camel_url_set_user, { G_STRUCT_OFFSET (EMAccountEditorService, username), G_STRUCT_OFFSET (EMAccountEditorService, userlabel), } },
 	{ CAMEL_URL_PART_AUTH, NULL, { 0, G_STRUCT_OFFSET (EMAccountEditorService, auth_frame), }, },
 	{ 0 },
@@ -1291,6 +1291,8 @@ static struct _service_info {
 	const gchar *description;
 	const gchar *hostname;
 	const gchar *hostlabel;
+	const gchar *port;
+	const gchar *portlabel;
 	const gchar *username;
 	const gchar *userlabel;
 	const gchar *path;
@@ -1324,6 +1326,8 @@ static struct _service_info {
 	  "source_description",
 	  "source_host",
 	  "source_host_label",
+	  "source_port",
+	  "source_port_label",
 	  "source_user",
 	  "source_user_label",
 	  "source_path",
@@ -1355,6 +1359,8 @@ static struct _service_info {
 	  "transport_description",
 	  "transport_host",
 	  "transport_host_label",
+	  "transport_port",
+	  "transport_port_label",
 	  "transport_user",
 	  "transport_user_label",
 	  NULL,
@@ -1399,16 +1405,23 @@ emae_uri_changed (EMAccountEditorService *service, CamelURL *url)
 }
 
 static void
-emae_service_url_changed (EMAccountEditorService *service, void (*setval)(CamelURL *, const gchar *), GtkEntry *entry)
+emae_service_url_changed (EMAccountEditorService *service, void (*setval)(CamelURL *, const gchar *), GtkWidget *entry)
 {
 	GtkComboBox *dropdown;
 	gint id;
 	GtkTreeModel *model;
 	GtkTreeIter iter;
 	CamelServiceAuthType *authtype;
+	gchar *text;
 
 	CamelURL *url = emae_account_url (service->emae, emae_service_info[service->type].account_uri_key);
-	gchar *text = g_strdup (gtk_entry_get_text (entry));
+
+	if (GTK_IS_ENTRY (entry))
+		text = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+	else if (E_IS_PORT_ENTRY (entry)) {
+		text = g_strdup_printf ("%i", e_port_entry_get_port (E_PORT_ENTRY (entry)));
+	} else
+		return;
 
 	g_strstrip (text);
 
@@ -1470,13 +1483,19 @@ emae_service_url_path_changed (EMAccountEditorService *service, void (*setval)(C
 static void
 emae_hostname_changed (GtkEntry *entry, EMAccountEditorService *service)
 {
-	emae_service_url_changed (service, emae_url_set_hostport, entry);
+	emae_service_url_changed (service, emae_url_set_host, GTK_WIDGET (entry));
+}
+
+static void
+emae_port_changed (EPortEntry *pentry, EMAccountEditorService *service)
+{
+	emae_service_url_changed (service, emae_url_set_port, GTK_WIDGET (pentry));
 }
 
 static void
 emae_username_changed (GtkEntry *entry, EMAccountEditorService *service)
 {
-	emae_service_url_changed (service, camel_url_set_user, entry);
+	emae_service_url_changed (service, camel_url_set_user, GTK_WIDGET (entry));
 }
 
 static void
@@ -1501,7 +1520,11 @@ emae_ssl_update (EMAccountEditorService *service, CamelURL *url)
 		gtk_tree_model_get (model, &iter, 1, &ssl, -1);
 		if (!strcmp (ssl, "none"))
 			ssl = NULL;
+
+		e_port_entry_security_port_changed (service->port, ssl);
+
 		camel_url_set_param (url, "use_ssl", ssl);
+		camel_url_set_port (url, e_port_entry_get_port (service->port));
 		return 1;
 	}
 
@@ -1523,6 +1546,7 @@ emae_service_provider_changed (EMAccountEditorService *service)
 {
 	EAccount *account;
 	gint i, j;
+	gint old_port;
 	void (*show)(GtkWidget *);
 	CamelURL *url = emae_account_url (service->emae, emae_service_info[service->type].account_uri_key);
 
@@ -1548,6 +1572,9 @@ emae_service_provider_changed (EMAccountEditorService *service)
 		enable = e_account_writable (account, emae_service_info[service->type].save_passwd_key);
 		gtk_widget_set_sensitive ((GtkWidget *)service->remember, enable);
 
+		if (service->port && service->provider->port_entries)
+			e_port_entry_set_camel_entries (service->port, service->provider->port_entries);
+
 		for (i=0;emae_service_info[service->type].host_info[i].flag;i++) {
 			GtkWidget *w;
 			gint hide;
@@ -1564,8 +1591,13 @@ emae_service_provider_changed (EMAccountEditorService *service)
 						if (dwidget == NULL && enable)
 							dwidget = w;
 
-						if (info->setval && !hide)
-							info->setval (url, enable?gtk_entry_get_text ((GtkEntry *)w):NULL);
+						if (info->setval && !hide) {
+							if (GTK_IS_ENTRY (w))
+								info->setval (url, enable?gtk_entry_get_text ((GtkEntry *)w):NULL);
+							else if (E_IS_PORT_ENTRY (w))
+								info->setval (url, enable?g_strdup_printf("%i",
+											e_port_entry_get_port (E_PORT_ENTRY (w))):NULL);
+						}
 					}
 				}
 			}
@@ -1598,6 +1630,7 @@ emae_service_provider_changed (EMAccountEditorService *service)
 				gtk_widget_hide ((GtkWidget *)service->needs_auth);
 		}
 #ifdef HAVE_SSL
+		old_port = url->port;
 		gtk_widget_hide (service->no_ssl);
 		if (service->provider->flags & CAMEL_PROVIDER_SUPPORTS_SSL) {
 			emae_ssl_update (service, url);
@@ -1613,6 +1646,13 @@ emae_service_provider_changed (EMAccountEditorService *service)
 		gtk_widget_show (service->no_ssl);
 		camel_url_set_param (url, "use_ssl", NULL);
 #endif
+
+		/* This must be done AFTER use_ssl is set; changing use_ssl overwrites
+		   the old port, which could be SSL port, but also could be some special
+		   port and we would otherwise lost it */
+		if (url->port)
+			e_port_entry_set_port (service->port, old_port);
+
 	} else {
 		camel_url_set_protocol (url, NULL);
 		gtk_label_set_text (service->description, "");
@@ -1982,6 +2022,8 @@ emae_setup_service (EMAccountEditor *emae, EMAccountEditorService *service, GtkB
 	service->description = GTK_LABEL (e_builder_get_widget (builder, info->description));
 	service->hostname = GTK_ENTRY (e_builder_get_widget (builder, info->hostname));
 	service->hostlabel = (GtkLabel *)e_builder_get_widget (builder, info->hostlabel);
+	service->port = E_PORT_ENTRY (e_builder_get_widget (builder, info->port));
+	service->portlabel = (GtkLabel *)e_builder_get_widget (builder, info->portlabel);
 	service->username = GTK_ENTRY (e_builder_get_widget (builder, info->username));
 	service->userlabel = (GtkLabel *)e_builder_get_widget (builder, info->userlabel);
 	if (info->pathentry) {
@@ -1997,17 +2039,17 @@ emae_setup_service (EMAccountEditor *emae, EMAccountEditorService *service, GtkB
 
 	/* configure ui for current settings */
 	if (url->host) {
-		if (url->port) {
-			gchar *host = g_strdup_printf ("%s:%d", url->host, url->port);
-
-			gtk_entry_set_text (service->hostname, host);
-			g_free (host);
-		} else
-			gtk_entry_set_text (service->hostname, url->host);
+		gtk_entry_set_text (service->hostname, url->host);
 	}
+
 	if (url->user && *url->user) {
 		gtk_entry_set_text (service->username, url->user);
 	}
+
+	if (url->port) {
+		e_port_entry_set_port (service->port, url->port);
+	}
+
 	if (service->pathentry) {
 		GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
 
@@ -2033,6 +2075,7 @@ emae_setup_service (EMAccountEditor *emae, EMAccountEditorService *service, GtkB
 	}
 
 	g_signal_connect (service->hostname, "changed", G_CALLBACK (emae_hostname_changed), service);
+	g_signal_connect (service->port, "changed", G_CALLBACK (emae_port_changed), service);
 	g_signal_connect (service->username, "changed", G_CALLBACK (emae_username_changed), service);
 	if (service->pathentry)
 		g_signal_connect (GTK_FILE_CHOOSER (service->pathentry), "selection-changed", G_CALLBACK (emae_path_changed), service);
@@ -3344,7 +3387,7 @@ emae_service_complete (EMAccountEditor *emae, EMAccountEditorService *service)
 		return FALSE;
 
 	if (CAMEL_PROVIDER_NEEDS (service->provider, CAMEL_URL_PART_HOST)) {
-		if (url->host == NULL || url->host[0] == 0)
+		if (url->host == NULL || url->host[0] == 0 || !(e_port_entry_is_valid (service->port))
 			ok = FALSE;
 	}
 	/* We only need the user if the service needs auth as well, i think */
diff --git a/mail/mail-config.ui b/mail/mail-config.ui
index 289b052..523c5da 100644
--- a/mail/mail-config.ui
+++ b/mail/mail-config.ui
@@ -625,7 +625,7 @@ For example: "Work" or "Personal"</property>
               <object class="GtkTable" id="source-config-table">
                 <property name="visible">True</property>
                 <property name="n_rows">3</property>
-                <property name="n_columns">2</property>
+                <property name="n_columns">4</property>
                 <property name="column_spacing">12</property>
                 <property name="row_spacing">6</property>
                 <child>
@@ -637,10 +637,29 @@ For example: "Work" or "Personal"</property>
                     <property name="mnemonic_widget">source_host</property>
                   </object>
                   <packing>
+                    <property name="top_attach">0</property>
+                    <property name="bottom_attach">1</property>
+                    <property name="left_attach">0</property>
                     <property name="x_options">GTK_FILL</property>
                     <property name="y_options"></property>
                   </packing>
                 </child>
+		<child>
+		  <object class="GtkLabel" id="source_port_label">
+		    <property name="visible">True</property>
+		    <property name="xalign">1</property>
+		    <property name="label">_Port:</property>
+		    <property name="use_underline">True</property>
+		    <property name="mnemonic_widget">source_port</property>
+		  </object>
+		  <packing>
+                    <property name="top_attach">0</property>
+                    <property name="bottom_attach">1</property>
+                    <property name="left_attach">2</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+		  </packing>
+		</child>
                 <child>
                   <object class="GtkLabel" id="source_user_label">
                     <property name="visible">True</property>
@@ -651,7 +670,6 @@ For example: "Work" or "Personal"</property>
                   </object>
                   <packing>
                     <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
                     <property name="x_options">GTK_FILL</property>
                     <property name="y_options"></property>
                   </packing>
@@ -664,8 +682,20 @@ For example: "Work" or "Personal"</property>
                   </object>
                   <packing>
                     <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="y_options"></property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="EPortEntry" type-func="e_port_entry_get_type" id="source_port">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="has-entry">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">3</property>
+                    <property name="top_attach">0</property>
+                    <property name="x_options"></property>
+                    <property name="y_options"></property>		    
                   </packing>
                 </child>
                 <child>
@@ -676,7 +706,7 @@ For example: "Work" or "Personal"</property>
                   </object>
                   <packing>
                     <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
+                    <property name="right_attach">4</property>
                     <property name="top_attach">1</property>
                     <property name="bottom_attach">2</property>
                     <property name="y_options"></property>
@@ -1053,7 +1083,7 @@ For example: "Work" or "Personal"</property>
               <object class="GtkTable" id="transport-server-table">
                 <property name="visible">True</property>
                 <property name="n_rows">2</property>
-                <property name="n_columns">2</property>
+                <property name="n_columns">4</property>
                 <property name="column_spacing">12</property>
                 <property name="row_spacing">6</property>
                 <child>
@@ -1062,7 +1092,6 @@ For example: "Work" or "Personal"</property>
                     <property name="xalign">1</property>
                     <property name="label" translatable="yes">_Server:</property>
                     <property name="use_underline">True</property>
-                    <property name="justify">right</property>
                     <property name="mnemonic_widget">transport_host</property>
                   </object>
                   <packing>
@@ -1071,6 +1100,20 @@ For example: "Work" or "Personal"</property>
                   </packing>
                 </child>
                 <child>
+                  <object class="GtkLabel" id="transport_port_label">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">_Port:</property>
+                    <property name="use_underline">True</property>
+                    <property name="justify">right</property>
+                    <property name="mnemonic_widget">transport_port</property>
+                  </object>
+                  <packing>
+                    <property name="left-attach">2</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
                   <object class="GtkEntry" id="transport_host">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
@@ -1083,6 +1126,18 @@ For example: "Work" or "Personal"</property>
                   </packing>
                 </child>
                 <child>
+                  <object class="EPortEntry" type-func="e_port_entry_get_type" id="transport_port">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="has-entry">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">3</property>
+                    <property name="x_options"></property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
                   <object class="GtkCheckButton" id="transport_needs_auth">
                     <property name="label" translatable="yes">Ser_ver requires authentication</property>
                     <property name="visible">True</property>
@@ -1092,6 +1147,7 @@ For example: "Work" or "Personal"</property>
                     <property name="draw_indicator">True</property>
                   </object>
                   <packing>
+                    <property name="left_attach">1</property>
                     <property name="right_attach">2</property>
                     <property name="top_attach">1</property>
                     <property name="bottom_attach">2</property>
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index 7e9ce9c..774cc9d 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -47,6 +47,7 @@ widgetsinclude_HEADERS =			\
 	e-picture-gallery.h			\
 	e-popup-action.h			\
 	e-popup-menu.h				\
+	e-portentry.h				\
 	e-preferences-window.h			\
 	e-preview-pane.h			\
 	e-printable.h				\
@@ -126,6 +127,7 @@ libemiscwidgets_la_SOURCES =			\
 	e-picture-gallery.c			\
 	e-popup-action.c			\
 	e-popup-menu.c				\
+	e-portentry.c				\
 	e-preferences-window.c			\
 	e-preview-pane.c			\
 	e-printable.c				\
diff --git a/widgets/misc/e-portentry.c b/widgets/misc/e-portentry.c
index e69de29..adfb314 100644
--- a/widgets/misc/e-portentry.c
+++ b/widgets/misc/e-portentry.c
@@ -0,0 +1,460 @@
+/*
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Authors:
+ *	Dan Vratil <dvratil@redhat.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stddef.h>
+#include <glib.h>
+#include <string.h>
+
+#include "e-portentry.h"
+
+struct _EPortEntryPrivate {
+	guint port;
+	gboolean is_valid;
+};
+
+enum {
+	PORT_NUM_COLUMN,
+	PORT_DESC_COLUMN,
+	PORT_IS_SSL_COLUMN
+};
+
+enum {
+	PROP_0,
+	PROP_IS_VALID,
+	PROP_PORT
+};
+
+G_DEFINE_TYPE (
+	EPortEntry,
+	e_port_entry,
+	GTK_TYPE_COMBO_BOX)
+
+
+static void port_entry_get_preferred_width	(GtkWidget *widget, gint *minimum_size, gint *natural_size);
+
+static void port_entry_dispose			(GObject *object);
+
+static GObject* port_entry_constructor		(GType type, guint n_construct_properties, GObjectConstructParam *construct_properties);
+
+static void port_entry_finalize 		(GObject *object);
+
+static void port_entry_set_property 		(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
+
+static void port_entry_get_property 		(GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
+
+static void port_entry_port_changed		(EPortEntry *pentry);
+
+static void port_entry_set_is_valid 		(EPortEntry *pentry, gboolean is_valid);
+
+/**
+ * Returns number of port currently selected in the widget, no matter
+ * what value is in the PORT property
+ */
+static gint port_entry_get_model_active_port	(EPortEntry *pentry);
+
+
+
+static void
+port_entry_get_preferred_width (GtkWidget *widget, gint *minimum_size, gint *natural_size)
+{
+  	PangoContext *context;
+  	PangoFontMetrics *metrics;
+  	PangoFontDescription *font_desc;
+	GtkStyleContext	*style_context;
+	GtkStateFlags state;
+  	gint digit_width;
+	gint parent_entry_width_min;
+	gint parent_width_min;
+	GtkWidget *entry;
+
+  	style_context = gtk_widget_get_style_context (widget);
+  	state = gtk_widget_get_state_flags (widget);
+  	gtk_style_context_get (style_context, state,
+        	               "font", &font_desc,
+                               NULL);
+  	context = gtk_widget_get_pango_context (GTK_WIDGET (widget));
+  	metrics = pango_context_get_metrics (context, font_desc,
+        	                             pango_context_get_language (context));
+
+
+        digit_width = PANGO_PIXELS (pango_font_metrics_get_approximate_digit_width (metrics));
+
+	/* Preferred width of the entry */
+   	entry = gtk_bin_get_child (GTK_BIN (widget));
+  	gtk_widget_get_preferred_width (entry, NULL, &parent_entry_width_min);
+
+	/* Preferred width of a standard combobox */
+	GTK_WIDGET_CLASS (e_port_entry_parent_class)->get_preferred_width (widget, &parent_width_min, NULL);
+
+	/* 6*digit_width - port number has max 5 digits + extra free space for better look */
+  	if (minimum_size)
+    		*minimum_size = parent_width_min - parent_entry_width_min + 6*digit_width;
+
+	if (natural_size)
+    		*natural_size = parent_width_min - parent_entry_width_min + 6*digit_width;
+
+
+    	pango_font_metrics_unref (metrics);
+  	pango_font_description_free (font_desc);
+}
+
+static void
+port_entry_dispose (GObject *object)
+{
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_port_entry_parent_class)->dispose (object);
+}
+
+static GObject*
+port_entry_constructor (GType type,
+			guint n_construct_properties,
+			GObjectConstructParam *construct_properties)
+{
+	GObject *object;
+	GObjectClass *parent_class;
+	parent_class = G_OBJECT_CLASS (e_port_entry_parent_class);
+	object = parent_class->constructor (
+		type, n_construct_properties, construct_properties);
+
+	return object;
+}
+
+static void
+port_entry_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (e_port_entry_parent_class)->finalize (object);
+}
+
+static void
+port_entry_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_IS_VALID:
+			port_entry_set_is_valid (E_PORT_ENTRY (object),
+					      	 g_value_get_boolean (value));
+			return;
+		case PROP_PORT:
+			e_port_entry_set_port (E_PORT_ENTRY (object),
+					       g_value_get_uint (value));
+			return;
+	}
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+port_entry_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_IS_VALID:
+			g_value_set_boolean (value,
+					     e_port_entry_is_valid (E_PORT_ENTRY (object)));
+			return;
+		case PROP_PORT:
+			g_value_set_uint (value,
+				 	  e_port_entry_get_port (E_PORT_ENTRY (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+port_entry_port_changed (EPortEntry *pentry)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	const gchar *port;
+
+	g_return_if_fail (E_IS_PORT_ENTRY (pentry));
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (pentry));
+	g_return_if_fail (model);
+
+	if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (pentry), &iter)) {
+		GtkWidget *entry = gtk_bin_get_child (GTK_BIN (pentry));
+		port = gtk_entry_get_text (GTK_ENTRY (entry));
+	} else {
+		gtk_tree_model_get (model, &iter, PORT_NUM_COLUMN, &port, -1);
+	}
+
+	if (!port || !*port) {
+		pentry->priv->port = 0;
+		port_entry_set_is_valid (pentry, FALSE);
+	} else if (atoi (port) <= 0) {
+		pentry->priv->port = 0;
+		port_entry_set_is_valid (pentry, FALSE);
+	} else {
+		pentry->priv->port = atoi (port);
+		port_entry_set_is_valid (pentry, TRUE);
+	}
+
+	g_object_notify (G_OBJECT (pentry), "port");
+}
+
+static void
+port_entry_set_is_valid (EPortEntry *pentry, gboolean is_valid)
+{
+	g_return_if_fail (E_IS_PORT_ENTRY (pentry));
+
+	pentry->priv->is_valid = is_valid;
+}
+
+static gint
+port_entry_get_model_active_port (EPortEntry *pentry)
+{
+	const gchar *port;
+
+	port = gtk_combo_box_get_active_id (GTK_COMBO_BOX (pentry));
+
+	if (!port) {
+		GtkWidget *entry = gtk_bin_get_child (GTK_BIN (pentry));
+		port = gtk_entry_get_text (GTK_ENTRY (entry));
+	}
+
+	return atoi (port);
+}
+
+static void
+e_port_entry_class_init (EPortEntryClass *klass)
+{
+	GObjectClass *object_class;
+	GtkWidgetClass *widget_class;
+
+	g_type_class_add_private (klass, sizeof (EPortEntryPrivate));
+
+	object_class = G_OBJECT_CLASS (klass);
+	object_class->dispose = port_entry_dispose;
+	object_class->constructor = port_entry_constructor;
+	object_class->finalize = port_entry_finalize;
+	object_class->set_property = port_entry_set_property;
+	object_class->get_property = port_entry_get_property;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_IS_VALID,
+		g_param_spec_boolean (
+			"is_valid",
+			NULL,
+			NULL,
+			FALSE,
+			G_PARAM_READABLE));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_PORT,
+		g_param_spec_uint (
+			"port",
+			NULL,
+			NULL,
+			0,		/* Min port, 0 = invalid port */
+			G_MAXUINT16,	/* Max port */
+			0,
+			G_PARAM_READWRITE));
+
+	widget_class = (GtkWidgetClass *)klass;
+	widget_class->get_preferred_width = port_entry_get_preferred_width;
+}
+
+static void
+e_port_entry_init (EPortEntry *pentry)
+{
+	GtkCellRenderer *renderer;
+	GtkTreeModel *model = GTK_TREE_MODEL (gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN));
+
+	pentry->priv = G_TYPE_INSTANCE_GET_PRIVATE ((pentry), E_TYPE_PORT_ENTRY, EPortEntryPrivate);
+	pentry->priv->port = 0;
+	pentry->priv->is_valid = FALSE;
+
+	gtk_combo_box_set_model (GTK_COMBO_BOX (pentry), model);
+	gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (pentry), PORT_NUM_COLUMN);
+	gtk_combo_box_set_id_column (GTK_COMBO_BOX (pentry), PORT_NUM_COLUMN);
+
+	renderer = gtk_cell_renderer_text_new();
+	gtk_cell_renderer_set_sensitive (renderer, TRUE);
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (pentry), renderer, FALSE);
+	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (pentry), renderer, "text", PORT_NUM_COLUMN);
+
+	renderer = gtk_cell_renderer_text_new();
+	gtk_cell_renderer_set_sensitive (renderer, TRUE);
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (pentry), renderer, TRUE);
+	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (pentry), renderer, "text", PORT_DESC_COLUMN);
+
+	/* Update the port property when port is changed */
+	g_signal_connect (pentry, "changed", G_CALLBACK (port_entry_port_changed), NULL);
+}
+
+GtkWidget *
+e_port_entry_new (void)
+{
+	EPortEntry *pentry;
+
+	pentry = g_object_new (E_TYPE_PORT_ENTRY,
+			       "has-entry", TRUE,
+			       NULL);
+
+	return GTK_WIDGET (pentry);
+}
+
+void
+e_port_entry_set_camel_entries (EPortEntry *pentry, CamelProviderPortEntry *entries)
+{
+	GtkTreeIter iter;
+	GtkListStore *store;
+	gint i = 0;
+
+	g_return_if_fail (E_IS_PORT_ENTRY (pentry));
+	g_return_if_fail (entries);
+
+	store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (pentry)));
+	g_return_if_fail (store);
+
+	gtk_list_store_clear (store);
+
+	while (entries[i].port > 0)
+	{
+		gtk_list_store_append (store, &iter);
+		gtk_list_store_set (store, &iter,
+				    PORT_NUM_COLUMN, g_strdup_printf ("%i", entries[i].port),
+				    PORT_DESC_COLUMN, entries[i].desc,
+				    PORT_IS_SSL_COLUMN, entries[i].is_ssl,
+				    -1);
+		i++;
+	}
+
+	/* Activate the first port */
+	if (i>0)
+		e_port_entry_set_port (pentry, entries[0].port);
+}
+
+void
+e_port_entry_security_port_changed (EPortEntry *pentry, gchar *ssl)
+{
+	g_return_if_fail (E_IS_PORT_ENTRY (pentry));
+
+	if (!strcmp (ssl, "always")) {
+		e_port_entry_activate_secured_port (pentry, 0);
+	} else {
+		e_port_entry_activate_nonsecured_port (pentry, 0);
+	}
+}
+
+gint
+e_port_entry_get_port (EPortEntry *pentry)
+{
+	g_return_val_if_fail (E_IS_PORT_ENTRY (pentry), 0);
+
+	return pentry->priv->port;
+}
+
+void
+e_port_entry_set_port (EPortEntry *pentry, gint port)
+{
+	g_return_if_fail (E_IS_PORT_ENTRY (pentry));
+
+	pentry->priv->port = port;
+	if (port <= 0)
+		port_entry_set_is_valid (pentry, FALSE);
+	else {
+		gtk_combo_box_set_active_id (GTK_COMBO_BOX (pentry), g_strdup_printf ("%i", port));
+
+		if (port_entry_get_model_active_port (pentry) != port) {
+			GtkWidget *entry = gtk_bin_get_child (GTK_BIN (pentry));
+			gtk_entry_set_text (GTK_ENTRY (entry), g_strdup_printf ("%i", port));
+		}
+		port_entry_set_is_valid (pentry, TRUE);
+	}
+
+	g_object_notify (G_OBJECT (pentry), "port");
+}
+
+gboolean
+e_port_entry_is_valid (EPortEntry *pentry)
+{
+	g_return_val_if_fail (E_IS_PORT_ENTRY (pentry), FALSE);
+
+	return pentry->priv->is_valid;
+}
+
+/**
+ * If there are more then one secured port in the model, you can specify
+ * which of the secured ports should be activated by specifying the index.
+ * The index counts only for secured ports, so if you have 5 ports of which
+ * ports 1, 3 and 5 are secured, the association is 0=>1, 1=>3, 2=>5
+ */
+void
+e_port_entry_activate_secured_port (EPortEntry *pentry, gint index)
+{
+	gint iters = 0;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gboolean is_ssl;
+
+	g_return_if_fail (E_IS_PORT_ENTRY (pentry));
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (pentry));
+
+
+	if (!gtk_tree_model_get_iter_first (model, &iter))
+		return;
+
+	do {
+		gtk_tree_model_get (model, &iter, PORT_IS_SSL_COLUMN, &is_ssl, -1);
+		if (is_ssl && (iters == index)) {
+			gtk_combo_box_set_active_iter (GTK_COMBO_BOX (pentry), &iter);
+			return;
+		}
+
+		if (is_ssl)
+			iters++;
+
+	} while (gtk_tree_model_iter_next (model, &iter));
+}
+
+/**
+ * If there are more then one unsecured port in the model, you can specify
+ * which of the unsecured ports should be activated by specifiying the index.
+ * THe index counts only for unsecured ports, so if you have 5 ports, of which
+ * ports 2 and 4 are unsecured, the associtation is 0=>2, 1=>4
+ */
+void
+e_port_entry_activate_nonsecured_port (EPortEntry *pentry, gint index)
+{
+	gint iters = 0;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gboolean is_ssl;
+
+	g_return_if_fail (E_IS_PORT_ENTRY (pentry));
+
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (pentry));
+
+	if (!gtk_tree_model_get_iter_first (model, &iter))
+		return;
+
+	do {
+		gtk_tree_model_get (model, &iter, PORT_IS_SSL_COLUMN, &is_ssl, -1);
+		if (!is_ssl && (iters == index)) {
+			gtk_combo_box_set_active_iter (GTK_COMBO_BOX (pentry), &iter);
+			return;
+		}
+
+		if (!is_ssl)
+			iters++;
+
+	} while (gtk_tree_model_iter_next (model, &iter));
+}
diff --git a/widgets/misc/e-portentry.h b/widgets/misc/e-portentry.h
index e69de29..5da7ab5 100644
--- a/widgets/misc/e-portentry.h
+++ b/widgets/misc/e-portentry.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ * Authors:
+ *	Dan Vratil <dvratil@redhat.com>
+ */
+
+#ifndef __E_PORT_ENTRY_H_
+#define __E_PORT_ENTRY_H_
+
+#include <gtk/gtk.h>
+#include <camel/camel.h>
+
+#define E_TYPE_PORT_ENTRY            (e_port_entry_get_type ())
+#define E_PORT_ENTRY(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_PORT_ENTRY, EPortEntry))
+#define E_PORT_ENTRY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_PORT_ENTRY, EPortEntryClass))
+#define E_IS_PORT_ENTRY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_PORT_ENTRY))
+#define E_IS_PORT_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_PORT_ENTRY))
+
+typedef struct _EPortEntry        EPortEntry;
+typedef struct _EPortEntryPrivate EPortEntryPrivate;
+typedef struct _EPortEntryClass   EPortEntryClass;
+
+struct _EPortEntry {
+	GtkComboBox parent;
+	EPortEntryPrivate *priv;
+};
+
+struct _EPortEntryClass {
+	GtkComboBoxClass parent_class;
+};
+
+GType      e_port_entry_get_type			(void);
+GtkWidget* e_port_entry_new				(void);
+
+void e_port_entry_set_camel_entries
+		(EPortEntry *pentry, CamelProviderPortEntry *entries);
+
+void e_port_entry_security_port_changed
+		(EPortEntry *pentry, gchar *ssl);
+
+gint e_port_entry_get_port 				(EPortEntry *pentry);
+
+void e_port_entry_set_port				(EPortEntry *pentry, gint port);
+
+gboolean e_port_entry_is_valid				(EPortEntry *pentry);
+
+void e_port_entry_activate_secured_port 		(EPortEntry *pentry, gint index);
+
+void e_port_entry_activate_nonsecured_port 		(EPortEntry *pentry, gint index);
+
+#endif
