diff --git a/plugins/templates/org-gnome-templates.eplug.xml b/plugins/templates/org-gnome-templates.eplug.xml
index 7c19a6e..5bfa8a1 100644
--- a/plugins/templates/org-gnome-templates.eplug.xml
+++ b/plugins/templates/org-gnome-templates.eplug.xml
@@ -5,9 +5,12 @@
         id="org.gnome.evolution.plugin.templates"
         location="@PLUGINDIR@/liborg-gnome-templates@SOEXT@"
         _name="Templates">
-        <_description>Drafts based template plugin</_description>
+        <_description>Drafts based template plugin.
+        
+        You can use variables like $ORIG[subject], $ORIG[from], $ORIG[to] or $ORIG[body], which will be replaced by values from an email you are replying to.</_description>
         <author name="Bharath Acharya" email="abharath@novell.com"/>
         <author name="Diego Escalante Urrelo" email="diegoe@gnome.org"/>
+        <author name="Dan Vratil" email="dvratil@redhat.com"/>
 
         <hook class="org.gnome.evolution.ui:1.0">
           <ui-manager id="org.gnome.evolution.shell"
diff --git a/plugins/templates/templates.c b/plugins/templates/templates.c
index fd8f802..1dec4ec 100644
--- a/plugins/templates/templates.c
+++ b/plugins/templates/templates.c
@@ -465,15 +465,198 @@ e_plugin_lib_get_configure_widget (EPlugin *epl)
 	return hbox;
 }
 
