Change GMime dependency from 2.6.17 to 3.2.4
This commit squashes several non-compiling commits: 66dd6500 Change required GMime version to 3.2.4 or higher 4b9c8a38 Fix some compilations errors in test code 98aa5a2e Fix some (hopefully) last compilation errors 558360c6 Fix parser format when getting message headers cc248ffc Fix name of stream-buffer mode b293c66b Fix another iteration over a header-list 52fa183f Fix parsing of Gmime parameters e078ee62 Use Unix2Dos-, Dos2Unix- and/or SmtpData-filters instead of 'FilterCRLF' ff31b8e5 Fix setting of email headers eb676482 Fix compilation errros due to string-uint8-char conversion problems 8558769f Fix datetime conversion d44a28cd Remove some obsolete arguments 1ce81662 Pass charset where it's required 6013806f Pass GMime.ParserOptions to header-decode methods 986d05a0 Pass GMime.FormatOptions where it's required e9b93187 Pass GMime.ParserOptions where it's required 640ce667 Fix compilation errors in GMime initialization 312f80bf Remove use of GMime.HeaderIter acc73d14 Change GMime dependency from 2.6 to 3.0 54fc250a Adapt names to 'offical' gmime-2.6 bindings The commits are part of the branch 'letorbi/gmime-3-spread', which can be found at: https://gitlab.gnome.org/letorbi/geary/tree/letorbi/gmime-3-spread
This commit is contained in:
parent
fced79bfd2
commit
1aac6f2284
17 changed files with 236 additions and 203 deletions
|
|
@ -57,7 +57,7 @@ target_webkit = '2.24'
|
|||
|
||||
# Primary deps
|
||||
glib = dependency('glib-2.0', version: '>=' + target_glib)
|
||||
gmime = dependency('gmime-2.6', version: '>= 2.6.17')
|
||||
gmime = dependency('gmime-3.0', version: '>= 3.2.4')
|
||||
gtk = dependency('gtk+-3.0', version: '>=' + target_gtk)
|
||||
sqlite = dependency('sqlite3', version: '>= 3.24')
|
||||
webkit2gtk = dependency('webkit2gtk-4.0', version: '>=' + target_webkit)
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ private class Geary.ImapDB.Attachment : Geary.Attachment {
|
|||
target_stream
|
||||
);
|
||||
stream = new GMime.StreamBuffer(
|
||||
stream, GMime.StreamBufferMode.BLOCK_WRITE
|
||||
stream, GMime.StreamBufferMode.WRITE
|
||||
);
|
||||
|
||||
part.write_to_stream(stream, RFC822.Part.EncodingConversion.NONE);
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ public class Geary.Mime.ContentDisposition : Geary.BaseObject {
|
|||
out is_unknown);
|
||||
is_unknown_disposition_type = is_unknown;
|
||||
original_disposition_type_string = content_disposition.get_disposition();
|
||||
params = new ContentParameters.from_gmime(content_disposition.get_params());
|
||||
params = new ContentParameters.from_gmime(content_disposition.get_parameters());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,11 +51,13 @@ public class Geary.Mime.ContentParameters : BaseObject {
|
|||
}
|
||||
}
|
||||
|
||||
internal ContentParameters.from_gmime(GMime.Param? gmime_param) {
|
||||
internal ContentParameters.from_gmime(GMime.ParamList? gmime_params) {
|
||||
Gee.Map<string,string> params = new Gee.HashMap<string,string>();
|
||||
while (gmime_param != null) {
|
||||
params.set(gmime_param.get_name(), gmime_param.get_value());
|
||||
gmime_param = gmime_param.get_next();
|
||||
if (gmime_params != null) {
|
||||
for (int i=0; i < gmime_params.length(); i++) {
|
||||
GMime.Param gmime_param = gmime_params.get_parameter_at(i);
|
||||
params.set(gmime_param.get_name(), gmime_param.get_value());
|
||||
}
|
||||
}
|
||||
this(params);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,10 @@ public class Geary.Mime.ContentType : Geary.BaseObject {
|
|||
if (!str.contains("/"))
|
||||
throw new MimeError.PARSE("Invalid MIME Content-Type: %s", str);
|
||||
|
||||
return new ContentType.from_gmime(new GMime.ContentType.from_string(str));
|
||||
return new ContentType.from_gmime(GMime.ContentType.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
str
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -158,7 +161,7 @@ public class Geary.Mime.ContentType : Geary.BaseObject {
|
|||
internal ContentType.from_gmime(GMime.ContentType content_type) {
|
||||
media_type = content_type.get_media_type().strip();
|
||||
media_subtype = content_type.get_media_subtype().strip();
|
||||
params = new ContentParameters.from_gmime(content_type.get_params());
|
||||
params = new ContentParameters.from_gmime(content_type.get_parameters());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ private class Geary.RFC822.FilterBlockquotes : GMime.Filter {
|
|||
return new_filter;
|
||||
}
|
||||
|
||||
private void do_filter(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
private void do_filter(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace, bool flush) {
|
||||
|
||||
// This may not be strictly necessary.
|
||||
|
|
@ -64,7 +64,7 @@ private class Geary.RFC822.FilterBlockquotes : GMime.Filter {
|
|||
}
|
||||
|
||||
for (uint i = 0; i < inbuf.length; i++) {
|
||||
char c = inbuf[i];
|
||||
uint8 c = inbuf[i];
|
||||
|
||||
if (in_prefix && !in_tag) {
|
||||
if (c == Geary.RFC822.Utils.QUOTE_MARKER) {
|
||||
|
|
@ -122,12 +122,12 @@ private class Geary.RFC822.FilterBlockquotes : GMime.Filter {
|
|||
outprespace = this.outpre;
|
||||
}
|
||||
|
||||
public override void filter(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
public override void filter(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace) {
|
||||
do_filter(inbuf, prespace, out processed_buffer, out outprespace, false);
|
||||
}
|
||||
|
||||
public override void complete(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
public override void complete(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace) {
|
||||
do_filter(inbuf, prespace, out processed_buffer, out outprespace, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ private class Geary.RFC822.FilterFlowed : GMime.Filter {
|
|||
return new_filter;
|
||||
}
|
||||
|
||||
public override void filter(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
public override void filter(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace) {
|
||||
|
||||
// Worst-case scenario: We are about to leave the prefix,
|
||||
|
|
@ -67,7 +67,7 @@ private class Geary.RFC822.FilterFlowed : GMime.Filter {
|
|||
|
||||
uint out_index = 0;
|
||||
for (uint i = 0; i < inbuf.length; i++) {
|
||||
char c = inbuf[i];
|
||||
uint8 c = inbuf[i];
|
||||
|
||||
if (this.in_prefix) {
|
||||
if (c == '>') {
|
||||
|
|
@ -147,7 +147,7 @@ private class Geary.RFC822.FilterFlowed : GMime.Filter {
|
|||
outprespace = this.outpre;
|
||||
}
|
||||
|
||||
public override void complete(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
public override void complete(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace) {
|
||||
filter(inbuf, prespace, out processed_buffer, out outprespace);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ private class Geary.RFC822.FilterPlain : GMime.Filter {
|
|||
return new_filter;
|
||||
}
|
||||
|
||||
public override void filter(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
public override void filter(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace) {
|
||||
|
||||
// This may not be strictly necessary.
|
||||
|
|
@ -34,7 +34,7 @@ private class Geary.RFC822.FilterPlain : GMime.Filter {
|
|||
|
||||
uint out_index = 0;
|
||||
for (uint i = 0; i < inbuf.length; i++) {
|
||||
char c = inbuf[i];
|
||||
uint8 c = inbuf[i];
|
||||
|
||||
if (in_prefix) {
|
||||
if (c == '>') {
|
||||
|
|
@ -56,7 +56,7 @@ private class Geary.RFC822.FilterPlain : GMime.Filter {
|
|||
outprespace = this.outpre;
|
||||
}
|
||||
|
||||
public override void complete(char[] inbuf, size_t prespace, out unowned char[] processed_buffer,
|
||||
public override void complete(uint8[] inbuf, size_t prespace, out unowned uint8[] processed_buffer,
|
||||
out size_t outprespace) {
|
||||
filter(inbuf, prespace, out processed_buffer, out outprespace);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,11 +42,17 @@ public class Geary.RFC822.MailboxAddress :
|
|||
}
|
||||
|
||||
private static string decode_name(string name) {
|
||||
return GMime.utils_header_decode_phrase(prepare_header_text_part(name));
|
||||
return GMime.utils_header_decode_phrase(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
prepare_header_text_part(name)
|
||||
);
|
||||
}
|
||||
|
||||
private static string decode_address_part(string mailbox) {
|
||||
return GMime.utils_header_decode_text(prepare_header_text_part(mailbox));
|
||||
return GMime.utils_header_decode_text(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
prepare_header_text_part(mailbox)
|
||||
);
|
||||
}
|
||||
|
||||
private static bool display_name_needs_quoting(string name) {
|
||||
|
|
@ -118,8 +124,9 @@ public class Geary.RFC822.MailboxAddress :
|
|||
// _internet_address_decode_name() function.
|
||||
|
||||
// see if a broken mailer has sent raw 8-bit information
|
||||
string text = GMime.utils_text_is_8bit(part, part.length)
|
||||
? part : GMime.utils_decode_8bit(part, part.length);
|
||||
string text = GMime.utils_text_is_8bit(part.data)
|
||||
? part : GMime.utils_decode_8bit(Geary.RFC822.get_parser_options(),
|
||||
part.data);
|
||||
|
||||
// unquote the string then decode the text
|
||||
GMime.utils_unquote_string(text);
|
||||
|
|
@ -222,16 +229,19 @@ public class Geary.RFC822.MailboxAddress :
|
|||
}
|
||||
|
||||
public MailboxAddress.from_rfc822_string(string rfc822) throws RFC822Error {
|
||||
InternetAddressList addrlist = InternetAddressList.parse_string(rfc822);
|
||||
GMime.InternetAddressList addrlist = GMime.InternetAddressList.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
rfc822
|
||||
);
|
||||
if (addrlist == null)
|
||||
return;
|
||||
|
||||
int length = addrlist.length();
|
||||
for (int ctr = 0; ctr < length; ctr++) {
|
||||
InternetAddress? addr = addrlist.get_address(ctr);
|
||||
GMime.InternetAddress? addr = addrlist.get_address(ctr);
|
||||
|
||||
// TODO: Handle group lists
|
||||
InternetAddressMailbox? mbox_addr = addr as InternetAddressMailbox;
|
||||
GMime.InternetAddressMailbox? mbox_addr = addr as GMime.InternetAddressMailbox;
|
||||
if (mbox_addr != null) {
|
||||
this.gmime(mbox_addr);
|
||||
return;
|
||||
|
|
@ -240,7 +250,7 @@ public class Geary.RFC822.MailboxAddress :
|
|||
throw new RFC822Error.INVALID("Could not parse RFC822 address: %s", rfc822);
|
||||
}
|
||||
|
||||
public MailboxAddress.gmime(InternetAddressMailbox mailbox) {
|
||||
public MailboxAddress.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();
|
||||
|
|
@ -456,7 +466,11 @@ public class Geary.RFC822.MailboxAddress :
|
|||
public string to_rfc822_string() {
|
||||
return has_distinct_name()
|
||||
? "%s <%s>".printf(
|
||||
GMime.utils_header_encode_phrase(this.name),
|
||||
GMime.utils_header_encode_phrase(
|
||||
Geary.RFC822.get_format_options(),
|
||||
this.name,
|
||||
Geary.RFC822.get_charset()
|
||||
),
|
||||
to_rfc822_address()
|
||||
)
|
||||
: to_rfc822_address();
|
||||
|
|
|
|||
|
|
@ -74,27 +74,30 @@ public class Geary.RFC822.MailboxAddresses :
|
|||
}
|
||||
|
||||
public MailboxAddresses.from_rfc822_string(string rfc822) {
|
||||
InternetAddressList addrlist = InternetAddressList.parse_string(rfc822);
|
||||
GMime.InternetAddressList addrlist = GMime.InternetAddressList.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
rfc822
|
||||
);
|
||||
if (addrlist == null)
|
||||
return;
|
||||
|
||||
int length = addrlist.length();
|
||||
for (int ctr = 0; ctr < length; ctr++) {
|
||||
InternetAddress? addr = addrlist.get_address(ctr);
|
||||
GMime.InternetAddress? addr = addrlist.get_address(ctr);
|
||||
|
||||
InternetAddressMailbox? mbox_addr = addr as InternetAddressMailbox;
|
||||
GMime.InternetAddressMailbox? mbox_addr = addr as GMime.InternetAddressMailbox;
|
||||
if (mbox_addr != null) {
|
||||
this.addrs.add(new MailboxAddress.gmime(mbox_addr));
|
||||
} else {
|
||||
// XXX this is pretty bad - we just flatten the
|
||||
// group's addresses into this list, merging lists and
|
||||
// losing the group names.
|
||||
InternetAddressGroup? mbox_group = addr as InternetAddressGroup;
|
||||
GMime.InternetAddressGroup? mbox_group = addr as GMime.InternetAddressGroup;
|
||||
if (mbox_group != null) {
|
||||
InternetAddressList group_list = mbox_group.get_members();
|
||||
GMime.InternetAddressList group_list = mbox_group.get_members();
|
||||
for (int i = 0; i < group_list.length(); i++) {
|
||||
InternetAddressMailbox? group_addr =
|
||||
addrlist.get_address(i) as InternetAddressMailbox;
|
||||
GMime.InternetAddressMailbox? group_addr =
|
||||
addrlist.get_address(i) as GMime.InternetAddressMailbox;
|
||||
if (group_addr != null) {
|
||||
this.addrs.add(new MailboxAddress.gmime(group_addr));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,27 +173,13 @@ public class Geary.RFC822.Date : Geary.RFC822.MessageData, Geary.MessageData.Abs
|
|||
public DateTime value { get; private set; }
|
||||
|
||||
public Date(string rfc822) throws ImapError {
|
||||
int offset = 0;
|
||||
int64 time_t_utc = GMime.utils_header_decode_date(rfc822, out offset);
|
||||
if (time_t_utc == 0)
|
||||
throw new ImapError.PARSE_ERROR(
|
||||
"Unable to parse \"%s\": Not ISO-8601 date", rfc822
|
||||
);
|
||||
|
||||
DateTime? value = new DateTime.from_unix_utc(time_t_utc);
|
||||
DateTime? value = GMime.utils_header_decode_date(rfc822);
|
||||
if (value == null) {
|
||||
throw new ImapError.PARSE_ERROR(
|
||||
"Unable to parse \"%s\": Outside supported range", rfc822
|
||||
);
|
||||
}
|
||||
this.value = value;
|
||||
|
||||
if (offset != 0) {
|
||||
this.value = value.to_timezone(
|
||||
new GLib.TimeZone("%+05d".printf(offset))
|
||||
);
|
||||
}
|
||||
|
||||
this.original = rfc822;
|
||||
}
|
||||
|
||||
|
|
@ -206,18 +192,7 @@ public class Geary.RFC822.Date : Geary.RFC822.MessageData, Geary.MessageData.Abs
|
|||
* Returns the {@link Date} in RFC 822 format.
|
||||
*/
|
||||
public string to_rfc822_string() {
|
||||
// Although GMime documents its conversion methods as
|
||||
// requiring the tz offset in hours, it appears the number is
|
||||
// handed directly to the string (i.e. an offset of -7:30 becomes
|
||||
// "-0007", whereas we want "-0730").
|
||||
int hours = (int) GLib.Math.floor(value.get_utc_offset() / TimeSpan.HOUR);
|
||||
int minutes = (int) (
|
||||
(value.get_utc_offset() % TimeSpan.HOUR) / (double) TimeSpan.HOUR * 60
|
||||
);
|
||||
return GMime.utils_header_format_date(
|
||||
(time_t) this.value.to_utc().to_unix(),
|
||||
(hours * 100) + minutes
|
||||
);
|
||||
return GMime.utils_header_format_date(this.value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -261,7 +236,7 @@ public class Geary.RFC822.Subject : Geary.MessageData.StringMessageData,
|
|||
}
|
||||
|
||||
public Subject.decode(string value) {
|
||||
base (GMime.utils_header_decode_text(value));
|
||||
base (GMime.utils_header_decode_text(Geary.RFC822.get_parser_options(), value));
|
||||
original = value;
|
||||
}
|
||||
|
||||
|
|
@ -337,9 +312,10 @@ public class Geary.RFC822.Header : Geary.MessageData.BlockMessageData, Geary.RFC
|
|||
|
||||
GMime.Parser parser = new GMime.Parser.with_stream(Utils.create_stream_mem(buffer));
|
||||
parser.set_respect_content_length(false);
|
||||
parser.set_scan_from(false);
|
||||
// TODO Could this be omitted?
|
||||
parser.set_format(GMime.Format.MESSAGE);
|
||||
|
||||
message = parser.construct_message();
|
||||
message = parser.construct_message(Geary.RFC822.get_parser_options());
|
||||
if (message == null)
|
||||
throw new RFC822Error.INVALID("Unable to parse RFC 822 headers");
|
||||
|
||||
|
|
@ -347,17 +323,15 @@ public class Geary.RFC822.Header : Geary.MessageData.BlockMessageData, Geary.RFC
|
|||
}
|
||||
|
||||
public string? get_header(string name) throws RFC822Error {
|
||||
return get_headers().get(name);
|
||||
return get_headers().get_header(name).get_value();
|
||||
}
|
||||
|
||||
public string[] get_header_names() throws RFC822Error {
|
||||
if (this.names == null) {
|
||||
this.names = new string[0];
|
||||
GMime.HeaderIter iter = new GMime.HeaderIter();
|
||||
if (get_headers().get_iter(iter) && iter.first()) {
|
||||
do {
|
||||
names += iter.get_name();
|
||||
} while (iter.next());
|
||||
GMime.HeaderList headers = get_headers();
|
||||
for (int i = 0; i < headers.get_count(); i++) {
|
||||
names += headers.get_header_at(i).get_name();
|
||||
}
|
||||
}
|
||||
return this.names;
|
||||
|
|
@ -388,7 +362,7 @@ public class Geary.RFC822.PreviewText : Geary.RFC822.Text {
|
|||
// Parse the header.
|
||||
GMime.Stream header_stream = Utils.create_stream_mem(preview_header);
|
||||
GMime.Parser parser = new GMime.Parser.with_stream(header_stream);
|
||||
GMime.Part? gpart = parser.construct_part() as GMime.Part;
|
||||
GMime.Part? gpart = parser.construct_part(Geary.RFC822.get_parser_options()) as GMime.Part;
|
||||
if (gpart != null) {
|
||||
Part part = new Part(gpart);
|
||||
|
||||
|
|
@ -402,7 +376,7 @@ public class Geary.RFC822.PreviewText : Geary.RFC822.Text {
|
|||
new GMime.StreamMem.with_buffer(preview.get_uint8_array()),
|
||||
gpart.get_content_encoding()
|
||||
);
|
||||
gpart.set_content_object(body);
|
||||
gpart.set_content(body);
|
||||
|
||||
try {
|
||||
Memory.Buffer preview_buffer = part.write_to_buffer(
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
*/
|
||||
public delegate string? InlinePartReplacer(Part part);
|
||||
|
||||
private const string HEADER_DATE = "Date";
|
||||
private const string HEADER_SENDER = "Sender";
|
||||
private const string HEADER_IN_REPLY_TO = "In-Reply-To";
|
||||
private const string HEADER_REFERENCES = "References";
|
||||
|
|
@ -89,7 +90,7 @@ 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();
|
||||
message = parser.construct_message(Geary.RFC822.get_parser_options());
|
||||
if (message == null)
|
||||
throw new RFC822Error.INVALID("Unable to parse RFC 822 message");
|
||||
|
||||
|
|
@ -115,7 +116,7 @@ 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();
|
||||
message = parser.construct_message(Geary.RFC822.get_parser_options());
|
||||
if (message == null)
|
||||
throw new RFC822Error.INVALID("Unable to parse RFC 822 message");
|
||||
|
||||
|
|
@ -136,67 +137,71 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
this.from = email.from;
|
||||
this.date = email.date;
|
||||
|
||||
// GMimeMessage.set_sender actually sets the From header - and
|
||||
// although the API docs make it sound otherwise, it also
|
||||
// supports a list of addresses
|
||||
message.set_sender(this.from.to_rfc822_string());
|
||||
message.set_date_as_string(this.date.serialize());
|
||||
if (message_id != null) {
|
||||
this.message_id = new MessageID(message_id);
|
||||
message.set_message_id(message_id);
|
||||
//message.set_date_as_string(this.date.serialize());
|
||||
this.message.set_header(HEADER_DATE,
|
||||
this.date.serialize(),
|
||||
Geary.RFC822.get_charset());
|
||||
|
||||
if (email.from != null) {
|
||||
foreach (RFC822.MailboxAddress mailbox in email.from)
|
||||
this.message.add_mailbox(GMime.AddressType.FROM, mailbox.name, mailbox.address);
|
||||
}
|
||||
|
||||
if (email.sender != null) {
|
||||
this.message.add_mailbox(GMime.AddressType.SENDER, this.sender.name, this.sender.address);
|
||||
// TODO Is setting the header still required?
|
||||
this.message.set_header(HEADER_SENDER,
|
||||
this.sender.to_rfc822_string(),
|
||||
Geary.RFC822.get_charset());
|
||||
}
|
||||
|
||||
// Optional headers
|
||||
if (email.to != null) {
|
||||
this.to = email.to;
|
||||
foreach (RFC822.MailboxAddress mailbox in email.to)
|
||||
this.message.add_recipient(GMime.RecipientType.TO, mailbox.name, mailbox.address);
|
||||
this.message.add_mailbox(GMime.AddressType.TO, mailbox.name, mailbox.address);
|
||||
}
|
||||
|
||||
if (email.cc != null) {
|
||||
this.cc = email.cc;
|
||||
foreach (RFC822.MailboxAddress mailbox in email.cc)
|
||||
this.message.add_recipient(GMime.RecipientType.CC, mailbox.name, mailbox.address);
|
||||
this.message.add_mailbox(GMime.AddressType.CC, mailbox.name, mailbox.address);
|
||||
}
|
||||
|
||||
if (email.bcc != null) {
|
||||
this.bcc = email.bcc;
|
||||
foreach (RFC822.MailboxAddress mailbox in email.bcc)
|
||||
this.message.add_recipient(GMime.RecipientType.BCC, mailbox.name, mailbox.address);
|
||||
}
|
||||
|
||||
if (email.sender != null) {
|
||||
this.sender = email.sender;
|
||||
this.message.set_header(HEADER_SENDER,
|
||||
email.sender.to_rfc822_string());
|
||||
}
|
||||
|
||||
if (email.reply_to != null) {
|
||||
this.reply_to = email.reply_to;
|
||||
this.message.set_reply_to(email.reply_to.to_rfc822_string());
|
||||
this.message.add_mailbox(GMime.AddressType.BCC, mailbox.name, mailbox.address);
|
||||
}
|
||||
|
||||
if (email.in_reply_to != null) {
|
||||
this.in_reply_to = email.in_reply_to;
|
||||
foreach (RFC822.MailboxAddress mailbox in email.reply_to)
|
||||
this.message.add_mailbox(GMime.AddressType.BCC, mailbox.name, mailbox.address);
|
||||
// TODO Is setting the header still required?
|
||||
this.message.set_header(HEADER_IN_REPLY_TO,
|
||||
email.in_reply_to.to_rfc822_string());
|
||||
email.in_reply_to.to_rfc822_string(),
|
||||
Geary.RFC822.get_charset());
|
||||
}
|
||||
|
||||
if (email.references != null) {
|
||||
this.references = email.references;
|
||||
this.message.set_header(HEADER_REFERENCES,
|
||||
email.references.to_rfc822_string());
|
||||
email.references.to_rfc822_string(),
|
||||
Geary.RFC822.get_charset());
|
||||
}
|
||||
|
||||
if (email.subject != null) {
|
||||
this.subject = email.subject;
|
||||
this.message.set_subject(email.subject.value);
|
||||
this.message.set_subject(email.subject.value,
|
||||
Geary.RFC822.get_charset());
|
||||
}
|
||||
|
||||
// User-Agent
|
||||
if (!Geary.String.is_empty(email.mailer)) {
|
||||
this.mailer = email.mailer;
|
||||
this.message.set_header(HEADER_MAILER, email.mailer);
|
||||
this.message.set_header(HEADER_MAILER, email.mailer,
|
||||
Geary.RFC822.get_charset());
|
||||
}
|
||||
|
||||
// Build the message's body mime parts
|
||||
|
|
@ -406,7 +411,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
string type) {
|
||||
GMime.Object? part = coalesce_parts(parts, "related");
|
||||
if (parts.size > 1) {
|
||||
part.set_header("Type", type);
|
||||
part.set_header("Type", type, Geary.RFC822.get_charset());
|
||||
}
|
||||
return part;
|
||||
}
|
||||
|
|
@ -437,7 +442,8 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
part.set_disposition(disposition.serialize());
|
||||
part.set_filename(file.get_basename());
|
||||
|
||||
GMime.ContentType content_type = new GMime.ContentType.from_string(
|
||||
GMime.ContentType content_type = GMime.ContentType.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
file_info.get_content_type()
|
||||
);
|
||||
part.set_content_type(content_type);
|
||||
|
|
@ -468,7 +474,10 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
);
|
||||
}
|
||||
|
||||
GMime.ContentType? content_type = new GMime.ContentType.from_string(mime_type.get_mime_type());
|
||||
GMime.ContentType? content_type = GMime.ContentType.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
mime_type.get_mime_type()
|
||||
);
|
||||
|
||||
if (content_type == null) {
|
||||
throw new RFC822Error.INVALID(
|
||||
|
|
@ -515,7 +524,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
}
|
||||
|
||||
part.set_content_encoding(encoding);
|
||||
part.set_content_object(
|
||||
part.set_content(
|
||||
new GMime.DataWrapper.with_stream(
|
||||
stream, GMime.ContentEncoding.BINARY
|
||||
)
|
||||
|
|
@ -536,7 +545,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
Geary.Email email = new Geary.Email(id);
|
||||
|
||||
email.set_message_header(new Geary.RFC822.Header(new Geary.Memory.StringBuffer(
|
||||
message.get_headers())));
|
||||
message.get_headers(Geary.RFC822.get_format_options()))));
|
||||
email.set_send_date(date);
|
||||
email.set_originators(from, sender, reply_to);
|
||||
email.set_receivers(to, cc, bcc);
|
||||
|
|
@ -884,68 +893,72 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
}
|
||||
|
||||
private void stock_from_gmime() {
|
||||
this.message.get_header_list().foreach((name, value) => {
|
||||
switch (name.down()) {
|
||||
case "from":
|
||||
this.from = append_address(this.from, value);
|
||||
break;
|
||||
GMime.HeaderList headers = this.message.get_header_list();
|
||||
for (int i=0; i < headers.get_count(); i++) {
|
||||
GMime.Header header = headers.get_header_at(i);
|
||||
string name = header.get_name();
|
||||
string value = header.get_value();
|
||||
switch (name.down()) {
|
||||
case "from":
|
||||
this.from = append_address(this.from, value);
|
||||
break;
|
||||
|
||||
case "sender":
|
||||
try {
|
||||
this.sender = new RFC822.MailboxAddress.from_rfc822_string(value);
|
||||
} catch (Error err) {
|
||||
debug("Could parse subject: %s", err.message);
|
||||
}
|
||||
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 RFC822.Subject.decode(value);
|
||||
break;
|
||||
|
||||
case "date":
|
||||
try {
|
||||
this.date = new Geary.RFC822.Date(value);
|
||||
} catch (Error err) {
|
||||
debug("Could not parse date: %s", err.message);
|
||||
}
|
||||
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(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
case "sender":
|
||||
try {
|
||||
this.sender = new RFC822.MailboxAddress.from_rfc822_string(value);
|
||||
} catch (Error err) {
|
||||
debug("Could parse subject: %s", err.message);
|
||||
}
|
||||
});
|
||||
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 RFC822.Subject.decode(value);
|
||||
break;
|
||||
|
||||
case "date":
|
||||
try {
|
||||
this.date = new Geary.RFC822.Date(value);
|
||||
} catch (Error err) {
|
||||
debug("Could not parse date: %s", err.message);
|
||||
}
|
||||
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(Geary.RFC822.get_parser_options(), value);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private MailboxAddresses append_address(MailboxAddresses? existing,
|
||||
|
|
@ -990,11 +1003,11 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
|
||||
if (requested_disposition == Mime.DispositionType.UNSPECIFIED || disposition == requested_disposition) {
|
||||
GMime.Stream stream = new GMime.StreamMem();
|
||||
message.write_to_stream(stream);
|
||||
message.write_to_stream(Geary.RFC822.get_format_options(), stream);
|
||||
GMime.DataWrapper data = new GMime.DataWrapper.with_stream(stream,
|
||||
GMime.ContentEncoding.BINARY); // Equivalent to no encoding
|
||||
GMime.Part part = new GMime.Part.with_type("message", "rfc822");
|
||||
part.set_content_object(data);
|
||||
part.set_content(data);
|
||||
part.set_filename((message.get_subject() ?? _("(no subject)")) + ".eml");
|
||||
attachments.add(new Part(part));
|
||||
}
|
||||
|
|
@ -1017,7 +1030,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
#if WITH_TNEF_SUPPORT
|
||||
if (content_type.is_type("application", "vnd.ms-tnef")) {
|
||||
GMime.StreamMem stream = new GMime.StreamMem();
|
||||
((GMime.Part) root).get_content_object().write_to_stream(stream);
|
||||
((GMime.Part) root).get_content().write_to_stream(stream);
|
||||
ByteArray tnef_data = stream.get_byte_array();
|
||||
Ytnef.TNEFStruct tn;
|
||||
if (Ytnef.ParseMemory(tnef_data.data, out tn) == 0) {
|
||||
|
|
@ -1052,8 +1065,8 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
|
||||
GMime.Part part = new GMime.Part();
|
||||
part.set_filename(filename);
|
||||
part.set_content_type(new GMime.ContentType.from_string(GLib.ContentType.guess(filename, data, null)));
|
||||
part.set_content_object(new GMime.DataWrapper.with_stream(new GMime.StreamMem.with_buffer(data), GMime.ContentEncoding.BINARY));
|
||||
part.set_content_type(GMime.ContentType.parse(Geary.RFC822.get_parser_options(), GLib.ContentType.guess(filename, data, null)));
|
||||
part.set_content(new GMime.DataWrapper.with_stream(new GMime.StreamMem.with_buffer(data), GMime.ContentEncoding.BINARY));
|
||||
return part;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1092,9 +1105,17 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
stream.set_owner(false);
|
||||
|
||||
GMime.StreamFilter stream_filter = new GMime.StreamFilter(stream);
|
||||
stream_filter.add(new GMime.FilterCRLF(encoded, dotstuffed));
|
||||
if (encoded) {
|
||||
stream_filter.add(new GMime.FilterUnix2Dos(false));
|
||||
}
|
||||
else {
|
||||
stream_filter.add(new GMime.FilterDos2Unix(false));
|
||||
}
|
||||
if (dotstuffed) {
|
||||
stream_filter.add(new GMime.FilterSmtpData());
|
||||
}
|
||||
|
||||
if (message.write_to_stream(stream_filter) < 0)
|
||||
if (message.write_to_stream(Geary.RFC822.get_format_options(), stream_filter) < 0)
|
||||
throw new RFC822Error.FAILED("Unable to write RFC822 message to memory buffer");
|
||||
|
||||
if (stream_filter.flush() != 0)
|
||||
|
|
@ -1104,7 +1125,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
}
|
||||
|
||||
public string to_string() {
|
||||
return message.to_string();
|
||||
return message.to_string(Geary.RFC822.get_format_options());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1152,11 +1173,13 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
// Base64-encoded text needs to have CR's added after LF's
|
||||
// before encoding, otherwise it breaks format=flowed. See
|
||||
// Bug 753528.
|
||||
filter_stream.add(new GMime.FilterCRLF(true, false));
|
||||
filter_stream.add(new GMime.FilterUnix2Dos(false));
|
||||
}
|
||||
|
||||
GMime.ContentType complete_type =
|
||||
new GMime.ContentType.from_string(content_type);
|
||||
GMime.ContentType complete_type = GMime.ContentType.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
content_type
|
||||
);
|
||||
complete_type.set_parameter("charset", charset);
|
||||
if (is_flowed) {
|
||||
complete_type.set_parameter("format", "flowed");
|
||||
|
|
@ -1168,7 +1191,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
|||
|
||||
GMime.Part body_part = new GMime.Part();
|
||||
body_part.set_content_type(complete_type);
|
||||
body_part.set_content_object(body);
|
||||
body_part.set_content(body);
|
||||
body_part.set_content_encoding(encoding);
|
||||
return body_part;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ public class Geary.RFC822.Part : Object {
|
|||
BodyFormatting format = BodyFormatting.NONE)
|
||||
throws RFC822Error {
|
||||
GMime.DataWrapper? wrapper = (this.source_part != null)
|
||||
? this.source_part.get_content_object() : null;
|
||||
? this.source_part.get_content() : null;
|
||||
if (wrapper == null) {
|
||||
throw new RFC822Error.INVALID(
|
||||
"Could not get the content wrapper for content-type %s",
|
||||
|
|
@ -201,7 +201,7 @@ public class Geary.RFC822.Part : Object {
|
|||
if ((this.source_part == null ||
|
||||
this.source_part.encoding != BASE64) &&
|
||||
!(content_type.media_subtype in CR_PRESERVING_TEXT_TYPES)) {
|
||||
filter.add(new GMime.FilterCRLF(false, false));
|
||||
filter.add(new GMime.FilterDos2Unix(false));
|
||||
}
|
||||
|
||||
if (flowed) {
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ public string email_addresses_for_reply(Geary.RFC822.MailboxAddresses? addresses
|
|||
}
|
||||
|
||||
|
||||
public bool comp_char_arr_slice(char[] array, uint start, string comp) {
|
||||
public bool comp_char_arr_slice(uint8[] array, uint start, string comp) {
|
||||
for (int i = 0; i < comp.length; i++) {
|
||||
if (array[start + i] != comp[i])
|
||||
return false;
|
||||
|
|
@ -277,7 +277,7 @@ public async string get_best_charset(GMime.Stream in_stream,
|
|||
},
|
||||
cancellable
|
||||
);
|
||||
return filter.charset();
|
||||
return filter.get_charset();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -32,18 +32,7 @@ public void init() {
|
|||
if (init_count++ != 0)
|
||||
return;
|
||||
|
||||
GMime.init(GMime.ENABLE_RFC2047_WORKAROUNDS);
|
||||
|
||||
// This has the effect of ensuring all non US-ASCII and non-ISO-8859-1
|
||||
// headers are always encoded as UTF-8. This should be fine because
|
||||
// message bodies are also always sent as UTF-8.
|
||||
const string?[] USER_CHARSETS = {
|
||||
UTF8_CHARSET,
|
||||
// GMime.set_user_charsets calls g_strdupv under the hood, so
|
||||
// the array needs to be null-terminated
|
||||
null
|
||||
};
|
||||
GMime.set_user_charsets(USER_CHARSETS);
|
||||
GMime.init();
|
||||
|
||||
try {
|
||||
invalid_filename_character_re = new Regex("[/\\0]");
|
||||
|
|
@ -52,6 +41,17 @@ public void init() {
|
|||
}
|
||||
}
|
||||
|
||||
public GMime.FormatOptions get_format_options() {
|
||||
return new GMime.FormatOptions();
|
||||
}
|
||||
|
||||
public GMime.ParserOptions get_parser_options() {
|
||||
return new GMime.ParserOptions();
|
||||
}
|
||||
|
||||
public string? get_charset() {
|
||||
return null;
|
||||
}
|
||||
|
||||
internal bool is_utf_8(string charset) {
|
||||
string up = charset.up();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class Geary.ImapDB.AttachmentTest : TestCase {
|
|||
|
||||
public void new_from_minimal_mime_part() throws Error {
|
||||
GMime.Part part = new_part(null, ATTACHMENT_BODY.data);
|
||||
part.set_header("Content-Type", "");
|
||||
part.set_header("Content-Type", "", Geary.RFC822.get_charset());
|
||||
|
||||
Attachment test = new Attachment.from_part(
|
||||
1, new Geary.RFC822.Part(part)
|
||||
|
|
@ -51,7 +51,8 @@ class Geary.ImapDB.AttachmentTest : TestCase {
|
|||
part.set_content_id(ID);
|
||||
part.set_content_description(DESC);
|
||||
part.set_content_disposition(
|
||||
new GMime.ContentDisposition.from_string(
|
||||
GMime.ContentDisposition.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
"attachment; filename=%s".printf(NAME)
|
||||
)
|
||||
);
|
||||
|
|
@ -74,7 +75,10 @@ class Geary.ImapDB.AttachmentTest : TestCase {
|
|||
public void new_from_inline_mime_part() throws Error {
|
||||
GMime.Part part = new_part(null, ATTACHMENT_BODY.data);
|
||||
part.set_content_disposition(
|
||||
new GMime.ContentDisposition.from_string("inline")
|
||||
GMime.ContentDisposition.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
"inline"
|
||||
)
|
||||
);
|
||||
|
||||
Attachment test = new Attachment.from_part(
|
||||
|
|
@ -205,7 +209,8 @@ CREATE TABLE MessageAttachmentTable (
|
|||
part.set_content_id(ID);
|
||||
part.set_content_description(DESCRIPTION);
|
||||
part.set_content_disposition(
|
||||
new GMime.ContentDisposition.from_string(
|
||||
GMime.ContentDisposition.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
"inline; filename=%s;".printf(FILENAME)
|
||||
));
|
||||
|
||||
|
|
@ -352,12 +357,15 @@ private GMime.Part new_part(string? mime_type,
|
|||
GMime.ContentEncoding encoding = GMime.ContentEncoding.DEFAULT) {
|
||||
GMime.Part part = new GMime.Part();
|
||||
if (mime_type != null) {
|
||||
part.set_content_type(new GMime.ContentType.from_string(mime_type));
|
||||
part.set_content_type(GMime.ContentType.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
mime_type
|
||||
));
|
||||
}
|
||||
GMime.DataWrapper body_wrapper = new GMime.DataWrapper.with_stream(
|
||||
new GMime.StreamMem.with_buffer(body),
|
||||
encoding
|
||||
);
|
||||
part.set_content_object(body_wrapper);
|
||||
part.set_content(body_wrapper);
|
||||
return part;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,10 @@ class Geary.RFC822.PartTest : TestCase {
|
|||
part.set_content_id(ID);
|
||||
part.set_content_description(DESC);
|
||||
part.set_content_disposition(
|
||||
new GMime.ContentDisposition.from_string("inline")
|
||||
GMime.ContentDisposition.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
"inline"
|
||||
)
|
||||
);
|
||||
|
||||
Part test = new Part(part);
|
||||
|
|
@ -93,13 +96,16 @@ class Geary.RFC822.PartTest : TestCase {
|
|||
uint8[] body) {
|
||||
GMime.Part part = new GMime.Part();
|
||||
if (mime_type != null) {
|
||||
part.set_content_type(new GMime.ContentType.from_string(mime_type));
|
||||
part.set_content_type(GMime.ContentType.parse(
|
||||
Geary.RFC822.get_parser_options(),
|
||||
mime_type
|
||||
));
|
||||
}
|
||||
GMime.DataWrapper body_wrapper = new GMime.DataWrapper.with_stream(
|
||||
new GMime.StreamMem.with_buffer(body),
|
||||
GMime.ContentEncoding.BINARY
|
||||
);
|
||||
part.set_content_object(body_wrapper);
|
||||
part.set_content(body_wrapper);
|
||||
part.encode(GMime.EncodingConstraint.7BIT);
|
||||
return part;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue