예제 #1
0
void
filter_gui_add_from_message (EMailSession *session,
                             CamelMimeMessage *msg,
                             const gchar *source,
                             gint flags)
{
	EMFilterContext *fc;
	const gchar *config_dir;
	gchar *user, *system;
	EFilterRule *rule;

	g_return_if_fail (E_IS_MAIL_SESSION (session));
	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (msg));

	fc = em_filter_context_new (session);
	config_dir = mail_session_get_config_dir ();
	user = g_build_filename (config_dir, "filters.xml", NULL);
	system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL);
	e_rule_context_load ((ERuleContext *) fc, system, user);
	g_free (system);

	rule = filter_rule_from_message (fc, msg, flags);

	e_filter_rule_set_source (rule, source);

	e_rule_context_add_rule_gui (
		(ERuleContext *) fc, rule, _("Add Filter Rule"), user);
	g_free (user);
	g_object_unref (fc);
}
예제 #2
0
EFilterRule *
em_vfolder_rule_from_message (EMVFolderContext *context,
                              CamelMimeMessage *msg,
                              gint flags,
                              CamelFolder *folder)
{
	EFilterRule *rule;
	EMailSession *session;
	gchar *uri;

	g_return_val_if_fail (EM_IS_VFOLDER_CONTEXT (context), NULL);
	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (msg), NULL);
	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);

	uri = e_mail_folder_uri_from_folder (folder);

	session = em_vfolder_editor_context_get_session ((EMVFolderEditorContext *) context);

	rule = em_vfolder_editor_rule_new (session);
	em_vfolder_rule_add_source (EM_VFOLDER_RULE (rule), uri);
	rule_from_message (rule, E_RULE_CONTEXT (context), msg, flags);

	g_free (uri);

	return rule;
}
예제 #3
0
void
vfolder_gui_add_from_message (EMailSession *session,
                              CamelMimeMessage *message,
                              gint flags,
                              CamelFolder *folder)
{
	EMVFolderRule *rule;

	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));

	rule = (EMVFolderRule *) em_vfolder_rule_from_message (
		context, message, flags, folder);
	vfolder_gui_add_rule (rule);
}
gboolean
e_mail_session_handle_draft_headers_sync (EMailSession *session,
                                          CamelMimeMessage *message,
                                          GCancellable *cancellable,
                                          GError **error)
{
	CamelFolder *folder;
	CamelMedium *medium;
	const gchar *folder_uri;
	const gchar *message_uid;
	const gchar *header_name;
	gboolean success;

	g_return_val_if_fail (E_IS_MAIL_SESSION (session), FALSE);
	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);

	medium = CAMEL_MEDIUM (message);

	header_name = "X-Evolution-Draft-Folder";
	folder_uri = camel_medium_get_header (medium, header_name);

	header_name = "X-Evolution-Draft-Message";
	message_uid = camel_medium_get_header (medium, header_name);

	/* Don't report errors about missing X-Evolution-Draft
	 * headers.  These headers are optional, so their absence
	 * is handled by doing nothing. */
	if (folder_uri == NULL || message_uid == NULL)
		return TRUE;

	folder = e_mail_session_uri_to_folder_sync (
		session, folder_uri, 0, cancellable, error);

	if (folder == NULL)
		return FALSE;

	camel_folder_set_message_flags (
		folder, message_uid,
		CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN,
		CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN);

	success = camel_folder_synchronize_message_sync (
		folder, message_uid, cancellable, error);

	g_object_unref (folder);

	return success;
}
/**
 * camel_junk_filter_learn_junk:
 * @junk_filter: a #CamelJunkFilter
 * @message: a #CamelMimeMessage
 * @cancellable: optional #GCancellable object, or %NULL
 * @error: return location for a #GError, or %NULL
 *
 * Instructs @junk_filter to classify @message as junk.  If using an
 * adaptive junk filtering algorithm, explicitly marking @message as
 * junk will influence the classification of future messages.
 *
 * If an error occurs, the function sets @error and returns %FALSE.
 *
 * Returns: %TRUE if @message was successfully classified
 *
 * Since: 3.2
 **/
