GithubHelp home page GithubHelp logo

jstedfast / gmime Goto Github PK

View Code? Open in Web Editor NEW
115.0 7.0 36.0 13.16 MB

A C/C++ MIME creation and parser library with support for S/MIME, PGP, and Unix mbox spools.

License: GNU Lesser General Public License v2.1

Makefile 0.61% M4 1.83% Shell 0.70% C 96.21% HTML 0.63% Vala 0.02%
c email mime parser mime-parser mbox pgp smime

gmime's People

Contributors

aklapper avatar albrechtd avatar bellegarde-c avatar biswa96 avatar cgwalters avatar dagle avatar djcb avatar dkg avatar ehwat avatar eli-schwartz avatar ezeeyahoo avatar fdanis-oss avatar gauteh avatar jjardon avatar joeshaw avatar jstedfast avatar jwilk avatar lazyhamster avatar mattst88 avatar mjog avatar nemequ avatar ojwb avatar ovitters avatar psankar avatar ricotz avatar sigasigasiga avatar thomasnoll avatar timmooney avatar vrutkovs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

gmime's Issues

segfault in g_mime_parser_options_set_address_compliance_mode from internet_address_list_parse

Hi, not sure if this is a gmime bug yet, but I've had two reports of segfaults in g_mime_parser_options_set_address_compliance_mode from internet_address_list_parse. The crash happens when trying to build a list of threads from a notmuch query, so this is highly dependent on user input. I do not yet have a string that causes this error.

Two reports: astroidmail/astroid#405 (comment) and astroidmail/astroid#388 (comment), backtrace looks like this:

Thread 5 "astroid" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffd8ddf700 (LWP 14120)]
0x00007fffed5122f7 in g_mime_parser_options_get_address_compliance_mode () from /usr/lib/libgmime-3.0.so.0
(gdb) bt
#0  0x00007fffed5122f7 in g_mime_parser_options_get_address_compliance_mode () at /usr/lib/libgmime-3.0.so.0
#1  0x00007fffed523210 in  () at /usr/lib/libgmime-3.0.so.0
#2  0x00007fffed524aec in internet_address_list_parse () at /usr/lib/libgmime-3.0.so.0
#3  0x00007ffff71022fb in _thread_add_message (exclude_terms=0x7fffd0025ef0, omit_exclude=NOTMUCH_EXCLUDE_TRUE, message=0x7fffd00349e0, thread=<optimized out>) at lib/thread.cc:278
#4  0x00007ffff71022fb in _notmuch_thread_create(void*, notmuch_database_t*, unsigned int, notmuch_doc_id_set_t*, notmuch_string_list_t*, notmuch_exclude_t, notmuch_sort_t) (ctx=0x7fffd0022790, notmuch=<optimized out>, seed_doc_id=52595, match_set=match_set@entry=0x7fffd0001af8, exclude_terms=0x7fffd0025ef0, omit_excluded=NOTMUCH_EXCLUDE_TRUE, sort=NOTMUCH_SORT_NEWEST_FIRST) at lib/thread.cc:526
#5  0x00007ffff70fefe9 in notmuch_threads_get(notmuch_threads_t*) (threads=0x7fffd0001ae0) at lib/query.cc:579
#6  0x00005555558c584a in Astroid::QueryLoader::loader() (this=0x555555dde9a0) at src/modes/thread_index/query_loader.cc:156
#7  0x00005555558c8926 in std::__invoke_impl<void, void (Astroid::QueryLoader::*)(), Astroid::QueryLoader*>(std::__invoke_memfun_deref, void (Astroid::QueryLoader::*&&)(), Astroid::QueryLoader*&&) (__f=@0x5555563eba10: (void (Astroid::QueryLoader::*)(Astroid::QueryLoader * const)) 0x5555558c5540 <Astroid::QueryLoader::loader()>, __t=@0x5555563eba08: 0x555555dde9a0) at /usr/include/c++/7.2.0/bits/invoke.h:73
#8  0x00005555558c7e4d in std::__invoke<void (Astroid::QueryLoader::*)(), Astroid::QueryLoader*>(void (Astroid::QueryLoader::*&&)(), Astroid::QueryLoader*&&) (__fn=@0x5555563eba10: (void (Astroid::QueryLoader::*)(Astroid::QueryLoader * const)) 0x5555558c5540 <Astroid::QueryLoader::loader()>, __args#0=@0x5555563eba08: 0x555555dde9a0) at /usr/include/c++/7.2.0/bits/invoke.h:95
#9  0x00005555558cae39 in std::thread::_Invoker<std::tuple<void (Astroid::QueryLoader::*)(), Astroid::QueryLoader*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) (this=0x5555563eba08) at /usr/include/c++/7.2.0/thread:234
#10 0x00005555558cadda in std::thread::_Invoker<std::tuple<void (Astroid::QueryLoader::*)(), Astroid::QueryLoader*> >::operator()() (this=0x5555563eba08) at /usr/include/c++/7.2.0/thread:243
#11 0x00005555558cadaa in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (Astroid::QueryLoader::*)(), Astroid::QueryLoader*> > >::_M_run() (this=0x5555563eba00) at /usr/include/c++/7.2.0/thread:186
#12 0x00007fffee752a6f in std::execute_native_thread_routine(void*) (__p=0x5555563eba00) at /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:83
#13 0x00007fffedf1f08a in start_thread () at /usr/lib/libpthread.so.0
#14 0x00007fffedc571bf in clone () at /usr/lib/libc.so.6

g_mime_object_write_to_stream() with GMimeStreamFs does not work as before with GMime 3

Hi,

I'm trying to port my code for sending messages through piping them to a stdin file descriptor to GMime 3. The following code seems to just produce empty messages, I am testing with piping into tee file:

      /* write message to sendmail */
      GMimeStream * stream = g_mime_stream_fs_new (stdin);
      g_mime_stream_fs_set_owner (GMIME_STREAM_FS(stream), true);
      g_mime_object_write_to_stream(GMIME_OBJECT(message), g_mime_format_options_get_default (), stream);
      g_mime_stream_flush (stream);
      g_object_unref (stream); // closes stdin

      /* wait for sendmail to finish */
      int status;
      pid_t wp = waitpid (pid, &status, 0);

If I use file_new with an actual file it works fine, g_mime_object_to_ string() also shows a nice message.

uuencode example fails with "illegal seek" when reading input from a pipe

It looks like the failure is happening inside g_mime_stream_write_to_stream

For more details, see the debian bug report: https://bugs.debian.org/887625

1 dkg@alice:~$ echo test | strace gmime-uuencode test.txt
execve("/usr/bin/gmime-uuencode", ["gmime-uuencode", "test.txt"], 0x7ffeb5243b58 /* 46 vars */) = 0
brk(NULL)                               = 0x557cd9282000
  […]