+/* Replaces $ORIG[variable] in given template by given replacement from the original message */
+static void
+replace_template_variable (GString **template, const gchar *variable, const gchar *replacement)
+{
+	const gchar *lower_modifier = g_utf8_strdown (variable, -1);
+	const gchar *full_modifier = g_strconcat ("$ORIG[", lower_modifier, "]\0", NULL);
+	gchar *modifier_pos, *end_string_start; /* Pointers into template */
+	gchar *t_str = (*template)->str;
+
+	while ((modifier_pos = g_strstr_len (t_str, -1, full_modifier)) != NULL)
+	{
+		end_string_start  = modifier_pos + strlen (full_modifier);
+
+		g_return_if_fail (modifier_pos != t_str);
+
+		/* Remove the $ORIG[variable] string and insert the replacement on the same position */
+		g_string_erase (*template, (modifier_pos - t_str), (end_string_start - modifier_pos));
+		g_string_insert_len (*template, (modifier_pos - t_str), replacement, strlen (replacement));
+	}
+}
+
+static CamelMimePart*
+fill_template (CamelMimeMessage *message, CamelMimePart *template)
+{
+	struct _camel_header_raw *header = CAMEL_MIME_PART (message)->headers;
+	CamelContentType *ct;
+	CamelStream *stream;
+	CamelMimePart *return_part;
+	CamelMimePart *message_part = NULL;
+	CamelDataWrapper *dw;
+
+	CamelInternetAddress *internet_address;
+	gint address_index;
+
+	GString *template_body;
+	const gchar *address_name, *address_email;
+	GString *emails;
+
+	gchar *buffer;
+	gsize buffer_len;
+
+	gint i;
+	gboolean message_html, template_html;
+
+	ct = camel_mime_part_get_content_type (template);
+	template_html = camel_content_type_is (ct, "text", "html");
+
+	message_html = FALSE;
+	/* When template is html, then prefer HTML part of the original message. Otherwise go for plaintext */
+	dw = camel_medium_get_content (CAMEL_MEDIUM (message));
+	if (CAMEL_IS_MULTIPART (dw))
+	{
+		for (i = 0; i < camel_multipart_get_number (CAMEL_MULTIPART (dw)); i++)
+		{
+			CamelMimePart *part = camel_multipart_get_part (CAMEL_MULTIPART (dw), i);
+			CamelContentType *ct = camel_mime_part_get_content_type (part);
+
+			if (camel_content_type_is (ct, "text", "html") && template_html)
+			{
+				message_part = camel_multipart_get_part (CAMEL_MULTIPART (dw), i);
+				message_html = TRUE;
+				break;
+			} else if (camel_content_type_is (ct, "text", "plain") && message_html == FALSE)
+			{
+				message_part = camel_multipart_get_part (CAMEL_MULTIPART (dw), i);
+			}
+		}
+	 } else
+	 	message_part  = CAMEL_MIME_PART (message);
+
+	/* Get body of template part */
+	stream = camel_stream_mem_new();
+	camel_data_wrapper_write_to_stream_sync (camel_medium_get_content (CAMEL_MEDIUM (template)), stream, NULL, NULL);
+	camel_stream_reset (stream, NULL);
+	buffer = g_malloc (1024);
+	template_body = g_string_new ("");
+	while ((buffer_len = camel_stream_read (stream, buffer, 1024, NULL, NULL)) > 0)
+	{
+		g_string_append_len (template_body, buffer, buffer_len);
+	}
+	g_free (buffer);
+	g_object_unref (stream);
+
+	/* Replace all $ORIG[header_name] by respective values */
+	while (header)
+	{
+		if (g_ascii_strncasecmp (header->name, "content-", 8) != 0 &&
+		    g_ascii_strncasecmp (header->name, "to", 2) != 0 &&
+		    g_ascii_strncasecmp (header->name, "from", 4) != 0 &&
+		    g_ascii_strncasecmp (header->name, "subject", 7) != 0)
+
+			replace_template_variable (&template_body, header->name, header->value);
+
+		header = header->next;
+	}
+
+	/* Now manually replace the *subject* header. The header->value for subject header could be
+	   base64 encoded, so let camel_mime_message to decode it for us if needed */
+	replace_template_variable (&template_body, "subject", camel_mime_message_get_subject (message));
+
+	/* Replace TO and FROM modifiers. */
+	internet_address = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
+	address_index = 0;
+	while (camel_internet_address_get (internet_address, address_index, &address_name, &address_email))
+	{
+		gchar *address;
+		address = g_strdup_printf ("%s <%s>", address_name, address_email);
+
+		if (address_index > 0)
+			g_string_append_printf (emails, ", %s", address);
+		else
+			emails = g_string_new (address);
+
+		address_index++;
+		g_free (address);
+	}
+	replace_template_variable (&template_body, "to", emails->str);
+	g_string_free (emails, TRUE);
+
+	internet_address = camel_mime_message_get_from (message);
+	camel_internet_address_get (internet_address, 0, &address_name, &address_email);
+	emails = g_string_new ("");
+	g_string_append_printf (emails, "%s <%s>", address_name, address_email);
+	replace_template_variable (&template_body, "from", emails->str);
+	g_string_free (emails, TRUE);
+
+	/* Now extract body of the original message and replace the $ORIG[body] modifier in template */
+	if (message_part)
+	{
+		GString *message_body = g_string_new ("");
+
+		stream = camel_stream_mem_new();
+		camel_data_wrapper_write_to_stream_sync (camel_medium_get_content (CAMEL_MEDIUM (message_part)), stream, NULL, NULL);
+		camel_stream_reset (stream, NULL);
+		buffer = g_malloc (1024);
+		while ((buffer_len = camel_stream_read (stream, buffer, 1024, NULL, NULL)) > 0)
+		{
+			g_string_append_len (message_body, buffer, buffer_len);
+		}
+		g_free (buffer);
+		g_object_unref (stream);
+
+		if (template_html && !message_html) {
+			gchar *html = camel_text_to_html (message_body->str, CAMEL_MIME_FILTER_TOHTML_CONVERT_NL |
+									     CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES |
+									     CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
+									     CAMEL_MIME_FILTER_TOHTML_MARK_CITATION |
+									     CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES, 0);
+			g_string_assign (message_body, html);
+			g_free (html);
+		} else if (!template_html && message_html) {
+			g_string_prepend (message_body, "<pre>");
+			g_string_append (message_body, "</pre>");
+		} /* Other cases should not occur. And even if they happen to do, there's nothing we can really do about it */
+
+		replace_template_variable (&template_body, "body", message_body->str);
+
+		g_string_free (message_body, TRUE);
+
+	} else {
+		replace_template_variable (&template_body, "body", "");
+	}
+
+
+	return_part = camel_mime_part_new();
+
+	if (template_html)
+		camel_mime_part_set_content (return_part, template_body->str, template_body->len, "text/html");
+	else
+		camel_mime_part_set_content (return_part, template_body->str, template_body->len, "text/plain");
+
+	g_string_free (template_body, TRUE);
+
+	return return_part;
+}
+
 static void
 create_new_message (CamelFolder *folder, const gchar *uid, CamelMimeMessage *message, gpointer data)
 {
 	GtkAction *action = data;
 	CamelMimeMessage *new, *template;
+	CamelMultipart *new_multipart;
+	CamelContentType *new_content_type = NULL;
+	CamelDataWrapper *dw;
 	struct _camel_header_raw *header;
-	CamelStream *mem;
 	EShell *shell;
 
+	gint i;
+
+	CamelMimePart *template_part = NULL;
+	CamelMimePart *out_part = NULL;
+
 	g_return_if_fail (data != NULL);
 	g_return_if_fail (message != NULL);
 
@@ -483,27 +666,74 @@ create_new_message (CamelFolder *folder, const gchar *uid, CamelMimeMessage *mes
 	folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_TEMPLATES);
 	template = g_object_get_data (G_OBJECT (action), "template");
 
-	/* The new message we are creating */
 	new = camel_mime_message_new ();
+	new_multipart = camel_multipart_new ();
+	camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (new_multipart), "multipart/alternative");
+	camel_multipart_set_boundary (new_multipart, NULL);
+
+	dw = camel_medium_get_content (CAMEL_MEDIUM (template));
+	/* If template is a multipart, then try to use HTML. When no HTML part is available, use plaintext. Every other
+	   add as an attachment */
+	if (CAMEL_IS_MULTIPART (dw))
+	{
+		for (i = 0; i < camel_multipart_get_number (CAMEL_MULTIPART (dw)); i++)
+		{
+			CamelMimePart *part = camel_multipart_get_part (CAMEL_MULTIPART (dw), i);
+			CamelContentType *ct = camel_mime_part_get_content_type (part);
+
+			if (camel_content_type_is (ct, "text", "html"))
+			{
+				new_content_type = ct;
+				template_part = camel_multipart_get_part (CAMEL_MULTIPART (dw), i);
+			} else if (camel_content_type_is (ct, "text", "plain") && new_content_type == NULL)
+			{
+				new_content_type = ct;
+				template_part = camel_multipart_get_part (CAMEL_MULTIPART (dw), i);
+			} else {
+				/* Copy any other parts (attachments...) to the output message */
+				camel_mime_part_set_disposition (part, "attachment");
+				camel_multipart_add_part (new_multipart, part);
+			}
+		}
+	} else {
+		CamelContentType *ct = camel_mime_part_get_content_type (CAMEL_MIME_PART (template));
 
-	/* make the exact copy of the template message, with all
-	   its attachments and message structure */
-	mem = camel_stream_mem_new ();
-	camel_data_wrapper_write_to_stream_sync (
-		CAMEL_DATA_WRAPPER (template), mem, NULL, NULL);
-	camel_stream_reset (mem, NULL);
-	camel_data_wrapper_construct_from_stream_sync (
-		CAMEL_DATA_WRAPPER (new), mem, NULL, NULL);
-	g_object_unref (mem);
+		if (camel_content_type_is (ct, "text", "html") ||
+		    camel_content_type_is (ct, "text", "plain")) {
+		    	template_part = CAMEL_MIME_PART (template);
+			new_content_type = ct;
+		}
+	}
+
+	/* Here replace all the modifiers in template by values from message and return the newly created part */
+	out_part = fill_template (message, template_part);
+
+	/* Assigning part directly to mime_message causes problem with "Content-type" header displaying
+	   in the HTML message (camel parsing bug?) */
+	camel_multipart_add_part (new_multipart, out_part);
+	camel_medium_set_content (CAMEL_MEDIUM (new), CAMEL_DATA_WRAPPER (new_multipart));
 
 	/* Add the headers from the message we are replying to, so CC and that
-	 * stuff is preserved. */
-	header = ((CamelMimePart *)message)->headers;
+	   stuff is preserved. Also replace any $ORIG[header-name] modifiers ignoring
+	   'content-*' headers */
+	header = CAMEL_MIME_PART (message)->headers;
 	while (header) {
-		if (g_ascii_strncasecmp (header->name, "content-", 8) != 0) {
-			camel_medium_add_header ((CamelMedium *) new,
-					header->name,
-					header->value);
+		if (g_ascii_strncasecmp (header->name, "content-", 8) != 0)
+		{
+			if (g_ascii_strncasecmp (header->name, "subject", 7) == 0)
+			{
+				GString *subject = g_string_new (camel_mime_message_get_subject (template));
+				/* Can't use directly header->value as it can be base64-encoded, but camel_mime_message
+				   will decode it for us if needed */
+				replace_template_variable (&subject, "subject",
+					camel_mime_message_get_subject (message));
+				header->value = g_strdup (subject->str);
+				g_string_free (subject, TRUE);
+			}
+
+			camel_medium_add_header (CAMEL_MEDIUM (new),
+						 header->name,
+						 header->value);
 		}
 		header = header->next;
 	}
@@ -522,6 +752,8 @@ create_new_message (CamelFolder *folder, const gchar *uid, CamelMimeMessage *mes
 	/* Create the composer */
 	em_utils_edit_message (shell, folder, new);
 
+	g_object_unref (template);
+	g_object_unref (new_multipart);
 	g_object_unref (new);
 }
 