gboolean
camel_junk_filter_learn_junk (CamelJunkFilter *junk_filter,
                              CamelMimeMessage *message,
                              GCancellable *cancellable,
                              GError **error)
{
	CamelJunkFilterInterface *interface;

	g_return_val_if_fail (CAMEL_IS_JUNK_FILTER (junk_filter), FALSE);
	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);

	interface = CAMEL_JUNK_FILTER_GET_INTERFACE (junk_filter);
	g_return_val_if_fail (interface->learn_junk != NULL, FALSE);

	return interface->learn_junk (
		junk_filter, message, cancellable, error);
}
/**
 * camel_junk_filter_classify:
 * @junk_filter: a #CamelJunkFilter
 * @message: a #CamelMimeMessage
 * @cancellable: optional #GCancellable object, or %NULL
 * @error: return location for a #GError, or %NULL
 *
 * Classifies @message as junk, not junk or inconclusive.
 *
 * If an error occurs, the function sets @error and returns
 * %CAMEL_JUNK_STATUS_ERROR.
 *
 * Returns: the junk status determined by @junk_filter
 *
 * Since: 3.2
 **/
CamelJunkStatus
camel_junk_filter_classify (CamelJunkFilter *junk_filter,
                            CamelMimeMessage *message,
                            GCancellable *cancellable,
                            GError **error)
{
	CamelJunkFilterInterface *interface;

	g_return_val_if_fail (CAMEL_IS_JUNK_FILTER (junk_filter), 0);
	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), 0);

	interface = CAMEL_JUNK_FILTER_GET_INTERFACE (junk_filter);
	g_return_val_if_fail (interface->classify != NULL, 0);

	return interface->classify (
		junk_filter, message, cancellable, error);
}
예제 #7
0
static void
message_dump_rec (CamelMimeMessage *msg,
                  CamelMimePart *part,
                  gint depth)
{
	CamelDataWrapper *containee;
	gint parts, i;
	gchar *s;
	gchar *mime_type;

	s = alloca (depth + 1);
	memset (s, ' ', depth);
	s[depth] = 0;

	mime_type = camel_data_wrapper_get_mime_type ((CamelDataWrapper *) part);
	printf ("%sPart <%s>\n", s, G_OBJECT_TYPE_NAME (part));
	printf ("%sContent-Type: %s\n", s, mime_type);
	g_free (mime_type);
	printf ("%s encoding: %s\n", s, camel_transfer_encoding_to_string (((CamelDataWrapper *)part)->encoding));
	printf ("%s part encoding: %s\n", s, camel_transfer_encoding_to_string (camel_mime_part_get_encoding (part)));

	containee = camel_medium_get_content (CAMEL_MEDIUM (part));

	if (containee == NULL)
		return;

	mime_type = camel_data_wrapper_get_mime_type (containee);
	printf ("%sContent <%s>\n", s, G_OBJECT_TYPE_NAME (containee));
	printf ("%sContent-Type: %s\n", s, mime_type);
	g_free (mime_type);
	printf ("%s encoding: %s\n", s, camel_transfer_encoding_to_string (((CamelDataWrapper *)containee)->encoding));

	/* using the object types is more accurate than using the mime/types */
	if (CAMEL_IS_MULTIPART (containee)) {
		parts = camel_multipart_get_number (CAMEL_MULTIPART (containee));
		for (i = 0; i < parts; i++) {
			CamelMimePart *part = camel_multipart_get_part (CAMEL_MULTIPART (containee), i);

			message_dump_rec (msg, part, depth + 1);
		}
	} else if (CAMEL_IS_MIME_MESSAGE (containee)) {
		message_dump_rec (msg, (CamelMimePart *) containee, depth + 1);
	}
}
예제 #8
0
ESource *
em_utils_guess_mail_identity (ESourceRegistry *registry,
                              CamelMimeMessage *message,
                              CamelFolder *folder,
                              const gchar *message_uid)
{
	ESource *source;
	ESourceExtension *extension;
	const gchar *extension_name;
	const gchar *uid;

	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);

	if (folder != NULL)
		g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);

	source = em_utils_guess_mail_account (registry, message, folder, message_uid);

	if (source == NULL)
		return NULL;

	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
	extension = e_source_get_extension (source, extension_name);

	uid = e_source_mail_account_get_identity_uid (
		E_SOURCE_MAIL_ACCOUNT (extension));
	if (uid == NULL)
		return NULL;

	source = e_source_registry_ref_source (registry, uid);
	if (source == NULL)
		return NULL;

	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
	if (!e_source_has_extension (source, extension_name)) {
		g_object_unref (source);
		return NULL;
	}

	return source;
}
예제 #9
0
ESource *
em_utils_guess_mail_identity_with_recipients_and_sort (ESourceRegistry *registry,
                                                       CamelMimeMessage *message,
                                                       CamelFolder *folder,
                                                       const gchar *message_uid,
                                                       EMailUtilsSourtSourcesFunc sort_func,
                                                       gpointer sort_func_data)
{
	ESource *source;
	ESourceExtension *extension;
	const gchar *extension_name;
	const gchar *uid;

	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);

	source = em_utils_guess_mail_account_with_recipients_and_sort (
		registry, message, folder, message_uid, sort_func, sort_func_data);

	if (source == NULL)
		return NULL;

	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
	extension = e_source_get_extension (source, extension_name);

	uid = e_source_mail_account_get_identity_uid (
		E_SOURCE_MAIL_ACCOUNT (extension));
	if (uid == NULL)
		return NULL;

	source = e_source_registry_ref_source (registry, uid);
	if (source == NULL)
		return NULL;

	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
	if (!e_source_has_extension (source, extension_name)) {
		g_object_unref (source);
		return NULL;
	}

	return source;
}
static void
mail_attachment_handler_update_actions (EAttachmentView *view,
                                        EAttachmentHandler *handler)
{
	EAttachment *attachment;
	CamelMimePart *mime_part;
	GtkActionGroup *action_group;
	GList *selected;
	gboolean visible = FALSE;

	selected = e_attachment_view_get_selected_attachments (view);

	if (g_list_length (selected) != 1)
		goto exit;

	attachment = E_ATTACHMENT (selected->data);

	if (e_attachment_get_loading (attachment) ||
	    e_attachment_get_saving (attachment))
		goto exit;

	mime_part = e_attachment_ref_mime_part (attachment);

	if (mime_part != NULL) {
		CamelMedium *medium;
		CamelDataWrapper *content;

		medium = CAMEL_MEDIUM (mime_part);
		content = camel_medium_get_content (medium);
		visible = CAMEL_IS_MIME_MESSAGE (content);

		g_object_unref (mime_part);
	}

exit:
	action_group = e_attachment_view_get_action_group (view, "mail");
	gtk_action_group_set_visible (action_group, visible);

	g_list_foreach (selected, (GFunc) g_object_unref, NULL);
	g_list_free (selected);
}
예제 #11
0
EFilterRule *
filter_rule_from_message (EMFilterContext *context,
                          CamelMimeMessage *msg,
                          gint flags)
{
	EFilterRule *rule;
	EFilterPart *part;

	g_return_val_if_fail (EM_IS_FILTER_CONTEXT (context), NULL);
	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (msg), NULL);

	rule = em_filter_rule_new ();
	rule_from_message (rule, E_RULE_CONTEXT (context), msg, flags);

	part = em_filter_context_next_action (context, NULL);

	em_filter_rule_add_action (
		EM_FILTER_RULE (rule), e_filter_part_clone (part));

	return rule;
}
/* there is also an identical copy of this in camel-filter-search.c */
gboolean
camel_search_message_body_contains (CamelDataWrapper *object, regex_t *pattern)
{
	CamelDataWrapper *containee;
	gint truth = FALSE;
	gint parts, i;

	containee = camel_medium_get_content (CAMEL_MEDIUM (object));

	if (containee == NULL)
		return FALSE;

	/* using the object types is more accurate than using the mime/types */
	if (CAMEL_IS_MULTIPART (containee)) {
		parts = camel_multipart_get_number (CAMEL_MULTIPART (containee));
		for (i = 0; i < parts && truth == FALSE; i++) {
			CamelDataWrapper *part = (CamelDataWrapper *)camel_multipart_get_part (CAMEL_MULTIPART (containee), i);
			if (part)
				truth = camel_search_message_body_contains (part, pattern);
		}
	} else if (CAMEL_IS_MIME_MESSAGE (containee)) {
		/* for messages we only look at its contents */
		truth = camel_search_message_body_contains ((CamelDataWrapper *)containee, pattern);
	} else if (camel_content_type_is(CAMEL_DATA_WRAPPER (containee)->mime_type, "text", "*")
		|| camel_content_type_is(CAMEL_DATA_WRAPPER (containee)->mime_type, "x-evolution", "evolution-rss-feed")) {
		/* for all other text parts, we look inside, otherwise we dont care */
		CamelStream *stream;
		GByteArray *byte_array;

		byte_array = g_byte_array_new ();
		stream = camel_stream_mem_new_with_byte_array (byte_array);
		camel_data_wrapper_write_to_stream_sync (
			containee, stream, NULL, NULL);
		camel_stream_write (stream, "", 1, NULL, NULL);
		truth = regexec (pattern, (gchar *) byte_array->data, 0, NULL, 0) == 0;
		g_object_unref (stream);
	}

	return truth;
}
예제 #13
0
void
e_mail_session_append_to_local_folder (EMailSession *session,
                                       EMailLocalFolder local_id,
                                       CamelMimeMessage *message,
                                       CamelMessageInfo *info,
                                       gint io_priority,
                                       GCancellable *cancellable,
                                       GAsyncReadyCallback callback,
                                       gpointer user_data)
{
	GSimpleAsyncResult *simple;
	AsyncContext *context;

	g_return_if_fail (E_IS_MAIL_SESSION (session));
	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));

	context = g_slice_new0 (AsyncContext);
	context->local_id = local_id;
	context->message = g_object_ref (message);

	if (info != NULL)
		context->info = camel_message_info_ref (info);

	simple = g_simple_async_result_new (
		G_OBJECT (session), callback, user_data,
		e_mail_session_append_to_local_folder);

	g_simple_async_result_set_check_cancellable (simple, cancellable);

	g_simple_async_result_set_op_res_gpointer (
		simple, context, (GDestroyNotify) async_context_free);

	g_simple_async_result_run_in_thread (
		simple, mail_session_append_to_local_folder_thread,
		io_priority, cancellable);

	g_object_unref (simple);
}
예제 #14
0
static void
fill_model_rec(CamelMimeMessage *msg, CamelMimePart *part, GtkTreeStore *model, GtkTreeIter *parent, GString *name)
{
	CamelDataWrapper *containee;
	int parts, i;
	char *type;
	GtkTreeIter iter;
	int len = name->len;
	CamelContentType *mime;

	containee = camel_medium_get_content_object((CamelMedium *)part);
	if (containee == NULL)
		return;

	mime = ((CamelDataWrapper *)containee)->mime_type;
	type = camel_content_type_simple(mime);

	if (CAMEL_IS_MULTIPART(containee)) {
		gtk_tree_store_append(model, &iter, parent);
		g_string_append_printf(name, ".multipart");
		gtk_tree_store_set(model, &iter, 0, FALSE, 1, type, 2, name->str, 3, name->str, 4, part, -1);

		parts = camel_multipart_get_number((CamelMultipart *)containee);
		for (i = 0; i < parts; i++) {
			CamelMimePart *mpart = camel_multipart_get_part((CamelMultipart *)containee, i);

			g_string_truncate(name, len);
			g_string_append_printf(name, ".%d", i);
			fill_model_rec(msg, mpart, model, &iter, name);
		}
	} else if (CAMEL_IS_MIME_MESSAGE(containee)) {
		gtk_tree_store_append(model, &iter, parent);
		g_string_append_printf(name, ".msg");
		gtk_tree_store_set(model, &iter, 0, FALSE, 1, type, 2, name->str, 3, name->str, 4, part, -1);
		fill_model_rec(msg, (CamelMimePart *)containee, model, &iter, name);
	} else {
		char *filename = NULL;
		const char *ext = NULL, *tmp;
		int save = FALSE;

		gtk_tree_store_append(model, &iter, parent);
		tmp = camel_mime_part_get_filename(part);
		if (tmp) {
			filename = clean_name(tmp);
			ext = strrchr(filename, '.');
		}
		tmp = camel_mime_part_get_disposition(part);
		if (tmp && !strcmp(tmp, "attachment"))
			save = TRUE;

		if (camel_content_type_is(mime, "text", "*")) {
			if (ext == NULL) {
				if ((ext = mime->subtype) == NULL || !strcmp(ext, "plain"))
					ext = "text";
			}
		} else if (camel_content_type_is(mime, "image", "*")) {
			if (ext == NULL) {
				if ((ext = mime->subtype) == NULL)
					ext = "image";
			}
			save = TRUE;
		}

		g_string_append_printf(name, ".%s", ext);
		gtk_tree_store_set(model, &iter, 0, save, 1, type, 2, filename?filename:name->str, 3, filename?NULL:name->str, 4, part, -1);
		g_free(filename);
	}
	g_free(type);

	g_string_truncate(name, len);
}
예제 #15
0
ESource *
em_utils_guess_mail_account_with_recipients_and_sort (ESourceRegistry *registry,
                                                      CamelMimeMessage *message,
                                                      CamelFolder *folder,
                                                      const gchar *message_uid,
                                                      EMailUtilsSourtSourcesFunc sort_func,
                                                      gpointer sort_func_data)
{
	ESource *source = NULL;
	GHashTable *recipients;
	CamelInternetAddress *addr;
	GList *list, *iter;
	const gchar *extension_name;
	const gchar *type;
	const gchar *key;

	/* This policy is subject to debate and tweaking,
	 * but please also document the rational here. */

	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);

	/* Build a set of email addresses in which to test for membership.
	 * Only the keys matter here; the values just need to be non-NULL. */
	recipients = g_hash_table_new (g_str_hash, g_str_equal);

	type = CAMEL_RECIPIENT_TYPE_TO;
	addr = camel_mime_message_get_recipients (message, type);
	if (addr != NULL) {
		gint index = 0;

		while (camel_internet_address_get (addr, index++, NULL, &key))
			g_hash_table_add (recipients, (gpointer) key);
	}

	type = CAMEL_RECIPIENT_TYPE_CC;
	addr = camel_mime_message_get_recipients (message, type);
	if (addr != NULL) {
		gint index = 0;

		while (camel_internet_address_get (addr, index++, NULL, &key))
			g_hash_table_add (recipients, (gpointer) key);
	}

	/* First Preference: We were given a folder that maps to an
	 * enabled mail account, and that account's address appears
	 * in the list of To: or Cc: recipients. */

	if (folder != NULL)
		source = guess_mail_account_from_folder (
			registry, folder, message_uid);

	if (source == NULL)
		goto second_preference;

	if (mail_account_in_recipients (registry, source, recipients))
		goto exit;