mprotect(0x7f884f746000, 4096, PROT_READ) = 0
mprotect(0x7f884f338000, 28672, PROT_READ) = 0
mprotect(0x7f884f542000, 4096, PROT_READ) = 0
mprotect(0x7f884f9ab000, 24576, PROT_READ) = 0
mprotect(0x557cd8df1000, 4096, PROT_READ) = 0
mprotect(0x7f884fbe6000, 4096, PROT_READ) = 0
munmap(0x7f884fba5000, 265044)          = 0
set_tid_address(0x7f884fb98b50)         = 12162
set_robust_list(0x7f884fb98b60, 24)     = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x7f884dd86c20, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f884dd93160}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x7f884dd86cc0, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x7f884dd93160}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=8192*1024}) = 0
statfs("/sys/fs/selinux", 0x7fff67fce0f0) = -1 ENOENT (No such file or directory)
statfs("/selinux", 0x7fff67fce0f0)      = -1 ENOENT (No such file or directory)
brk(NULL)                               = 0x557cd9282000
brk(0x557cd92a3000)                     = 0x557cd92a3000
openat(AT_FDCWD, "/proc/filesystems", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(3, "nodev\tsysfs\nnodev\trootfs\nnodev\tr"..., 1024) = 324
read(3, "", 1024)                       = 0
close(3)                                = 0
access("/etc/selinux/config", F_OK)     = -1 ENOENT (No such file or directory)
futex(0x7f884ed52e28, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f884ed52e28, FUTEX_WAKE_PRIVATE, 2147483647) = 0
dup(0)                                  = 3
fstat(3, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 21), ...}) = 0
write(1, "begin 600 test.txt\n", 19begin 600 test.txt
)    = 19
lseek(3, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
lseek(3, 0, SEEK_SET)                   = -1 ESPIPE (Illegal seek)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/charset.alias", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=26258, ...}) = 0
mmap(NULL, 26258, PROT_READ, MAP_SHARED, 4, 0) = 0x7f884fbdf000
close(4)                                = 0
futex(0x7f884dd7c9e8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
write(2, "gmime-uuencode: Illegal seek\n", 29gmime-uuencode: Illegal seek
) = 29
close(3)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++
1 dkg@alice:~$ echo test | ltrace gmime-uuencode test.txt
strrchr("gmime-uuencode", '/')                   = nil
g_option_context_new(0x558474a8c74d, 47, 1, 0)   = 0x558476664e60
g_option_context_add_main_entries(0x558476664e60, 0x558474c8d020, 0x7ffc4aa74944, 0x656d616e205d45) = 0
g_option_context_set_help_enabled(0x558476664e60, 1, 0x558476664f60, 0x7f6736aec660) = 1
g_option_context_parse(0x558476664e60, 0x7ffc4aa7255c, 0x7ffc4aa72560, 0x7ffc4aa72568) = 1
g_option_context_free(0x558476664e60, 2, 0x7ffc4aa72720, 0) = 0
dup(0, 0x558476658010, 0x7ffc4aa72718, 4)        = 3
__fxstat(1, 3, 0x7ffc4aa72570)                   = 0
__printf_chk(1, 0x558474a8c77a, 0x558474a8c747, 384begin 600 test.txt
) = 19
fflush(0x7f6735dd8740)                           = 0
g_mime_stream_fs_new(3, 0x7f6735dd98a0, 0, 2880) = 0x558476666800
g_mime_stream_pipe_new(1, 0, -1, 0)              = 0x558476666850
g_mime_stream_pipe_set_owner(0x558476666850, 0, -1, 0) = 0x558476667610
g_mime_stream_filter_new(0x558476666850, 0, 0x558476667700, 0) = 0x5584766668a0
g_mime_filter_basic_new(6, 1, -1, 0)             = 0x55847666a000
g_mime_stream_filter_add(0x5584766668a0, 0x55847666a000, 0x558476669560, 0) = 0
g_object_unref(0x55847666a000, 2000, 0, 0x558476663300) = 2
g_mime_stream_write_to_stream(0x558476666800, 0x5584766668a0, 1, 0) = -1
__errno_location()                               = 0x7f6737bf47f8
g_strerror(29, 0, -136, 0)                       = 0x558476669960
__fprintf_chk(0x7f6735dd8660, 1, 0x558474a8c772, 0x7ffc4aa74944gmime-uuencode: Illegal seek
) = 29
g_object_unref(0x5584766668a0, 29, 0x7f6735dd9890, 0) = 0
g_object_unref(0x558476666800, 4, 0x5584766677e0, 1) = 0
g_object_unref(0x558476666850, 4, 0x5584766660b0, 1) = 0
+++ exited (status 1) +++
0 dkg@alice:~$ 

Headers parser error corner case

Hi,

I ran into a strange parser issue which can be reproduced using the attached minimal sample (which is clean and RFC-compliant IMHO), e.g. by running the msgcheck example application:

albrecht@deneb:~/OSS/gmime$ examples/msgcheck sample_parser.mbx 

(process:1907): gmime-WARNING **: 19:04:18.557: Invalid header at 4095: '
'
sample_parser.mbx: message contains 2 RFC violations:
offset 4095: [9] invalid header name, parser may skip the message or parts of it: ''
offset 4097: [9] invalid header name, parser may skip the message or parts of it: 'c29tZSBvdGhlciBkYXRhLi4uCg=='

The issue seems to be reproducible if

  • the 2nd LF of the CR LF CR LF sequence terminating the headers of a part does not fit into a 4k block and
  • if the headers block is sufficiently large (didn't figure out the exact limit, though).

Apparently, the warning is produced in gmime/gmime-parser.c, function header_parse(), line 888.

Simply shifting the 2nd message part a byte forward or backward (by adding or removing a char in the 1st part) “fixes” the issue.

It might be possible that the call to _g_mime_parser_options_warn() (IIRC, it was me who added it there…😕️) in line 887 is just wrong, but at first glance this looks more like a corner case where the buffer is not filled sufficiently for parsing the headers.

Any idea what goes wrong here?

Thanks in advance, Albrecht.

P.S.: BTW, it is not possible to build gmime with the --enable-warnings configure option due to a compiler error in internet-address.c, so I had to enable the warning manually in gmime-parser.c.

sample_parser.zip

GMime parsing bad-header behavior differs from some common implementations

GMime has sub-optimal behavior when faced with malformed headers. There's some logic in parser_step_headers to proceed past some bad lines, but as-implemented there are header combinations that will fool GMime into stopping header parsing early.

Specifically, I want to focus on sub-sections of the RFC 7103, because clients (e.g. Outlook?, Evolution/Camel, Thunderbird) seem to implement approach 1, whereas GMime implements approach 2:

  1. Header Anomalies
    This section covers common syntactic and semantic anomalies found in
    a message header and presents suggested methods of mitigation.
    ...
    7.2. Non-Header Lines

Some messages contain a line of text in the header that is not a
valid message header field of any kind. For example:

  From: [email protected] {1}
  To: [email protected] {2}
  Subject: This is your reminder {3}
  about the football game tonight {4}
  Date: Wed, 20 Oct 2010 20:53:35 -0400 {5}

The suggested ways of dealing with this kind of stuff are:

  1. Some agents choose to separate the header of the message from the
    body only at the first empty line (that is, a CRLF immediately
    followed by another CRLF).

  2. Some agents assume this anomaly should be interpreted to mean the
    body starts at line {4}, as the end of the header is assumed by
    encountering something that is not a valid header field or folded
    portion thereof.

  3. Some agents assume this should be interpreted as an intended
    header folding as described above and thus simply append a single
    space character (ASCII 0x20) and the content of line {4} to that
    of line {3}.

  4. Some agents reject this outright as line {4} is neither a valid
    header field nor a folded continuation of a header field prior to
    an empty line.

GMime mainly does 2 (with the message/content headers heuristic), and doesn't implement 3 (headers are never treated as a mis-fold and "recovered").

--- Below here might not be interesting in light of Outlook not actually implementing 3 either.

I found the rspamd thread on this - I'd like to improve the behavior though, if possible, instead of abandoning GMime altogether. What kind of error recovery is in line with your goals for GMime?

Currently I've modified the logic in parser_step_headers to be a bit more tolerant, but...

  1. For the pasting of lines, manipulating the appended line (ends up in raw_value) means we're changing the email representation.
  2. It's very hard to reconcile the "guess we've hit a broken mailer" jump-to-content code already in GMime and this kind of RFC 7103 approach 3 behavior. From my limited testing, Outlook doesn't care to jump to content, even for multipart parts.
  3. If we do move it outside (... e.g. roll a priv_headers_to_object or whatever with enough options to support all the construct callers, and store broken lines as key-less lines in the array), then that information isn't available to decide whether to end header parsing (and you might have to dump a bunch of fake headers and re-parse as body).

Moving it outside seems like a better approach (just because you have more flexibility in seeking across the different lines and don't have to worry about the 4k limit), but nothing about this screams elegant; what are your thoughts? I guess header_cb should be called on the re-folded version as well?

The two most-interesting cases RE actual samples:

  1. Stopping header parsing too early because of badly-folded headers. Outlook 2016, Thunderbird 60, etc. chew through these bad boys just fine. This sometimes causes GMime to miss important headers (boundaries, content types, etc.).

From: [email protected]
To: [email protected]
Message-ID: [email protected]
Subject: Confirmed email
X-IBM-SpamModules-Scores: A=1; B=2;
C=3; D=4; E=5;
X-IBM-SpamModules-Versions: A=1; B=2; C=3;
D=4; E=5; F=6;
G=7; H=8;
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

...
  1. Malformed header lines that could benefit from re-folding, e.g. as described here:

Content-Type: application/x-zip-compressed; x-unix-mode=0600;
name="7DDA4_foo_9E5D72.zip"`

Although it does seem like the re-folding needs to be line-parsing-aware, since I have cases like:

Content-Type: application/x-zip-compressed; x-unix-mode=0600; name="
7DDA4_foo_9E5D72.zip"`

Maybe that's overkill though, haven't tested whether common clients end up recovering the attachment name properly here.

Building on CentOS / RHEL 8

Any documentation on how to build this on CentOS /RHEL 8 Tried using autoconf/automake but both failed

$ autoconf
configure.ac:53: error: possibly undefined macro: AM_INIT_AUTOMAKE
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation.
configure.ac:58: error: possibly undefined macro: AM_CONFIG_HEADER
configure.ac:59: error: possibly undefined macro: AM_MAINTAINER_MODE
configure.ac:116: error: possibly undefined macro: AM_CONDITIONAL
configure.ac:137: error: possibly undefined macro: AM_PROG_CC_STDC
configure.ac:150: error: possibly undefined macro: AC_PROG_LIBTOOL
configure.ac:308: error: possibly undefined macro: AM_PATH_GLIB_2_0

Failing tests on Alpine Linux (w/ musl libc)

Hello,

while trying to upgrade to GMime 3.2.4 on Alpine Linux I've noticed the following test failures:

Testing charset conversion utils: failed (1 errors, 0 warnings)
Testing Stream tests: passed
Testing GMimeStreamCat: passed
Testing Content-Transfer-Encoding: passed
Testing base64: passed
Testing uuencode: passed
Testing quoted-printable: passed
Testing GMimeFilter: failed (1 errors, 0 warnings)
Testing indexing: passed
Testing removing: passed
Testing removing at an index: passed
Testing header synchronization: passed
Testing header formatting: passed
Testing GMimePart: passed
Testing message/partial: passed
Testing Mbox parser: passed
Testing Autocrypt: generate headers: passed
Testing Autocrypt: import OpenPGP secret key: passed
Testing Autocrypt: parse messages: passed
Testing Autocrypt: inject headers: passed
Testing addr-spec parser (strict): passed
Testing addr-spec parser (loose): passed
Testing date parser: passed
Testing rfc2047 encoding/decoding (strict): passed
Testing rfc2047 encoding/decoding (loose): passed
Testing rfc2184 encoding/decoding: passed
Testing quoted-strings: passed
Testing header folding: passed
Testing references: passed
Testing GnuPG crypto context: passed
Testing PGP/MIME implementation: passed
Results: 11 tests passed; 2 tests failed.
Failed tests: 
 test-iconv
 test-filters
/bin/sh: exit: line 23: Illegal number: -1

Sadly I'm not quite sure how to make more useful, more verbose logs of the tests. We haven' t run tests on 3.2.3.

No plain part if the Content-Type is multipart/alternative

I am using gmime to decode the message body. I am not sure if it's a bug or that's how it should be, but I am unable to retrieve plain part from the message body. The Iterator only returns one part ( html part) even though both parts are present in the message. However, if the context type is multipart/mixed (with attachment), Iterator returns all the parts (plain, html, attachment).

GMimeObject *mime = g_mime_message_get_mime_part(message);
GMimePartIter *iter = g_mime_part_iter_new (mime);

while (g_mime_part_iter_next (iter)) {
...
}

Below is the multipart-message

Content-Type: multipart/alternative;
 boundary="b1_Y2t1lEr6GADYZN0KffJwRMAB2lWd3ExEuRJKjCFRQ4"
Content-Transfer-Encoding: 8bit

This is a multi-part message in MIME format.
--b1_Y2t1lEr6GADYZN0KffJwRMAB2lWd3ExEuRJKjCFRQ4
Content-Type: text/plain; charset=us-ascii

This is the body in plain text for non-HTML mail clients

--b1_Y2t1lEr6GADYZN0KffJwRMAB2lWd3ExEuRJKjCFRQ4
Content-Type: text/html; charset=us-ascii

This is the HTML message body <b>in bold!</b>


--b1_Y2t1lEr6GADYZN0KffJwRMAB2lWd3ExEuRJKjCFRQ4--

Parsing stdin

After this commit it is no longer possible to parse emails from stdin, as a seek on stdin returns error 29.
Using stdin is necessary for use with .forward, where the syntax allows you to specify a program to pipe email to (|/receive_mail.sh).
Am I right that the easiest workaround is to replace the read function? The code demonstrates the issue and workaround. Note that without patching ./test-parser empty2.msg works, while cat empty2.msg | ./test-parser does not work.

Unlikely NULL-pointer dereference

The latest cppcheck v. 1.85 detetcs a (rather unlikely) NULL pointer dereference in g_mime_references_parse(), which can be trivially fixed by just shifting the initialisation of the local var inptr as in the attached diff.

Note that cppcheck also reports a possible null pointer dereference for html_tag in fuction enriched_to_html() which is actually a false-positive. It could be avoided by changing line 497 to
if (html_tag != NULL) {
which should (I think…) be logically equivalent.
gmime-references-NULL-ptr-deref.zip

Fix '-Wstrict-prototypes' compile warning

Building applications using gmime with the gcc/clang compiler flag '-Wstrict-prototypes' produces a warning in the header file gmime-autocrypt.h. Trivial fix:

--- a/gmime/gmime-autocrypt.h
+++ b/gmime/gmime-autocrypt.h
@@ -133,7 +133,7 @@ struct _GMimeAutocryptHeaderListClass {
 
 GType g_mime_autocrypt_header_list_get_type (void);
 
-GMimeAutocryptHeaderList *g_mime_autocrypt_header_list_new ();
+GMimeAutocryptHeaderList *g_mime_autocrypt_header_list_new (void);
 guint g_mime_autocrypt_header_list_add_missing_addresses (GMimeAutocryptHeaderList *ahl, InternetAddressList *list);
 void g_mime_autocrypt_header_list_add (GMimeAutocryptHeaderList *ahl, GMimeAutocryptHeader *ah);
 

BTW, it might be a good idea to add this warning option to gmime's compiler flags…

handle PKCS#7 authEnveloped-data

AuthEnvelopedData is basically AEAD applied to CMS in place of traditional encryption. It provides robust message integrity in addition to encryption.

See §3.4 of RFC 8551

It should probably behave in GMime in exactly the same way as EnvelopedData, but it's a different smime-type tag.

warnings from zentimer.h in tests/test-parser.c

Trying to compile tests/test-parser.o results in the following warnings:

  CC     test-parser.o
In file included from test-parser.c:38:0:
../zentimer.h:121:1: warning: ‘ZenTimerResume’ defined but not used [-Wunused-function]
 ZenTimerResume (ztimer_t *ztimer)
 ^~~~~~~~~~~~~~
../zentimer.h:112:1: warning: ‘ZenTimerPause’ defined but not used [-Wunused-function]
 ZenTimerPause (ztimer_t *ztimer)
 ^~~~~~~~~~~~~

I don't understand enough about zentimer to know how to avoid this warning, but if it's not a real problem, we should find a way to suppress the warning so that useful warnings are not obscured by the noise.

stack overflow in group_parse()

Parsing malformed address that contain a very long sequence of colons can exhaust stack:

$ perl -E 'say "From: " . ":" x 99999' > stackoverflow.822
$ tests/test-parser stackoverflow.822

Testing MIME parser...

Segmentation fault

Backtrace:

#0  0xb7c6e5df in g_private_get () from /lib/i386-linux-gnu/libglib-2.0.so.0
#1  0xb7c44ffe in g_slice_alloc () from /lib/i386-linux-gnu/libglib-2.0.so.0
#2  0xb7bf97fb in g_ptr_array_sized_new () from /lib/i386-linux-gnu/libglib-2.0.so.0
#3  0xb7bf9856 in g_ptr_array_new () from /lib/i386-linux-gnu/libglib-2.0.so.0
#4  0xb7f6fdfe in g_mime_event_new (owner=0x8024ff30) at gmime-events.c:74
#5  0xb7f9798a in internet_address_list_init (list=0x8024ff30, klass=0x8000f8a0) at internet-address.c:702
#6  0xb7d3d4b0 in g_type_create_instance () from /usr/lib/i386-linux-gnu/libgobject-2.0.so.0
#7  0xb7d1ebc7 in ?? () from /usr/lib/i386-linux-gnu/libgobject-2.0.so.0
#8  0xb7d2062c in g_object_newv () from /usr/lib/i386-linux-gnu/libgobject-2.0.so.0
#9  0xb7d20cbd in g_object_new () from /usr/lib/i386-linux-gnu/libgobject-2.0.so.0
#10 0xb7f9981f in internet_address_list_new () at internet-address.c:743
#11 0xb7f99849 in internet_address_group_init (group=0x80250800, klass=0x8002d888) at internet-address.c:543
#12 0xb7d3d4b0 in g_type_create_instance () from /usr/lib/i386-linux-gnu/libgobject-2.0.so.0
#13 0xb7d1ebc7 in ?? () from /usr/lib/i386-linux-gnu/libgobject-2.0.so.0
#14 0xb7d2062c in g_object_newv () from /usr/lib/i386-linux-gnu/libgobject-2.0.so.0
#15 0xb7d20cbd in g_object_new () from /usr/lib/i386-linux-gnu/libgobject-2.0.so.0
#16 0xb7f98bee in internet_address_group_new (name=0x8002d828 "") at internet-address.c:577
#17 0xb7f9917f in address_parse (flags=ALLOW_ANY, address=<synthetic pointer>, charset=0xbff004e8, in=0xbff004ec, options=0x8000a5c0) at internet-address.c:1933
#18 address_list_parse (list=list@entry=0x8024feb0, options=options@entry=0x8000a5c0, in=in@entry=0xbff0057c, is_group=1) at internet-address.c:2078
#19 0xb7f99299 in address_list_parse (is_group=1, in=<optimized out>, options=<optimized out>, list=0x8024feb0) at internet-address.c:2064
#20 group_parse (in=0xbff00570, options=0x8000a5c0, group=0x8024d9c0) at internet-address.c:1774
#21 address_parse (flags=ALLOW_ANY, address=<synthetic pointer>, charset=0xbff00568, in=0xbff0056c, options=0x8000a5c0) at internet-address.c:1937
#22 address_list_parse (list=list@entry=0x8024fe50, options=options@entry=0x8000a5c0, in=in@entry=0xbff005fc, is_group=1) at internet-address.c:2078
#23 0xb7f99299 in address_list_parse (is_group=1, in=<optimized out>, options=<optimized out>, list=0x8024fe50) at internet-address.c:2064
#24 group_parse (in=0xbff005f0, options=0x8000a5c0, group=0x8024d9a0) at internet-address.c:1774
#25 address_parse (flags=ALLOW_ANY, address=<synthetic pointer>, charset=0xbff005e8, in=0xbff005ec, options=0x8000a5c0) at internet-address.c:1937
#26 address_list_parse (list=list@entry=0x8024fdc0, options=options@entry=0x8000a5c0, in=in@entry=0xbff0067c, is_group=1) at internet-address.c:2078
#27 0xb7f99299 in address_list_parse (is_group=1, in=<optimized out>, options=<optimized out>, list=0x8024fdc0) at internet-address.c:2064
...
#32644 group_parse (in=0xbffff370, options=0x8000a5c0, group=0x80011080) at internet-address.c:1774
#32645 address_parse (flags=ALLOW_ANY, address=<synthetic pointer>, charset=0xbffff368, in=0xbffff36c, options=0x8000a5c0) at internet-address.c:1937
#32646 address_list_parse (list=list@entry=0x8000a880, options=options@entry=0x8000a5c0, in=in@entry=0xbffff3fc, is_group=1) at internet-address.c:2078
#32647 0xb7f99299 in address_list_parse (is_group=1, in=<optimized out>, options=<optimized out>, list=0x8000a880) at internet-address.c:2064
#32648 group_parse (in=0xbffff3f0, options=0x8000a5c0, group=0x80011060) at internet-address.c:1774
#32649 address_parse (flags=ALLOW_ANY, address=<synthetic pointer>, charset=0xbffff3e8, in=0xbffff3ec, options=0x8000a5c0) at internet-address.c:1937
#32650 address_list_parse (list=list@entry=0x8000a820, options=options@entry=0x8000a5c0, in=in@entry=0xbffff43c, is_group=0) at internet-address.c:2078
#32651 0xb7f9a5da in address_list_parse (is_group=0, in=<optimized out>, options=<optimized out>, list=0x8000a820) at internet-address.c:2064
#32652 internet_address_list_parse (options=0x8000a5c0, str=0x800242f8 " ", ':' <repeats 199 times>...) at internet-address.c:2129
#32653 0xb7f79bdc in message_update_addresses (message=message@entry=0x80005358, options=0x8000a5c0, options@entry=0xb7f7a3a0 <from_changed>, type=GMIME_ADDRESS_TYPE_FROM) at gmime-message.c:289
#32654 0xb7f79eb4 in process_header (object=object@entry=0x80005358, header=0x80005358, header@entry=0x80005410) at gmime-message.c:331
#32655 0xb7f79f8f in message_header_added (object=0x80005358, header=0x80005410) at gmime-message.c:363
#32656 0xb7f6ffe3 in g_mime_event_emit (event=0x80009758, args=0xbffff4e8) at gmime-events.c:221
#32657 0xb7f78496 in _g_mime_header_list_append (headers=0x80011040, name=0x8000de30 "From", raw_name=0x8000f2b8 "From", raw_value=0x8001ac88 " ", ':' <repeats 199 times>..., offset=0) at gmime-header.c:1218
#32658 0xb7f7f830 in _g_mime_object_append_header (object=<optimized out>, header=0x8000de30 "From", raw_name=0x8000f2b8 "From", raw_value=0x8001ac88 " ", ':' <repeats 199 times>..., offset=0) at gmime-object.c:848
#32659 0xb7f860ca in parser_construct_message (options=0x0, parser=0x8000f900) at gmime-parser.c:1999
#32660 g_mime_parser_construct_message (parser=<optimized out>, options=0x0) at gmime-parser.c:2044
#32661 0x80000f7d in test_parser (stream=<optimized out>) at test-parser.c:170
#32662 main (argc=2, argv=0xbffff674) at test-parser.c:268

Tested with v3.0.2.

Found using American Fuzzy Lop.

Macro G_OS_WIN32 is used before it can be defined.

Latest commit for gmime-utils.c broke Windows build.
You've moved #include <glib.h> lower and now it is after check for G_OS_WIN32. But this macro is defined with glib.h. So now it is always false and winsock headers can not be used.

PGP encryption: allow hiding the key IDs for some recipients and not others

currently, when trying to use g_mime_multipart_encrypted_encrypt we get only the choice to hide all recipient key IDs, or to to hide none of them.

this isn't a great fit with a typical e-mail that has some addresses in To: and Cc: and others in Bcc: -- you'd like to hide the key IDs for the Bcc:'ed addresses and expose the others.

This is currently pretty hard to do given constraints of GPGME. I'm asking GPGME to improve things over there: https://dev.gnupg.org/T3775

Questions about the g_mime_header_list_prepend function

According to the manual, after executing the function I think a new line will be added to the top of the mail header.But I found it not the case in some cases.

for example

To: frf621 <[email protected]>
Subject: check this
Message-Id: <[email protected]>
Content-Type: multipart/mixed; boundary="----=_NextPart_0"

------=_NextPart_0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64

dGVzdCBzdHJpbmc=
------=_NextPart_0--

after executing g_mime_header_list_prepend(obj,"x-add-test","test",NULL) header will become

Content-Type: multipart/mixed; boundary="----=_NextPart_0"
x-add-test: test
To: frf621 <[email protected]>
Subject: check this
Message-Id: <[email protected]>


------=_NextPart_0
……The following is omitted……

Test version gmime 3.2.0
Test Platform Ubuntu 16.04 LTS
The following is the test code

#include <gmime/gmime.h>
#include <stdio.h>
#include <string>

void print_message(GMimeObject* gobj)
{
    char* sz_msg = g_mime_object_to_string(gobj, NULL);
    printf("%s",sz_msg);
}

static const char* initial[] = {
    "From: [email protected]", 
    "To: frf621 <[email protected]>", 
    "Subject: check this",
    "Content-Type: multipart/mixed; boundary=\"----=_NextPart_0\"", 
    "Message-Id: <[email protected]>",
    "", 
    "------=_NextPart_0", 
    "Content-Type: text/plain; charset=\"utf-8\"", 
    "Content-Transfer-Encoding: base64", 
    "",
    "dGVzdCBzdHJpbmc=", 
    "------=_NextPart_0--",
};

GMimeMessage* message_from_std_sting(const std::string& input_string)
{
    GMimeStream* g_stream = g_mime_stream_mem_new_with_buffer(input_string.c_str(), input_string.size());
    GMimeParser* g_parser = g_mime_parser_new();
    g_mime_parser_init_with_stream(g_parser, g_stream);
    GMimeParserOptions* g_parser_options = g_mime_parser_options_get_default();
    GMimeMessage* gmime_message = g_mime_parser_construct_message(g_parser, g_parser_options);
    g_mime_parser_options_free(g_parser_options);
    g_object_unref(g_stream);
    g_object_unref(g_parser);
    return gmime_message;
}

void header_list_prepend(GMimeMessage* g_msg, const char* sz_name, const char* sz_value)
{
    GMimeHeaderList* p_header_list = g_mime_object_get_header_list(((GMimeObject*)g_msg));
    g_mime_header_list_prepend(p_header_list, sz_name, sz_value, NULL);
}

int main(int argc, char** argv)
{
    g_mime_init();

    std::string str_data;
    for(unsigned int i = 0; i < sizeof(initial) / sizeof(char*); i++) {
        str_data.append(initial[i]);
        str_data.append("\n");
    }
	//create test mime data
    printf("%s",str_data.c_str());
    printf("%s","------------------split--------------------------\n");
    GMimeMessage* g_msg = message_from_std_sting(str_data);
    //call g_mime_header_list_prepend
    header_list_prepend(g_msg, "X-TEST", "TEST");
    print_message((GMimeObject*)g_msg);

    g_mime_shutdown();
    return 0;
}

tests/Makefile.am: exit -1

tests/Makefile.am contains this rule:

	echo "Results: $${passed} tests passed; $${failed} tests failed."; \
	if [ $${failed} -ne 0 ]; then \
		echo -e "Failed tests: $${failed_tests}"; \
		exit -1; \
	fi

-1 is an invalid argument for exit. From the POSIX spec:

        The exit utility shall cause the shell to exit from its current
        execution environment with the exit status specified by the
        unsigned decimal integer n.

Please use a positive number.

Parse MIME created by web browser during file upload?

Can GMime be used to parse the MIME sent to a webserver during a file upload?

Assume that the user posts the following form via a web browser:

<form action="upload.php" method="post" enctype="multipart/form-data">
    Select image to upload:
    <input type="file" name="fileToUpload" id="fileToUpload">
    <input type="submit" value="Upload Image" name="submit">
</form>

Example MIME received by web server:

------WebKitFormBoundaryFuv4ThyECHCwguJb

Content-Disposition: form-data; name="fileToUpload"; filename="gordo 2.jpg"

Content-Type: image/jpeg



***JPEG*BINARY*DATA*GOES*HERE***MADE*UP*OF*MOSTLY*NON-PRINTABLE*CHARACTERS

------WebKitFormBoundaryFuv4ThyECHCwguJb

Content-Disposition: form-data; name="submit"



Upload Image

------WebKitFormBoundaryFuv4ThyECHCwguJb--

Thank you!

New line issue with GMimeMessagePart

When parsing an existing message containing a message/rfc822 part, an extra new line is inserted above the sub-message headers on writing the GMimeObject to stream:

For example:

--------------BE59E1D6AC7C8CA44EB57E2E
Content-Type: message/rfc822;
 name="AttachedMessage.eml"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="AttachedMessage.eml"
                                        <---- Multiple new lines here

X-Account-Key: account1
X-Mozilla-Keys:
[... AttachedMessage.eml headers continue ...]                                           

instead of

--------------BE59E1D6AC7C8CA44EB57E2E
Content-Type: message/rfc822;
 name="AttachedMessage.eml"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="AttachedMessage.eml"

X-Account-Key: account1
X-Mozilla-Keys:
[... AttachedMessage.eml headers continue ...]                                           

This causes the raw source to the rendered by many email clients (tested - Outlook, Thunderbird, MacOS Mail)

"Delivery of non-mail file" by `notmuch insert`

Hello

Not long ago I switched my mail setup to use notmuch insert (via mailfilter) instead of good old procmail, intending to avoid duplicate processing during delivery. However, since then a number of emails are reported by notmuch as "non-mail", which in my read of the code ultimately comes from g_mime_parser_construct_message rejecting the message.

This is with the Debian-packaged version of gmime, which as best as I can tell corresponds to GMime 3.2.0.

One such failing message is attached:
1547741331.eml.txt This message was posted to the [email protected] list; you can see it as https://postgr.es/m/[email protected] in parsed form. It was generated by mutt. At first I thought the problem might be related to #52 but now I doubt it.

Manually scanning the message does not reveal anything obviously broken. I'm not familiar with either notmuch nor gmime, but looking at ltrace notmuch insert < thefile it seems to me that partway through reading the diffstat part, g_mime_parser_construct_message gives up and g_mime_parser_eos is called, and things go south.

I can provide more information as needed, but at this point I'm at a loss on how to debug this further and would very much welcome some input.

Thanks

Reintroduced message headers

RFC 5322, Sect. 3.6.6 defines Resent-* headers which can be used when a message is reintroduced (not forwarded!) into the transport infrastructure. Although it is possible to access them using gmime's generic header access methods, it would be very helpful if they could be read or written by the more specialised methods like g_mime_message_get_addresses() etc.

Note 1: According to the RFC, a new set of resent fields is prepended to the message for each reintorduction. I.e. a header like Resent-From: may occur multiple times, unlike From:.
Note 2: This feature seems to be used rarely.

memory leak in message_write_to_stream()

Valgrind detected a memory leak in file gmime/gmime-message.c, function message_write_to_stream(): The passed GMimeFormatOptions options are cloned in line 590, but the clone is never freed.

messages still persist even after unref


bool parse_message(std::string strMsg) {
	GMimeMessage* message;
	GMimeStream* stream;
	GMimeParser* parser;
	GMimeParserOptions* options;

	g_mime_init();

	stream = g_mime_stream_mem_new_with_buffer(strMsg.c_str(), strMsg.length());
	parser = g_mime_parser_new_with_stream(stream);

	message = g_mime_parser_construct_message(parser, NULL);

	const char* subject = g_mime_message_get_subject(message);
	const char* body = g_mime_message_get_body(message);
	if (in_array(std::string(subject), possibleSubjects))
	{
		std::cout << g_mime_message_get_body(message) << std::endl;
		g_object_unref(stream);
		g_object_unref(parser);
		g_object_unref(message);
		return true;
	}
	g_object_unref(stream);
	g_object_unref(parser);
	g_object_unref(message);
	g_mime_shutdown();
	return false;
}


for (size_t i = result.size() - 10; i < result.size(); i++) {
			std::string strMsg;
                       IMAPClient.GetString(result[i], strMsg);
			if (parse_message(strMsg)) {
				std::cout << +"\n\n\n --------- " + result[i] + "\n : \n\n" << std::endl;
			        std::cout << strMsg << std::endl;
			}
		}

the parse_message get different strMsg from my IMAP Client, but after looping; the first one is the only one messages that get persisted

RFC2047 format_options encoding mode doesn't work as expected

Hello, it's really helpful with the new param encoding mode format options.
But I have tested both RFC2047 and RFC2231 encoding mode.
The result is always
Content-Disposition: attachment; name*=gb2312''%C3%FB%B3%C6%D7%D6%B6%CE
It seems RFC2047 option doesn't work.
Gmime version: 3.0.0+dfsg1-1 in Debian experimental

handle PKCS#7 CompressedData

gmime currently has some commented out/unimplemented functions for handling PKCS#7 CompressedData messages. These should be implemented, so i'm just recording that as an open issue.

The functions in particular are:

  • g_mime_application_pkcs7_mime_compress
  • g_mime_application_pkcs7_mime_decompress

for specification reference, see § 3.6 of RFC 8551

stack overread on malformed input in uudecode

To see this bug you have to compile with address sanitizer (-fsanitize=address in CFLAGS+LDFLAGS).

A malformed input will lead to an out of bounds stack read in the uudecode example code:

echo -e "begin a\n\x00" | examples/uudecode -

Error:

==11077==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd7d4f042f at pc 0x0000004f84a4 bp 0x7ffd7d4f03d0 sp 0x7ffd7d4f03c8
READ of size 1 at 0x7ffd7d4f042f thread T0
    #0 0x4f84a3 in uudecode /mnt/ram/gmime/examples/uudecode.c:198:14
    #1 0x4f84a3 in main /mnt/ram/gmime/examples/uudecode.c:240
    #2 0x7f2e531584ea in __libc_start_main (/lib64/libc.so.6+0x244ea)
    #3 0x41c479 in _start (/mnt/ram/gmime/examples/uudecode+0x41c479)

Address 0x7ffd7d4f042f is located in stack of thread T0 at offset 79 in frame
    #0 0x4f6e2f in main /mnt/ram/gmime/examples/uudecode.c:228

  This frame has 8 object(s):
    [32, 36) 'argc.addr.i' (line 67)
    [48, 56) 'argv.addr.i' (line 67)
    [80, 4176) 'inbuf.i' (line 72) <== Memory access at offset 79 underflows this variable
    [4304, 4312) 'q.i' (line 72)
    [4336, 4344) 'err.i' (line 74)
    [4368, 8468) 'outbuf.i' (line 76)
    [8736, 8740) 'save.i' (line 78)
    [8752, 8756) 'state.i' (line 80)

some memory leak

int main()
{
CURL *pCurl = curl_easy_init();
curl_easy_setopt(pCurl, CURLOPT_URL, "imaps://imap.qq.com/INBOX;MAILINDEX=1");
curl_easy_setopt(pCurl, CURLOPT_USERNAME, "xxxx");
curl_easy_setopt(pCurl, CURLOPT_PASSWORD, PWD);
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0);
//curl_easy_setopt(pCurl, CURLOPT_CUSTOMREQUEST, "CAPABILITY");
std::string str;
curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &str);
CURLcode res = curl_easy_perform(pCurl);

g_mime_init();
while (true)
{

	/* load a GMimeMessage from a stream */
	GMimeMessage *message;
	GMimeStream *stream;
	GMimeParser *parser;
	GByteArray array;
	array.data = (guint8 *)&str[0];
	array.len = str.length();
	stream = g_mime_stream_mem_new_with_byte_array(&array);
	parser = g_mime_parser_new_with_stream(stream);
	g_object_unref(stream);
	message = g_mime_parser_construct_message(parser, NULL);
	g_object_unref(parser);
	//g_mime_message_foreach(message, GMimeObjectForeachCallback, nullptr);
}
g_mime_shutdown();

}

the memory will increase always!

gmime hangs when decrypting an email (from notmuch) when a TOFU conflict is encountered.


/usr/bin/notmuch show --format=sexp --format-version=1 --decrypt --exclude=false ' thread:0000000000001885 and ( tag:unread )'

#0  0x00007fa50708a530 in __poll_nocancel ()
    at ../sysdeps/unix/syscall-template.S:84
#1  0x00007fa507cfef5f in poll (__timeout=10000, __nfds=5, 
    __fds=0x7ffe9d71a4b0) at /usr/include/x86_64-linux-gnu/bits/poll2.h:46
#2  gpg_ctx_op_step (gpg=gpg@entry=0x55eb6dd218c0, 
    err=err@entry=0x7ffe9d71b5d8) at gmime-gpg-context.c:1631
#3  0x00007fa507d00733 in gpg_decrypt_session (context=<optimized out>, 
    session_key=0x0, istream=<optimized out>, ostream=<optimized out>, 
    err=0x7ffe9d71b5d8) at gmime-gpg-context.c:2147
#4  0x00007fa507d07b28 in g_mime_multipart_encrypted_decrypt_session (
    mpe=<optimized out>, ctx=ctx@entry=0x55eb6dd1c9c0, 
    session_key=session_key@entry=0x0, result=result@entry=0x7ffe9d71b5e0, 
    err=err@entry=0x7ffe9d71b5d8) at gmime-multipart-encrypted.c:407
