diff --git a/camel/camel-provider.h b/camel/camel-provider.h
index 2ffc172..0eb335e 100644
--- a/camel/camel-provider.h
+++ b/camel/camel-provider.h
@@ -69,6 +69,8 @@ extern gchar *camel_provider_type_name[CAMEL_NUM_PROVIDER_TYPES];
 #define CAMEL_PROVIDER_SUPPORTS_SSL	(1 << 5)
 #define CAMEL_PROVIDER_HAS_LICENSE      (1 << 6)
 #define CAMEL_PROVIDER_DISABLE_SENT_FOLDER (1 << 7)
+#define CAMEL_PROVIDER_ALLOW_REAL_TRASH_FOLDER (1 << 8)
+#define CAMEL_PROVIDER_ALLOW_REAL_JUNK_FOLDER  (1 << 9)
 
 /* Flags for url_flags. "ALLOW" means the config dialog will let the
  * user configure it. "NEED" implies "ALLOW" but means the user must
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index 57c3e36..daa0ebf 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -121,6 +121,12 @@ static CamelImapMessageInfo * imap_folder_summary_uid_or_error(
 	const gchar * uid,
 	CamelException *ex);
 
+static gboolean
+imap_transfer_messages (CamelFolder *source, GPtrArray *uids,
+			CamelFolder *dest, GPtrArray **transferred_uids,
+			gboolean delete_originals, CamelException *ex,
+			gboolean can_call_sync);
+
 #ifdef G_OS_WIN32
 /* The strtok() in Microsoft's C library is MT-safe (but still uses
  * only one buffer pointer per thread, but for the use of strtok_r()
@@ -259,7 +265,7 @@ camel_imap_folder_class_init (CamelImapFolderClass *class)
 	folder_class->get_quota_info = imap_get_quota_info;
 	folder_class->refresh_info = imap_refresh_info;
 	folder_class->expunge = imap_expunge;
-	folder_class->sync= imap_sync;
+	folder_class->sync = imap_sync;
 	folder_class->append_message = imap_append_online;
 	folder_class->sync_message = imap_sync_message;
 	folder_class->transfer_messages_to = imap_transfer_online;
@@ -395,6 +401,14 @@ camel_imap_folder_new (CamelStore *parent, const gchar *folder_name,
 	} else {
 		if ((imap_store->parameters & (IMAP_PARAM_FILTER_JUNK|IMAP_PARAM_FILTER_JUNK_INBOX)) == (IMAP_PARAM_FILTER_JUNK))
 			folder->folder_flags |= CAMEL_FOLDER_FILTER_JUNK;
+
+		if ((parent->flags & CAMEL_STORE_VTRASH) == 0 && imap_store->real_trash_path && g_ascii_strcasecmp (imap_store->real_trash_path, folder_name) == 0) {
+			folder->folder_flags |= CAMEL_FOLDER_IS_TRASH;
+		}
+
+		if ((parent->flags & CAMEL_STORE_VJUNK) == 0 && imap_store->real_junk_path && g_ascii_strcasecmp (imap_store->real_junk_path, folder_name) == 0) {
+			folder->folder_flags |= CAMEL_FOLDER_IS_JUNK;
+		}
 	}
 
 	imap_folder->search = camel_imap_search_new(folder_dir);
@@ -1245,7 +1259,7 @@ get_message_uid (CamelFolder *folder, CamelImapMessageInfo *info)
  * caller must free the infos, the array, and the set string.
  */
 static GPtrArray *
-get_matching (CamelFolder *folder, guint32 flags, guint32 mask, CamelMessageInfo *master_info, gchar **set, GPtrArray *summary)
+get_matching (CamelFolder *folder, guint32 flags, guint32 mask, CamelMessageInfo *master_info, gchar **set, GPtrArray *summary, GPtrArray *deleted_uids, GPtrArray *junked_uids)
 {
 	GPtrArray *matches;
 	CamelImapMessageInfo *info;
@@ -1343,6 +1357,12 @@ get_matching (CamelFolder *folder, guint32 flags, guint32 mask, CamelMessageInfo
 			}
 		}
 
