Example #1
0
static void
import_mbox_add_message (CamelFolder *folder,
			 CamelMimeMessage *msg,
			 GCancellable *cancellable,
			 GError **error)
{
	CamelMessageInfo *info;
	CamelMedium *medium;
	guint32 flags = 0;
	const gchar *tmp;

	g_return_if_fail (CAMEL_IS_FOLDER (folder));
	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (msg));

	medium = CAMEL_MEDIUM (msg);

	tmp = camel_medium_get_header (medium, "X-Mozilla-Status");
	if (tmp)
		flags |= decode_mozilla_status (tmp);
	tmp = camel_medium_get_header (medium, "Status");
	if (tmp)
		flags |= decode_status (tmp);
	tmp = camel_medium_get_header (medium, "X-Status");
	if (tmp)
		flags |= decode_status (tmp);

	info = camel_message_info_new (NULL);

	camel_message_info_set_flags (info, flags, ~0);
	camel_folder_append_message_sync (
		folder, msg, info, NULL,
		cancellable, error);
	camel_message_info_unref (info);
}
Example #2
0
static void
test_add_message (CamelFolder *folder,
                  gint j)
{
	CamelMimeMessage *msg;
	gchar *content;
	gchar *subject;
	GError *error = NULL;

	push ("creating message %d\n", j);
	msg = test_message_create_simple ();
	content = g_strdup_printf ("Test message %08x contents\n\n", j);
	test_message_set_content_simple (
		(CamelMimePart *) msg, 0, "text/plain",
							content, strlen (content));
	test_free (content);
	subject = g_strdup_printf ("Test message %08x subject", j);
	camel_mime_message_set_subject (msg, subject);
	pull ();

	push ("appending simple message %d", j);
	camel_folder_append_message_sync (
		folder, msg, NULL, NULL, NULL, &error);
	check_msg (error == NULL, "%s", error->message);
	g_clear_error (&error);
	pull ();

	check_unref (msg, 1);
}
static gint
exchange_entry_play_append (CamelOfflineJournal *journal,
                            CamelExchangeJournalEntry *entry,
                            GCancellable *cancellable,
                            GError **error)
{
	CamelExchangeFolder *exchange_folder = (CamelExchangeFolder *) journal->folder;
	CamelFolder *folder = journal->folder;
	CamelMimeMessage *message;
	CamelMessageInfo *info, *real;
	CamelStream *stream;
	gchar *uid = NULL;

	/* if the message isn't in the cache, the user went behind our backs so "not our problem" */
	if (!exchange_folder->cache || !(stream = camel_data_cache_get (exchange_folder->cache, "cache", entry->uid, NULL)))
		goto done;

	message = camel_mime_message_new ();
	if (!camel_data_wrapper_construct_from_stream_sync (
		(CamelDataWrapper *) message, stream, cancellable, NULL)) {
		g_object_unref (message);
		g_object_unref (stream);
		goto done;
	}

	g_object_unref (stream);

	if (!(info = camel_folder_summary_get (folder->summary, entry->uid))) {
		/* Should have never happened, but create a new info to avoid further crashes */
		info = camel_message_info_new (NULL);
	}

	if (!camel_folder_append_message_sync (
		folder, message, info, &uid, cancellable, error))
		return -1;

	real = camel_folder_summary_info_new_from_message (folder->summary, message, NULL);
	g_object_unref (message);

	if (uid != NULL && real) {
		real->uid = camel_pstring_strdup (uid);
		exchange_message_info_dup_to ((CamelMessageInfoBase *) real, (CamelMessageInfoBase *) info);
		camel_folder_summary_add (folder->summary, real);
		/* FIXME: should a folder_changed event be triggered? */
	}
	camel_message_info_free (info);
	g_free (uid);

 done:

	camel_exchange_folder_remove_message (exchange_folder, entry->uid);

	return 0;
}
static void
mail_send_short_to_thread (GSimpleAsyncResult *simple, EMailSession *session,
						GCancellable *cancellable)
{
	SendAsyncContext *context;
	CamelFolder *local_sent_folder;
	CamelProvider *provider;
	CamelService *service;
	CamelInternetAddress *cia;
	const gchar *addr;
	gint i, len;
	gboolean copy_to_sent = TRUE;
	GError *error = NULL;
	gboolean success = FALSE;
	gboolean did_connect = FALSE;
	gboolean cancelled = FALSE;

	context = g_simple_async_result_get_op_res_gpointer (simple);

	/* Connect transport service */

	service = context->transport;

	if (camel_service_get_connection_status (service) !=
						CAMEL_SERVICE_CONNECTED) {
		did_connect = TRUE;

		if (!camel_service_connect_sync (service, &error)) {
			mail_send_short_connection_fail (context);
			g_simple_async_result_take_error (simple, error);
			return;
		}
	}

	provider = camel_service_get_provider (service);

	if (provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER)
		copy_to_sent = FALSE;

	/* Send the message to each individual recipient. */

	len = camel_address_length (context->recipients);
	for (i = 0; i < len; i++) {
		if (!cancelled) {
			if (!camel_internet_address_get(
				CAMEL_INTERNET_ADDRESS(context->recipients),
				i, NULL, &addr))
					continue;

			cia = camel_internet_address_new ();
			camel_internet_address_add (cia, NULL, addr);
			camel_transport_send_to_sync (
				CAMEL_TRANSPORT (service), context->message,
				context->from, CAMEL_ADDRESS(cia),
				cancellable, &error);
			g_object_unref(cia);
		}

		if (error) {
			g_variant_builder_add (context->result, "(sssi)", addr,
					error->message,
					g_quark_to_string(error->domain),
					error->code);
			if (g_error_matches (error, G_IO_ERROR,
							G_IO_ERROR_CANCELLED))
				cancelled = TRUE;
			else
				g_clear_error (&error);
		} else {
			g_variant_builder_add (context->result, "(sssi)", addr,
								"", "", 0);
			success = TRUE;
		}

		camel_operation_progress (cancellable, (i+1)*100/len);
	}

	g_clear_error (&error);

	if (did_connect)
		camel_service_disconnect_sync (service, FALSE, NULL);

	/*** Post Processing ***/

	if (!success) {
		g_simple_async_result_set_error (
					simple, E_MAIL_ERROR,
					E_MAIL_ERROR_POST_PROCESSING,
					_("All recipients failed"));
		return;
	}

	/* Run filters on the outgoing message. */
	if (context->driver != NULL) {
		camel_filter_driver_filter_message (
			context->driver, context->message, context->info,
			NULL, NULL, NULL, "", cancellable, &error);

		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
			goto exit;
		g_clear_error (&error);
	}

	if (!copy_to_sent)
		goto cleanup;

	/* Append the sent message to a Sent folder. */
	local_sent_folder = e_mail_session_get_local_folder (session,
						E_MAIL_LOCAL_FOLDER_SENT);

	/* Try to extract a CamelFolder from the Sent folder URI. */
	if (context->sent_folder_uri != NULL) {
		context->sent_folder = e_mail_session_uri_to_folder_sync (
					session, context->sent_folder_uri, 0,
					cancellable, &error);
		if (error != NULL) {
			g_warn_if_fail (context->sent_folder == NULL);
			g_clear_error (&error);
		}
	}

	/* Fall back to the local Sent folder. */
	if (context->sent_folder == NULL)
		context->sent_folder = g_object_ref (local_sent_folder);

	/* Append the message. */
	camel_folder_append_message_sync (
				context->sent_folder, context->message,
				context->info, NULL, cancellable, &error);

	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
		goto exit;

	if (error == NULL)
		goto cleanup;

	/* If appending to a remote Sent folder failed,
	 * try appending to the local Sent folder. */
	if (context->sent_folder != local_sent_folder) {
		g_clear_error (&error);
		camel_folder_append_message_sync (local_sent_folder,
					context->message, context->info, NULL,
					cancellable, &error);
	}

	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
		goto exit;

	/* We can't even append to the local Sent folder?
	 * In that case just leave the message in Outbox. */
	if (error != NULL) {
		g_clear_error (&error);
		goto exit;
	}

cleanup:

	/* The send operation was successful; ignore cleanup errors. */

	/* Mark the draft message for deletion, if present. */
	e_mail_session_handle_draft_headers_sync (session, context->message,
							cancellable, &error);
	if (error != NULL) {
		g_warning ("%s", error->message);
		g_clear_error (&error);
	}

	/* Set flags on the original source message, if present.
	 * Source message refers to the message being forwarded
	 * or replied to. */
	e_mail_session_handle_source_headers_sync (session, context->message,
							cancellable, &error);
	if (error != NULL) {
		g_warning ("%s", error->message);
		g_clear_error (&error);
	}

exit:

	/* If we were cancelled, disregard any other errors. */
	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
		g_simple_async_result_take_error (simple, error);

	/* Stuff the accumulated error messages in a GError. */
	} else if (error != NULL) {
		g_simple_async_result_set_error (simple, E_MAIL_ERROR,
			E_MAIL_ERROR_POST_PROCESSING, "%s", error->message);
	}

	/* Synchronize the Sent folder. */
	if (context->sent_folder != NULL)
		camel_folder_synchronize_sync (context->sent_folder, FALSE,
							cancellable, NULL);
}
static void
mail_session_send_to_thread (GSimpleAsyncResult *simple,
                             EMailSession *session,
                             GCancellable *cancellable)
{
	AsyncContext *context;
	CamelProvider *provider;
	CamelFolder *folder = NULL;
	CamelFolder *local_sent_folder;
	CamelServiceConnectionStatus status;
	GString *error_messages;
	gboolean copy_to_sent = TRUE;
	gboolean did_connect = FALSE;
	guint ii;
	GError *error = NULL;

	context = g_simple_async_result_get_op_res_gpointer (simple);

	if (camel_address_length (context->recipients) == 0)
		goto skip_send;

	/* Send the message to all recipients. */

	/* XXX Leave this untranslated in gnome-3-8.
	 *     It was added during the string freeze,
	 *     but should rarely ever be seen by users. */
	if (context->transport == NULL) {
		g_simple_async_result_set_error (
			simple, CAMEL_SERVICE_ERROR,
			CAMEL_SERVICE_ERROR_UNAVAILABLE,
			"No mail transport service available");
		return;
	}

	status = camel_service_get_connection_status (context->transport);
	if (status != CAMEL_SERVICE_CONNECTED) {
		did_connect = TRUE;

		camel_service_connect_sync (
			context->transport, cancellable, &error);

		if (error != NULL) {
			g_simple_async_result_take_error (simple, error);
			return;
		}
	}

	provider = camel_service_get_provider (context->transport);

	if (provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER)
		copy_to_sent = FALSE;

	camel_transport_send_to_sync (
		CAMEL_TRANSPORT (context->transport),
		context->message, context->from,
		context->recipients, cancellable, &error);

	if (did_connect) {
		/* Disconnect regardless of error or cancellation,
		 * but be mindful of these conditions when calling
		 * camel_service_disconnect_sync(). */
		if (g_cancellable_is_cancelled (cancellable)) {
			camel_service_disconnect_sync (
				context->transport, FALSE, NULL, NULL);
		} else if (error != NULL) {
			camel_service_disconnect_sync (
				context->transport, FALSE, cancellable, NULL);
		} else {
			camel_service_disconnect_sync (
				context->transport, TRUE, cancellable, &error);
		}

		if (error != NULL) {
			g_simple_async_result_take_error (simple, error);
			return;
		}
	}

skip_send:
	/* Post the message to requested folders. */
	for (ii = 0; ii < context->post_to_uris->len; ii++) {
		CamelFolder *folder;
		const gchar *folder_uri;

		folder_uri = g_ptr_array_index (context->post_to_uris, ii);

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

		if (error != NULL) {
			g_warn_if_fail (folder == NULL);
			g_simple_async_result_take_error (simple, error);
			return;
		}

		g_return_if_fail (CAMEL_IS_FOLDER (folder));

		camel_folder_append_message_sync (
			folder, context->message, context->info,
			NULL, cancellable, &error);

		g_object_unref (folder);

		if (error != NULL) {
			g_simple_async_result_take_error (simple, error);
			return;
		}
	}

	/*** Post Processing ***/

	/* This accumulates error messages during post-processing. */
	error_messages = g_string_sized_new (256);

	mail_tool_restore_xevolution_headers (context->message, context->xev);

	/* Run filters on the outgoing message. */
	if (context->driver != NULL) {
		camel_filter_driver_filter_message (
			context->driver, context->message, context->info,
			NULL, NULL, NULL, "", cancellable, &error);

		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
			goto exit;

		if (error != NULL) {
			g_string_append_printf (
				error_messages,
				_("Failed to apply outgoing filters: %s"),
				error->message);
			g_clear_error (&error);
		}

		if ((camel_message_info_flags (context->info) & CAMEL_MESSAGE_DELETED) != 0)
			copy_to_sent = FALSE;
	}

	if (!copy_to_sent)
		goto cleanup;

	/* Append the sent message to a Sent folder. */

	local_sent_folder =
		e_mail_session_get_local_folder (
		session, E_MAIL_LOCAL_FOLDER_SENT);

	folder = e_mail_session_get_fcc_for_message_sync (
		session, context->message, cancellable, &error);

	/* Sanity check. */
	g_return_if_fail (
		((folder != NULL) && (error == NULL)) ||
		((folder == NULL) && (error != NULL)));

	/* Append the message. */
	if (folder != NULL)
		camel_folder_append_message_sync (
			folder, context->message,
			context->info, NULL, cancellable, &error);

	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
		goto exit;

	if (error == NULL)
		goto cleanup;

	if (folder != NULL && folder != local_sent_folder) {
		const gchar *description;

		description = camel_folder_get_description (folder);

		if (error_messages->len > 0)
			g_string_append (error_messages, "\n\n");
		g_string_append_printf (
			error_messages,
			_("Failed to append to %s: %s\n"
			"Appending to local 'Sent' folder instead."),
			description, error->message);
	}

	/* If appending to a remote Sent folder failed,
	 * try appending to the local Sent folder. */
	if (folder != local_sent_folder) {

		g_clear_error (&error);

		camel_folder_append_message_sync (
			local_sent_folder, context->message,
			context->info, NULL, cancellable, &error);
	}

	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
		goto exit;

	/* We can't even append to the local Sent folder?
	 * In that case just leave the message in Outbox. */
	if (error != NULL) {
		if (error_messages->len > 0)
			g_string_append (error_messages, "\n\n");
		g_string_append_printf (
			error_messages,
			_("Failed to append to local 'Sent' folder: %s"),
			error->message);
		g_clear_error (&error);
		goto exit;
	}

cleanup:

	/* The send operation was successful; ignore cleanup errors. */

	/* Mark the draft message for deletion, if present. */
	e_mail_session_handle_draft_headers_sync (
		session, context->message, cancellable, &error);
	if (error != NULL) {
		g_warning ("%s", error->message);
		g_clear_error (&error);
	}

	/* Set flags on the original source message, if present.
	 * Source message refers to the message being forwarded
	 * or replied to. */
	e_mail_session_handle_source_headers_sync (
		session, context->message, cancellable, &error);
	if (error != NULL) {
		g_warning ("%s", error->message);
		g_clear_error (&error);
	}

exit:

	/* If we were cancelled, disregard any other errors. */
	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
		g_simple_async_result_take_error (simple, error);

	/* Stuff the accumulated error messages in a GError. */
	} else if (error_messages->len > 0) {
		g_simple_async_result_set_error (
			simple, E_MAIL_ERROR,
			E_MAIL_ERROR_POST_PROCESSING,
			"%s", error_messages->str);
	}

	/* Synchronize the Sent folder. */
	if (folder != NULL) {
		camel_folder_synchronize_sync (
			folder, FALSE, cancellable, NULL);
		g_object_unref (folder);
	}

	g_string_free (error_messages, TRUE);
}
/* this should probably take a folder instead of a session ... */
void
test_folder_message_ops (CamelSession *session,
                         const gchar *name,
                         gint local,
                         const gchar *mailbox)
{
	CamelStore *store;
	CamelService *service;
	CamelFolder *folder;
	CamelMimeMessage *msg;
	gint j;
	gint indexed, max;
	GPtrArray *uids;
	CamelMessageInfo *info;
	GError *error = NULL;

	max = local ? 2 : 1;

	for (indexed = 0; indexed < max; indexed++) {
		gchar *what = g_strdup_printf ("folder ops: %s %s", name, local ? (indexed?"indexed":"non-indexed"):"");
		gint flags;

		camel_test_start (what);
		test_free (what);

		push ("getting store");
		service = camel_session_add_service (
			session, name, name, CAMEL_PROVIDER_STORE, &error);
		check_msg (error == NULL, "adding store: %s", error->message);
		check (CAMEL_IS_STORE (service));
		store = CAMEL_STORE (service);
		g_clear_error (&error);
		pull ();

		push ("creating %sindexed folder", indexed?"":"non-");
		if (indexed)
			flags = CAMEL_STORE_FOLDER_CREATE | CAMEL_STORE_FOLDER_BODY_INDEX;
		else
			flags = CAMEL_STORE_FOLDER_CREATE;
		folder = camel_store_get_folder_sync (
			store, mailbox, flags, NULL, &error);

		/* we can't create mailbox outside of namespace, since we have no api for it, try
		 * using inbox namespace, works for courier */
		if (folder == NULL) {
			gchar *mbox = g_strdup_printf ("INBOX/%s", mailbox);
			mailbox = mbox;
			g_clear_error (&error);
			folder = camel_store_get_folder_sync (
				store, mailbox, flags, NULL, &error);
		}

		check_msg (error == NULL, "%s", error->message);
		check (folder != NULL);

		/* verify empty/can't get nonexistant stuff */
		test_folder_counts (folder, 0, 0);
		test_folder_not_message (folder, "0");
		test_folder_not_message (folder, "");

		for (j = 0; j < 10; j++) {
			gchar *content, *subject;

			push ("creating test message");
			msg = test_message_create_simple ();
			content = g_strdup_printf ("Test message %d contents\n\n", j);
			test_message_set_content_simple (
				(CamelMimePart *) msg, 0, "text/plain",
							content, strlen (content));
			test_free (content);
			subject = g_strdup_printf ("Test message %d", j);
			camel_mime_message_set_subject (msg, subject);
			pull ();

			push ("appending simple message %d", j);
			camel_folder_append_message_sync (
				folder, msg, NULL, NULL, NULL, &error);
			check_msg (error == NULL, "%s", error->message);

#if 0
			/* sigh, this shouldn't be required, but the imap code is too dumb to do it itself */
			if (!local) {
				push ("forcing a refresh of folder updates");
				camel_folder_refresh_info (folder, ex);
				check_msg (error == NULL, "%s", error->message);
				pull ();
			}
#endif
			/*if (!local)
			  camel_test_nonfatal ("unread counts dont seem right for imap");*/

			test_folder_counts (folder, j + 1, j + 1);

			/*if (!local)
			  camel_test_fatal ();*/

			push ("checking it is in the right uid slot & exists");
			uids = camel_folder_get_uids (folder);
			check (uids != NULL);
			check (uids->len == j + 1);
			if (uids->len > j)
				test_folder_message (folder, uids->pdata[j]);
			pull ();

			push ("checking it is the right message (subject): %s", subject);
			if (uids->len > j) {
				info = camel_folder_get_message_info (folder, uids->pdata[j]);
				check (info != NULL);
				check_msg (
					strcmp (camel_message_info_get_subject (info), subject) == 0,
					"info->subject %s", camel_message_info_get_subject (info));
				camel_message_info_unref (info);
			}
			camel_folder_free_uids (folder, uids);
			pull ();

			test_free (subject);

			/*if (!local)
			  camel_test_fatal ();*/

			check_unref (msg, 1);
			pull ();
		}

		if (local)
			check_unref (folder, 1);
		else
			check_unref (folder, 2);
		pull ();

#if 0
		push ("deleting test folder, with messages in it");
		camel_store_delete_folder (store, mailbox, ex);
		check (camel_exception_is_set (ex));
		camel_exception_clear (ex);
		pull ();
#endif

		push ("re-opening folder");
		folder = camel_store_get_folder_sync (
			store, mailbox, flags, NULL, &error);
		check_msg (error == NULL, "%s", error->message);
		check (folder != NULL);
		g_clear_error (&error);

			/* verify counts */
		test_folder_counts (folder, 10, 10);

		/* re-check uid's, after a reload */
		uids = camel_folder_get_uids (folder);
		check (uids != NULL);
		check (uids->len == 10);
		for (j = 0; j < 10; j++) {
			gchar *subject = g_strdup_printf ("Test message %d", j);

			push ("verify reload of %s", subject);
			test_folder_message (folder, uids->pdata[j]);

			info = camel_folder_get_message_info (folder, uids->pdata[j]);
			check_msg (
				strcmp (camel_message_info_get_subject (info), subject) == 0,
				"info->subject %s", camel_message_info_get_subject (info));
			test_free (subject);
			camel_message_info_unref (info);
			pull ();
		}

		push ("deleting first message & expunging");
		camel_folder_delete_message (folder, uids->pdata[0]);
		test_folder_counts (folder, 10, 9);
		camel_folder_expunge_sync (folder, NULL, &error);
		check_msg (error == NULL, "%s", error->message);
		g_clear_error (&error);
		test_folder_not_message (folder, uids->pdata[0]);
		test_folder_counts (folder, 9, 9);

		camel_folder_free_uids (folder, uids);

		uids = camel_folder_get_uids (folder);
		check (uids != NULL);
		check (uids->len == 9);
		for (j = 0; j < 9; j++) {
			gchar *subject = g_strdup_printf ("Test message %d", j + 1);

			push ("verify after expunge of %s", subject);
			test_folder_message (folder, uids->pdata[j]);

			info = camel_folder_get_message_info (folder, uids->pdata[j]);
			check_msg (
				strcmp (camel_message_info_get_subject (info), subject) == 0,
				"info->subject %s", camel_message_info_get_subject (info));
			test_free (subject);
			camel_message_info_unref (info);
			pull ();
		}
		pull ();

		push ("deleting last message & expunging");
		camel_folder_delete_message (folder, uids->pdata[8]);
		/* sync? */
		test_folder_counts (folder, 9, 8);
		camel_folder_expunge_sync (folder, NULL, &error);
		check_msg (error == NULL, "%s", error->message);
		g_clear_error (&error);
		test_folder_not_message (folder, uids->pdata[8]);
		test_folder_counts (folder, 8, 8);

		camel_folder_free_uids (folder, uids);

		uids = camel_folder_get_uids (folder);
		check (uids != NULL);
		check (uids->len == 8);
		for (j = 0; j < 8; j++) {
			gchar *subject = g_strdup_printf ("Test message %d", j + 1);

			push ("verify after expunge of %s", subject);
			test_folder_message (folder, uids->pdata[j]);

			info = camel_folder_get_message_info (folder, uids->pdata[j]);
			check_msg (
				strcmp (camel_message_info_get_subject (info), subject) == 0,
				"info->subject %s", camel_message_info_get_subject (info));
			test_free (subject);
			camel_message_info_unref (info);
			pull ();
		}
		pull ();

		push ("deleting all messages & expunging");
		for (j = 0; j < 8; j++) {
			camel_folder_delete_message (folder, uids->pdata[j]);
		}
		/* sync? */
		test_folder_counts (folder, 8, 0);
		camel_folder_expunge_sync (folder, NULL, &error);
		check_msg (error == NULL, "%s", error->message);
		g_clear_error (&error);
		for (j = 0; j < 8; j++) {
			test_folder_not_message (folder, uids->pdata[j]);
		}
		test_folder_counts (folder, 0, 0);

		camel_folder_free_uids (folder, uids);
		pull ();

		if (local)
			check_unref (folder, 1);
		else
			check_unref (folder, 2);
		pull (); /* re-opening folder */

		if (g_ascii_strcasecmp (mailbox, "INBOX") != 0) {
			push ("deleting test folder, with no messages in it");
			camel_store_delete_folder_sync (
				store, mailbox, NULL, &error);
			check_msg (error == NULL, "%s", error->message);
			g_clear_error (&error);
			pull ();
		}

		if (!local) {
			push ("disconneect service");
			camel_service_disconnect_sync (
				CAMEL_SERVICE (store), TRUE, NULL, &error);
			check_msg (error == NULL, "%s", error->message);
			g_clear_error (&error);
			pull ();
		}

		check_unref (store, 1);
		camel_test_end ();
	}
}
Example #7
0
static void
mail_session_send_to_thread (GSimpleAsyncResult *simple,
                             EMailSession *session,
                             GCancellable *cancellable)
{
	AsyncContext *context;
	CamelFolder *local_sent_folder;
	GString *error_messages;
	gboolean copy_to_sent = TRUE;
	guint ii;
	GError *error = NULL;

	context = g_simple_async_result_get_op_res_gpointer (simple);

	/* Send the message to all recipients. */
	if (camel_address_length (context->recipients) > 0) {
		CamelProvider *provider;
		CamelService *service;
		gboolean did_connect = FALSE;

		service = camel_session_get_service (
			CAMEL_SESSION (session), context->transport_uid);

		if (!CAMEL_IS_TRANSPORT (service)) {
			g_simple_async_result_set_error (simple,
				CAMEL_SERVICE_ERROR,
				CAMEL_SERVICE_ERROR_URL_INVALID,
				_("Cannot get transport for account '%s'"),
				context->transport_uid);
			return;
		}

		if (camel_service_get_connection_status (service) != CAMEL_SERVICE_CONNECTED) {
			did_connect = TRUE;

			/* XXX This API does not allow for cancellation. */
			if (!em_utils_connect_service_sync (service, cancellable, &error)) {
				g_simple_async_result_take_error (simple, error);
				return;
			}
		}

		provider = camel_service_get_provider (service);

		if (provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER)
			copy_to_sent = FALSE;

		camel_transport_send_to_sync (
			CAMEL_TRANSPORT (service),
			context->message, context->from,
			context->recipients, cancellable, &error);

		if (did_connect)
			em_utils_disconnect_service_sync (
				service, error == NULL,
				cancellable, error ? NULL : &error);

		if (error != NULL) {
			g_simple_async_result_take_error (simple, error);
			return;
		}
	}

	/* Post the message to requested folders. */
	for (ii = 0; ii < context->post_to_uris->len; ii++) {
		CamelFolder *folder;
		const gchar *folder_uri;

		folder_uri = g_ptr_array_index (context->post_to_uris, ii);

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

		if (error != NULL) {
			g_warn_if_fail (folder == NULL);
			g_simple_async_result_take_error (simple, error);
			return;
		}

		g_return_if_fail (CAMEL_IS_FOLDER (folder));

		camel_folder_append_message_sync (
			folder, context->message, context->info,
			NULL, cancellable, &error);

		g_object_unref (folder);

		if (error != NULL) {
			g_simple_async_result_take_error (simple, error);
			return;
		}
	}

	/*** Post Processing ***/

	/* This accumulates error messages during post-processing. */
	error_messages = g_string_sized_new (256);

	mail_tool_restore_xevolution_headers (context->message, context->xev);

	/* Run filters on the outgoing message. */
	if (context->driver != NULL) {
		camel_filter_driver_filter_message (
			context->driver, context->message, context->info,
			NULL, NULL, NULL, "", cancellable, &error);

		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
			goto exit;

		if (error != NULL) {
			g_string_append_printf (
				error_messages,
				_("Failed to apply outgoing filters: %s"),
				error->message);
			g_clear_error (&error);
		}
	}

	if (!copy_to_sent)
		goto cleanup;

	/* Append the sent message to a Sent folder. */

	local_sent_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT);

	/* Try to extract a CamelFolder from the Sent folder URI. */
	if (context->sent_folder_uri != NULL) {
		context->sent_folder = e_mail_session_uri_to_folder_sync (
			session, context->sent_folder_uri, 0,
			cancellable, &error);
		if (error != NULL) {
			g_warn_if_fail (context->sent_folder == NULL);
			if (error_messages->len > 0)
				g_string_append (error_messages, "\n\n");
			g_string_append_printf (
				error_messages,
				_("Failed to append to %s: %s\n"
				  "Appending to local 'Sent' folder instead."),
				context->sent_folder_uri, error->message);
			g_clear_error (&error);
		}
	}

	/* Fall back to the local Sent folder. */
	if (context->sent_folder == NULL)
		context->sent_folder = g_object_ref (local_sent_folder);

	/* Append the message. */
	camel_folder_append_message_sync (
		context->sent_folder, context->message,
		context->info, NULL, cancellable, &error);

	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
		goto exit;

	if (error == NULL)
		goto cleanup;

	/* If appending to a remote Sent folder failed,
	 * try appending to the local Sent folder. */
	if (context->sent_folder != local_sent_folder) {
		const gchar *description;

		description = camel_folder_get_description (
			context->sent_folder);

		if (error_messages->len > 0)
			g_string_append (error_messages, "\n\n");
		g_string_append_printf (
			error_messages,
			_("Failed to append to %s: %s\n"
			  "Appending to local 'Sent' folder instead."),
			description, error->message);
		g_clear_error (&error);

		camel_folder_append_message_sync (
			local_sent_folder, context->message,
			context->info, NULL, cancellable, &error);
	}

	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
		goto exit;

	/* We can't even append to the local Sent folder?
	 * In that case just leave the message in Outbox. */
	if (error != NULL) {
		if (error_messages->len > 0)
			g_string_append (error_messages, "\n\n");
		g_string_append_printf (
			error_messages,
			_("Failed to append to local 'Sent' folder: %s"),
			error->message);
		g_clear_error (&error);
		goto exit;
	}

