Usecases: # plaintext msg + attachment * ContentPart => cp1 * AttachmentPart => ap1 (cp1) == collect(select=NoEncapsulatedMessages) (ap1) == collect(select=NoEncapsulatedMessages) (PlainText) == cp1.availableContent() # html msg + related attachment + normal attachment * ContentPart => cp1 * AttachmentPart(mimetype="*/related", cid="12345678") => ap1 * AttachmentPart => ap2 (cp1) == collect(select=NoEncapsulatedMessages) (ap1, ap2) == collect(select=NoEncapsulatedMessages) (ap2) == collect(select=NoEncapsulatedMessages, filter=filterelated) ap1 == getPart("cid:12345678") (Html) == cp1.availableContent() # alternative msg + attachment * ContentPart(html=[TextPart("HTML"),], plaintext=[TextPart("Text"),]) => cp1 * AttachmentPart => ap1 (cp1) == collect(select=NoEncapsulatedMessages) (ap1) == collect(select=NoEncapsulatedMessages) (Html, PlainText) == cp1.availableContent() [TextPart("HTML"),] == cp1.content(Html) [TextPart("Text"),] == cp1.content(Plaintext) # alternative msg with GPGInlin * ContentPart( plaintext=[TextPart("Text"), TextPart("foo", encryption=(enc1))], html=[TextPart("HTML"),] ) => cp1 (Html, PlainText) == cp1.availableContent() [TextPart("HTML"),] == cp1.content(Html) [TextPart("Text"),TextPart("foo", encryption=(enc1))] == cp1.content(Plaintext) # encrypted msg (not encrypted/error) with unencrypted attachment * EncryptionErrorPart => cp1 * AttachmentPart => ap1 (cp1) == collect(select=NoEncapsulatedMessages) (ap1) == collect(select=NoEncapsulatedMessages) #encrypted msg (decrypted with attachment) + unencrypted attachment * encrytion=(rec1,rec2) => enc1 * ContentPart(encrytion = (enc1,)) => cp1 * AttachmentPart(encryption = (enc1,)) => ap1 * AttachmentPart => ap2 (cp1) == collect(select=NoEncapsulatedMessages) (ap1, ap2) == collect(select=NoEncapsulatedMessages) #INLINE GPG encrypted msg + attachment * ContentPart => cp1 with plaintext=[TextPart, TextPart(encrytion = (enc1(rec1,rec2),)), TextPart(signed = (sig1,)), TextPart] * AttachmentPart => ap1 (cp1) == collect(select=NoEncapsulatedMessages) (ap1) == collect(select=NoEncapsulatedMessages) [TextPart, TextPart(encrytion = (enc1(rec1,rec2),)), TextPart(signed = (sig1,)), TextPart] == cp1.content(Plaintext) #forwared encrypted msg + attachments * ContentPart => cp1 * EncapsulatedPart => ep1 * Encrytion=(rec1,rec2) => enc1 * Signature => sig1 * ContentPart(encrytion = (enc1,), signature = (sig1,)) => cp2 * TextPart(encrytion = (enc1,), signature = (sig1,)) * TextPart(encrytion = (enc1, enc2(rec3,rec4),), signature = (sig1,)) * AttachmentPart(encrytion = (enc1,), signature = (sig1,)) => ap1 * AttachmentPart => ap2 (cp1) = collect(select=NoEncapsulatedMessages) (ap2) = collect(select=NoEncapsulatedMessages) (cp2) = collect(ep1, select=NoEncapsulatedMessages) (ap1) = collect(ep1, select=NoEncapsulatedMessages) (cp1, cp2) == collect() (ap1, ap2) == collect()[TextPart, TextPart(encrytion = (enc1(rec1,rec2),)), TextPart(signed = (sig1,)), TextPart] # plaintext msg + attachment + cert * ContentPart => cp1 * AttachmentPart => ap1 * CertPart => cep1 (cp1) == collect(select=NoEncapsulatedMessages) (ap1, cep1) == collect(select=NoEncapsulatedMessages) (ap1) == collect(select=NoEncapsulatedMessages, filter=filterSubAttachmentParts) (cep1) == collect(select=NoEncapsulatedMessages) collect function: bool noEncapsulatedMessages(Part part) { if (is(part)) { return false; } return true; } bool filterRelated(T part) { if (part.mimetype == related && !part.cid.isEmpty()) { return false; //filter out related parts } return true; } bool filterSubAttachmentParts(AttachmentPart part) { if (isSubPart(part)) { return false; // filter out CertPart f.ex. } return true; } List collect(Part start, std::function select, std::function &)> filter) { List col; if (!select(start)) { return col; } if(isOrSubTypeIs(start) && filter(start.staticCast)){ col.append(p); } foreach(childs as child) { if (select(child)) { col.expand(collect(child,select,filter); } } return col; }