second_preference:

	/* Second Preference: Choose any enabled mail account whose
	 * address appears in the list to To: or Cc: recipients. */

	if (source != NULL) {
		g_object_unref (source);
		source = NULL;
	}

	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
	list = e_source_registry_list_sources (registry, extension_name);

	if (sort_func)
		sort_func (&list, sort_func_data);

	for (iter = list; iter != NULL; iter = g_list_next (iter)) {
		ESource *temp = E_SOURCE (iter->data);

		if (e_source_registry_check_enabled (registry, temp) &&
		    mail_account_in_recipients (registry, temp, recipients)) {
			source = g_object_ref (temp);
			break;
		}
	}

	g_list_free_full (list, (GDestroyNotify) g_object_unref);

	if (source != NULL)
		goto exit;

	/* Last Preference: Defer to em_utils_guess_mail_account(). */
	source = em_utils_guess_mail_account (
		registry, message, folder, message_uid);

exit:
	g_hash_table_destroy (recipients);

	return source;
}
예제 #16
0
void
e_mail_session_send_to (EMailSession *session,
                        CamelMimeMessage *message,
                        gint io_priority,
                        GCancellable *cancellable,
                        CamelFilterGetFolderFunc get_folder_func,
                        gpointer get_folder_data,
                        GAsyncReadyCallback callback,
                        gpointer user_data)
{
	GSimpleAsyncResult *simple;
	AsyncContext *context;
	CamelAddress *from;
	CamelAddress *recipients;
	CamelMedium *medium;
	CamelMessageInfo *info;
	CamelService *transport;
	GPtrArray *post_to_uris;
	struct _camel_header_raw *xev;
	struct _camel_header_raw *header;
	const gchar *resent_from;
	GError *error = NULL;

	g_return_if_fail (E_IS_MAIL_SESSION (session));
	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));

	medium = CAMEL_MEDIUM (message);

	camel_medium_set_header (medium, "X-Mailer", X_MAILER);

	/* Do this before removing "X-Evolution" headers. */
	transport = e_mail_session_ref_transport_for_message (
		session, message);

	xev = mail_tool_remove_xevolution_headers (message);

	/* Extract directives from X-Evolution headers. */

	post_to_uris = g_ptr_array_new ();
	for (header = xev; header != NULL; header = header->next) {
		gchar *folder_uri;

		if (g_strcmp0 (header->name, "X-Evolution-PostTo") != 0)
			continue;

		folder_uri = g_strstrip (g_strdup (header->value));
		g_ptr_array_add (post_to_uris, folder_uri);
	}

	/* Collect sender and recipients from headers. */

	from = (CamelAddress *) camel_internet_address_new ();
	recipients = (CamelAddress *) camel_internet_address_new ();
	resent_from = camel_medium_get_header (medium, "Resent-From");

	if (resent_from != NULL) {
		const CamelInternetAddress *addr;
		const gchar *type;

		camel_address_decode (from, resent_from);

		type = CAMEL_RECIPIENT_TYPE_RESENT_TO;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_RESENT_CC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_RESENT_BCC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

	} else {
		const CamelInternetAddress *addr;
		const gchar *type;

		addr = camel_mime_message_get_from (message);
		camel_address_copy (from, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_TO;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_CC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_BCC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));
	}

	/* Miscellaneous preparations. */

	info = camel_message_info_new_from_header (
		NULL, CAMEL_MIME_PART (message)->headers);
	((CamelMessageInfoBase *) info)->size =
		get_message_size (message, cancellable);
	camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0);

	/* expand, or remove empty, group addresses */
	em_utils_expand_groups (CAMEL_INTERNET_ADDRESS (recipients));

	/* The rest of the processing happens in a thread. */

	context = g_slice_new0 (AsyncContext);
	context->message = g_object_ref (message);
	context->io_priority = io_priority;
	context->from = from;
	context->recipients = recipients;
	context->info = info;
	context->xev = xev;
	context->post_to_uris = post_to_uris;
	context->transport = transport;

	if (G_IS_CANCELLABLE (cancellable))
		context->cancellable = g_object_ref (cancellable);

	/* Failure here emits a runtime warning but is non-fatal. */
	context->driver = camel_session_get_filter_driver (
		CAMEL_SESSION (session), E_FILTER_SOURCE_OUTGOING, &error);
	if (context->driver != NULL && get_folder_func)
		camel_filter_driver_set_folder_func (
			context->driver, get_folder_func, get_folder_data);
	if (error != NULL) {
		g_warn_if_fail (context->driver == NULL);
		g_warning ("%s", error->message);
		g_error_free (error);
	}

	/* This gets popped in async_context_free(). */
	camel_operation_push_message (
		context->cancellable, _("Sending message"));

	simple = g_simple_async_result_new (
		G_OBJECT (session), callback,
		user_data, e_mail_session_send_to);

	g_simple_async_result_set_check_cancellable (simple, cancellable);

	g_simple_async_result_set_op_res_gpointer (
		simple, context, (GDestroyNotify) async_context_free);

	g_simple_async_result_run_in_thread (
		simple, (GSimpleAsyncThreadFunc)
		mail_session_send_to_thread,
		context->io_priority,
		context->cancellable);

	g_object_unref (simple);
}
예제 #17
0
gboolean
e_mail_session_handle_source_headers_sync (EMailSession *session,
                                           CamelMimeMessage *message,
                                           GCancellable *cancellable,
                                           GError **error)
{
	CamelFolder *folder;
	CamelMedium *medium;
	CamelMessageFlags flags = 0;
	const gchar *folder_uri;
	const gchar *message_uid;
	const gchar *flag_string;
	const gchar *header_name;
	gboolean success;
	guint length, ii;
	gchar **tokens;
	gchar *string;

	g_return_val_if_fail (E_IS_MAIL_SESSION (session), FALSE);
	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);

	medium = CAMEL_MEDIUM (message);

	header_name = "X-Evolution-Source-Folder";
	folder_uri = camel_medium_get_header (medium, header_name);

	header_name = "X-Evolution-Source-Message";
	message_uid = camel_medium_get_header (medium, header_name);

	header_name = "X-Evolution-Source-Flags";
	flag_string = camel_medium_get_header (medium, header_name);

	/* Don't report errors about missing X-Evolution-Source
	 * headers.  These headers are optional, so their absence
	 * is handled by doing nothing. */
	if (folder_uri == NULL || message_uid == NULL || flag_string == NULL)
		return TRUE;

	/* Convert the flag string to CamelMessageFlags. */

	string = g_strstrip (g_strdup (flag_string));
	tokens = g_strsplit (string, " ", 0);
	g_free (string);

	/* If tokens is NULL, a length of 0 will skip the loop. */
	length = (tokens != NULL) ? g_strv_length (tokens) : 0;

	for (ii = 0; ii < length; ii++) {
		/* Note: We're only checking for flags known to
		 * be used in X-Evolution-Source-Flags headers.
		 * Add more as needed. */
		if (g_strcmp0 (tokens[ii], "ANSWERED") == 0)
			flags |= CAMEL_MESSAGE_ANSWERED;
		else if (g_strcmp0 (tokens[ii], "ANSWERED_ALL") == 0)
			flags |= CAMEL_MESSAGE_ANSWERED_ALL;
		else if (g_strcmp0 (tokens[ii], "FORWARDED") == 0)
			flags |= CAMEL_MESSAGE_FORWARDED;
		else if (g_strcmp0 (tokens[ii], "SEEN") == 0)
			flags |= CAMEL_MESSAGE_SEEN;
		else
			g_warning (
				"Unknown flag '%s' in %s",
				tokens[ii], header_name);
	}

	g_strfreev (tokens);

	folder = e_mail_session_uri_to_folder_sync (
		session, folder_uri, 0, cancellable, error);

	if (folder == NULL)
		return FALSE;

	camel_folder_set_message_flags (
		folder, message_uid, flags, flags);

	success = camel_folder_synchronize_message_sync (
		folder, message_uid, cancellable, error);

	g_object_unref (folder);

	return success;
}
예제 #18
0
/**
 * e_mail_session_get_fcc_for_message_sync:
 * @session: an #EMailSession
 * @message: a #CamelMimeMessage
 * @cancellable: optional #GCancellable object, or %NULL
 * @error: return location for a #GError, or %NULL
 *
 * Obtains the preferred "carbon-copy" folder (a.k.a Fcc) for @message
 * by first checking @message for an "X-Evolution-Identity" header, and
 * then an "X-Evolution-Fcc" header.  Failing that, the function checks
 * the default mail identity (if available), and failing even that, the
 * function falls back to the Sent folder from the built-in mail store.
 *
 * Where applicable, the function attempts to honor the
 * #ESourceMailSubmission:replies-to-origin-folder preference.
 *
 * The returned #CamelFolder is referenced for thread-safety and must be
 * unreferenced with g_object_unref() when finished with it.
 *
 * If a non-recoverable error occurs, the function sets @error and returns
 * %NULL.
 *
 * Returns: a #CamelFolder, or %NULL
 **/