+		if (deleted_uids && (info->info.flags & CAMEL_MESSAGE_DELETED) != 0) {
+			g_ptr_array_add (deleted_uids, (gpointer) camel_pstring_strdup (camel_message_info_uid (info)));
+		} else if (junked_uids && (info->info.flags & CAMEL_MESSAGE_JUNK) != 0) {
+			g_ptr_array_add (junked_uids, (gpointer) camel_pstring_strdup (camel_message_info_uid (info)));
+		}
+
 		g_ptr_array_add (matches, info);
 		/* Remove the uid from the list, to optimize*/
 		camel_pstring_free(summary->pdata[i]);
@@ -1414,6 +1434,26 @@ imap_sync_offline (CamelFolder *folder,
 	return TRUE;
 }
 
+static void
+move_messages (CamelFolder *src_folder, GPtrArray *uids, CamelFolder *des_folder, CamelException *ex)
+{
+	g_return_if_fail (src_folder != NULL);
+
+	/* it's OK to have these NULL */
+	if (!uids || uids->len == 0 || des_folder == NULL)
+		return;
+
+	/* moving to the same folder means expunge only */
+	if (src_folder != des_folder) {
+		/* do 'copy' to not be bothered with CAMEL_MESSAGE_DELETED again */
+		if (!imap_transfer_messages (src_folder, uids, des_folder, NULL, FALSE, ex, FALSE))
+			return;
+	}
+
+	if (!camel_exception_is_set (ex))
+		camel_imap_expunge_uids_only (src_folder, uids, ex);
+}
+
 static gboolean
 imap_sync (CamelFolder *folder,
            gboolean expunge,
@@ -1425,8 +1465,9 @@ imap_sync (CamelFolder *folder,
 	CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
 	gboolean success;
 	CamelException local_ex;
+	CamelFolder *real_trash = NULL, *real_junk = NULL;
 
-	GPtrArray *matches, *summary;
+	GPtrArray *matches, *summary, *deleted_uids = NULL, *junked_uids = NULL;
 	gchar *set, *flaglist, *uid;
 	gint i, j, max;
 
@@ -1455,6 +1496,53 @@ imap_sync (CamelFolder *folder,
 	camel_folder_sort_uids (folder, summary);
 	max = summary->len;
 
+	/* deleted_uids is NULL when not using real trash */
+	if (store->real_trash_path && *store->real_trash_path) {
+		if ((folder->folder_flags & CAMEL_FOLDER_IS_TRASH) != 0) {
+			/* syncing the trash, expunge deleted when found any */
+			real_trash = folder;
+			g_object_ref (real_trash);
+		} else {
+			CamelException ex2;
+
+			camel_exception_init (&ex2);
+			real_trash = camel_store_get_trash (parent_store, &ex2);
+			camel_exception_clear (&ex2);
+
+			if (!store->real_trash_path && real_trash) {
+				/* failed to open real trash */
+				g_object_unref (real_trash);
+				real_trash = NULL;
+			}
+		}
+	}
+
+	if (real_trash)
+		deleted_uids = g_ptr_array_new ();
+
+	/* junked_uids is NULL when not using real junk */
+	if (store->real_junk_path && *store->real_junk_path) {
+		if ((folder->folder_flags & CAMEL_FOLDER_IS_JUNK) != 0) {
+			/* syncing the junk, but cannot move messages to itself, thus do nothing */
+			real_junk = NULL;
+		} else {
+			CamelException ex2;
+
+			camel_exception_init (&ex2);
+			real_junk = camel_store_get_junk (parent_store, &ex2);
+			camel_exception_clear (&ex2);
+
+			if (!store->real_junk_path && real_junk) {
+				/* failed to open real junk */
+				g_object_unref (real_junk);
+				real_junk = NULL;
+			}
+		}
+	}
+
+	if (real_junk)
+		junked_uids = g_ptr_array_new ();
+
 	for (i = 0; i < max; i++) {
 		gboolean unset = FALSE;
 		CamelImapResponse *response = NULL;
@@ -1479,7 +1567,8 @@ imap_sync (CamelFolder *folder,
 		   they will be scooped up later by our parent loop (I
 		   think?). -- Jeff */
 		matches = get_matching (folder, info->info.flags & (folder->permanent_flags | CAMEL_MESSAGE_FOLDER_FLAGGED),
-					folder->permanent_flags | CAMEL_MESSAGE_FOLDER_FLAGGED, (CamelMessageInfo *)info, &set, summary);
+					folder->permanent_flags | CAMEL_MESSAGE_FOLDER_FLAGGED, (CamelMessageInfo *)info, &set, summary,
+					deleted_uids, junked_uids);
 		if (matches == NULL) {
 			camel_message_info_free(info);
 			continue;
@@ -1492,6 +1581,11 @@ imap_sync (CamelFolder *folder,
 			break;
 		}
 
+		if (deleted_uids && (info->info.flags & CAMEL_MESSAGE_DELETED) != 0) {
+			/* there is a real trash, do not set it on the server */
+			info->info.flags &= ~CAMEL_MESSAGE_DELETED;
+		}
+
 		flaglist = imap_create_flag_list (info->info.flags & folder->permanent_flags, (CamelMessageInfo *)info, folder->permanent_flags);
 
 		if (strcmp (flaglist, "()") == 0) {
@@ -1539,6 +1633,11 @@ imap_sync (CamelFolder *folder,
 		if (!camel_exception_is_set (&local_ex)) {
 			for (j = 0; j < matches->len; j++) {
 				info = matches->pdata[j];
+				if (deleted_uids) {
+					/* there is a real trash, do not keep this set */
+					info->info.flags &= ~CAMEL_MESSAGE_DELETED;
+				}
+
 				info->info.flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
 				((CamelImapMessageInfo *) info)->server_flags =	info->info.flags & CAMEL_IMAP_SERVER_FLAGS;
 				info->info.dirty = TRUE; /* Sync it back to the DB */
@@ -1560,6 +1659,18 @@ imap_sync (CamelFolder *folder,
 		/* check for an exception */
 		if (camel_exception_is_set (&local_ex)) {
 			camel_exception_xfer (ex, &local_ex);
+			if (deleted_uids) {
+				g_ptr_array_foreach (deleted_uids, (GFunc) camel_pstring_free, NULL);
+				g_ptr_array_free (deleted_uids, TRUE);
+			}
+			if (junked_uids) {
+				g_ptr_array_foreach (junked_uids, (GFunc) camel_pstring_free, NULL);
+				g_ptr_array_free (junked_uids, TRUE);
+			}
+			if (real_trash)
+				g_object_unref (real_trash);
+			if (real_junk)
+				g_object_unref (real_junk);
 			return FALSE;
 		}
 
@@ -1567,7 +1678,27 @@ imap_sync (CamelFolder *folder,
 		camel_service_lock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 	}
 
-	if (expunge)
+	if (!camel_exception_is_set (ex))
+		move_messages (folder, deleted_uids, real_trash, &local_ex);
+	if (!camel_exception_is_set (&local_ex))
+		move_messages (folder, junked_uids, real_junk, &local_ex);
+	if (camel_exception_is_set (&local_ex))
+		camel_exception_xfer (ex, &local_ex);
+
+	if (deleted_uids) {
+		g_ptr_array_foreach (deleted_uids, (GFunc) camel_pstring_free, NULL);
+		g_ptr_array_free (deleted_uids, TRUE);
+	}
+	if (junked_uids) {
+		g_ptr_array_foreach (junked_uids, (GFunc) camel_pstring_free, NULL);
+		g_ptr_array_free (junked_uids, TRUE);
+	}
+	if (real_trash)
+		g_object_unref (real_trash);
+	if (real_junk)
+		g_object_unref (real_junk);
+
+	if (expunge && !camel_exception_is_set (ex))
 		imap_expunge (folder, ex);
 
 	g_ptr_array_foreach (summary, (GFunc) camel_pstring_free, NULL);
@@ -1735,7 +1866,7 @@ imap_expunge (CamelFolder *folder,
               CamelException *ex)
 {
 	CamelStore *parent_store;
-	GPtrArray *uids;
+	GPtrArray *uids = NULL;
 	const gchar *full_name;
 	gboolean success;
 
@@ -1743,7 +1874,25 @@ imap_expunge (CamelFolder *folder,
 	parent_store = camel_folder_get_parent_store (folder);
 
 	camel_folder_summary_save_to_db (folder->summary, ex);
-	uids = camel_db_get_folder_deleted_uids (parent_store->cdb_r, full_name, ex);
+
+	if ((parent_store->flags & CAMEL_STORE_VTRASH) == 0) {
+		CamelFolder *trash;
+		CamelException ex2;
+
+		camel_exception_init (&ex2);
+		trash = camel_store_get_trash (parent_store, &ex2);
+
+		if (!camel_exception_is_set (&ex2) && trash && (folder == trash || g_ascii_strcasecmp (full_name, camel_folder_get_full_name (trash)) == 0)) {
+			/* it's a real trash folder, thus get all mails from there */
+			uids = camel_folder_summary_array (folder->summary);
+		}
+
+		camel_exception_clear (&ex2);
+	}
+
+	if (!uids)
+		uids = camel_db_get_folder_deleted_uids (parent_store->cdb_r, full_name, ex);
+
 	if (!uids)
 		return TRUE;
 
@@ -1929,6 +2078,24 @@ camel_imap_expunge_uids_resyncing (CamelFolder *folder,
 	return TRUE;
 }
 
+void
+camel_imap_expunge_uids_only (CamelFolder *folder, GPtrArray *uids, CamelException *ex)
+{
+	CamelStore *parent_store;
+
+	g_return_if_fail (folder != NULL);
+
+	parent_store = camel_folder_get_parent_store (folder);
+	g_return_if_fail (parent_store != NULL);
+
+	g_return_if_fail (uids != NULL);
+
+	if (CAMEL_OFFLINE_STORE (parent_store)->state == CAMEL_OFFLINE_STORE_NETWORK_AVAIL)
+		camel_imap_expunge_uids_resyncing (folder, uids, ex);
+	else
+		imap_expunge_uids_offline (folder, uids, ex);
+}
+
 static gchar *
 get_temp_uid (void)
 {
@@ -2528,12 +2695,13 @@ do_copy (CamelFolder *source,
 }
 
 static gboolean
-imap_transfer_online (CamelFolder *source,
-                      GPtrArray *uids,
-                      CamelFolder *dest,
-                      GPtrArray **transferred_uids,
-                      gboolean delete_originals,
-                      CamelException *ex)
+imap_transfer_messages (CamelFolder *source,
+			GPtrArray *uids,
+			CamelFolder *dest,
+			GPtrArray **transferred_uids,
+			gboolean delete_originals,
+			CamelException *ex,
+			gboolean can_call_sync)
 {
 	CamelStore *parent_store;
 	CamelImapStore *store;
@@ -2549,7 +2717,7 @@ imap_transfer_online (CamelFolder *source,
 			delete_originals, ex);
 
 	/* Sync message flags if needed. */
-	if (!imap_sync (source, FALSE, ex))
+	if (can_call_sync && !imap_sync (source, FALSE, ex))
 		return FALSE;
 
 	count = camel_folder_summary_count (dest->summary);
@@ -2572,6 +2740,17 @@ imap_transfer_online (CamelFolder *source,
 	return success;
 }
 
+static gboolean
+imap_transfer_online (CamelFolder *source,
+                      GPtrArray *uids,
+                      CamelFolder *dest,
+                      GPtrArray **transferred_uids,
+                      gboolean delete_originals,
+                      CamelException *ex)
+{
+	return imap_transfer_messages (source, uids, dest, transferred_uids, delete_originals, ex, TRUE);
+}
+
 gboolean
 camel_imap_transfer_resyncing (CamelFolder *source,
                                GPtrArray *uids,
diff --git a/camel/providers/imap/camel-imap-folder.h b/camel/providers/imap/camel-imap-folder.h
index 60ce871..423e2be 100644
--- a/camel/providers/imap/camel-imap-folder.h
+++ b/camel/providers/imap/camel-imap-folder.h
@@ -113,6 +113,10 @@ gboolean	camel_imap_expunge_uids_resyncing
 						 GPtrArray *uids,
 						 CamelException *ex);
 
+void		camel_imap_expunge_uids_only	(CamelFolder *folder,
+						 GPtrArray *uids,
+						 CamelException *ex);
+
 G_END_DECLS
 
 #endif /* CAMEL_IMAP_FOLDER_H */
diff --git a/camel/providers/imap/camel-imap-provider.c b/camel/providers/imap/camel-imap-provider.c
index 90c6bd1..9cc1561 100644
--- a/camel/providers/imap/camel-imap-provider.c
+++ b/camel/providers/imap/camel-imap-provider.c
@@ -83,7 +83,8 @@ static CamelProvider imap_provider = {
 	"mail",
 
 	CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE |
-	CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL,
+	CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL |
+	CAMEL_PROVIDER_ALLOW_REAL_TRASH_FOLDER | CAMEL_PROVIDER_ALLOW_REAL_JUNK_FOLDER,
 
 	CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH,
 
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 8bfea3b..cbc3a24 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -140,6 +140,8 @@ imap_store_finalize (GObject *object)
 	g_free (imap_store->storage_path);
 	g_free (imap_store->users_namespace);
 	g_free (imap_store->custom_headers);
+	g_free (imap_store->real_trash_path);
+	g_free (imap_store->real_junk_path);
 
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (camel_imap_store_parent_class)->finalize (object);
@@ -255,6 +257,27 @@ construct (CamelService *service, CamelSession *session,
 		imap_store->custom_headers = g_strdup(camel_url_get_param (url, "imap_custom_headers"));
 	}
 
+	imap_store->real_trash_path = g_strdup (camel_url_get_param (url, "real_trash_path"));
+	imap_store->real_junk_path = g_strdup (camel_url_get_param (url, "real_junk_path"));
+
+	if (imap_store->real_trash_path && !*imap_store->real_trash_path) {
+		g_free (imap_store->real_trash_path);
+		imap_store->real_trash_path = NULL;
+	}
+
+	if (imap_store->real_trash_path && *imap_store->real_trash_path)
+		store->flags &= ~CAMEL_STORE_VTRASH;
+
+	if (imap_store->real_junk_path && !*imap_store->real_junk_path) {
+		g_free (imap_store->real_junk_path);
+		imap_store->real_junk_path = NULL;
+	}
+
+	if (imap_store->real_junk_path && *imap_store->real_junk_path) {
+		store->flags &= ~CAMEL_STORE_VJUNK;
+		store->flags |= CAMEL_STORE_REAL_JUNK_FOLDER;
+	}
+
 	/* setup/load the store summary */
 	tmp = alloca(strlen(imap_store->storage_path)+32);
 	sprintf(tmp, "%s/.ev-store-summary", imap_store->storage_path);
@@ -1548,7 +1571,29 @@ done:
 static CamelFolder *
 imap_get_trash(CamelStore *store, CamelException *ex)
 {
-	CamelFolder *folder = CAMEL_STORE_CLASS(camel_imap_store_parent_class)->get_trash(store, ex);
+	CamelFolder *folder = NULL;
+	CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
+
+	if (imap_store->real_trash_path && *imap_store->real_trash_path) {
+		CamelException ex2;
+
+		camel_exception_init (&ex2);
+
+		folder = camel_store_get_folder (store, imap_store->real_trash_path, 0, &ex2);
+		if (!folder) {
+			/* cannot find configured folder, just report on console and unset in a store structure to not try again */
+			g_print ("%s: Cannot open '%s': %s", G_STRFUNC, imap_store->real_trash_path, camel_exception_get_description (&ex2) ? camel_exception_get_description (&ex2) : "Unknown error.");
+			g_free (imap_store->real_trash_path);
+			imap_store->real_trash_path = NULL;
+		}
+
+		camel_exception_clear (&ex2);
+	}
+
+	if (folder)
+		return folder;
+
+	folder = CAMEL_STORE_CLASS(camel_imap_store_parent_class)->get_trash(store, ex);
 
 	if (folder) {
 		CamelObject *object = CAMEL_OBJECT (folder);
@@ -1566,7 +1611,29 @@ imap_get_trash(CamelStore *store, CamelException *ex)
 static CamelFolder *
 imap_get_junk(CamelStore *store, CamelException *ex)
 {
-	CamelFolder *folder = CAMEL_STORE_CLASS(camel_imap_store_parent_class)->get_junk(store, ex);
+	CamelFolder *folder = NULL;
+	CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
+
+	if (imap_store->real_junk_path && *imap_store->real_junk_path) {
+		CamelException ex2;
+
+		camel_exception_init (&ex2);
+
+		folder = camel_store_get_folder (store, imap_store->real_junk_path, 0, &ex2);
+		if (!folder) {
+			/* cannot find configured folder, just report on console and unset in a store structure to not try again */
+			g_print ("%s: Cannot open '%s': %s", G_STRFUNC, imap_store->real_junk_path, camel_exception_get_description (&ex2) ? camel_exception_get_description (&ex2) : "Unknown error.");
+			g_free (imap_store->real_junk_path);
+			imap_store->real_junk_path = NULL;
+		}
+
+		camel_exception_clear (&ex2);
+	}
+
+	if (folder)
+		return folder;
+
+	folder = CAMEL_STORE_CLASS(camel_imap_store_parent_class)->get_junk(store, ex);
 
 	if (folder) {
 		CamelObject *object = CAMEL_OBJECT (folder);
@@ -2846,6 +2913,18 @@ get_folder_info_offline (CamelStore *store, const gchar *top,
 			if (!g_ascii_strcasecmp(fi->full_name, "inbox"))
 				fi->flags = (fi->flags & ~CAMEL_FOLDER_TYPE_MASK) | CAMEL_FOLDER_TYPE_INBOX;
 
+			if ((fi->flags & CAMEL_FOLDER_TYPE_MASK) == 0 &&
+			    imap_store->real_trash_path && *imap_store->real_trash_path &&
+			    g_ascii_strcasecmp (fi->full_name, imap_store->real_trash_path) == 0) {
+				fi->flags = (fi->flags & ~CAMEL_FOLDER_TYPE_MASK) | CAMEL_FOLDER_TYPE_TRASH;
+			}
+
+			if ((fi->flags & CAMEL_FOLDER_TYPE_MASK) == 0 &&
+			    imap_store->real_junk_path && *imap_store->real_junk_path &&
+			    g_ascii_strcasecmp (fi->full_name, imap_store->real_junk_path) == 0) {
+				fi->flags = (fi->flags & ~CAMEL_FOLDER_TYPE_MASK) | CAMEL_FOLDER_TYPE_JUNK;
+			}
+
 			if (si->flags & CAMEL_FOLDER_NOSELECT) {
 				CamelURL *url = camel_url_new(fi->uri, NULL);
 
diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h
index a8b18a2..703e976 100644
--- a/camel/providers/imap/camel-imap-store.h
+++ b/camel/providers/imap/camel-imap-store.h
@@ -160,6 +160,8 @@ struct _CamelImapStore {
 
 	guint32 headers;
 	gchar *custom_headers;
+
+	gchar *real_trash_path, *real_junk_path;
 };
 
 struct _CamelImapStoreClass {