#5  0x00007fa507d07d0d in g_mime_multipart_encrypted_decrypt (
    mpe=<optimized out>, ctx=ctx@entry=0x55eb6dd1c9c0, 
    result=result@entry=0x7ffe9d71b5e0, err=err@entry=0x7ffe9d71b5d8)
    at gmime-multipart-encrypted.c:295
#6  0x000055eb6d77579e in node_decrypt_and_verify (cryptoctx=0x55eb6dd1c9c0, 
    part=0x55eb6dd1ee40, node=0x55eb6dd1d4b0) at mime-node.c:182
#7  _mime_node_create (part=0x55eb6dd1ee40, parent=0x55eb6dd22d90)
    at mime-node.c:258
#8  mime_node_child (parent=parent@entry=0x55eb6dd22d90, child=child@entry=0)
    at mime-node.c:296
#9  0x000055eb6d77281d in format_part_sprinter (ctx=0x55eb6dcfe7b0, 
    sp=0x55eb6dcfd8b0, node=0x55eb6dd22d90, first=1, output_body=1, 
    include_html=0) at notmuch-show.c:563
#10 0x000055eb6d772f36 in format_part_sprinter_entry (ctx=<optimized out>, 
    sp=<optimized out>, node=<optimized out>, indent=<optimized out>, 
    params=<optimized out>) at notmuch-show.c:670
