Do not throw exception for normal code flow (exceptions::no_such_field).

This commit is contained in:
Vincent Richard 2013-11-22 13:32:52 +01:00
parent b075256d8d
commit 96077ce7e6
12 changed files with 297 additions and 303 deletions

View File

@ -41,12 +41,14 @@ namespace vmime
bool attachmentHelper::isBodyPartAnAttachment
(shared_ptr <const bodyPart> part, const unsigned int options)
{
try
{
const contentDispositionField& cdf =
*part->getHeader()->findField <contentDispositionField>(fields::CONTENT_DISPOSITION);
// First, try with "Content-Disposition" field.
// If not present, we will try with "Content-Type" field.
shared_ptr <const contentDispositionField> cdf =
part->getHeader()->findField <contentDispositionField>(fields::CONTENT_DISPOSITION);
const contentDisposition disp = *cdf.getValue <const contentDisposition>();
if (cdf)
{
const contentDisposition disp = *cdf->getValue <contentDisposition>();
if (disp.getName() != contentDispositionTypes::INLINE)
return true;
@ -68,26 +70,22 @@ bool attachmentHelper::isBodyPartAnAttachment
return false;
}
}
catch (exceptions::no_such_field&)
{
// Will try using Content-Type
}
// Assume "attachment" if type is not "text/..." or "multipart/...".
mediaType type;
bool hasContentTypeName = false;
try
shared_ptr <const contentTypeField> ctf =
part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
if (ctf)
{
const contentTypeField& ctf =
*part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
type = *ctf->getValue <mediaType>();
type = *ctf.getValue <const mediaType>();
if (ctf.hasParameter("name"))
if (ctf->hasParameter("name"))
hasContentTypeName = true;
}
catch (exceptions::no_such_field&)
else
{
// 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
@ -132,14 +130,14 @@ shared_ptr <const attachment> attachmentHelper::getBodyPartAttachment
mediaType type;
try
{
const contentTypeField& ctf =
*part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
shared_ptr <const contentTypeField> ctf =
part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
type = *ctf.getValue <mediaType>();
if (ctf)
{
type = *ctf->getValue <mediaType>();
}
catch (exceptions::no_such_field&)
else
{
// No "Content-type" field: assume "application/octet-stream".
type = mediaType(mediaTypes::APPLICATION,
@ -217,8 +215,6 @@ void attachmentHelper::addAttachment(shared_ptr <message> msg, shared_ptr <attac
// the root part of the message
shared_ptr <bodyPart> container = make_shared <bodyPart>();
try
{
if (msg->getHeader()->hasField(fields::CONTENT_TYPE))
{
container->getHeader()->ContentType()->setValue
@ -230,11 +226,6 @@ void attachmentHelper::addAttachment(shared_ptr <message> msg, shared_ptr <attac
container->getHeader()->ContentTransferEncoding()->setValue
(msg->getHeader()->ContentTransferEncoding()->getValue());
}
}
catch (exceptions::no_such_field&)
{
// Ignore
}
// Move parts from the root part to this new part
const std::vector <shared_ptr <bodyPart> > partList =

View File

@ -150,15 +150,16 @@ void body::parseImpl
return;
}
// Check whether the body is a MIME-multipart
// Check whether the body is a MIME-multipart.
// If it is, also get (or try to guess) the boundary separator.
bool isMultipart = false;
string boundary;
try
{
const shared_ptr <const contentTypeField> ctf =
shared_ptr <const contentTypeField> ctf =
m_part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
if (ctf)
{
const mediaType type = *ctf->getValue <mediaType>();
if (type.getType() == mediaTypes::MULTIPART)
@ -239,10 +240,6 @@ void body::parseImpl
}
}
}
catch (exceptions::no_such_field&)
{
// No "Content-Type" field...
}
// This is a multi-part body
if (isMultipart && !boundary.empty())
@ -353,14 +350,14 @@ void body::parseImpl
{
encoding enc;
try
{
const shared_ptr <headerField> cef =
shared_ptr <const headerField> cef =
m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING);
if (cef)
{
enc = *cef->getValue <encoding>();
}
catch (exceptions::no_such_field&)
else
{
// Defaults to "7bit" (RFC-1521)
enc = vmime::encoding(encodingTypes::SEVEN_BIT);
@ -432,21 +429,26 @@ void body::generateImpl
}
else
{
try
{
// Use current boundary string, if specified. If no "Content-Type" field is
// present, or the boundary is not specified, generate a random one
shared_ptr <contentTypeField> ctf =
m_part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
boundary = ctf->getBoundary();
}
catch (exceptions::no_such_field&)
if (ctf)
{
// Warning: no content-type and no boundary string specified!
boundary = generateRandomBoundaryString();
try
{
boundary = ctf->getBoundary();
}
catch (exceptions::no_such_parameter&)
{
// Warning: no boundary string specified!
// No boundary string specified
boundary = generateRandomBoundaryString();
}
}
else
{
// No Content-Type (and no boundary string specified)
boundary = generateRandomBoundaryString();
}
}
@ -658,14 +660,14 @@ void body::setContentType(const mediaType& type)
const mediaType body::getContentType() const
{
try
{
shared_ptr <const contentTypeField> ctf =
m_part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
return (*ctf->getValue <mediaType>());
if (ctf)
{
return *ctf->getValue <mediaType>();
}
catch (exceptions::no_such_field&)
else
{
// Defaults to "text/plain" (RFC-1521)
return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN));
@ -675,17 +677,17 @@ const mediaType body::getContentType() const
void body::setCharset(const charset& chset)
{
// If a Content-Type field exists, set charset
try
{
shared_ptr <contentTypeField> ctf =
m_part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
// If a Content-Type field exists, set charset
if (ctf)
{
ctf->setCharset(chset);
}
// Else, create a new Content-Type field of default type "text/plain"
// and set charset on it
catch (exceptions::no_such_field&)
else
{
setContentType(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN), chset);
}
@ -694,11 +696,13 @@ void body::setCharset(const charset& chset)
const charset body::getCharset() const
{
try
{
const shared_ptr <const contentTypeField> ctf =
m_part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
if (ctf)
{
try
{
return (ctf->getCharset());
}
catch (exceptions::no_such_parameter&)
@ -706,7 +710,8 @@ const charset body::getCharset() const
// Defaults to "us-ascii" (RFC-1521)
return (vmime::charset(charsets::US_ASCII));
}
catch (exceptions::no_such_field&)
}
else
{
// Defaults to "us-ascii" (RFC-1521)
return (vmime::charset(charsets::US_ASCII));
@ -722,25 +727,21 @@ void body::setEncoding(const encoding& enc)
const encoding body::getEncoding() const
{
try
{
const shared_ptr <const headerField> cef =
shared_ptr <const headerField> cef =
m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING);
if (cef)
{
return *cef->getValue <encoding>();
}
catch (exceptions::no_such_field&)
{
if (m_contents->isEncoded())
{
return m_contents->getEncoding();
}
else
{
if (m_contents->isEncoded())
return m_contents->getEncoding();
}
// Defaults to "7bit" (RFC-1521)
return vmime::encoding(encodingTypes::SEVEN_BIT);
}
}
}
@ -879,11 +880,11 @@ void body::initNewPart(shared_ptr <bodyPart> part)
shared_ptr <header> hdr = m_part->getHeader();
// Check whether we have a boundary string
try
{
shared_ptr <contentTypeField> ctf =
hdr->findField <contentTypeField>(fields::CONTENT_TYPE);
if (ctf)
{
try
{
const string boundary = ctf->getBoundary();
@ -903,12 +904,11 @@ void body::initNewPart(shared_ptr <bodyPart> part)
// not specified as "multipart/..."
}
}
catch (exceptions::no_such_field&)
else
{
// No "Content-Type" field: create a new one and generate
// a random boundary string.
shared_ptr <contentTypeField> ctf =
hdr->getField <contentTypeField>(fields::CONTENT_TYPE);
ctf = hdr->getField <contentTypeField>(fields::CONTENT_TYPE);
ctf->setValue(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED));
ctf->setBoundary(generateRandomBoundaryString());

View File

@ -36,20 +36,18 @@ bodyPartAttachment::bodyPartAttachment(shared_ptr <const bodyPart> part)
const mediaType bodyPartAttachment::getType() const
{
mediaType type;
shared_ptr <const contentTypeField> ctf = getContentType();
try
if (ctf)
{
type = *getContentType()->getValue <mediaType>();
return *ctf->getValue <mediaType>();
}
catch (exceptions::no_such_field&)
else
{
// No "Content-type" field: assume "application/octet-stream".
type = mediaType(mediaTypes::APPLICATION,
return mediaType(mediaTypes::APPLICATION,
mediaTypes::APPLICATION_OCTET_STREAM);
}
return type;
}
@ -58,38 +56,48 @@ const word bodyPartAttachment::getName() const
word name;
// Try the 'filename' parameter of 'Content-Disposition' field
shared_ptr <const contentDispositionField> cdf = getContentDisposition();
if (cdf)
{
try
{
name = getContentDisposition()->getFilename();
}
catch (exceptions::no_such_field&)
{
// No 'Content-Disposition' field
name = cdf->getFilename();
}
catch (exceptions::no_such_parameter&)
{
// No 'filename' parameter
}
}
else
{
// No 'Content-Disposition' field
}
// Try the 'name' parameter of 'Content-Type' field
if (name.getBuffer().empty())
{
shared_ptr <const contentTypeField> ctf = getContentType();
if (ctf)
{
try
{
shared_ptr <parameter> prm = getContentType()->findParameter("name");
shared_ptr <const parameter> prm = ctf->findParameter("name");
if (prm != NULL)
name = prm->getValue();
}
catch (exceptions::no_such_field&)
{
// No 'Content-Type' field
}
catch (exceptions::no_such_parameter&)
{
// No attachment name available
}
}
else
{
// No 'Content-Type' field
}
}
return name;
}
@ -99,14 +107,14 @@ const text bodyPartAttachment::getDescription() const
{
text description;
try
{
shared_ptr <const headerField> cd =
getHeader()->findField(fields::CONTENT_DESCRIPTION);
if (cd)
{
description = *cd->getValue <text>();
}
catch (exceptions::no_such_field&)
else
{
// No description available.
}

View File

@ -171,14 +171,10 @@ shared_ptr <headerField> header::findField(const string& fieldName) const
// No field with this name can be found
if (pos == m_fields.end())
{
throw exceptions::no_such_field();
}
return null;
// Else, return a reference to the existing field
else
{
return (*pos);
}
}

View File

@ -135,27 +135,13 @@ void htmlTextPart::findEmbeddedParts(const bodyPart& part,
{
shared_ptr <const bodyPart> p = part.getBody()->getPartAt(i);
// For a part to be an embedded object, it must have a
// For a part to be an embedded object, it must have either a
// Content-Id field or a Content-Location field.
try
{
p->getHeader()->findField(fields::CONTENT_ID);
if (p->getHeader()->hasField(fields::CONTENT_ID))
cidParts.push_back(p);
}
catch (exceptions::no_such_field)
{
// No "Content-id" field.
}
try
{
p->getHeader()->findField(fields::CONTENT_LOCATION);
if (p->getHeader()->hasField(fields::CONTENT_LOCATION))
locParts.push_back(p);
}
catch (exceptions::no_such_field)
{
// No "Content-Location" field.
}
findEmbeddedParts(*p, cidParts, locParts);
}
@ -172,12 +158,14 @@ void htmlTextPart::addEmbeddedObject(const bodyPart& part, const string& id,
mediaType type;
try
shared_ptr <const headerField> ctf =
part.getHeader()->findField(fields::CONTENT_TYPE);
if (ctf)
{
const shared_ptr <const headerField> ctf = part.getHeader()->ContentType();
type = *ctf->getValue <mediaType>();
}
catch (exceptions::no_such_field)
else
{
// No "Content-type" field: assume "application/octet-stream".
}
@ -206,21 +194,25 @@ void htmlTextPart::parse(shared_ptr <const bodyPart> message, shared_ptr <const
m_text = textPart->getBody()->getContents()->clone();
try
{
const shared_ptr <const contentTypeField> ctf =
// Find charset
shared_ptr <const contentTypeField> ctf =
textPart->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
m_charset = ctf->getCharset();
}
catch (exceptions::no_such_field)
if (ctf)
{
// No "Content-type" field.
try
{
m_charset = ctf->getCharset();
}
catch (exceptions::no_such_parameter)
{
// No "charset" parameter.
}
}
else
{
// No "Content-type" field.
}
// Extract embedded objects. The algorithm is quite simple: for each previously
// found inline part, we check if its CID/Location is contained in the HTML text.
@ -267,11 +259,11 @@ void htmlTextPart::parse(shared_ptr <const bodyPart> message, shared_ptr <const
bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& parent, const bodyPart& textPart)
{
// We search for the nearest "multipart/alternative" part.
try
{
const shared_ptr <const headerField> ctf =
part.getHeader()->findField(fields::CONTENT_TYPE);
if (ctf)
{
const mediaType type = *ctf->getValue <mediaType>();
if (type.getType() == mediaTypes::MULTIPART &&
@ -299,11 +291,12 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
{
const shared_ptr <const bodyPart> p = part.getBody()->getPartAt(i);
try
{
const shared_ptr <const headerField> ctf =
p->getHeader()->findField(fields::CONTENT_TYPE);
if (ctf)
{
const mediaType type = *ctf->getValue <mediaType>();
if (type.getType() == mediaTypes::TEXT &&
@ -313,7 +306,7 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
found = true;
}
}
catch (exceptions::no_such_field)
else
{
// No "Content-type" field.
}
@ -326,7 +319,7 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
}
}
}
catch (exceptions::no_such_field)
else
{
// No "Content-type" field.
}

View File

@ -110,18 +110,23 @@ void receivedMDNInfos::extract()
header fields;
fields.parse(oss.str());
try { m_omid = *fields.OriginalMessageId()->getValue <messageId>(); }
catch (exceptions::no_such_field&) { /* Ignore */ }
shared_ptr <messageId> omid =
fields.findFieldValue <messageId>(fields::ORIGINAL_MESSAGE_ID);
try { m_disp = *fields.Disposition()->getValue <disposition>(); }
catch (exceptions::no_such_field&) { /* Ignore */ }
if (omid)
m_omid = *omid;
try
{
text t = *fields.findField("Received-content-MIC")->getValue <text>();
m_contentMIC = t.generate();
}
catch (exceptions::no_such_field&) { /* Ignore */ }
shared_ptr <disposition> disp =
fields.findFieldValue <disposition>(fields::DISPOSITION);
if (disp)
m_disp = *disp;
shared_ptr <text> contentMIC =
fields.findFieldValue <text>("Received-content-MIC");
if (contentMIC)
m_contentMIC = contentMIC->generate();
}
}
}

View File

@ -63,8 +63,11 @@ void messageParser::parse(shared_ptr <const message> msg)
#ifndef VMIME_BUILDING_DOC
#define TRY_FIELD(var, type, name) \
try { var = *msg->getHeader()->findField(name)->getValue <type>(); } \
catch (exceptions::no_such_field) { }
{ \
shared_ptr <type> fldValue = msg->getHeader()->findFieldValue <type>(name); \
if (fldValue) \
var = *fldValue; \
}
TRY_FIELD(m_from, mailbox, fields::FROM);
@ -79,23 +82,21 @@ void messageParser::parse(shared_ptr <const message> msg)
#endif // VMIME_BUILDING_DOC
// Date
try
shared_ptr <const headerField> recv = msg->getHeader()->findField(fields::RECEIVED);
if (recv)
{
const headerField& recv = *msg->getHeader()->findField(fields::RECEIVED);
m_date = recv.getValue <relay>()->getDate();
m_date = recv->getValue <relay>()->getDate();
}
catch (vmime::exceptions::no_such_field&)
{
try
{
const headerField& date = *msg->getHeader()->findField(fields::DATE);
m_date = *date.getValue <datetime>();
}
catch (vmime::exceptions::no_such_field&)
else
{
shared_ptr <const headerField> date = msg->getHeader()->findField(fields::DATE);
if (date)
m_date = *date->getValue <datetime>();
else
m_date = datetime::now();
}
}
// Attachments
findAttachments(msg);
@ -120,13 +121,12 @@ void messageParser::findTextParts(shared_ptr <const bodyPart> msg, shared_ptr <c
mediaType type(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN);
bool accept = false;
try
{
const contentTypeField& ctf =
*msg->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
shared_ptr <const contentTypeField> ctf =
msg->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
const mediaType ctfType =
*ctf.getValue <mediaType>();
if (ctf)
{
const mediaType ctfType = *ctf->getValue <mediaType>();
if (ctfType.getType() == mediaTypes::TEXT)
{
@ -134,7 +134,7 @@ void messageParser::findTextParts(shared_ptr <const bodyPart> msg, shared_ptr <c
accept = true;
}
}
catch (exceptions::no_such_field&)
else
{
// No "Content-type" field: assume "text/plain".
accept = true;
@ -169,24 +169,24 @@ bool messageParser::findSubTextParts(shared_ptr <const bodyPart> msg, shared_ptr
{
const shared_ptr <const bodyPart> p = part->getBody()->getPartAt(i);
try
{
const contentTypeField& ctf =
*p->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
shared_ptr <const contentTypeField> ctf =
p->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
const mediaType type = *ctf.getValue <mediaType>();
if (ctf)
{
const mediaType type = *ctf->getValue <mediaType>();
contentDisposition disp; // default should be inline
if (type.getType() == mediaTypes::TEXT)
{
try
{
shared_ptr <const contentDispositionField> cdf = p->getHeader()->
findField <contentDispositionField>(fields::CONTENT_DISPOSITION);
if (cdf)
{
disp = *cdf->getValue <contentDisposition>();
}
catch (exceptions::no_such_field&)
else
{
// No "Content-Disposition" field, assume default
}
@ -195,7 +195,7 @@ bool messageParser::findSubTextParts(shared_ptr <const bodyPart> msg, shared_ptr
textParts.push_back(p);
}
}
catch (exceptions::no_such_field&)
else
{
// No "Content-type" field.
}

View File

@ -39,25 +39,13 @@ void importanceHelper::resetImportance(shared_ptr <message> msg)
void importanceHelper::resetImportanceHeader(shared_ptr <header> hdr)
{
try
{
shared_ptr <headerField> fld = hdr->findField("X-Priority");
hdr->removeField(fld);
}
catch (exceptions::no_such_field)
{
// Ignore
}
shared_ptr <headerField> fld;
try
{
shared_ptr <headerField> fld = hdr->findField("Importance");
if ((fld = hdr->findField("X-Priority")))
hdr->removeField(fld);
if ((fld = hdr->findField("Importance")))
hdr->removeField(fld);
}
catch (exceptions::no_such_field)
{
// Ignore
}
}
@ -70,9 +58,10 @@ importanceHelper::Importance importanceHelper::getImportance(shared_ptr <const m
importanceHelper::Importance importanceHelper::getImportanceHeader(shared_ptr <const header> hdr)
{
// Try "X-Priority" field
try
shared_ptr <const headerField> fld = hdr->findField("X-Priority");
if (fld)
{
const shared_ptr <const headerField> fld = hdr->findField("X-Priority");
const string value = fld->getValue <text>()->getWholeBuffer();
int n = IMPORTANCE_NORMAL;
@ -93,12 +82,13 @@ importanceHelper::Importance importanceHelper::getImportanceHeader(shared_ptr <c
return (i);
}
catch (exceptions::no_such_field)
else
{
// Try "Importance" field
try
fld = hdr->findField("Importance");
if (fld)
{
const shared_ptr <const headerField> fld = hdr->findField("Importance");
const string value = utility::stringUtils::toLower(utility::stringUtils::trim
(fld->getValue <text>()->getWholeBuffer()));
@ -109,7 +99,7 @@ importanceHelper::Importance importanceHelper::getImportanceHeader(shared_ptr <c
else
return (IMPORTANCE_NORMAL);
}
catch (exceptions::no_such_field)
else
{
// Default
return (IMPORTANCE_NORMAL);

View File

@ -125,64 +125,48 @@ static void extractMailboxes
void transport::send(shared_ptr <vmime::message> msg, utility::progressListener* progress)
{
// Extract expeditor
mailbox expeditor;
shared_ptr <mailbox> fromMbox =
msg->getHeader()->findFieldValue <mailbox>(fields::FROM);
try
{
const mailbox& mbox =
*msg->getHeader()->findField(fields::FROM)->getValue <mailbox>();
expeditor = mbox;
}
catch (exceptions::no_such_field&)
{
if (!fromMbox)
throw exceptions::no_expeditor();
}
mailbox expeditor = *fromMbox;
// Extract sender
shared_ptr <mailbox> senderMbox =
msg->getHeader()->findFieldValue <mailbox>(fields::SENDER);
mailbox sender;
try
{
const mailbox& mbox =
*msg->getHeader()->findField(fields::SENDER)->getValue <mailbox>();
sender = mbox;
}
catch (exceptions::no_such_field&)
{
if (!senderMbox)
sender = expeditor;
}
else
sender = *senderMbox;
// Extract recipients
mailboxList recipients;
try
{
const addressList& to =
*msg->getHeader()->findField(fields::TO)->getValue <addressList>();
// -- "To" field
shared_ptr <addressList> addresses =
msg->getHeader()->findFieldValue <addressList>(fields::TO);
extractMailboxes(recipients, to);
}
catch (exceptions::no_such_field&) { }
if (addresses)
extractMailboxes(recipients, *addresses);
try
{
const addressList& cc =
*msg->getHeader()->findField(fields::CC)->getValue <addressList>();
// -- "Cc" field
addresses =
msg->getHeader()->findFieldValue <addressList>(fields::CC);
extractMailboxes(recipients, cc);
}
catch (exceptions::no_such_field&) { }
if (addresses)
extractMailboxes(recipients, *addresses);
try
{
const addressList& bcc =
*msg->getHeader()->findField(fields::BCC)->getValue <addressList>();
// -- "Bcc" field
addresses =
msg->getHeader()->findFieldValue <addressList>(fields::BCC);
extractMailboxes(recipients, bcc);
}
catch (exceptions::no_such_field&) { }
if (addresses)
extractMailboxes(recipients, *addresses);
// Process message header by removing fields that should be removed
// before transmitting the message to MSA, and adding missing fields

View File

@ -75,21 +75,24 @@ void plainTextPart::parse(shared_ptr <const bodyPart> /* message */,
{
m_text = vmime::clone(textPart->getBody()->getContents());
shared_ptr <const contentTypeField> ctf =
textPart->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
if (ctf)
{
try
{
const contentTypeField& ctf =
*textPart->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
m_charset = ctf.getCharset();
}
catch (exceptions::no_such_field&)
{
// No "Content-type" field.
m_charset = ctf->getCharset();
}
catch (exceptions::no_such_parameter&)
{
// No "charset" parameter.
}
}
else
{
// No "Content-type" field.
}
}

View File

@ -59,8 +59,8 @@ VMIME_TEST_SUITE_BEGIN(importanceHelperTest)
vmime::misc::importanceHelper::resetImportanceHeader(hdr);
VASSERT_THROW("3", hdr->findField("Importance"), vmime::exceptions::no_such_field);
VASSERT_THROW("4", hdr->findField("X-Priority"), vmime::exceptions::no_such_field);
VASSERT_NULL("3", hdr->findField("Importance"));
VASSERT_NULL("4", hdr->findField("X-Priority"));
}

View File

@ -90,6 +90,7 @@ public:
#undef FIELD_ACCESS
/** Checks whether (at least) one field with this name exists.
* Field name is case-insensitive.
*
* @return true if at least one field with the specified name
* exists, or false otherwise
@ -97,18 +98,21 @@ public:
bool hasField(const string& fieldName) const;
/** Find the first field that matches the specified name.
* If no field is found, an exception is thrown.
* Field name is case-insensitive.
* If no field is found, NULL is returned.
*
* @throw exceptions::no_such_field if no field with this name exists
* @return first field with the specified name
* @return first field with the specified name, or NULL if no field
* with this name was found
*/
shared_ptr <headerField> findField(const string& fieldName) const;
/** Find the first field that matches the specified name,
* casted to the specified type.
* If no field is found, an exception is thrown.
* casted to the specified field type. Field name is case-insensitive.
* If no field is found, or the field is not of the specified type,
* NULL is returned.
*
* @return value object
* @return first field with the specified name, or NULL if no field
* with this name was found
*/
template <typename T>
shared_ptr <T> findField(const string& fieldName) const
@ -116,6 +120,26 @@ public:
return dynamicCast <T>(findField(fieldName));
}
/** Find the value of the first field that matches the specified name,
* casted to the specified value type. Field name is case-insensitive.
* If no field is found, or the field value is not of the specified
* type, NULL is returned.
*
* @return value of the first field with the specified name, or NULL
* if no field with this name was found, or the value is not of the
* specified type
*/
template <typename T>
shared_ptr <T> findFieldValue(const string& fieldName) const
{
shared_ptr <headerField> field = findField(fieldName);
if (field)
return dynamicCast <T>(field->getValue());
else
return null;
}
/** Find all fields that match the specified name.
* If no field is found, an empty vector is returned.
*