CamelFolder *
e_mail_session_get_fcc_for_message_sync (EMailSession *session,
                                         CamelMimeMessage *message,
                                         GCancellable *cancellable,
                                         GError **error)
{
	CamelFolder *folder = NULL;

	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);

	/* Check for "X-Evolution-Identity" header. */
	if (folder == NULL) {
		GError *local_error = NULL;

		/* This may return NULL without setting a GError. */
		folder = mail_session_ref_fcc_from_x_identity (
			session, message, cancellable, &local_error);

		if (local_error != NULL) {
			g_warn_if_fail (folder == NULL);
			g_propagate_error (error, local_error);
			return NULL;
		}
	}

	/* Check for "X-Evolution-Fcc" header. */
	if (folder == NULL) {
		GError *local_error = NULL;

		/* This may return NULL without setting a GError. */
		folder = mail_session_ref_fcc_from_x_fcc (
			session, message, cancellable, &local_error);

		if (local_error != NULL) {
			g_warn_if_fail (folder == NULL);
			g_propagate_error (error, local_error);
			return NULL;
		}
	}

	/* Check the default mail identity. */
	if (folder == NULL) {
		GError *local_error = NULL;

		/* This may return NULL without setting a GError. */
		folder = mail_session_ref_fcc_from_default_identity (
			session, message, cancellable, &local_error);

		if (local_error != NULL) {
			g_warn_if_fail (folder == NULL);
			g_propagate_error (error, local_error);
			return NULL;
		}
	}

	/* Last resort - local Sent folder. */
	if (folder == NULL) {
		folder = e_mail_session_get_local_folder (
			session, E_MAIL_LOCAL_FOLDER_SENT);
		g_object_ref (folder);
	}

	return folder;
}
예제 #19
0
void
e_mail_session_send_to (EMailSession *session,
                        CamelMimeMessage *message,
                        gint io_priority,
                        GCancellable *cancellable,
                        CamelFilterGetFolderFunc get_folder_func,
                        gpointer get_folder_data,
                        GAsyncReadyCallback callback,
                        gpointer user_data)
{
	GSimpleAsyncResult *simple;
	AsyncContext *context;
	CamelAddress *from;
	CamelAddress *recipients;
	CamelMedium *medium;
	CamelMessageInfo *info;
	EAccount *account = NULL;
	GPtrArray *post_to_uris;
	struct _camel_header_raw *xev;
	struct _camel_header_raw *header;
	const gchar *string;
	const gchar *resent_from;
	gchar *transport_uid = NULL;
	gchar *sent_folder_uri = NULL;
	GError *error = NULL;

	g_return_if_fail (E_IS_MAIL_SESSION (session));
	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));

	medium = CAMEL_MEDIUM (message);

	camel_medium_set_header (medium, "X-Mailer", X_MAILER);

	xev = mail_tool_remove_xevolution_headers (message);

	/* Extract directives from X-Evolution headers. */

	string = camel_header_raw_find (&xev, "X-Evolution-Account", NULL);
	if (string != NULL) {
		gchar *account_uid;

		account_uid = g_strstrip (g_strdup (string));
		account = e_get_account_by_uid (account_uid);
		g_free (account_uid);
	}

	if (account != NULL) {
		if (account->transport != NULL) {

			/* XXX Transport UIDs are kludgy right now.  We
			 *     use the EAccount's regular UID and tack on
			 *     "-transport".  Will be better soon. */
			transport_uid = g_strconcat (
				account->uid, "-transport", NULL);

			/* to reprompt password on sending if needed */
			account->transport->get_password_canceled = FALSE;
		}
		sent_folder_uri = g_strdup (account->sent_folder_uri);
	}

	string = camel_header_raw_find (&xev, "X-Evolution-Fcc", NULL);
	if (sent_folder_uri == NULL && string != NULL)
		sent_folder_uri = g_strstrip (g_strdup (string));

	string = camel_header_raw_find (&xev, "X-Evolution-Transport", NULL);
	if (transport_uid == NULL && string != NULL)
		transport_uid = g_strstrip (g_strdup (string));

	post_to_uris = g_ptr_array_new ();
	for (header = xev; header != NULL; header = header->next) {
		gchar *folder_uri;

		if (g_strcmp0 (header->name, "X-Evolution-PostTo") != 0)
			continue;

		folder_uri = g_strstrip (g_strdup (header->value));
		g_ptr_array_add (post_to_uris, folder_uri);
	}

	/* Collect sender and recipients from headers. */

	from = (CamelAddress *) camel_internet_address_new ();
	recipients = (CamelAddress *) camel_internet_address_new ();
	resent_from = camel_medium_get_header (medium, "Resent-From");

	if (resent_from != NULL) {
		const CamelInternetAddress *addr;
		const gchar *type;

		camel_address_decode (from, resent_from);

		type = CAMEL_RECIPIENT_TYPE_RESENT_TO;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_RESENT_CC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_RESENT_BCC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

	} else {
		const CamelInternetAddress *addr;
		const gchar *type;

		addr = camel_mime_message_get_from (message);
		camel_address_copy (from, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_TO;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_CC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_BCC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));
	}

	/* Miscellaneous preparations. */

	info = camel_message_info_new (NULL);
	camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0);

	/* The rest of the processing happens in a thread. */

	context = g_slice_new0 (AsyncContext);
	context->message = g_object_ref (message);
	context->io_priority = io_priority;
	context->from = from;
	context->recipients = recipients;
	context->message = g_object_ref (message);
	context->info = info;
	context->xev = xev;
	context->post_to_uris = post_to_uris;
	context->transport_uid = transport_uid;
	context->sent_folder_uri = sent_folder_uri;

	if (G_IS_CANCELLABLE (cancellable))
		context->cancellable = g_object_ref (cancellable);

	/* Failure here emits a runtime warning but is non-fatal. */
	context->driver = camel_session_get_filter_driver (
		CAMEL_SESSION (session), E_FILTER_SOURCE_OUTGOING, &error);
	if (context->driver != NULL && get_folder_func)
		camel_filter_driver_set_folder_func (
			context->driver, get_folder_func, get_folder_data);
	if (error != NULL) {
		g_warn_if_fail (context->driver == NULL);
		g_warning ("%s", error->message);
		g_error_free (error);
	}

	/* This gets popped in async_context_free(). */
	camel_operation_push_message (
		context->cancellable, _("Sending message"));

	simple = g_simple_async_result_new (
		G_OBJECT (session), callback,
		user_data, e_mail_session_send_to);

	g_simple_async_result_set_op_res_gpointer (
		simple, context, (GDestroyNotify) async_context_free);

	g_simple_async_result_run_in_thread (
		simple, (GSimpleAsyncThreadFunc)
		mail_session_send_to_thread,
		context->io_priority,
		context->cancellable);

	g_object_unref (simple);
}