#11 0x000055eb6d771a70 in show_message (ctx=ctx@entry=0x55eb6dcd71d0, 
    sp=sp@entry=0x55eb6dcfd8b0, message=message@entry=0x55eb6dd184b0, 
    indent=indent@entry=1, params=params@entry=0x7ffe9d71b830, 
    format=<optimized out>) at notmuch-show.c:827
#12 0x000055eb6d771b69 in show_messages (ctx=ctx@entry=0x55eb6dcd71d0, 
    format=format@entry=0x55eb6d980d40 <format_sexp>, 
    sp=sp@entry=0x55eb6dcfd8b0, messages=0x55eb6dd1e910, 
    indent=indent@entry=1, params=params@entry=0x7ffe9d71b830)
    at notmuch-show.c:863
#13 0x000055eb6d771bac in show_messages (ctx=ctx@entry=0x55eb6dcd71d0, 
    format=format@entry=0x55eb6d980d40 <format_sexp>, 
    sp=sp@entry=0x55eb6dcfd8b0, messages=0x55eb6dcfe300, 
    indent=indent@entry=0, params=params@entry=0x7ffe9d71b830)
    at notmuch-show.c:871
#14 0x000055eb6d77384f in do_show (params=0x7ffe9d71b830, sp=0x55eb6dcfd8b0, 
    format=0x55eb6d980d40 <format_sexp>, query=0x55eb6dcdd1e0, 
    ctx=0x55eb6dcd71d0) at notmuch-show.c:959
#15 notmuch_show_command (config=0x55eb6dcd71d0, argc=<optimized out>, 
    argv=<optimized out>) at notmuch-show.c:1171
#16 0x000055eb6d76562f in main (argc=<optimized out>, argv=0x7ffe9d71bce8)
    at notmuch.c:421



gpg2 --verbose --no-secmem-warning --no-greeting --no-tty --charset=UTF-8 --status-fd=16 --command-fd=17 --use-agent --decrypt --output -

#0  0x00007f503b88d5a0 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
#1  0x0000557612c95661 in read (__nbytes=1, __buf=0x5576136ac930, __fd=17) at /usr/include/x86_64-linux-gnu/bits/unistd.h:44
#2  myread (count=1, buf=0x5576136ac930, fd=17) at ../../g10/cpr.c:377
#3  do_get_from_fd (keyword=keyword@entry=0x557612d1a049 "tofu.conflict", hidden=hidden@entry=0, getbool=getbool@entry=0)
    at ../../g10/cpr.c:434
#4  0x0000557612c95f17 in cpr_get (keyword=keyword@entry=0x557612d1a049 "tofu.conflict", prompt=<optimized out>) at ../../g10/cpr.c:483
#5  0x0000557612cd7dbe in ask_about_binding (now=1492082038, user_id=0x5576136978fc "xxx <foo@bar>", 
    email=0x55761367ba00 "a@dress", fingerprint=0x5576136986e0 "XXXFPRXXX", 
    conflict_set=<optimized out>, trust_level=<synthetic pointer>, policy=<synthetic pointer>, ctrl=0x557613664b60) at ../../g10/tofu.c:1962
#6  get_trust (ctrl=ctrl@entry=0x557613664b60, pk=pk@entry=0x557613699fd0, 
    fingerprint=fingerprint@entry=0x5576136986e0 "XXXFPRXXX", 
    email=email@entry=0x55761367ba00 "a@dress", 
    user_id=user_id@entry=0x5576136978fc "xxx <foo@bar>", may_ask=<optimized out>, may_ask@entry=1, 
    policyp=0x7ffc4a63859c, conflict_setp=0x7ffc4a6385a0, now=1492082038) at ../../g10/tofu.c:2761
#7  0x0000557612cd9443 in tofu_get_validity (ctrl=ctrl@entry=0x557613664b60, pk=pk@entry=0x557613699fd0, user_id_list=0x5576136ae310, 
    may_ask=may_ask@entry=1) at ../../g10/tofu.c:3730
#8  0x0000557612ccfce6 in tdb_get_validity_core (ctrl=ctrl@entry=0x557613664b60, kb=0x5576136945a0, kb@entry=0x0, 
    pk=pk@entry=0x557613699fd0, uid=uid@entry=0x0, main_pk=main_pk@entry=0x557613699fd0, sig=sig@entry=0x55761368c7f0, may_ask=1)
    at ../../g10/trustdb.c:1150
#9  0x0000557612ccbcfa in get_validity (ctrl=ctrl@entry=0x557613664b60, kb=kb@entry=0x0, pk=pk@entry=0x557613699fd0, uid=uid@entry=0x0, 
    sig=sig@entry=0x55761368c7f0, may_ask=may_ask@entry=1) at ../../g10/trust.c:354
#10 0x0000557612ca0771 in check_signatures_trust (ctrl=0x557613664b60, sig=sig@entry=0x55761368c7f0) at ../../g10/pkclist.c:572
#11 0x0000557612c846a5 in check_sig_and_print (c=c@entry=0x5576136a67b0, node=node@entry=0x5576136ad3e0) at ../../g10/mainproc.c:2144
#12 0x0000557612c851ab in proc_tree (node=<optimized out>, c=0x5576136a67b0) at ../../g10/mainproc.c:2332
#13 release_list (c=c@entry=0x5576136a67b0) at ../../g10/mainproc.c:127
#14 0x0000557612c8589c in do_proc_packets (ctrl=0x557613664b60, c=0x5576136a67b0, a=0x5576136701e0) at ../../g10/mainproc.c:1480
#15 0x0000557612c85b0a in proc_packets (ctrl=ctrl@entry=0x557613664b60, anchor=anchor@entry=0x557613678120, a=0x5576136701e0)
    at ../../g10/mainproc.c:1205
#16 0x0000557612c7445f in handle_compressed (ctrl=0x557613664b60, procctx=procctx@entry=0x557613678120, cd=0x5576136a0970, 
    callback=callback@entry=0x0, passthru=passthru@entry=0x0) at ../../g10/compress.c:324
#17 0x0000557612c82b20 in proc_compressed (c=c@entry=0x557613678120, pkt=pkt@entry=0x55761369f730) at ../../g10/mainproc.c:824
#18 0x0000557612c857cb in do_proc_packets (ctrl=0x557613664b60, c=0x557613678120, a=0x5576136701e0) at ../../g10/mainproc.c:1437
#19 0x0000557612c85b0a in proc_packets (ctrl=ctrl@entry=0x557613664b60, anchor=anchor@entry=0x5576136743a0, a=0x5576136701e0)
    at ../../g10/mainproc.c:1205
#20 0x0000557612ca5501 in decrypt_data (ctrl=0x557613664b60, procctx=procctx@entry=0x5576136743a0, ed=0x557613679f30, dek=0x7f503ce15008)
    at ../../g10/decrypt-data.c:253
#21 0x0000557612c82322 in proc_encrypted (c=c@entry=0x5576136743a0, pkt=pkt@entry=0x557613665a40) at ../../g10/mainproc.c:603
#22 0x0000557612c8581b in do_proc_packets (ctrl=0x557613664b60, c=0x5576136743a0, a=0x5576136701e0) at ../../g10/mainproc.c:1435
#23 0x0000557612c85d91 in proc_encryption_packets (ctrl=ctrl@entry=0x557613664b60, anchor=anchor@entry=0x0, a=a@entry=0x5576136701e0)
    at ../../g10/mainproc.c:1304
#24 0x0000557612ca40d6 in decrypt_message (ctrl=0x557613664b60, filename=<optimized out>) at ../../g10/decrypt.c:88
#25 0x0000557612c60f06 in main (argc=<optimized out>, argv=<optimized out>) at ../../g10/gpg.c:4197

With --batch it shouldn't hang, because with the new TOFU policy, gpg seems to require user interaction (unless --batch is given).
Hence notmuch hangs when encountering new conflicting (uid,key)-bindings under the TOFU model.

I see

	if (!gpg->need_passwd) {
		/* only use batch mode if we don't intend on using the
                   interactive --command-fd option to send it the
                   user's password */
		g_ptr_array_add (args, "--batch");
	}
	
	g_ptr_array_add (args, "--charset=UTF-8");
	
	(*strv)[v++] = buf = g_strdup_printf ("--status-fd=%d", status_fd);
	g_ptr_array_add (args, buf);
	
	if (gpg->need_passwd && !gpg->override_session_key) {
		(*strv)[v++] = buf = g_strdup_printf ("--command-fd=%d", secret_fd);
		g_ptr_array_add (args, buf);
}

