Re: [gmime-devel] Accessing attachments including inline-parts.



Hi Steve,

On 5/25/2014 12:57 PM, Steve Kemp wrote:
[snip]
Your iterator loop above will iterate over all attachment and inline
parts. You can use the following logic to determine if a part is an
attachment (if it's not an attachment, then it is an inline part):

GMimeContentDisposition *disposition =
g_mime_object_get_content_disposition (part);

if (disposition != null && disposition->disposition != null &&
!g_strcasecmp (disposition->disposition, "attachment")) {
     // the part is an attachment
} else {
     // the part is an inline part
}
   This doesn't quite seem to be working how I expect, because
  the body parts are missing.

   If you have the patience I wrote a simple test-program which
  I've been using on messages:

     https://raw.githubusercontent.com/skx/lumail/master/util/attachments.c

   It looks like something is screwy getting the content, and I'm
  still not seeing the full number of parts that Mutt displays
  on some messages.

   e.g:

shelob ~/git/lumail/util $ ./attachments cur/x.msg\:2\,S

Handling input message: cur/x.msg:2,S
XX  Inline part.
XX  Inline part.
XX  Inline part.
XX  Inline part.
Parsing has completed
We received 4 attachment(s).
     NAME: un-named size: 16
     NAME: un-named size: 16
     NAME: un-named size: 16
     NAME: un-named size: 16


   vs.

   I     1 <no description>                                                                                   
    [multipa/mixed, 7bit, 7.2K]
   I     2 ├─><no description>                                                                              
[text/plain, quoted, utf-8, 0.1K]
   I     3 └─>Weitergeleitete Nachricht - Re: [lumail]                                                        
   [message/rfc822, 7bit, 6.8K]
   I     4   └─><no description>                                                                             
[multipa/alternativ, 7bit, 1.9K]
   I     5     ├─><no description>                                                                          
[text/plain, quoted, utf-8, 0.6K]
   I     6     └─><no description>                                                                           
[text/html, quoted, utf-8, 1.0K]
   I     7 This is a digitally signed message part                                                           
[applica/pgp-signat, 7bit, 0.2K]

   The count differs ("4 vs 7") and the sizes are bogus.

The count differs because your loop is ignoring everything except GMimeParts:

        if ( (! GMIME_IS_OBJECT( part ) ) ||
             ( !GMIME_IS_PART(part) ) )
            continue;

(FWIW, the check for GMIME_IS_OBJECT is not necessary)

This filters out the multipart/mixed, the message/rfc822 and the multipart/alternative parts listed in mutt's output.

The multiparts can't ever be considered "attachments", so it's fine to ignore those. However, the message/rfc822 part might be considered an attachment. You can check for message/rfc822 parts by using GMIME_IS_MESSAGE_PART().

Once you know a part is a GMimePart, you can simplify your code to get the file name by using g_mime_part_get_filename() which is a convenience function to do what you are currently doing. There's nothing wrong with your current code for that, but I figured I'd point out a simpler way in case you didn't know about it.

That said, a GMimeMessagePart does not subclass GMimePart, so keeping your current code is useful if you want to handle message/rfc822 parts as attachments.


As far as bogus content sizes goes, this seems to be part of the problem:

guint8 len= g_mime_data_wrapper_write_to_stream( content, memstream );


guint8 is an 8-bit integer while g_mime_data_wrapper_write_to_stream() returns a size_t (which is typically a 32-bit integer).

You probably also don't want to use the return value of g_mime_data_wrapper_write_to_stream() as an exact number of bytes written because the data goes through a decoder transform which may alter the number of bytes actually written. I think I tried to make GMimeStreamFilter account for that, but it's probably safer to measure the stream length instead (the GByteArray has a 'len' struct member that holds the number of bytes in the 'data' struct member, so that's probably what you want to use).


Unfortunately, even after these changes that I made locally, it still gave me bogus size values when printing out the CAttachment vector items. I think the problem is that you are creating the CAttachment items on the stack instead of the heap, so when the caller function iterates over the vector, the items are completely bogus.

I'm not very sharp with c++, though, so my understanding of the CAttachment constructor syntax could be totally wrong - either way, the size values printed in your "for (CAttachment cur : result)" loop do not match the size values that I was printing inside of handle_mail(), so something isn't quite right with the vector results.


Oh, and it's not necessary to call g_mime_stream_close() if you are going to unref it. The final unref of the stream will close it for you.


Hope that helps,

Jeff


Attachment: smime.p7s
Description: S/MIME Cryptographic Signature



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]