Index: mail/ChangeLog
===================================================================
--- mail/ChangeLog	(revision 37067)
+++ mail/ChangeLog	(working copy)
@@ -1,3 +1,14 @@
+2009-01-14  Milan Crha  <mcrha@redhat.com>
+
+	** Fix for bug #204891
+
+	* filtertypes.xml:
+	* em-composer-utils.h: (em_utils_forward_message_raw):
+	* em-composer-utils.c: (emu_forward_raw_done),
+	(em_utils_forward_message_raw):
+	* mail-session.c: (ms_forward_to), (class_init):
+	Implement "forward-to" rule for message filters.
+
 2009-01-13  Felix Riemann  <friemann@svn.gnome.org>
 
 	** Fix for bug #563867
Index: mail/em-composer-utils.c
===================================================================
--- mail/em-composer-utils.c	(revision 37067)
+++ mail/em-composer-utils.c	(working copy)
@@ -1565,6 +1565,102 @@ em_utils_send_receipt (CamelFolder *fold
 	mail_append_mail (out_folder, receipt, info, em_utils_receipt_done, NULL);
 }
 
+static void
+emu_forward_raw_done (CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *info,
+		       int queued, const char *appended_uid, void *data)
+{
+	camel_message_info_free (info);
+	/* do not call mail send, just pile them all in the outbox */
+	/* mail_send (); */
+}
+
+/**
+ * em_utils_forward_message_raw:
+ * @param folder Where's a message located.
+ * @param message Message to forward.
+ * @param address Forward to whom.
+ * @param ex Exception.
+ * Forwards message to the address, in very similar way as redirect does.
+ **/
+void
+em_utils_forward_message_raw (CamelFolder *folder, CamelMimeMessage *message, const char *address, CamelException *ex)
+{
+	EAccount *account;
+	CamelMimeMessage *forward;
+	CamelStream *mem;
+	CamelInternetAddress *addr;
+	CamelFolder *out_folder;
+	CamelMessageInfo *info;
+	struct _camel_header_raw *xev;
+	char *subject;
+
+	g_return_if_fail (folder != NULL);
+	g_return_if_fail (message != NULL);
+	g_return_if_fail (address != NULL);
+
+	if (!*address) {
+		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("No destination address provided, forward of the message has been cancelled."));
+		return;
+	}
+
+	account = guess_account (message, folder);
+	if (!account) {
+		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("No account found to use, forward of the message has been cancelled."));
+		return;
+	}
+
+	forward = camel_mime_message_new ();
+
+	/* make copy of the message, because we are going to modify it */
+	mem = camel_stream_mem_new ();
+	camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, mem);
+	camel_seekable_stream_seek (CAMEL_SEEKABLE_STREAM (mem), 0, CAMEL_STREAM_SET);
+	camel_data_wrapper_construct_from_stream ((CamelDataWrapper *)forward, mem);
+	camel_object_unref (mem);
+
+	/* clear previous recipients */
+	camel_mime_message_set_recipients (forward, CAMEL_RECIPIENT_TYPE_TO, NULL);
+	camel_mime_message_set_recipients (forward, CAMEL_RECIPIENT_TYPE_CC, NULL);
+	camel_mime_message_set_recipients (forward, CAMEL_RECIPIENT_TYPE_BCC, NULL);
+	camel_mime_message_set_recipients (forward, CAMEL_RECIPIENT_TYPE_RESENT_TO, NULL);
+	camel_mime_message_set_recipients (forward, CAMEL_RECIPIENT_TYPE_RESENT_CC, NULL);
+	camel_mime_message_set_recipients (forward, CAMEL_RECIPIENT_TYPE_RESENT_BCC, NULL);
+
+	/* remove all delivery and notification headers */
+	while (camel_medium_get_header (CAMEL_MEDIUM (forward), "Disposition-Notification-To"))
+		camel_medium_remove_header (CAMEL_MEDIUM (forward), "Disposition-Notification-To");
+
+	while (camel_medium_get_header (CAMEL_MEDIUM (forward), "Delivered-To"))
+		camel_medium_remove_header (CAMEL_MEDIUM (forward), "Delivered-To");
+
+	/* remove any X-Evolution-* headers that may have been set */
+	xev = mail_tool_remove_xevolution_headers (forward);
+	camel_header_raw_clear (&xev);
+
+	/* from */
+	addr = camel_internet_address_new ();
+	camel_internet_address_add (addr, account->id->name, account->id->address);
+	camel_mime_message_set_from (forward, addr);
+	camel_object_unref (addr);
+
+	/* to */
+	addr = camel_internet_address_new ();
+	camel_address_decode (CAMEL_ADDRESS (addr), address);
+	camel_mime_message_set_recipients (forward, CAMEL_RECIPIENT_TYPE_TO, addr);
+	camel_object_unref (addr);
+
+	/* subject */
+	subject = mail_tool_generate_forward_subject (message);
+	camel_mime_message_set_subject (forward, subject);
+	g_free (subject);
+
+	/* and send it */
+	out_folder = mail_component_get_folder (NULL, MAIL_COMPONENT_FOLDER_OUTBOX);
+	info = camel_message_info_new (NULL);
+	camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN);
+	mail_append_mail (out_folder, forward, info, emu_forward_raw_done, NULL);
+}
+
 /* Replying to messages... */
 
 static GHashTable *