in https://github.com/jstedfast/gmime/blob/gmime-2-6/gmime/gmime-gpg-context.c

Maybe an option for gmime is to make gpg use an agent. Probably at the expense to break the offered API reg. password handling. Another option is to not support newer gpg versions with TOFU model. If that route is chosen, it would be nice to make a statement about it, so that distributions can model the incompatibility.

GMimeSignature created and expires are time_t, fail in Y2038 on platforms with 32-bit signed time_t

g_mime_signature_{s,g}et_{created,expires} uses time_t.

They are produced from the underlying GPGME gpgme_signature_t object, which indicate that they are unsigned long values.

But time(2) from linux manpages says that time_t is 32-bit signed on some platforms:

On Linux, a call to time() with tloc specified as NULL cannot fail with
the error EOVERFLOW, even on ABIs where time_t is a signed 32-bit inte‐
ger and the clock ticks past the time 2**31 (2038-01-19 03:14:08 UTC,
ignoring leap seconds). (POSIX.1 permits, but does not require, the
EOVERFLOW error in the case where the seconds since the Epoch will not
fit in time_t.) Instead, the behavior on Linux is undefined when the
system time is out of the time_t range. Applications intended to run
after 2038 should use ABIs with time_t wider than 32 bits.

This means that on a platform where long is 32 bits (e.g. x86_64), even though GPGME can correctly report a signature with validity ranges between 2**31 and 2**32 seconds, or (2038-01-19 03:14:08 → 2106-02-07 06:28:16 UTC), GMime wraps those values around into the negative range.

I'm running into this when I use GMime to handle sample S/MIME certificates whose expiration dates are later than Y2038.

g_mime_part_get_openpgp_data returns GMIME_OPENPGP_DATA_NONE if part is base64 encoded

Some MTAs re-base64-encode everything, even if the content is in fact 7-bit clean.

The result is that some message parts get wrapped in base64 and have a Content-Transfer-Encoding: base64 header added, even though they contain nothing but a -----BEGIN PGP MESSAGE----- block. When calling g_mime_part_get_openpgp_data() on such a MIME part, it returns GMIME_OPENPGP_DATA_NONE, though i believe it should return GMIME_OPENPGP_DATA_ENCRYPTED.

GMime does not check for unknown bits set in GMimeVerifyFlags or GMimeDecryptFlags

If i set some currently-unused bit in a GMimeVerifyFlags or GMimeDecryptFlags variable, and then try to use it, I don't think GMime notices that the unused bit is set.

This results in a potential for a broken API -- if version X of gmime introduces a new flag, and i build against it and use that flag, and then i run against version X-1, then the flag will be supplied and ignored.

