diff --git a/src/engine/rfc822/rfc822-message-data.vala b/src/engine/rfc822/rfc822-message-data.vala index 91ec0f8c..ee06727a 100644 --- a/src/engine/rfc822/rfc822-message-data.vala +++ b/src/engine/rfc822/rfc822-message-data.vala @@ -369,9 +369,15 @@ public class Geary.RFC822.Header : Geary.MessageData.BlockMessageData, EncodedMessageData { - private GMime.Message? message = null; + private GMime.HeaderList headers; private string[]? names = null; + + // The ctors for this class seem the wrong way around, but the + // default accepts a memory buffer and not a GMime.HeaderList to + // keep it consistent with other EncodedMessageData + // implementations. + public Header(Memory.Buffer buffer) throws Error { base("RFC822.Header", buffer); @@ -381,15 +387,25 @@ public class Geary.RFC822.Header : parser.set_respect_content_length(false); parser.set_format(MESSAGE); - this.message = parser.construct_message(null); - if (this.message == null) { + var message = parser.construct_message(null); + if (message == null) { throw new Error.INVALID("Unable to parse RFC 822 headers"); } + + this.headers = message.get_header_list(); + } + + public Header.from_gmime(GMime.Object gmime) { + base( + "RFC822.Header", + new Memory.StringBuffer(gmime.get_headers(get_format_options())) + ); + this.headers = gmime.get_header_list(); } public string? get_header(string name) { string? value = null; - var header = this.message.get_header_list().get_header(name); + var header = this.headers.get_header(name); if (header != null) { value = header.get_value(); } @@ -398,7 +414,7 @@ public class Geary.RFC822.Header : public string? get_raw_header(string name) { string? value = null; - var header = this.message.get_header_list().get_header(name); + var header = this.headers.get_header(name); if (header != null) { value = header.get_raw_value(); } @@ -407,10 +423,9 @@ public class Geary.RFC822.Header : public string[] get_header_names() { if (this.names == null) { - GMime.HeaderList headers = this.message.get_header_list(); - var names = new string[headers.get_count()]; + var names = new string[this.headers.get_count()]; for (int i = 0; i < names.length; i++) { - names[i] = headers.get_header_at(i).get_name(); + names[i] = this.headers.get_header_at(i).get_name(); } this.names = names; } @@ -422,10 +437,49 @@ public class Geary.RFC822.Header : public class Geary.RFC822.Text : Geary.MessageData.BlockMessageData, EncodedMessageData { + + private class GMimeBuffer : Memory.Buffer, Memory.UnownedBytesBuffer { + + + public override size_t allocated_size { + get { return (size_t) this.stream.length; } + } + + public override size_t size { + get { return (size_t) this.stream.length; } + } + + private GMime.Stream stream; + private GLib.Bytes buf = null; + + public GMimeBuffer(GMime.Stream stream) { + this.stream = stream; + } + + public override GLib.Bytes get_bytes() { + if (this.buf == null) { + this.stream.seek(0, SET); + uint8[] bytes = new uint8[this.stream.length()]; + this.stream.read(bytes); + this.buf = new GLib.Bytes.take(bytes); + } + return this.buf; + } + + public unowned uint8[] to_unowned_uint8_array() { + return get_bytes().get_data(); + } + + } + public Text(Memory.Buffer buffer) { base("RFC822.Text", buffer); } + public Text.from_gmime(GMime.Stream gmime) { + base("RFC822.Text", new GMimeBuffer(gmime)); + } + } public class Geary.RFC822.Full : diff --git a/src/engine/rfc822/rfc822-message.vala b/src/engine/rfc822/rfc822-message.vala index f0f47d57..fc830839 100644 --- a/src/engine/rfc822/rfc822-message.vala +++ b/src/engine/rfc822/rfc822-message.vala @@ -658,6 +658,21 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet { return (addrs.size > 0) ? addrs : null; } + /** + * Returns the header of the message. + */ + public Header get_header() { + return new Header.from_gmime(this.message); + } + + /** + * Returns the possibly body of the message. + */ + public Text get_body() { + GMime.Part part = (GMime.Part) this.message.get_mime_part(); + return new Text.from_gmime(part.get_content().get_stream()); + } + /** * Serialises the message using native (i.e. LF) line endings. */ diff --git a/test/engine/rfc822/rfc822-message-test.vala b/test/engine/rfc822/rfc822-message-test.vala index fa8b5779..2d151ba3 100644 --- a/test/engine/rfc822/rfc822-message-test.vala +++ b/test/engine/rfc822/rfc822-message-test.vala @@ -53,6 +53,8 @@ This is the second line. multipart_alternative_as_converted_html); add_test("multipart_alternative_as_html", multipart_alternative_as_html); + add_test("get_header", get_header); + add_test("get_body", get_body); add_test("get_preview", get_preview); add_test("get_recipients", get_recipients); add_test("get_searchable_body", get_searchable_body); @@ -177,6 +179,18 @@ This is the second line. assert_equal(test.get_html_body(null), BASIC_HTML_BODY); } + public void get_header() throws GLib.Error { + Message message = resource_to_message(BASIC_TEXT_PLAIN); + Header header = message.get_header(); + assert(header.get_header("From") == "Alice "); + } + + public void get_body() throws GLib.Error { + Message message = resource_to_message(BASIC_TEXT_PLAIN); + Text body = message.get_body(); + assert(body.buffer.to_string().replace("\r", "") == BASIC_PLAIN_BODY); + } + public void get_preview() throws GLib.Error { Message multipart_signed = string_to_message(MULTIPART_SIGNED_MESSAGE_TEXT);