Index: mail/em-composer-utils.h
===================================================================
--- mail/em-composer-utils.h	(revision 37067)
+++ mail/em-composer-utils.h	(working copy)
@@ -33,6 +33,7 @@ extern "C" {
 
 struct _CamelFolder;
 struct _CamelMimeMessage;
+struct _CamelException;
 struct _EMsgComposer;
 struct _EMFormat;
 struct _EAccount;
@@ -65,6 +66,8 @@ void em_utils_forward_messages (struct _
 void em_utils_redirect_message (struct _CamelMimeMessage *message);
 void em_utils_redirect_message_by_uid (struct _CamelFolder *folder, const char *uid);
 
+void em_utils_forward_message_raw (struct _CamelFolder *folder, struct _CamelMimeMessage *message, const char *address, struct _CamelException *ex);
+
 void em_utils_handle_receipt (struct _CamelFolder *folder, const char *uid, struct _CamelMimeMessage *msg);
 void em_utils_send_receipt   (struct _CamelFolder *folder, struct _CamelMimeMessage *message);
 
Index: mail/filtertypes.xml
===================================================================
--- mail/filtertypes.xml	(revision 37067)
+++ mail/filtertypes.xml	(working copy)
@@ -1012,5 +1012,11 @@
   <code>(pipe-message "/bin/sh" "-c" ${command})</code>
   <input type="command" name="command"/>
  </part>
+
+ <part name="forward">
+  <title>Forward to</title>
+  <code>(forward-to ${address})</code>
+  <input type="address" name="address"/>
+ </part>
 </actionset>
 </filterdescription>
Index: mail/mail-session.c
===================================================================
--- mail/mail-session.c	(revision 37067)
+++ mail/mail-session.c	(working copy)
@@ -47,6 +47,7 @@
 #include "e-util/e-util-private.h"
 #include "e-account-combo-box.h"
 
+#include "em-composer-utils.h"
 #include "em-filter-context.h"
 #include "em-filter-rule.h"
 #include "em-utils.h"
@@ -93,6 +94,7 @@ static gboolean lookup_addressbook(Camel
 static void ms_thread_status(CamelSession *session, CamelSessionThreadMsg *msg, const char *text, int pc);
 static void *ms_thread_msg_new(CamelSession *session, CamelSessionThreadOps *ops, unsigned int size);
 static void ms_thread_msg_free(CamelSession *session, CamelSessionThreadMsg *m);
+static void ms_forward_to (CamelSession *session, CamelFolder *folder, CamelMimeMessage *message, const char *address, CamelException *ex);
 
 static void
 init (MailSession *session)
@@ -124,6 +126,7 @@ class_init (MailSessionClass *mail_sessi
 	camel_session_class->thread_msg_new = ms_thread_msg_new;
 	camel_session_class->thread_msg_free = ms_thread_msg_free;
 	camel_session_class->thread_status = ms_thread_status;
+	camel_session_class->forward_to = ms_forward_to;
 }
 
 static CamelType
@@ -618,6 +621,16 @@ static void ms_thread_status(CamelSessio
 	printf("Thread status '%s' %d%%\n", text, pc);
 }
 
+static void
+ms_forward_to (CamelSession *session, CamelFolder *folder, CamelMimeMessage *message, const char *address, CamelException *ex)
+{
+	g_return_if_fail (session != NULL);
+	g_return_if_fail (message != NULL);
+	g_return_if_fail (address != NULL);
+
+	em_utils_forward_message_raw (folder, message, address, ex);
+}
+
 char *
 mail_session_get_password (const char *url_string)
 {
