Geary.RFC822.Message: Rework constructors and stocking from GMimeMessage

Make constructors use the Message.from_gmime where possible. Merge that
and stock_from_gmime so it's clear the stocking only happens in the
ctor. Update stocking to use high-level GMime APIs where available to
avoid re-parsing header values.
This commit is contained in:
Michael Gratton 2020-05-06 12:21:16 +10:00 committed by Michael James Gratton
parent 6e7631b8d3
commit 288c78a93a
4 changed files with 91 additions and 97 deletions

View file

@ -256,10 +256,10 @@ public class Geary.RFC822.MailboxAddress :
);
}
this.gmime(mbox_addr);
this.from_gmime(mbox_addr);
}
public MailboxAddress.gmime(GMime.InternetAddressMailbox mailbox) {
public MailboxAddress.from_gmime(GMime.InternetAddressMailbox mailbox) {
// GMime strips source route for us, so the address part
// should only ever contain a single '@'
string? name = mailbox.get_name();

View file

@ -100,7 +100,7 @@ public class Geary.RFC822.MailboxAddresses :
var addr = list.get_address(i);
var mbox_addr = addr as GMime.InternetAddressMailbox;
if (mbox_addr != null) {
this.addrs.add(new MailboxAddress.gmime(mbox_addr));
this.addrs.add(new MailboxAddress.from_gmime(mbox_addr));
} else {
// XXX this is pretty bad - we just flatten the
// group's addresses into this list, merging lists and
@ -112,7 +112,9 @@ public class Geary.RFC822.MailboxAddresses :
var group_addr =
group_list.get_address(j) as GMime.InternetAddressMailbox;
if (group_addr != null) {
this.addrs.add(new MailboxAddress.gmime(group_addr));
this.addrs.add(
new MailboxAddress.from_gmime(group_addr)
);
}
}
}

View file

@ -36,16 +36,14 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
private const string HEADER_BCC = "Bcc";
// Internal note: If a header field is added here, it *must* be
// set in stock_from_gmime().
/** {@inheritDoc} */
/** {@inheritDoc} */
public RFC822.MailboxAddress? sender { get; protected set; default = null; }
// set in Message.from_gmime_message(), below.
/** {@inheritDoc} */
public RFC822.MailboxAddresses? from { get; protected set; default = null; }
/** {@inheritDoc} */
public RFC822.MailboxAddress? sender { get; protected set; default = null; }
/** {@inheritDoc} */
public RFC822.MailboxAddresses? to { get; protected set; default = null; }
@ -87,23 +85,78 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
public Message(Full full) throws RFC822Error {
GMime.Parser parser = new GMime.Parser.with_stream(Utils.create_stream_mem(full.buffer));
message = parser.construct_message(Geary.RFC822.get_parser_options());
if (message == null)
GMime.Parser parser = new GMime.Parser.with_stream(
Utils.create_stream_mem(full.buffer)
);
var message = parser.construct_message(get_parser_options());
if (message == null) {
throw new RFC822Error.INVALID("Unable to parse RFC 822 message");
}
this.from_gmime_message(message);
// See the declaration of these fields for why we do this.
body_buffer = full.buffer;
body_offset = (size_t) parser.get_headers_end();
stock_from_gmime();
this.body_buffer = full.buffer;
this.body_offset = (size_t) parser.get_headers_end();
}
public Message.from_gmime_message(GMime.Message message)
throws RFC822Error {
this.message = message;
stock_from_gmime();
this.from = to_addresses(message.get_from());
this.to = to_addresses(message.get_to());
this.cc = to_addresses(message.get_cc());
this.bcc = to_addresses(message.get_bcc());
this.reply_to = to_addresses(message.get_reply_to());
var sender = (
message.get_sender().get_address(0) as GMime.InternetAddressMailbox
);
if (sender != null) {
this.sender = new MailboxAddress.from_gmime(sender);
}
var subject = message.get_subject();
if (subject != null) {
this.subject = new Subject(subject);
}
// Use a pointer here to work around GNOME/vala#986
GLib.DateTime* date = message.get_date();
if (date != null) {
this.date = new Date(date);
}
var message_id = message.get_message_id();
if (message_id != null) {
this.message_id = new MessageID(message_id);
}
// Since these headers may be specified multiple times, we
// need to iterate over all of them to find them.
var headers = message.get_header_list();
for (int i = 0; i < headers.get_count(); i++) {
var header = headers.get_header_at(i);
switch (header.get_name().down()) {
case "in-reply-to":
this.in_reply_to = append_message_id(
this.in_reply_to, header.get_raw_value()
);
break;
case "references":
this.references = append_message_id(
this.references, header.get_raw_value()
);
break;
default:
break;
}
}
this.mailer = message.get_header("X-Mailer");
}
public Message.from_buffer(Memory.Buffer full_email)
@ -118,14 +171,16 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
stream_cat.add_source(new GMime.StreamMem.with_buffer(body.buffer.get_bytes().get_data()));
GMime.Parser parser = new GMime.Parser.with_stream(stream_cat);
message = parser.construct_message(Geary.RFC822.get_parser_options());
if (message == null)
var message = parser.construct_message(Geary.RFC822.get_parser_options());
if (message == null) {
throw new RFC822Error.INVALID("Unable to parse RFC 822 message");
}
body_buffer = body.buffer;
body_offset = 0;
this.from_gmime_message(message);
stock_from_gmime();
// See the declaration of these fields for why we do this.
this.body_buffer = body.buffer;
this.body_offset = 0;
}
public async Message.from_composed_email(Geary.ComposedEmail email,
@ -887,73 +942,11 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
return attachments;
}
private void stock_from_gmime() throws RFC822Error {
GMime.HeaderList headers = this.message.headers;
for (int i = 0; i < headers.get_count(); i++) {
GMime.Header header = headers.get_header_at(i);
string value = header.get_value();
switch (header.get_name().down()) {
case "from":
this.from = append_address(this.from, value);
break;
case "sender":
this.sender = new MailboxAddress.from_rfc822_string(value);
break;
case "reply-to":
this.reply_to = append_address(this.reply_to, value);
break;
case "to":
this.to = append_address(this.to, value);
break;
case "cc":
this.cc = append_address(this.cc, value);
break;
case "bcc":
this.bcc = append_address(this.bcc, value);
break;
case "subject":
this.subject = new Subject.decode(value);
break;
case "date":
this.date = new Date(value);
break;
case "message-id":
this.message_id = new MessageID(value);
break;
case "in-reply-to":
this.in_reply_to = append_message_id(this.in_reply_to, value);
break;
case "references":
this.references = append_message_id(this.references, value);
break;
case "x-mailer":
this.mailer = GMime.utils_header_decode_text(null, value);
break;
default:
// Ignore anything else not
break;
}
}
}
private MailboxAddresses append_address(MailboxAddresses? existing,
string header_value)
private MailboxAddresses? to_addresses(GMime.InternetAddressList? list)
throws RFC822Error {
MailboxAddresses addresses = new MailboxAddresses.from_rfc822_string(header_value);
if (existing != null) {
addresses = existing.append(addresses);
MailboxAddresses? addresses = null;
if (list != null && list.length() > 0) {
addresses = new MailboxAddresses.from_gmime(list);
}
return addresses;
}
@ -971,7 +964,6 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
GMime.Object root,
Mime.DispositionType requested_disposition)
throws RFC822Error {
if (root is GMime.Multipart) {
GMime.Multipart multipart = (GMime.Multipart) root;
int count = multipart.get_count();

View file

@ -74,10 +74,10 @@ This is the second line.
assert_addresses(basic.to, "Charlie <charlie@example.net>");
assert_addresses(basic.cc, "Dave <dave@example.net>");
assert_addresses(basic.bcc, "Eve <eve@example.net>");
//assert_data(basic.message_id, "<3456@example.net>");
assert_data(basic.message_id, "3456@example.net");
assert_message_id_list(basic.in_reply_to, "<1234@local.machine.example>");
assert_message_id_list(basic.references, "<1234@local.machine.example>");
assert_data(basic.date, "Fri, 21 Nov 1997 10:01:10 -0600");
assert_data(basic.date, "1997-11-21T10:01:10-0600");
assert(basic.mailer == "Geary Test Suite 1.0");
}
@ -85,7 +85,7 @@ This is the second line.
Message enc = string_to_message(ENCODED_TO);
// Courtesy Mailsploit https://www.mailsploit.com
assert(enc.to[0].name == "potus@whitehouse.gov <test>");
assert_string("potus@whitehouse.gov <test>", enc.to[0].name);
}
public void duplicate_mailbox() throws Error {
@ -432,9 +432,9 @@ This is the second line.
private void assert_message_id_list(Geary.RFC822.MessageIDList? ids,
string expected)
throws Error {
assert_non_null(ids, expected);
assert(ids.to_rfc822_string() == expected);
throws GLib.Error {
assert_non_null(ids, "ids are null");
assert_string(expected, ids.to_rfc822_string());
}
// Courtesy Mailsploit https://www.mailsploit.com