Creating a message

About

This tutorial is about preparing a message that must be send or stored in a folder like the draft folder.

The basic idea

The platform factory can create TnyHeader, TnyMimePart and TnyMsg instances for you. You will usually create at least a TnyMsg and a TnyHeader instance with it, fill in the TnyHeader instance and assign it to the TnyMsg instance using the tny_msg_set_header API of TnyMsg. Because the TnyMsg type inherits from TnyMimePart, you now already have a first mime part instance. Whenever you do TnyMimePart API operations on this instance you will be working on the body part of the E-mail.

You can also add extra mime parts to the message using the tny_mime_part_add_part API of TnyMimePart. Each such mime part can be fed data using the tny_mime_part_construct_from_stream API of TnyMimePart.

The TnyStream API is a typical stream API which makes it possible to write-to and read-from it. A source stream can for example be a file stream that reads data from a file. A target stream can also be a file stream that writes to a file. When constructinga TnyMimePart from a stream, you need to pass a source stream. If you only want to set a simple piece of text, you can for example use the TnyCamelMemStream? type, which is a stream type that uses simple memory as storage.

For file attachments you will usually want the TnyFsStream type, or the TnyVfsStream type from libtinymail-gnomevfs.

Normal E-mail

A normal E-mail with no attachments, just a body in plain text, is created using a stream that contains the ASCII text and "text/plain" as type parameter for tny_mime_part_construct with "7bit" as transfer encoding.

Sample code

#define TEST_STRING "This is a test E-mail"

static TnyMsg*
create_test_msg (TnyPlatformFactory *platfact)
{
	TnyMsg *retval = tny_platform_factory_new_msg (platfact);
	TnyStream *stream = tny_camel_mem_stream_new ();
	TnyHeader *header = tny_platform_factory_new_header (platfact);

	tny_header_set_subject (header, TEST_STRING);
	tny_header_set_from (header, "from.my@self.com");
	tny_header_set_to (header, "to.my@buddy.com");

	tny_msg_set_header (retval, header);
	g_object_unref (header);

	tny_stream_write (stream, TEST_STRING, strlen (TEST_STRING));
	tny_stream_reset (stream);

	tny_mime_part_construct (TNY_MIME_PART (retval), stream, "text/plain", "7bit"); 

	g_object_unref (stream);

	return retval;
}

HTML E-mail

A HTML E-mail with no attachments, just a body in plain HTML, is created using a stream that contains the HTML data and "text/html" as type parameter for tny_mime_part_construct with also 7bit as transfer encoding.

Sample code

#define TEST_STRING "<html><body><b>This is a test E-mail</b></body></html>"

static TnyMsg*
create_test_msg (TnyPlatformFactory *platfact)
{
	TnyMsg *retval = tny_platform_factory_new_msg (platfact);
	TnyStream *stream = tny_camel_mem_stream_new ();
	TnyHeader *header = tny_platform_factory_new_header (platfact);

	tny_header_set_subject (header, TEST_STRING);
	tny_header_set_from (header, "from.my@self.com");
	tny_header_set_to (header, "to.my@buddy.com");

	tny_msg_set_header (retval, header);
	g_object_unref (G_OBJECT (header));

	tny_stream_write (stream, TEST_STRING, strlen (TEST_STRING));
	tny_stream_reset (stream);

	tny_mime_part_construct (TNY_MIME_PART (retval), stream, "text/html", "7bit"); 

	g_object_unref (G_OBJECT (stream));

	return retval;
}

Multipart text/plain and text/html E-mail

A text/html E-mail that as an alternative text/plain mime part with no attachments, just a body is created using two stream that contains the HTML and text data. They get "text/html" and "text/plain" as type parameter for their tny_mime_part_construct API call and they are added to the TnyMsg instance using the TnyMimePart API tny_mime_part_add_part.

This example is also used by the demo/test application msg-sender.c which is available in the tests/functional directory of the repository.

Sample code

static TnyMsg*
create_test_msg (TnyPlatformFactory *platfact)
{
	TnyMsg *retval = tny_platform_factory_new_msg (platfact);
	TnyHeader *header = tny_platform_factory_new_header (platfact);

	TnyStream *plain_stream = tny_camel_mem_stream_new ();
	TnyStream *html_stream = tny_camel_mem_stream_new ();
	TnyMimePart *plain_body = tny_platform_factory_new_mime_part (platfact);
	TnyMimePart *html_body = tny_platform_factory_new_mime_part (platfact);

	tny_header_set_subject (header, TEST_STRING);
	tny_header_set_from (header, "from.my@self.com");
	tny_header_set_to (header, "to.my@buddy.com");

	tny_msg_set_header (retval, header);
	g_object_unref (G_OBJECT (header));

	tny_stream_write (plain_stream, TEST_STRING, strlen (TEST_STRING));
	tny_stream_reset (plain_stream);

	tny_stream_write (html_stream, HTML_PRE TEST_STRING HTML_POST, 
		strlen (HTML_PRE TEST_STRING HTML_POST));
	tny_stream_reset (html_stream);

	tny_mime_part_construct (plain_body, plain_stream, "text/plain; charset=utf-8", "7bit"); 
	tny_mime_part_construct (html_body, html_stream, "text/html; charset=utf-8", "7bit"); 

	tny_mime_part_add_part (TNY_MIME_PART (retval), html_body);
	tny_mime_part_add_part (TNY_MIME_PART (retval), plain_body);

	g_object_unref (plain_stream);
	g_object_unref (html_stream);

	g_object_unref (plain_body);
	g_object_unref (html_body);

	return retval;
}

Constructing from a different source, not from memory

In the tinymail framework it's perfectly possible to construct mime parts from a non-memory stream too. The tny_mime_part_construct only requires that you use one of the existing stream types.

You can also use your own implementation of TnyStream. That way you can implement a stream type, and construct from that source. For example a GIO stream or any other kind of stream type.

Future

A Lemonade IMAP feature like Forward without Download will in future be possible too. Maybe an API like tny_mime_part_construct_from_imap. Though this is talking about future, and that is not what this part of the documentation is about.

References to related other documentation