cleanup:

	/* The send operation was successful; ignore cleanup errors. */

	/* Mark the draft message for deletion, if present. */
	e_mail_session_handle_draft_headers_sync (
		session, context->message, cancellable, &error);
	if (error != NULL) {
		g_warning ("%s", error->message);
		g_clear_error (&error);
	}

	/* Set flags on the original source message, if present.
	 * Source message refers to the message being forwarded
	 * or replied to. */
	e_mail_session_handle_source_headers_sync (
		session, context->message, cancellable, &error);
	if (error != NULL) {
		g_warning ("%s", error->message);
		g_clear_error (&error);
	}

exit:

	/* If we were cancelled, disregard any other errors. */
	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
		g_simple_async_result_take_error (simple, error);

	/* Stuff the accumulated error messages in a GError. */
	} else if (error_messages->len > 0) {
		g_simple_async_result_set_error (
			simple, E_MAIL_ERROR,
			E_MAIL_ERROR_POST_PROCESSING,
			"%s", error_messages->str);
	}

	/* Synchronize the Sent folder. */
	if (context->sent_folder != NULL)
		camel_folder_synchronize_sync (
			context->sent_folder, FALSE, cancellable, NULL);

	g_string_free (error_messages, TRUE);
}
Example #8
0
gint
main (gint argc,
      gchar **argv)
{
	CamelService *service;
	CamelSession *session;
	CamelStore *store;
	CamelFolder *folder;
	CamelMimeMessage *msg;
	gint i, j;
	gint indexed;
	GPtrArray *uids;
	GError *error = NULL;

	camel_test_init (argc, argv);
	camel_test_provider_init (1, local_drivers);

	/* clear out any camel-test data */
	system ("/bin/rm -rf /tmp/camel-test");

	session = camel_test_session_new ("/tmp/camel-test");

	/* todo: cross-check everything with folder_info checks as well */
	/* todo: work out how to do imap/pop/nntp tests */

	/* we iterate over all stores we want to test, with indexing or indexing turned on or off */
	for (i = 0; i < G_N_ELEMENTS (stores); i++) {
		const gchar *name = stores[i];
		for (indexed = 0; indexed < 2; indexed++) {
			gchar *what = g_strdup_printf ("folder search: %s (%sindexed)", name, indexed?"":"non-");
			gchar *uid;
			gint flags;

			camel_test_start (what);
			test_free (what);

			push ("getting store");
			uid = g_strdup_printf ("test-uid-%d", i);
			service = camel_session_add_service (
				session, uid, stores[i],
				CAMEL_PROVIDER_STORE, &error);
			g_free (uid);
			check_msg (error == NULL, "adding store: %s", error->message);
			check (CAMEL_IS_STORE (service));
			store = CAMEL_STORE (service);
			g_clear_error (&error);
			pull ();

			push ("creating %sindexed folder", indexed?"":"non-");
			if (indexed)
				flags = CAMEL_STORE_FOLDER_CREATE | CAMEL_STORE_FOLDER_BODY_INDEX;
			else
				flags = CAMEL_STORE_FOLDER_CREATE;
			folder = camel_store_get_folder_sync (
				store, "testbox", flags, NULL, &error);
			check_msg (error == NULL, "%s", error->message);
			check (folder != NULL);

			/* we need an empty folder for this to work */
			test_folder_counts (folder, 0, 0);
			g_clear_error (&error);
			pull ();

			/* append a bunch of messages with specific content */
			push ("appending 100 test messages");
			for (j = 0; j < 100; j++) {
				gchar *content, *subject;

				push ("creating test message");
				msg = test_message_create_simple ();
				content = g_strdup_printf ("data%d content\n", j);
				test_message_set_content_simple (
					(CamelMimePart *) msg, 0, "text/plain",
								content, strlen (content));
				test_free (content);
				subject = g_strdup_printf ("Test%d message%d subject", j, 100 - j);
				camel_mime_message_set_subject (msg, subject);

				camel_mime_message_set_date (msg, j * 60 * 24, 0);
				pull ();

				push ("appending simple message %d", j);
				camel_folder_append_message_sync (
					folder, msg, NULL, NULL, NULL, &error);
				check_msg (error == NULL, "%s", error->message);
				g_clear_error (&error);
				pull ();

				test_free (subject);

				check_unref (msg, 1);
			}
			pull ();

			push ("Setting up some flags &c");
			uids = camel_folder_get_uids (folder);
			check (uids->len == 100);
			for (j = 0; j < 100; j++) {
				gchar *uid = uids->pdata[j];

				if ((j / 13) * 13 == j) {
					camel_folder_set_message_user_flag (folder, uid, "every13", TRUE);
				}
				if ((j / 17) * 17 == j) {
					camel_folder_set_message_user_flag (folder, uid, "every17", TRUE);
				}
				if ((j / 7) * 7 == j) {
					gchar *tag = g_strdup_printf ("7tag%d", j / 7);
					camel_folder_set_message_user_tag (folder, uid, "every7", tag);
					test_free (tag);
				}
				if ((j / 11) * 11 == j) {
					camel_folder_set_message_user_tag (folder, uid, "every11", "11tag");
				}
			}
			camel_folder_free_uids (folder, uids);
			pull ();

			camel_test_nonfatal ("Index not guaranteed to be accurate before sync: should be fixed eventually");
			push ("Search before sync");
			run_search (folder, 100);
			pull ();
			camel_test_fatal ();

			push ("syncing folder, searching");
			camel_folder_synchronize_sync (
				folder, FALSE, NULL, NULL);
			run_search (folder, 100);
			pull ();

			push ("syncing wiht expunge, search");
			camel_folder_synchronize_sync (
				folder, TRUE, NULL, NULL);
			run_search (folder, 100);
			pull ();

			push ("deleting every 2nd message");
			uids = camel_folder_get_uids (folder);
			check (uids->len == 100);
			for (j = 0; j < uids->len; j+=2) {
				camel_folder_delete_message (folder, uids->pdata[j]);
			}
			camel_folder_free_uids (folder, uids);
			run_search (folder, 100);

			push ("syncing");
			camel_folder_synchronize_sync (
				folder, FALSE, NULL, &error);
			check_msg (error == NULL, "%s", error->message);
			run_search (folder, 100);
			g_clear_error (&error);
			pull ();

			push ("expunging");
			camel_folder_expunge_sync (folder, NULL, &error);
			check_msg (error == NULL, "%s", error->message);
			run_search (folder, 50);
			g_clear_error (&error);
			pull ();

			pull ();

			push ("closing and re-opening folder");
			check_unref (folder, 1);
			folder = camel_store_get_folder_sync (
				store, "testbox",
				flags & ~(CAMEL_STORE_FOLDER_CREATE),
				NULL, &error);
			check_msg (error == NULL, "%s", error->message);
			check (folder != NULL);
			g_clear_error (&error);

			push ("deleting remaining messages");
			uids = camel_folder_get_uids (folder);
			check (uids->len == 50);
			for (j = 0; j < uids->len; j++) {
				camel_folder_delete_message (folder, uids->pdata[j]);
			}
			camel_folder_free_uids (folder, uids);
			run_search (folder, 50);

			push ("syncing");
			camel_folder_synchronize_sync (
				folder, FALSE, NULL, &error);
			check_msg (error == NULL, "%s", error->message);
			run_search (folder, 50);
			g_clear_error (&error);
			pull ();

			push ("expunging");
			camel_folder_expunge_sync (folder, NULL, &error);
			check_msg (error == NULL, "%s", error->message);
			run_search (folder, 0);
			g_clear_error (&error);
			pull ();

			pull ();

			check_unref (folder, 1);
			pull ();

			push ("deleting test folder, with no messages in it");
			camel_store_delete_folder_sync (
				store, "testbox", NULL, &error);
			check_msg (error == NULL, "%s", error->message);
			g_clear_error (&error);
			pull ();

			check_unref (store, 1);
			camel_test_end ();
		}
	}

	check_unref (session, 1);

	return 0;
}
Example #9
0
static void
dbx_import_file (DbxImporter *m)
{
	EShell *shell;
	EShellBackend *shell_backend;
	EMailSession *session;
	GCancellable *cancellable;
	gchar *filename;
	CamelFolder *folder;
	gint tmpfile;
	gint i;
	gint missing = 0;
	m->status_what = NULL;
	filename = g_filename_from_uri (
		((EImportTargetURI *) m->target)->uri_src, NULL, NULL);

	/* Destination folder, was set in our widget */
	m->parent_uri = g_strdup (((EImportTargetURI *) m->target)->uri_dest);

	cancellable = m->base.cancellable;

	/* XXX Dig up the EMailSession from the default EShell.
	 *     Since the EImport framework doesn't allow for user
	 *     data, I don't see how else to get to it. */
	shell = e_shell_get_default ();
	shell_backend = e_shell_get_backend_by_name (shell, "mail");
	session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend));

	camel_operation_push_message (NULL, _("Importing ā€œ%sā€"), filename);
	folder = e_mail_session_uri_to_folder_sync (
		session, m->parent_uri, CAMEL_STORE_FOLDER_CREATE,
		cancellable, &m->base.error);
	if (!folder)
		return;
	d (printf ("importing to %s\n", camel_folder_get_full_name (folder)));

	camel_folder_freeze (folder);

	filename = g_filename_from_uri (
		((EImportTargetURI *) m->target)->uri_src, NULL, NULL);
	m->dbx_fd = g_open (filename, O_RDONLY, 0);
	g_free (filename);

	if (m->dbx_fd == -1) {
		g_set_error (
			&m->base.error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			"Failed to open import file");
		goto out;
	}

	if (!dbx_load_indices (m))
		goto out;

	tmpfile = e_mkstemp ("dbx-import-XXXXXX");
	if (tmpfile == -1) {
		g_set_error (
			&m->base.error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			"Failed to create temporary file for import");
		goto out;
	}

	for (i = 0; i < m->index_count; i++) {
		CamelMessageInfo *info;
		CamelMimeMessage *msg;
		CamelMimeParser *mp;
		gint dbx_flags = 0;
		gint flags = 0;
		gboolean success;

		camel_operation_progress (NULL, 100 * i / m->index_count);
		camel_operation_progress (cancellable, 100 * i / m->index_count);

		if (!dbx_read_email (m, m->indices[i], tmpfile, &dbx_flags)) {
			d (
				printf ("Cannot read email index %d at %x\n",
				i, m->indices[i]));
			if (m->base.error != NULL)
				goto out;
			missing++;
			continue;
		}
		if (dbx_flags & 0x40)
			flags |= CAMEL_MESSAGE_DELETED;
		if (dbx_flags & 0x80)
			flags |= CAMEL_MESSAGE_SEEN;
		if (dbx_flags & 0x80000)
			flags |= CAMEL_MESSAGE_ANSWERED;

		mp = camel_mime_parser_new ();

		lseek (tmpfile, 0, SEEK_SET);
		camel_mime_parser_init_with_fd (mp, tmpfile);

		msg = camel_mime_message_new ();
		if (!camel_mime_part_construct_from_parser_sync (
			(CamelMimePart *) msg, mp, NULL, NULL)) {
			/* set exception? */
			g_object_unref (msg);
			g_object_unref (mp);
			break;
		}

		info = camel_message_info_new (NULL);
		camel_message_info_set_flags (info, flags, ~0);
		success = camel_folder_append_message_sync (
			folder, msg, info, NULL,
			cancellable, &m->base.error);
		g_clear_object (&info);
		g_object_unref (msg);

		if (!success) {
			g_object_unref (mp);
			break;
		}
	}
 out:
	if (m->dbx_fd != -1)
		close (m->dbx_fd);
	if (m->indices)
		g_free (m->indices);
	/* FIXME Not passing GCancellable or GError here. */
	camel_folder_synchronize_sync (folder, FALSE, NULL, NULL);
	camel_folder_thaw (folder);
	g_object_unref (folder);
	if (missing && m->base.error == NULL) {
		g_set_error (
			&m->base.error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			"%d messages imported correctly; %d message "
			"bodies were not present in the DBX file",
			m->index_count - missing, missing);
	}
	camel_operation_pop_message (NULL);
}
Example #10
0
static void
import_kmail_folder (struct _import_mbox_msg *m,
                     gchar *k_path_in,
                     GCancellable *cancellable,
                     GError **error)
{
	const gchar *special_folders []= {"cur", "tmp", "new", NULL};
	gchar *special_path;
	const CamelStore *store;
	CamelFolder *folder;
	CamelMimeParser *mp = NULL;
	CamelMessageInfo *info;
	CamelMimeMessage *msg;
	guint32 flags = 0;

	gchar *e_uri, *e_path;
	gchar *k_path;
	const gchar *d;
	gchar *mail_url;
	GDir *dir;
	struct stat st;
	gint fd, i;

	e_uri = kuri_to_euri (k_path_in);
	/* we need to drop some folders, like: Trash */
	if (!e_uri)
		return;

	/* In case we using async way in the future */
	k_path = g_strdup (k_path_in);
	store = evolution_get_local_store ();
	e_path = e_uri + strlen (EVOLUTION_LOCAL_BASE) + 1;
	e_mail_store_create_folder_sync ((CamelStore *)store, e_path, NULL, NULL);
	folder = e_mail_session_uri_to_folder_sync (
			m->session, e_uri, CAMEL_STORE_FOLDER_CREATE,
			cancellable, NULL);

	if (folder == NULL) {
		g_free (k_path);
		g_warning ("evolution error: cannot get the folder\n");
		return;
	}

	camel_operation_push_message (
			cancellable, _("Importing '%s'"),
			camel_folder_get_display_name (folder));
	camel_folder_freeze (folder);

	for (i = 0; special_folders [i]; i++) {
		camel_operation_progress (cancellable, 100*i/3);
		special_path = g_build_filename (k_path, special_folders[i], NULL);
		dir = g_dir_open (special_path, 0, NULL);
		while ((d = g_dir_read_name (dir))) {
			if ((strcmp (d, ".") == 0) || (strcmp (d, "..") == 0)) {
				continue;
			}
			mail_url = g_build_filename (special_path, d, NULL);
			if (g_stat (mail_url, &st) == -1) {
				g_free (mail_url);
				continue;
			}
			if (S_ISREG (st.st_mode)) {
				fd = g_open (mail_url, O_RDONLY | O_BINARY, 0);
				g_free (mail_url);
				if (fd == -1) {
					continue;
				}
				mp = camel_mime_parser_new ();
				camel_mime_parser_scan_from (mp, FALSE);
				if (camel_mime_parser_init_with_fd (mp, fd) == -1) {
					/* will never happen - 0 is unconditionally returned */
					g_object_unref (mp);
					continue;
				}
				msg = camel_mime_message_new ();
				if (!camel_mime_part_construct_from_parser_sync (
						(CamelMimePart *) msg, mp, NULL, NULL)) {
					/* set exception? */
					g_object_unref (mp);
					g_object_unref (msg);
					continue;
				}
				info = camel_message_info_new (NULL);
				if (strcmp (special_folders[i], "cur") == 0) {
					flags |= CAMEL_MESSAGE_SEEN;
				} else if (strcmp (special_folders[i], "tmp") == 0) {
					flags |= CAMEL_MESSAGE_DELETED; /* Mark the 'tmp' mails as 'deleted' */
				}
				camel_message_info_set_flags (info, flags, ~0);
				camel_folder_append_message_sync (
					folder, msg, info, NULL,
					cancellable, error);
				camel_message_info_unref (info);
				g_object_unref (msg);
				g_object_unref (mp);
			} else {
				g_free (mail_url);
			}
		}
	}
	camel_operation_progress (cancellable, 100);
	camel_folder_synchronize_sync (folder, FALSE, NULL, NULL);
	camel_folder_thaw (folder);
	camel_operation_pop_message (cancellable);

	g_free (k_path);
}