GMime should check if any unused flags are set, and if so, raise an error (if you're not comfortable with this update in the 3.x series, please at least consider this defensive approach when considering how to resolve #70).

If this seems too extreme (for example, if you contemplate adding some flag or flags in the future that are or should be ignorable/best-effort, and therefore it isn't an error to send them to a non-implementing version), perhaps we could set aside some range of bits that would be ignorable/best-effort. Then when a new flag is added, we can reason about which bitfield to place the new flag in, based on our understanding of the intended semantics.

PGP/MIME tests currently failing

Maybe this is known but it looks like test-pgp and pest pgp-pgpmime need updating

 (process:4069): gmime-CRITICAL **: g_mime_crypto_context_set_request_password: assertion 'GMIME_IS_CRYPTO_CONTEXT (ctx)' failed

(process:4069): gmime-CRITICAL **: g_mime_crypto_context_import_keys: assertion 'GMIME_IS_CRYPTO_CONTEXT (ctx)' failed

(process:4069): gmime-CRITICAL **: g_mime_crypto_context_import_keys: assertion 'GMIME_IS_CRYPTO_CONTEXT (ctx)' failed

(process:4069): gmime-CRITICAL **: g_mime_crypto_context_export_keys: assertion 'GMIME_IS_CRYPTO_CONTEXT (ctx)' failed
/bin/bash: line 4:  4069 Segmentation fault      ./${test} -v ${testdir}

(process:4094): gmime-CRITICAL **: g_mime_crypto_context_set_request_password: assertion 'GMIME_IS_CRYPTO_CONTEXT (ctx)' failed

(process:4094): gmime-CRITICAL **: g_mime_crypto_context_import_keys: assertion 'GMIME_IS_CRYPTO_CONTEXT (ctx)' failed

(process:4094): gmime-CRITICAL **: g_mime_crypto_context_import_keys: assertion 'GMIME_IS_CRYPTO_CONTEXT (ctx)' failed

(process:4094): gmime-CRITICAL **: g_mime_multipart_signed_sign: assertion 'GMIME_IS_CRYPTO_CONTEXT (ctx)' failed

(process:4094): gmime-CRITICAL **: g_mime_message_set_mime_part: assertion 'GMIME_IS_OBJECT (mime_part)' failed

(process:4094): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed

(process:4094): gmime-CRITICAL **: g_mime_multipart_encrypted_encrypt: assertion 'GMIME_IS_CRYPTO_CONTEXT (ctx)' failed

(process:4094): gmime-CRITICAL **: g_mime_message_set_mime_part: assertion 'GMIME_IS_OBJECT (mime_part)' failed

(process:4094): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed

(process:4094): gmime-CRITICAL **: g_mime_multipart_encrypted_encrypt: assertion 'GMIME_IS_CRYPTO_CONTEXT (ctx)' failed

(process:4094): gmime-CRITICAL **: g_mime_message_set_mime_part: assertion 'GMIME_IS_OBJECT (mime_part)' failed

(process:4094): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed

(process:4094): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
Testing PGP/MIME implementation: failed (3 errors, 0 warnings)
Results: 7 tests passed; 2 tests failed.
Failed tests: 
 test-pgp
 test-pgpmime
Makefile:961: recipe for target 'check-local' failed
make[3]: *** [check-local] Error 255

unwrapping a PKCS#7 SignedData part without verifying the signature

In some circumstances, I don't care about the cryptographic signature on a MIME part, and doing proper signature verification is more expensive than i'd like.

For example, if it's only a proper subpart of a message that is signed (as opposed to a signature in the cryptographic payload), there is no way for me to sanely present the signature to the user. Or, i might have some sort of stashed information about the signature and there is no need to recompute it.

Rendering a lengthy thread under these conditions shouldn't require verifying signatures. But in the case of a PKCS#7 SignedData part, the only way that GMime offers for me to get access to the inner wrapped MIME part is g_mime_application_pkcs7_verify, which by default does perform the asymmetric cryptographic operations.

I would like to have a way to just "unwrap" the part without verifying it, if possible.

InternetAddress email part without name

Is there a way to get the email part without name? I am using below code to extract from address but could not find a way to extract only the email without name.

GMimeMessage *message = g_mime_parser_construct_message(parser, NULL);
InternetAddressList  *from = g_mime_message_get_from(message);
InternetAddress *addr = internet_address_list_get_address(from, 0);
printf("name: %s address: %s\n", internet_address_get_name(addr), internet_address_to_string(addr, NULL, 1));

Above code prints:

name: Baba Mailer address: Baba Mailer <[email protected]>

thanks

handle message/global (like message/rfc822)

Internationalized e-mail headers cause some level of confusion, but message/global looks like it is basically message/rfc822 but not necessarily 7-bit clean, and textual headers are expected to be utf-8 encoded.

it would be nice if gmime could handle this as smoothly as it handles message/rfc822.

See RFC 6532 for more details.

GMime 4.0 Plan

GMime 4.0 ideas:

  • Add padding to all object and class structs to allow for future expansion
  • Rename g_mime_object_encode() to g_mime_object_prepare() for API consistency with MimeKit?
  • Add a GMimeVisitor class and GMimeObjectClass::accept virtual method? If we do, we'll also want:
    • Add GMimeMultipartAlternative
    • Add GMimeMultipartRelated
    • Add GMimeMultipartReport
    • Add GMimeMessageDeliveryStatus
    • Add GMimeMessageDispositionNotification
    • Add GMimeTextRfc822Headers
  • Add g_mime_message_get_text_body() and g_mime_message_get_html_body() like MimeKit has? These would replace g_mime_message_get_body()
  • Update GMimeSignature and GMimeCertificate to use a gint64 (internally at most) or GDateTime (public API for sure and maybe internally as well?) for the timestamps. (issue #68 and issue #73)
  • Merge GMimeDecryptFlags and GMimeVerifyFlags (issue #70)?
  • Add support for application/pkcs7-mime; smime-type=compressed-data (issue #66)
  • Add support for application/pkcs7-mime; smime-type=authEnveloped-data (issue #65)
  • Can we get rid of g_mime_stream_close()? Disposing of the stream can (and already does to an extent) take the place of close(). This might eliminate confusion of reading/writing to a closed stream.
  • Should g_mime_crypto_context_sign() take an InternetAddressMailbox instead of const char *userid? Same idea for g_mime_crypto_context_encrypt() for both the userid and recipients arguments.
  • Should g_mime_object_write_to_stream() be fixed to return gint64?
  • Should GMimeStream's read/write functions take GError and/or GCancellation arguments? Same for GMimeParser APIs? And g_mime_object_write_to_stream(), etc.

3.2.6: test-filters test failure on NetBSD

When running the self tests for 3.2.6 on NetBSD-9.99.47/amd64 I see one test failure:

# ./test-filters -vv
Checking GMimeFilterCharset (cyrillic utf-8 -> cp1251)... PASSED
Checking GMimeFilterCharset (cyrillic cp1251 -> utf-8)... PASSED
Checking GMimeFilterCharset (cyrillic utf-8 -> iso-8859-5)... PASSED
Checking GMimeFilterCharset (cyrillic iso-8859-5 -> utf-8)... PASSED
Checking GMimeFilterCharset (cyrillic utf-8 -> koi8-r)... PASSED
Checking GMimeFilterCharset (cyrillic koi8-r -> utf-8)... PASSED
Checking GMimeFilterCharset (japanese utf-8 -> iso-2022-jp)... PASSED
Checking GMimeFilterCharset (japanese iso-2022-jp -> utf-8)... PASSED

(process:16627): gmime-CRITICAL **: 10:53:01.477: g_mime_stream_filter_add: assertion 'GMIME_IS_FILTER (filter)' failed

(process:16627): gmime-CRITICAL **: 10:53:01.478: g_mime_filter_reset: assertion 'GMIME_IS_FILTER (filter)' failed

(process:16627): GLib-GObject-CRITICAL **: 10:53:01.478: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
Checking GMimeFilterCharset (japanese utf-8 -> shift-jis)... FAILED

(process:16627): gmime-CRITICAL **: 10:53:01.478: g_mime_stream_filter_add: assertion 'GMIME_IS_FILTER (filter)' failed

(process:16627): gmime-CRITICAL **: 10:53:01.478: g_mime_filter_reset: assertion 'GMIME_IS_FILTER (filter)' failed

(process:16627): GLib-GObject-CRITICAL **: 10:53:01.478: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
Checking GMimeFilterCharset (japanese shift-jis -> utf-8)... FAILED
Checking GMimeFilterEnriched (enriched.txt)... PASSED
Checking GMimeFilterGzip::zip... PASSED
Checking GMimeFilterGzip::unzip... PASSED
Checking GMimeFilterHtml (html-input.txt blockquote)... PASSED
Checking GMimeFilterHtml (html-input.txt mark)... PASSED
Checking GMimeFilterHtml (html-input.txt cite)... PASSED
Checking GMimeFilterSmtpData... PASSED
Checking GMimeFilterWindows... PASSED
Testing GMimeFilter: failed (2 errors, 0 warnings)

gpg encryption: --hidden-recipient

Hi,

It would be great if we could have access to the --hidden-recipient (or -R) (https://www.gnupg.org/documentation/manuals/gnupg-devel/GPG-Key-related-Options.html) option when encrypting. Especially, when encrypting for Bcc: recipients this would be very useful. Otherwise it is very easy to see who all recipients are, with the option, it is only possible to see the number of recipients.

It would also be useful with an option to only hide Bcc: recipients.

Note that -R replaces -r.

Are there any plans to move to gpgme or similar?

vala build issue

The NEWS file for version 3.2.2 says: Fixed packaging to include Vala files.

But evidently it is not complete. During build, I get:

GICOMP GMime-3.0.gir
make[3]: *** No rule to make target 'GMime-3.0.metadata', needed by 'gmime-3.0.vapi'. Stop

I can build successfully with --enable-vala=no

-- Bruce Dubbs
linuxfromscratch.org

MIME header wrapping has unpredictable behavior

The following simple GMime program demonstrates a peculiarity of header wrapping. In particular, when a US-ASCII whitespace-delimited token is 38 characters wide, it is rendered simply. But when it is 39 characters wide, it is wrapped with =?us-ascii?Q?_ and ?=.

It seems like that this is related to a desire to wrap lines at 78-char, and two 39-char blobs won't fit if there's whitespace between them.

But since they're pure US-ASCII in the first place, there's really no need to wrap them in the QP RFC 2047 header, right?

#include <gmime/gmime.h>
#include <gmime/gmime-stream-mem.h>
#include <gmime/gmime-parser.h>
#include <gmime/gmime-message.h>
#include <stdio.h>

const char ex[] =
  "Date: Thu, 09 Nov 2017 10:44:22 +0100\n"
  "Subject: test\n"
  "From: [email protected]\n"
  "To: [email protected]\n"
  "Content-Type: text/plain\n"
  "\n"
  "hi there\n";

#define X "0123456789abcdef0123456789abcdef012345 "
const char header38[] = "testing " X X X X X X X X X X X X X X X;
#undef X
#define X "0123456789abcdef0123456789abcdef0123456 "
const char header39[] = "testing " X X X X X X X X X X X X X X X;


int main(int argc, char *argv[])
{
  g_mime_init ();
  GMimeStream *stream = g_mime_stream_mem_new_with_buffer (ex, sizeof(ex)-1);
  GMimeParser *parser = g_mime_parser_new_with_stream (stream);
  GMimeMessage *message = g_mime_parser_construct_message (parser, NULL);
  GMimeStream *out = g_mime_stream_mem_new ();

  g_mime_object_set_header (GMIME_OBJECT (message), "Testing38", header38, NULL);
  g_mime_object_set_header (GMIME_OBJECT (message), "Testing39", header39, NULL);
  
  ssize_t sz = g_mime_object_write_to_stream (GMIME_OBJECT (message), NULL, out);
  GByteArray *bytes = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (out));
  fwrite (bytes->data, bytes->len, 1, stdout);
  fflush (stdout);
  g_mime_shutdown ();
}

The output is:

Date: Thu, 09 Nov 2017 10:44:22 +0100
Subject: test
From: [email protected]
To: [email protected]
Content-Type: text/plain
Testing38: testing 0123456789abcdef0123456789abcdef012345
 0123456789abcdef0123456789abcdef012345 0123456789abcdef0123456789abcdef012345
 0123456789abcdef0123456789abcdef012345 0123456789abcdef0123456789abcdef012345
 0123456789abcdef0123456789abcdef012345 0123456789abcdef0123456789abcdef012345
 0123456789abcdef0123456789abcdef012345 0123456789abcdef0123456789abcdef012345
 0123456789abcdef0123456789abcdef012345 0123456789abcdef0123456789abcdef012345
 0123456789abcdef0123456789abcdef012345 0123456789abcdef0123456789abcdef012345
 0123456789abcdef0123456789abcdef012345 0123456789abcdef0123456789abcdef012345
Testing39: testing =?us-ascii?Q?0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=
 =?us-ascii?Q?_0123456789abcdef0123456789abcdef0123456?=

hi there

It looks to me like Testing39 is gratuitously encoded here.

Migrate Back to GNOME Infra?

gmime has a duplicate repo on GNOME infrastructure with no indication that the project's been moved to GitHub. Since we now use GitLab for GNOME and GMime is used in GNOME projects, it would be nice to have on GNOME infrastructure again.

g_mime_text_part_get_text will generate a warning

Calling g_mime_text_part_get_text on the text part in certain circumstances will generate some warnings.
example:
(process:25144): gmime-CRITICAL **: g_mime_stream_filter_add: assertion 'GMIME_IS_FILTER (filter)' failed

(process:25144): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed

(process:25144): gmime-CRITICAL **: g_mime_stream_filter_add: assertion 'GMIME_IS_FILTER (filter)' failed

(process:25144): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed

testing platform:
Ubuntu 16.04 LTS and gmime 3.2
test code:

#include <gmime/gmime.h>
#include <stdio.h>
#include <string>


static const char eml_raw_data[] = {
    0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2d, 0x49, 0x44, 0x3a, 0x20, 0x3c, 0x34, 0x35, 0x33, 
    0x30, 0x38, 0x37, 0x36, 0x34, 0x37, 0x31, 0x33, 0x32, 0x39, 0x35, 0x39, 0x36, 0x37, 0x33, 0x34, 
    0x32, 0x31, 0x35, 0x32, 0x32, 0x40, 0x65, 0x78, 0x63, 0x69, 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x2e, 
    0x75, 0x6b, 0x3e, 0xd, 0xa, 0x46, 0x72, 0x6f, 0x6d, 0x3a, 0x20, 0x22, 0x4a, 0x75, 0x6c, 0x79, 
    0x22, 0x20, 0x3c, 0x63, 0x68, 0x65, 0x66, 0x6b, 0x65, 0x76, 0x69, 0x6e, 0x34, 0x31, 0x31, 0x40, 
    0x65, 0x78, 0x63, 0x69, 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x2e, 0x75, 0x6b, 0x3e, 0xd, 0xa, 0x54, 
    0x6f, 0x3a, 0x20, 0x3c, 0x66, 0x6d, 0x6a, 0x37, 0x32, 0x31, 0x40, 0x65, 0x78, 0x61, 0x6d, 0x70, 
    0x6c, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x3e, 0xd, 0xa, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 
    0x3a, 0x20, 0x47, 0x65, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x6d, 0x65, 
    0x21, 0xd, 0xa, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x32, 0x38, 0x20, 0x41, 0x70, 0x72, 0x20, 
    0x32, 0x30, 0x31, 0x38, 0x20, 0x30, 0x34, 0x3a, 0x34, 0x33, 0x3a, 0x34, 0x36, 0x20, 0x2d, 0x30, 
    0x34, 0x30, 0x30, 0xd, 0xa, 0x4d, 0x49, 0x4d, 0x45, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 
    0x6e, 0x3a, 0x20, 0x31, 0x2e, 0x30, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 
    0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 
    0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x3b, 0xd, 0xa, 0x20, 0x62, 
    0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x3d, 0x22, 0x2d, 0x2d, 0x2d, 0x30, 0x41, 0x34, 0x44, 
    0x43, 0x42, 0x31, 0x32, 0x33, 0x30, 0x41, 0x31, 0x42, 0x34, 0x45, 0x39, 0x38, 0x33, 0x32, 0x35, 
    0x46, 0x43, 0x44, 0x45, 0x34, 0x46, 0x35, 0x41, 0x30, 0x37, 0x36, 0x44, 0x22, 0xd, 0xa, 0x58, 
    0x2d, 0x4d, 0x61, 0x69, 0x6c, 0x65, 0x72, 0x3a, 0x20, 0x59, 0x6a, 0x75, 0x79, 0x66, 0x78, 0x70, 
    0x6e, 0x20, 0x67, 0x6a, 0x6d, 0x6c, 0x64, 0x72, 0xd, 0xa, 0xd, 0xa, 0x54, 0x68, 0x69, 0x73, 
    0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x70, 0x61, 0x72, 0x74, 
    0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x4d, 0x49, 0x4d, 0x45, 
    0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2e, 0xd, 0xa, 0xd, 0xa, 0x2d, 0x2d, 0x2d, 0x2d, 
    0x2d, 0x30, 0x41, 0x34, 0x44, 0x43, 0x42, 0x31, 0x32, 0x33, 0x30, 0x41, 0x31, 0x42, 0x34, 0x45, 
    0x39, 0x38, 0x33, 0x32, 0x35, 0x46, 0x43, 0x44, 0x45, 0x34, 0x46, 0x35, 0x41, 0x30, 0x37, 0x36, 
    0x44, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 
    0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x3b, 0xd, 0xa, 0x20, 0x63, 
    0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x22, 0x63, 0x70, 0x2d, 0x38, 0x35, 0x30, 0x22, 0xd, 
    0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 
    0x72, 0x2d, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x71, 0x75, 0x6f, 0x74, 
    0x65, 0x64, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0xd, 0xa, 0xd, 0xa, 
    0x61, 0x72, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x74, 0x6f, 
    0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x65, 0x3f, 0x20, 0x69, 0x20, 0x77, 0x69, 
    0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x79, 0x20, 0x73, 
    0x33, 0x78, 0x73, 0x6c, 0x61, 0x76, 0x65, 0x21, 0xd, 0xa, 0x69, 0x27, 0x6d, 0x20, 0x32, 0x35, 
    0x2f, 0x66, 0x2e, 0x2e, 0x2e, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 
    0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x73, 0x74, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x6a, 0x75, 0x69, 
    0x63, 0x65, 0x21, 0xd, 0xa, 0xd, 0xa, 0x6d, 0x79, 0x20, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 
    0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x4d, 0x61, 0x73, 0x68, 0x61, 0x32, 0x36, 0xd, 0xa, 0x76, 
    0x69, 0x65, 0x77, 0x20, 0x6d, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x3d, 0x32, 
    0x30, 0xd, 0xa, 0x68, 0x65, 0x72, 0x65, 0x21, 0xd, 0xa, 0xd, 0xa, 0x54, 0x61, 0x6c, 0x6b, 
    0x20, 0x53, 0x6f, 0x6f, 0x6e, 0x21, 0xd, 0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x30, 0x41, 0x34, 
    0x44, 0x43, 0x42, 0x31, 0x32, 0x33, 0x30, 0x41, 0x31, 0x42, 0x34, 0x45, 0x39, 0x38, 0x33, 0x32, 
    0x35, 0x46, 0x43, 0x44, 0x45, 0x34, 0x46, 0x35, 0x41, 0x30, 0x37, 0x36, 0x44, 0xd, 0xa, 0x43, 
    0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 
    0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3b, 0xd, 0xa, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 
    0x74, 0x3d, 0x22, 0x63, 0x70, 0x2d, 0x38, 0x35, 0x30, 0x22, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 
    0x65, 0x6e, 0x74, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, 0x6e, 0x63, 
    0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x64, 0x2d, 0x70, 0x72, 
    0x69, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 
    0x3e, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x48, 0x74, 0x74, 
    0x70, 0x2d, 0x45, 0x71, 0x75, 0x69, 0x76, 0x3d, 0x33, 0x44, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 
    0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3d, 0x33, 
    0x44, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3b, 0x20, 0x3d, 0xd, 0xa, 
    0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x33, 0x44, 0x63, 0x70, 0x2d, 0x38, 0x35, 0x30, 
    0x22, 0x3e, 0xd, 0xa, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xd, 0xa, 0x3c, 0x62, 
    0x6f, 0x64, 0x79, 0x3e, 0x61, 0x72, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x61, 0x64, 
    0x79, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x65, 0x3f, 0x20, 
    0x69, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x20, 
    0x6d, 0x79, 0x20, 0x73, 0x33, 0x78, 0x73, 0x6c, 0x61, 0x76, 0x65, 0x21, 0x3c, 0x62, 0x72, 0x3e, 
    0xd, 0xa, 0x69, 0x27, 0x6d, 0x20, 0x32, 0x35, 0x2f, 0x66, 0x2e, 0x2e, 0x2e, 0x20, 0x63, 0x6f, 
    0x6d, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x73, 0x74, 
    0x65, 0x20, 0x6d, 0x79, 0x20, 0x6a, 0x75, 0x69, 0x63, 0x65, 0x21, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 
    0x62, 0x72, 0x3e, 0xd, 0xa, 0x6d, 0x79, 0x20, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 
    0x20, 0x69, 0x73, 0x20, 0x4d, 0x61, 0x73, 0x68, 0x61, 0x32, 0x36, 0x3c, 0x62, 0x72, 0x3e, 0xd, 
    0xa, 0x76, 0x69, 0x65, 0x77, 0x20, 0x6d, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 
    0x20, 0x3c, 0x61, 0x20, 0x3d, 0xd, 0xa, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x33, 0x44, 0x22, 0x68, 
    0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x67, 0x65, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 
    0x6d, 0x2f, 0x6c, 0x6f, 0x67, 0x65, 0x73, 0x2f, 0x74, 0x62, 0x6c, 0x6b, 0x6a, 0x77, 0x2f, 0x73, 
    0x6f, 0x74, 0x70, 0x69, 0x65, 0x2f, 0x22, 0x3e, 0x3c, 0x62, 0x3e, 0x68, 0x65, 0x72, 0x65, 0x21, 
    0x3c, 0x2f, 0x62, 0x3e, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0xd, 0xa, 0x3c, 0x62, 
    0x72, 0x3e, 0xd, 0xa, 0x54, 0x61, 0x6c, 0x6b, 0x20, 0x53, 0x6f, 0x6f, 0x6e, 0x21, 0x3c, 0x62, 
    0x72, 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 
    0xd, 0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x30, 0x41, 0x34, 0x44, 0x43, 0x42, 0x31, 0x32, 0x33, 
    0x30, 0x41, 0x31, 0x42, 0x34, 0x45, 0x39, 0x38, 0x33, 0x32, 0x35, 0x46, 0x43, 0x44, 0x45, 0x34, 
    0x46, 0x35, 0x41, 0x30, 0x37, 0x36, 0x44, 0x2d, 0x2d, 0xd, 0xa, 0xd, 0xa, 0xd, 0xa, 
};

GMimeMessage* message_from_std_sting(const std::string& input_string)
{
    GMimeStream* g_stream = g_mime_stream_mem_new_with_buffer(input_string.c_str(), input_string.size());
    GMimeParser* g_parser = g_mime_parser_new();
    g_mime_parser_init_with_stream(g_parser, g_stream);
    GMimeParserOptions* g_parser_options = g_mime_parser_options_get_default();
    GMimeMessage* gmime_message = g_mime_parser_construct_message(g_parser, g_parser_options);
    g_mime_parser_options_free(g_parser_options);
    g_object_unref(g_stream);
    g_object_unref(g_parser);
    return gmime_message;
}

std::string get_text_part_text_to_string(GMimeTextPart* g_part)
{
    std::string str_ret;
    char* sz_text = g_mime_text_part_get_text((GMimeTextPart*)g_part);
    if(sz_text == NULL)
    {
        return str_ret;
    }
    str_ret = sz_text;
    g_free(sz_text);
    return str_ret;
}

void get_body_foreach_func(GMimeObject *parent,
        GMimeObject *part,
        gpointer user_data)
{
    std::string *p_str_data = (std::string *)user_data;
    if (GMIME_IS_MESSAGE_PART (part))
    {
        /* message/rfc822 or message/news */
        GMimeMessage *message;
        message = g_mime_message_part_get_message ((GMimeMessagePart *) part);
        g_mime_message_foreach (message, get_body_foreach_func, user_data);
    }
    else if (GMIME_IS_MESSAGE_PARTIAL (part))
    {
        /* message/partial */
        return;
    }
    else if (GMIME_IS_MULTIPART (part))
    {
        return;
    }
    else if (GMIME_IS_PART (part))
    {
        if(GMIME_IS_TEXT_PART(part))
        {
            //TEXT_PART
            std::string str_text_body = get_text_part_text_to_string((GMimeTextPart*)part);
            p_str_data->append(str_text_body);
            return;
        }
    }
    else
    {
        g_assert_not_reached ();
    }

}

std::string get_message_body(GMimeMessage* g_msg)
{
    std::string str_body("");
    g_mime_message_foreach(g_msg,get_body_foreach_func, &str_body);
    return str_body;
}

int main(int argc, char** argv)
{
    g_mime_init();

    std::string str_data;
    for(unsigned int i = 0; i < sizeof(eml_raw_data) / sizeof(char); i++) {
        str_data.push_back(eml_raw_data[i]);
    }
	//create test mime data
    printf("%s",str_data.c_str());
    printf("%s","------------------split--------------------------\n");
    GMimeMessage* g_msg = message_from_std_sting(str_data);
    //get message body will generate a warning
    std::string str_body = get_message_body(g_msg);
    
    g_object_unref(g_msg);
    g_mime_shutdown();
    return 0;
}

Segfault in g_mime_filter_set_size

I'm getting a segfault in g_mime_filter_set_size. Not sure if you're interested in fixing this in 2.6, but it might still be present in 3.x?

malloc(): corrupted unsorted chunks 3

Thread 1 "geary" received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50	../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt full
#0  0x00007ffff1d6d077 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
        set = 
            {__val = {0, 11059880788374614528, 93825053528384, 140737335977072, 93825050479104, 93825053534096, 93825006904256, 140737338108812, 93825053528384, 93825050479104, 93824999481456, 140737353055436, 93825053528384, 93825053534048, 93825050479104, 140737336017539}}
        pid = <optimised out>
        tid = <optimised out>
#1  0x00007ffff1d4e535 in __GI_abort () at abort.c:79
        save_stage = 1
        act = 
          {__sigaction_handler = {sa_handler = 0x3c, sa_sigaction = 0x3c}, sa_mask = {__val = {140737252494400, 140734737117376, 56, 140734737117392, 140734737117376, 0, 93825001190832, 93825001190832, 140737349895916, 61, 140737349750269, 93824999158752, 93824999158752, 93824999152160, 140737488337040, 140737488337296}}, sa_flags = 1, sa_restorer = 0x1000}
        sigs = {__val = {32, 0 <repeats 15 times>}}
#2  0x00007ffff1db5516 in __libc_message
    (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff1ed9c00 "%s\n")
    at ../sysdeps/posix/libc_fatal.c:181
        ap = 
            {{gp_offset = 24, fp_offset = 32767, overflow_arg_area = 0x7fffffffb9a0, reg_save_area = 0x7fffffffb930}}
        fd = 2
        list = <optimised out>
        nlist = <optimised out>
        cp = <optimised out>
        written = <optimised out>
#3  0x00007ffff1dbc3aa in malloc_printerr
    (str=str@entry=0x7ffff1edbcb8 "malloc(): corrupted unsorted chunks 3") at malloc.c:5336
#4  0x00007ffff1dc009c in _int_malloc (av=av@entry=0x7ffff1f10c40 <main_arena>, bytes=bytes@entry=9567)
    at malloc.c:3763
        iters = <optimised out>
        nb = 9584
        idx = 109
        bin = <optimised out>
        victim = <optimised out>
        size = 7792
        victim_index = <optimised out>
        remainder = <optimised out>
        remainder_size = <optimised out>
        block = <optimised out>
        bit = <optimised out>
        map = <optimised out>
        fwd = <optimised out>
        bck = <optimised out>
        tcache_unsorted_count = 0
        tcache_nb = 0
        tc_idx = 597
--Type <RET> for more, q to quit, c to continue without paging--
        return_cached = <optimised out>
        __PRETTY_FUNCTION__ = "_int_malloc"
#5  0x00007ffff1dc1dea in __GI___libc_malloc (bytes=9567) at malloc.c:3049
        ar_ptr = 0x7ffff1f10c40 <main_arena>
        victim = <optimised out>
        hook = <optimised out>
        tbytes = <optimised out>
        tc_idx = 597
        __PRETTY_FUNCTION__ = "__libc_malloc"
#6  0x00007ffff7bf4651 in g_malloc (n_bytes=n_bytes@entry=9567) at ../../../../glib/gmem.c:99
        mem = <optimised out>
#7  0x00007ffff76869c5 in g_mime_filter_set_size
    (filter=0x555559184720 [GearyRFC822FilterBlockquotes], size=9311, keep=0) at gmime-filter.c:334
        offset = 0
        __func__ = "g_mime_filter_set_size"
#8  0x0000555555a04d26 in geary_rf_c822_filter_blockquotes_do_filter
    (self=0x555559184720 [GearyRFC822FilterBlockquotes], inbuf=0x555555dffb00 "\n:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;\n\n\n&#12288;&#12288;&#12288;&#12288;&#12288;&#1"..., inbuf_length1=9311, prespace=256, processed_buffer=0x7fffffffbca0, processed_buffer_length1=0x7fffffffbc98, outprespace=0x7fffffffbca8, flush=0) at ../src/engine/rfc822/rfc822-gmime-filter-blockquotes.vala:56
        _vala_processed_buffer = 0x0
        _vala_processed_buffer_length1 = 0
        _vala_outprespace = 0
        out_index = 0
        _tmp0_ = 0
        _tmp36_ = 0x7ffff7689a70 <html_convert+512> "\213Uh\366\302\020t-\200|$/"
        _tmp36__length1 = 1
        _tmp37_ = 0
        _tmp38_ = 140737488337992
        __func__ = "geary_rf_c822_filter_blockquotes_do_filter"
#9  0x0000555555a05501 in geary_rf_c822_filter_blockquotes_real_filter
    (base=0x555559184720 [GearyRFC822FilterBlockquotes], inbuf=0x555555dffb00 "\n:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;\n\n\n&#12288;&#12288;&#12288;&#12288;&#12288;&#1"..., inbuf_length1=9311, prespace=256, processed_buffer=0x7fffffffbd68, processed_buffer_length1=0x7fffffffbd58, outprespace=0x7fffffffbd70) at ../src/engine/rfc822/rfc822-gmime-filter-blockquotes.vala:127
        self = 0x555559184720 [GearyRFC822FilterBlockquotes]
        _vala_processed_buffer = 0x0
        _vala_processed_buffer_length1 = 0
        _vala_outprespace = 0
        _tmp0_ = 0x0
        _tmp1_ = -1321438720
        _tmp2_ = 0
#10 0x00007ffff76866de in g_mime_filter_filter
    (filter=0x555559184720 [GearyRFC822FilterBlockquotes], inbuf=0x555555dffb00 "\n:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#125--Type <RET> for more, q to quit, c to continue without paging--
39;&#176;:*:&#12539;&#176;\n\n\n&#12288;&#12288;&#12288;&#12288;&#12288;&#1"..., inlen=9311, prespace=256, outbuf=outbuf@entry=0x7fffffffbd68, outlen=outlen@entry=0x7fffffffbd58, outprespace=0x7fffffffbd70)
    at gmime-filter.c:225
        __func__ = "g_mime_filter_filter"
#11 0x00007ffff76a42a3 in stream_write
    (stream=0x7fff780230a0 [GMimeStreamFilter], buf=<optimised out>, n=<optimised out>)
    at gmime-stream-filter.c:250
        filter = 0x7fff780230a0 [GMimeStreamFilter]
        priv = <optimised out>
        buffer = 0x555555dffb00 "\n:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;:*:&#12539;&#176;\n\n\n&#12288;&#12288;&#12288;&#12288;&#12288;&#1"...
        nwritten = 2752
        f = 0x555555dddd20
        presize = 256
#12 0x00007ffff76a184a in g_mime_stream_write_to_stream
    (src=src@entry=0x7fff54066990 [GMimeStreamFilter], dest=dest@entry=0x7fff780230a0 [GMimeStreamFilter]) at gmime-stream.c:558
        len = <optimised out>
        nread = 2752
        nwritten = 0
        total = 0
        buf = "\r\n:*:\201E\201\213:*:\201E\201\213:*:\201E\201\213:*:\201E\201\213:*:\201E\201\213:*:\201E\201\213:*:\201E\201\213:*:\201E\201\213:*:\201E\201\213\r\n\r\n\r\n\201@\201@\201@\201@\201@\201@\201@\201@\201@LOTO\202U\201~\215ŐV\203e\203N\203m\203\215\203W\201[\r\n\r\n\204\254\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\252\204\255\r\n\201\241 \201@\201@\201@  \201"...
        __func__ = "g_mime_stream_write_to_stream"
#13 0x00007ffff76842fb in write_to_stream
    (wrapper=0x7fff604d3ca0 [GMimeDataWrapper], stream=0x7fff780230a0 [GMimeStreamFilter])
    at gmime-data-wrapper.c:255
        filtered_stream = 0x7fff54066990 [GMimeStreamFilter]
        filter = <optimised out>
        written = <optimised out>
#14 0x00005555558a3761 in geary_rf_c822_part_write_to_stream
    (self=0x7fff586e2700 [GearyRFC822Part], destination=0x7fff586fc800 [GMimeStreamMem], format=GEARY_RF_C822_PART_BODY_FORMATTING_HTML, error=0x7fffffffd0c0) at ../src/engine/rfc822/rfc822-part.vala:210
        _tmp17_ = 0x5555595d4e30 "shift_jis"
        _tmp20_ = 0x55555903d6a0 [GMimeFilterCharset]
        _tmp26_ = 0x7fff6c1d1d90 [GearyMimeContentParameters]
        _tmp35_ = 0
        charset = 0x5555595d4e30 "shift_jis"
        _tmp18_ = 0x7fff780230a0 [GMimeStreamFilter]
        _tmp21_ = 0x0
        _tmp27_ = 0x7fff6c1d1d90 [GearyMimeContentParameters]
        _tmp30_ = 0x55555820f540 "plain"
--Type <RET> for more, q to quit, c to continue without paging--
        filter = 0x7fff780230a0 [GMimeStreamFilter]
        _tmp13_ = 0x7fff780230a0 [GMimeStreamFilter]
        _tmp19_ = 0x5555595d4e30 "shift_jis"
        _tmp22_ = 0x7fff54075a50 [GearyMimeContentType]
        _tmp28_ = 0x5555576152f0
        _tmp31_ = 0x55555820f540 "plain"
        _tmp14_ = 0x7fff54075a50 [GearyMimeContentType]
        flowed = 0
        _tmp23_ = 0x7fff6c1d1d90 [GearyMimeContentParameters]
        _tmp29_ = 0x7fff54075a50 [GearyMimeContentType]
        _tmp50_ = 0x7fff604d3ca0 [GMimeDataWrapper]
        _tmp15_ = 0x7fff6c1d1d90 [GearyMimeContentParameters]
        _tmp24_ = 0x7fff6c1d1d90 [GearyMimeContentParameters]
        _tmp51_ = 0x7fff780230a0 [GMimeStreamFilter]
        _tmp16_ = 0x7fff6c1d1d90 [GearyMimeContentParameters]
        delsp = 0
        _tmp25_ = 0x7fff54075a50 [GearyMimeContentType]
        _tmp52_ = 0x7ffff7beb480
        _tmp0_ = 0x7fff604d3ca0 [GMimeDataWrapper]
        _tmp1_ = 0x555558d2cf00 [GMimePart]
        wrapper = 0x7fff604d3ca0 [GMimeDataWrapper]
        _tmp4_ = 0x7fff604d3ca0 [GMimeDataWrapper]
        _tmp5_ = 0x7fff604d3ca0 [GMimeDataWrapper]
        content_type = 0x7fff54075a50 [GearyMimeContentType]
        _tmp11_ = 0x7fff54075a50 [GearyMimeContentType]
        _tmp12_ = 0x7fff54075a50 [GearyMimeContentType]
        _inner_error_ = 0x0
        __func__ = "geary_rf_c822_part_write_to_stream"
#15 0x00005555558a2c75 in geary_rf_c822_part_write_to_buffer
    (self=0x7fff586e2700 [GearyRFC822Part], format=GEARY_RF_C822_PART_BODY_FORMATTING_HTML, error=0x7fffffffd1f8) at ../src/engine/rfc822/rfc822-part.vala:152
        result = 0x0
        byte_array = 0x7fff5c14d690
        _tmp0_ = 0x7fff5c14d690
        stream = 0x7fff586fc800 [GMimeStreamMem]
        _tmp1_ = 0x7fff586fc800 [GMimeStreamMem]
        _tmp2_ = 0x1586e2700
        _inner_error_ = 0x0
        __func__ = "geary_rf_c822_part_write_to_buffer"
#16 0x0000555555893a23 in geary_rf_c822_message_construct_body_from_mime_parts
    (self=0x555555dd1320 [GearyRFC822Message], node=0x555558d2cf00 [GMimePart], container_subtype=GEARY_MIME_MULTIPART_SUBTYPE_UNSPECIFIED, text_subtype=0x555555ab6a15 "plain", to_html=1, replacer=0x55555569fffa <_conversation_message_inline_image_replacer_geary_rf_c822_message_inline_part_replacer>, replacer_target=0x555558fc0580, body=0x7fffffffd408, error=0x7fffffffd410)
    at ../src/engine/rfc822/rfc822-message.vala:586
        _tmp42_ = GEARY_RF_C822_PART_BODY_FORMATTING_HTML
        _tmp44_ = 0x7fff586e2700 [GearyRFC822Part]
--Type <RET> for more, q to quit, c to continue without paging--
        _tmp48_ = 0x7fffffffd4b0 ""
        _tmp43_ = 0x0
        _tmp45_ = 0x7fff6023bc90 [GeeHashMap]
        _tmp41_ = 0x7fff54075a50 [GearyMimeContentType]
        result = 0
        part = 0x7fff586e2700 [GearyRFC822Part]
        _tmp0_ = 0x7fff586e2700 [GearyRFC822Part]
        content_type = 0x7fff54075a50 [GearyMimeContentType]
        _tmp1_ = 0x7fff586e2700 [GearyRFC822Part]
        _tmp2_ = 0x7fff54075a50 [GearyMimeContentType]
        multipart = 0x0
        _tmp3_ = 0x0
        _tmp4_ = 0x0
        disposition = GEARY_MIME_DISPOSITION_TYPE_UNSPECIFIED
        _tmp31_ = 0x7fff586e2700 [GearyRFC822Part]
        _tmp32_ = 0x0
        _tmp33_ = 0x0
        _tmp39_ = 1
        _inner_error_ = 0x0
        __func__ = "geary_rf_c822_message_construct_body_from_mime_parts"
#17 0x0000555555893f2c in geary_rf_c822_message_internal_get_body
    (self=0x555555dd1320 [GearyRFC822Message], text_subtype=0x555555ab6a15 "plain", to_html=1, replacer=0x55555569fffa <_conversation_message_inline_image_replacer_geary_rf_c822_message_inline_part_replacer>, replacer_target=0x555558fc0580, error=0x7fffffffd4b0) at ../src/engine/rfc822/rfc822-message.vala:606
        result = 0x0
        body = 0x0
        _tmp0_ = 0
        _tmp1_ = 0x555559034b10 [GMimeMessage]
        _tmp2_ = 0x555558d2cf00 [GMimePart]
        _tmp3_ = 21845
        _inner_error_ = 0x0
        __func__ = "geary_rf_c822_message_internal_get_body"
#18 0x0000555555894401 in geary_rf_c822_message_get_plain_body
    (self=0x555555dd1320 [GearyRFC822Message], convert_to_html=1, replacer=0x55555569fffa <_conversation_message_inline_image_replacer_geary_rf_c822_message_inline_part_replacer>, replacer_target=0x555558fc0580, error=0x7fff6004ebb0) at ../src/engine/rfc822/rfc822-message.vala:650
        result = 0x0
        _tmp0_ = 0x0
        _tmp1_ = 0x1 <error: Cannot access memory at address 0x1>
        _tmp2_ = 0x555555dd1320 "@\345\001YUU"
        _inner_error_ = 0x0
        __func__ = "geary_rf_c822_message_get_plain_body"
#19 0x00005555556a02be in conversation_message_load_message_body_co (_data_=0x7fff6004eb00)
    at ../src/client/conversation-viewer/conversation-message.vala:666
        __func__ = "conversation_message_load_message_body_co"
#20 0x000055555569ffaf in conversation_message_load_message_body
    (self=0x555558fc0580 [ConversationMessage], message=0x555555dd1320 [GearyRFC822Message], load_cancell--Type <RET> for more, q to quit, c to continue without paging--
ed=0x7fff6006fed0 [GCancellable], _callback_=0x5555556833f2 <conversation_email_update_body_ready>, _user_data_=0x555556a0c670) at ../src/client/conversation-viewer/conversation-message.vala:18
        _data_ = 0x7fff6004eb00
        _tmp0_ = 0x555558fc0580 [ConversationMessage]
        _tmp1_ = 0x555555dd1320 [GearyRFC822Message]
        _tmp2_ = 0x7fff6006fed0 [GCancellable]
#21 0x0000555555683d9a in conversation_email_update_body_co (_data_=0x555556a0c670)
    at ../src/client/conversation-viewer/conversation-email.vala:830
        __func__ = "conversation_email_update_body_co"
#22 0x00005555556833a7 in conversation_email_update_body
    (self=0x555558f2a980 [ConversationEmail], _callback_=0x55555568031a <conversation_email_load_body_ready>, _user_data_=0x555555c0cda0) at ../src/client/conversation-viewer/conversation-email.vala:19
        _data_ = 0x555556a0c670
        _tmp0_ = 0x555558f2a980 [ConversationEmail]
#23 0x0000555555680885 in conversation_email_load_body_co (_data_=0x555555c0cda0)
    at ../src/client/conversation-viewer/conversation-email.vala:623
        __func__ = "conversation_email_load_body_co"
#24 0x000055555568035a in conversation_email_load_body_ready
    (source_object=0x555556a05550 [GearyAppEmailStore], _res_=0x555559037000, _user_data_=0x555555c0cda0) at ../src/client/conversation-viewer/conversation-email.vala:600
        _data_ = 0x555555c0cda0
#25 0x00007ffff7559203 in g_task_return_now (task=0x555559037000 [GTask])
    at ../../../../gio/gtask.c:1148
#26 0x00007ffff7559ad6 in g_task_return (task=0x555559037000 [GTask], type=<optimised out>)
    at ../../../../gio/gtask.c:1206
        source = 0x555555e94000
#27 0x00005555557a2013 in geary_app_email_store_fetch_email_async_co (_data_=0x7fff60047060)
    at ../src/engine/app/app-email-store.vala:87
        __func__ = "geary_app_email_store_fetch_email_async_co"
#28 0x00005555557a1b91 in geary_app_email_store_fetch_email_async_ready
    (source_object=0x555556a05550 [GearyAppEmailStore], _res_=0x7fff54096ec0, _user_data_=0x7fff60047060) at ../src/engine/app/app-email-store.vala:82
        _data_ = 0x7fff60047060
#29 0x00007ffff7559203 in g_task_return_now (task=0x7fff54096ec0 [GTask])
    at ../../../../gio/gtask.c:1148
#30 0x00007ffff7559ad6 in g_task_return (task=0x7fff54096ec0 [GTask], type=<optimised out>)
    at ../../../../gio/gtask.c:1206
        source = 0x555555e94000
#31 0x00005555557a5941 in geary_app_email_store_do_folder_operation_async_co (_data_=0x555558f5e9c0)
    at ../src/engine/app/app-email-store.vala:155
        __func__ = "geary_app_email_store_do_folder_operation_async_co"
#32 0x00005555557a3c11 in geary_app_email_store_do_folder_operation_async_ready
    (source_object=0x5555569ebe40 [GearyImapEngineOtherFolder], _res_=0x555558f2de90, _user_data_=0x555558f5e9c0) at ../src/engine/app/app-email-store.vala:163
        _data_ = 0x555558f5e9c0
#33 0x00007ffff7559203 in g_task_return_now (task=0x555558f2de90 [GTask])
    at ../../../../gio/gtask.c:1148
--Type <RET> for more, q to quit, c to continue without paging--
#34 0x00007ffff7559ad6 in g_task_return (task=0x555558f2de90 [GTask], type=<optimised out>)
    at ../../../../gio/gtask.c:1206
        source = 0x555555e94000
#35 0x00005555559a2b41 in geary_imap_engine_minimal_folder_real_close_async_co (_data_=0x555559184160)
    at ../src/engine/imap-engine/imap-engine-minimal-folder.vala:269
        __func__ = "geary_imap_engine_minimal_folder_real_close_async_co"
#36 0x00005555559a27ef in geary_imap_engine_minimal_folder_close_async_ready
    (source_object=0x555559007a60 [GearyImapEngineUserClose], _res_=0x7fff6052ca10, _user_data_=0x555559184160) at ../src/engine/imap-engine/imap-engine-minimal-folder.vala:268
        _data_ = 0x555559184160
#37 0x00007ffff7559203 in g_task_return_now (task=0x7fff6052ca10 [GTask])
    at ../../../../gio/gtask.c:1148
#38 0x00007ffff7559ad6 in g_task_return (task=0x7fff6052ca10 [GTask], type=<optimised out>)
    at ../../../../gio/gtask.c:1206
        source = 0x555555e94000
#39 0x00005555559bf2fa in geary_imap_engine_replay_operation_wait_for_ready_async_co
    (_data_=0x55555749f800) at ../src/engine/imap-engine/imap-engine-replay-operation.vala:170
        __func__ = "geary_imap_engine_replay_operation_wait_for_ready_async_co"
#40 0x00005555559bf0ed in geary_imap_engine_replay_operation_wait_for_ready_async_ready
    (source_object=0x7fff5409af90 [GearyNonblockingSemaphore], _res_=0x7fff84008060, _user_data_=0x55555749f800) at ../src/engine/imap-engine/imap-engine-replay-operation.vala:171
        _data_ = 0x55555749f800
#41 0x00007ffff7559203 in g_task_return_now (task=0x7fff84008060 [GTask])
    at ../../../../gio/gtask.c:1148
#42 0x00007ffff7559ad6 in g_task_return (task=0x7fff84008060 [GTask], type=<optimised out>)
    at ../../../../gio/gtask.c:1206
        source = 0x555555e94000
#43 0x000055555588002c in geary_nonblocking_lock_real_wait_async_co (_data_=0x555559184280)
    at ../src/engine/nonblocking/nonblocking-lock.vala:194
        __func__ = "geary_nonblocking_lock_real_wait_async_co"
#44 0x000055555587fc07 in _geary_nonblocking_lock_real_wait_async_co_gsource_func (self=0x555559184280)
    at nonblocking-lock.c:639
        result = 32767
#45 0x00005555558dce11 in geary_scheduler_scheduled_instance_on_callback
    (self=0x7fff540820c0 [GearySchedulerScheduledInstance]) at ../src/engine/util/util-scheduler.vala:66
        _tmp2_ = 0x55555587fbef <_geary_nonblocking_lock_real_wait_async_co_gsource_func>
        _tmp2__target = 0x555559184280
        result = 0
        _tmp0_ = 0
        _tmp1_ = 0x55555587fbef <_geary_nonblocking_lock_real_wait_async_co_gsource_func>
        _tmp1__target = 0x555559184280
        again = 0
        _tmp3_ = 21845
        __func__ = "geary_scheduler_scheduled_instance_on_callback"
#46 0x00005555558dc8c6 in _geary_scheduler_scheduled_instance_on_callback_gsource_func
    (self=0x7fff540820c0) at src/engine/src@engine@@geary-engine@sta/util/util-scheduler.c:282
        result = 21845
--Type <RET> for more, q to quit, c to continue without paging--
#47 0x00007ffff7beeae8 in g_main_dispatch (context=0x555555bf8040) at ../../../../glib/gmain.c:3182
        dispatch = 0x7ffff7beb480 <g_idle_dispatch>
        prev_source = 0x0
        was_in_call = 0
        user_data = 0x7fff540820c0
        callback = 0x5555558dc8ae <_geary_scheduler_scheduled_instance_on_callback_gsource_func>
        cb_funcs = <optimised out>
        cb_data = 0x555555e811e0
        need_destroy = <optimised out>
        source = 0x555555e94000
        current = 0x555555c0dc50
        i = 1
        __func__ = "g_main_dispatch"
#48 0x00007ffff7beeae8 in g_main_context_dispatch (context=context@entry=0x555555bf8040)
    at ../../../../glib/gmain.c:3847
#49 0x00007ffff7beeed8 in g_main_context_iterate
    (context=context@entry=0x555555bf8040, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimised out>) at ../../../../glib/gmain.c:3920
        max_priority = 200
        timeout = 0
        some_ready = 1
        nfds = <optimised out>
        allocated_nfds = 9
        fds = 0x5555569948a0
#50 0x00007ffff7beef6c in g_main_context_iteration
    (context=context@entry=0x555555bf8040, may_block=may_block@entry=1) at ../../../../glib/gmain.c:3981
        retval = <optimised out>
#51 0x00007ffff756d13d in g_application_run
    (application=0x555555be11d0 [GearyApplication], argc=<optimised out>, argv=0x7fffffffdcd8)
    at ../../../../gio/gapplication.c:2470
        arguments = 0x555555be00d0
        status = 0
        context = 0x555555bf8040
        acquired_context = <optimised out>
        __func__ = "g_application_run"
#52 0x0000555555593b2e in _vala_main (args=0x7fffffffdcd8, args_length1=2)
    at ../src/client/application/main.vala:33
        result = 0
        app = 0x555555be11d0 [GearyApplication]
        _tmp0_ = 0x555555be11d0 [GearyApplication]
        ec = 0
        _tmp1_ = 0x0
#53 0x0000555555593b8e in main (argc=2, argv=0x7fffffffdcd8) at ../src/client/application/main.vala:7
(gdb) 

Don't canonicalise host names in Content-Ids values

Sorry to basically re-open Bug 762782, but there's a pretty good argument for not canonicalising the URI in a Content-Id: Since the message body itself refers to the CID URLs as-is in IMG SRC values, it breaks not only displaying the message, but also forwarding it, and there's no way for the application to work around it other than having to parse the HTML parts, guessing what GMime has done to the CID, and altering the message body to fix it.

It's kind of like a web browser canonicalising outgoing requests for URLs with trailing slashes by removing them, e.g. sending a GET for http://foo/bar when the user clicks on a link with http://foo/bar/ as the HREF. For the HTTP URL scheme these refer to the same resource, and it's shorter and arguably "more canonical" to remove the trailing slash, but it would break a whole lot of web sites.

I'm all for canonicalising the Content-ID header value, but leaving the URL alone so it matches any CID URLs in the message body is definitely the way to go.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.