Added an option to recognize inline objects as attachments.

This commit is contained in:
Vincent Richard 2010-09-07 10:46:24 +00:00
parent f1b5d7d7e2
commit def04e4ba5
2 changed files with 83 additions and 52 deletions

View File

@ -36,7 +36,8 @@ namespace vmime
// static // static
bool attachmentHelper::isBodyPartAnAttachment(ref <const bodyPart> part) bool attachmentHelper::isBodyPartAnAttachment
(ref <const bodyPart> part, const unsigned int options)
{ {
try try
{ {
@ -49,54 +50,63 @@ bool attachmentHelper::isBodyPartAnAttachment(ref <const bodyPart> part)
if (disp.getName() != contentDispositionTypes::INLINE) if (disp.getName() != contentDispositionTypes::INLINE)
return true; return true;
// If the Content-Disposition is 'inline' and there is no if ((options & INLINE_OBJECTS) == 0)
// Content-Id or Content-Location field, it may be an attachment
if (!part->getHeader()->hasField(vmime::fields::CONTENT_ID) &&
!part->getHeader()->hasField(vmime::fields::CONTENT_LOCATION))
{ {
// If this is the root part, it might not be an attachment // If the Content-Disposition is 'inline' and there is no
if (part->getParentPart() == NULL) // Content-Id or Content-Location field, it may be an attachment
return false; if (!part->getHeader()->hasField(vmime::fields::CONTENT_ID) &&
!part->getHeader()->hasField(vmime::fields::CONTENT_LOCATION))
{
// If this is the root part, it might not be an attachment
if (part->getParentPart() == NULL)
return false;
return true; return true;
}
return false;
} }
} }
catch (exceptions::no_such_field&) catch (exceptions::no_such_field&)
{ {
// No "Content-disposition" field: assume "attachment" if // Will try using Content-Type
// type is not "text/..." or "multipart/...". }
mediaType type;
try // Assume "attachment" if type is not "text/..." or "multipart/...".
{ mediaType type;
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
(*part->getHeader()->findField(fields::CONTENT_TYPE));
type = *ctf.getValue().dynamicCast <const mediaType>(); try
} {
catch (exceptions::no_such_field&) const contentTypeField& ctf = dynamic_cast<contentTypeField&>
{ (*part->getHeader()->findField(fields::CONTENT_TYPE));
// If this is the root part and no Content-Type field is present,
// then this may not be a MIME message, so do not assume it is
// an attachment
if (part->getParentPart() == NULL)
return false;
// No "Content-type" field: assume "application/octet-stream". type = *ctf.getValue().dynamicCast <const mediaType>();
type = mediaType(mediaTypes::APPLICATION, }
mediaTypes::APPLICATION_OCTET_STREAM); catch (exceptions::no_such_field&)
} {
// If this is the root part and no Content-Type field is present,
// then this may not be a MIME message, so do not assume it is
// an attachment
if (part->getParentPart() == NULL)
return false;
if (type.getType() != mediaTypes::TEXT && // No "Content-type" field: assume "application/octet-stream".
type.getType() != mediaTypes::MULTIPART) type = mediaType(mediaTypes::APPLICATION,
mediaTypes::APPLICATION_OCTET_STREAM);
}
if (type.getType() != mediaTypes::TEXT &&
type.getType() != mediaTypes::MULTIPART)
{
if ((options & INLINE_OBJECTS) == 0)
{ {
// If a "Content-Id" field is present, it might be an // If a "Content-Id" field is present, it might be an
// embedded object (MHTML messages) // embedded object (MHTML messages)
if (part->getHeader()->hasField(vmime::fields::CONTENT_ID)) if (part->getHeader()->hasField(vmime::fields::CONTENT_ID))
return false; return false;
return true;
} }
return true;
} }
return false; return false;
@ -104,10 +114,10 @@ bool attachmentHelper::isBodyPartAnAttachment(ref <const bodyPart> part)
// static // static
ref <const attachment> ref <const attachment> attachmentHelper::getBodyPartAttachment
attachmentHelper::getBodyPartAttachment(ref <const bodyPart> part) (ref <const bodyPart> part, const unsigned int options)
{ {
if (!isBodyPartAnAttachment(part)) if (!isBodyPartAnAttachment(part, options))
return NULL; return NULL;
mediaType type; mediaType type;
@ -140,22 +150,24 @@ ref <const attachment>
// static // static
const std::vector <ref <const attachment> > const std::vector <ref <const attachment> >
attachmentHelper::findAttachmentsInMessage(ref <const message> msg) attachmentHelper::findAttachmentsInMessage
(ref <const message> msg, const unsigned int options)
{ {
return findAttachmentsInBodyPart(msg); return findAttachmentsInBodyPart(msg, options);
} }
// static // static
const std::vector <ref <const attachment> > const std::vector <ref <const attachment> >
attachmentHelper::findAttachmentsInBodyPart(ref <const bodyPart> part) attachmentHelper::findAttachmentsInBodyPart
(ref <const bodyPart> part, const unsigned int options)
{ {
std::vector <ref <const attachment> > atts; std::vector <ref <const attachment> > atts;
// Test this part // Test this part
if (isBodyPartAnAttachment(part)) if (isBodyPartAnAttachment(part, options))
{ {
atts.push_back(getBodyPartAttachment(part)); atts.push_back(getBodyPartAttachment(part, options));
} }
// Find in sub-parts // Find in sub-parts
else else
@ -165,7 +177,7 @@ const std::vector <ref <const attachment> >
for (int i = 0 ; i < bdy->getPartCount() ; ++i) for (int i = 0 ; i < bdy->getPartCount() ; ++i)
{ {
std::vector <ref <const attachment> > partAtts = std::vector <ref <const attachment> > partAtts =
findAttachmentsInBodyPart(bdy->getPartAt(i)); findAttachmentsInBodyPart(bdy->getPartAt(i), options);
std::copy(partAtts.begin(), partAtts.end(), std::back_inserter(atts)); std::copy(partAtts.begin(), partAtts.end(), std::back_inserter(atts));
} }

View File

@ -30,10 +30,6 @@
#include "vmime/attachment.hpp" #include "vmime/attachment.hpp"
#include "vmime/message.hpp" #include "vmime/message.hpp"
#if VMIME_HAVE_MESSAGING_FEATURES
#include "vmime/net/message.hpp"
#endif
namespace vmime namespace vmime
{ {
@ -45,31 +41,57 @@ class attachmentHelper
{ {
public: public:
/** Options for use with the following functions:
* findAttachmentsInMessage,
* getBodyPartAttachment,
* and isBodyPartAnAttachment.
*/
enum FindOptions
{
INLINE_OBJECTS = (1 << 0) /**< Recognize and return inline objects. The aim is to
consider MHTML objects (parts with a "Content-Id" or
a "Content-Location", such as inline images) as attachments. */
};
/** Test whether a body part is an attachment. /** Test whether a body part is an attachment.
* *
* @param part message part to test * @param part message part to test
* @param options search options (see FindOptions)
* @return true if the part is an attachment, false otherwise * @return true if the part is an attachment, false otherwise
*/ */
static bool isBodyPartAnAttachment(ref <const bodyPart> part); static bool isBodyPartAnAttachment(ref <const bodyPart> part, const unsigned int options = 0);
/** Return attachment information in the specified body part. /** Return attachment information in the specified body part.
* If the specified body part does not contain attachment * If the specified body part does not contain attachment
* information (ie. is not an attachment), NULL is returned. * information (ie. is not an attachment), NULL is returned.
* *
* @param part message part in which to search * @param part message part in which to search
* @param options search options (see FindOptions)
* @return attachment found in the part, or NULL * @return attachment found in the part, or NULL
*/ */
static ref <const attachment> static ref <const attachment>
getBodyPartAttachment(ref <const bodyPart> part); getBodyPartAttachment(ref <const bodyPart> part, const unsigned int options = 0);
/** Find all attachments contained in the specified part
* and all its children parts.
* This is simply a recursive call to getBodyPartAttachment().
*
* @param part part in which to search
* @param options search options (see FindOptions)
* @return a list of attachments found
*/
static const std::vector <ref <const attachment> >
findAttachmentsInBodyPart(ref <const bodyPart> part, const unsigned int options = 0);
/** Find all attachments contained in the specified message. /** Find all attachments contained in the specified message.
* This is simply a recursive call to getBodyPartAttachment(). * This is simply a recursive call to getBodyPartAttachment().
* *
* @param msg message in which to search * @param msg message in which to search
* @param options search options (see FindOptions)
* @return a list of attachments found * @return a list of attachments found
*/ */
static const std::vector <ref <const attachment> > static const std::vector <ref <const attachment> >
findAttachmentsInMessage(ref <const message> msg); findAttachmentsInMessage(ref <const message> msg, const unsigned int options = 0);
/** Add an attachment to the specified message. /** Add an attachment to the specified message.
* *
@ -87,9 +109,6 @@ public:
protected: protected:
static const std::vector <ref <const attachment> >
findAttachmentsInBodyPart(ref <const bodyPart> part);
static ref <bodyPart> findBodyPart static ref <bodyPart> findBodyPart
(ref <bodyPart> part, const mediaType& type); (ref <bodyPart> part, const mediaType& type);
}; };