diff --git a/src/attachmentHelper.cpp b/src/attachmentHelper.cpp index 7168fd93..152daeed 100644 --- a/src/attachmentHelper.cpp +++ b/src/attachmentHelper.cpp @@ -41,12 +41,14 @@ namespace vmime bool attachmentHelper::isBodyPartAnAttachment (shared_ptr part, const unsigned int options) { - try - { - const contentDispositionField& cdf = - *part->getHeader()->findField (fields::CONTENT_DISPOSITION); + // First, try with "Content-Disposition" field. + // If not present, we will try with "Content-Type" field. + shared_ptr cdf = + part->getHeader()->findField (fields::CONTENT_DISPOSITION); - const contentDisposition disp = *cdf.getValue (); + if (cdf) + { + const contentDisposition disp = *cdf->getValue (); 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 ctf = + part->getHeader()->findField (fields::CONTENT_TYPE); + + if (ctf) { - const contentTypeField& ctf = - *part->getHeader()->findField (fields::CONTENT_TYPE); + type = *ctf->getValue (); - type = *ctf.getValue (); - - 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 attachmentHelper::getBodyPartAttachment mediaType type; - try - { - const contentTypeField& ctf = - *part->getHeader()->findField (fields::CONTENT_TYPE); + shared_ptr ctf = + part->getHeader()->findField (fields::CONTENT_TYPE); - type = *ctf.getValue (); + if (ctf) + { + type = *ctf->getValue (); } - catch (exceptions::no_such_field&) + else { // No "Content-type" field: assume "application/octet-stream". type = mediaType(mediaTypes::APPLICATION, @@ -217,23 +215,16 @@ void attachmentHelper::addAttachment(shared_ptr msg, shared_ptr container = make_shared (); - try + if (msg->getHeader()->hasField(fields::CONTENT_TYPE)) { - if (msg->getHeader()->hasField(fields::CONTENT_TYPE)) - { - container->getHeader()->ContentType()->setValue - (msg->getHeader()->ContentType()->getValue()); - } - - if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING)) - { - container->getHeader()->ContentTransferEncoding()->setValue - (msg->getHeader()->ContentTransferEncoding()->getValue()); - } + container->getHeader()->ContentType()->setValue + (msg->getHeader()->ContentType()->getValue()); } - catch (exceptions::no_such_field&) + + if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING)) { - // Ignore + container->getHeader()->ContentTransferEncoding()->setValue + (msg->getHeader()->ContentTransferEncoding()->getValue()); } // Move parts from the root part to this new part diff --git a/src/body.cpp b/src/body.cpp index 8d6bab3f..8251ab1f 100644 --- a/src/body.cpp +++ b/src/body.cpp @@ -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 ctf = - m_part->getHeader()->findField (fields::CONTENT_TYPE); + shared_ptr ctf = + m_part->getHeader()->findField (fields::CONTENT_TYPE); + if (ctf) + { const mediaType type = *ctf->getValue (); 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 cef = - m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING); + shared_ptr cef = + m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING); + if (cef) + { enc = *cef->getValue (); } - 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 - { - shared_ptr ctf = - m_part->getHeader()->findField (fields::CONTENT_TYPE); + // 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 ctf = + m_part->getHeader()->findField (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&) + { + // No boundary string specified + boundary = generateRandomBoundaryString(); + } } - catch (exceptions::no_such_parameter&) + else { - // Warning: no boundary string specified! + // 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 ctf = - m_part->getHeader()->findField (fields::CONTENT_TYPE); + shared_ptr ctf = + m_part->getHeader()->findField (fields::CONTENT_TYPE); - return (*ctf->getValue ()); + if (ctf) + { + return *ctf->getValue (); } - 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 ctf = - m_part->getHeader()->findField (fields::CONTENT_TYPE); + shared_ptr ctf = + m_part->getHeader()->findField (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,19 +696,22 @@ void body::setCharset(const charset& chset) const charset body::getCharset() const { - try - { - const shared_ptr ctf = - m_part->getHeader()->findField (fields::CONTENT_TYPE); + const shared_ptr ctf = + m_part->getHeader()->findField (fields::CONTENT_TYPE); - return (ctf->getCharset()); - } - catch (exceptions::no_such_parameter&) + if (ctf) { - // Defaults to "us-ascii" (RFC-1521) - return (vmime::charset(charsets::US_ASCII)); + try + { + return (ctf->getCharset()); + } + catch (exceptions::no_such_parameter&) + { + // 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 cef = - m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING); + shared_ptr cef = + m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING); + if (cef) + { return *cef->getValue (); } - catch (exceptions::no_such_field&) + else { if (m_contents->isEncoded()) - { return m_contents->getEncoding(); - } - else - { - // Defaults to "7bit" (RFC-1521) - return vmime::encoding(encodingTypes::SEVEN_BIT); - } } + + // Defaults to "7bit" (RFC-1521) + return vmime::encoding(encodingTypes::SEVEN_BIT); } @@ -879,11 +880,11 @@ void body::initNewPart(shared_ptr part) shared_ptr
hdr = m_part->getHeader(); // Check whether we have a boundary string - try - { - shared_ptr ctf = - hdr->findField (fields::CONTENT_TYPE); + shared_ptr ctf = + hdr->findField (fields::CONTENT_TYPE); + if (ctf) + { try { const string boundary = ctf->getBoundary(); @@ -903,12 +904,11 @@ void body::initNewPart(shared_ptr 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 ctf = - hdr->getField (fields::CONTENT_TYPE); + ctf = hdr->getField (fields::CONTENT_TYPE); ctf->setValue(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED)); ctf->setBoundary(generateRandomBoundaryString()); diff --git a/src/bodyPartAttachment.cpp b/src/bodyPartAttachment.cpp index c8361238..7b9adf01 100644 --- a/src/bodyPartAttachment.cpp +++ b/src/bodyPartAttachment.cpp @@ -36,20 +36,18 @@ bodyPartAttachment::bodyPartAttachment(shared_ptr part) const mediaType bodyPartAttachment::getType() const { - mediaType type; + shared_ptr ctf = getContentType(); - try + if (ctf) { - type = *getContentType()->getValue (); + return *ctf->getValue (); } - catch (exceptions::no_such_field&) + else { // No "Content-type" field: assume "application/octet-stream". - type = mediaType(mediaTypes::APPLICATION, - mediaTypes::APPLICATION_OCTET_STREAM); + return mediaType(mediaTypes::APPLICATION, + mediaTypes::APPLICATION_OCTET_STREAM); } - - return type; } @@ -58,37 +56,47 @@ const word bodyPartAttachment::getName() const word name; // Try the 'filename' parameter of 'Content-Disposition' field - try + shared_ptr cdf = getContentDisposition(); + + if (cdf) { - name = getContentDisposition()->getFilename(); + try + { + name = cdf->getFilename(); + } + catch (exceptions::no_such_parameter&) + { + // No 'filename' parameter + } } - catch (exceptions::no_such_field&) + else { // No 'Content-Disposition' field } - catch (exceptions::no_such_parameter&) - { - // No 'filename' parameter - } // Try the 'name' parameter of 'Content-Type' field if (name.getBuffer().empty()) { - try - { - shared_ptr prm = getContentType()->findParameter("name"); + shared_ptr ctf = getContentType(); - if (prm != NULL) - name = prm->getValue(); + if (ctf) + { + try + { + shared_ptr prm = ctf->findParameter("name"); + + if (prm != NULL) + name = prm->getValue(); + } + catch (exceptions::no_such_parameter&) + { + // No attachment name available + } } - catch (exceptions::no_such_field&) + else { // No 'Content-Type' field } - catch (exceptions::no_such_parameter&) - { - // No attachment name available - } } return name; @@ -99,14 +107,14 @@ const text bodyPartAttachment::getDescription() const { text description; - try - { - shared_ptr cd = - getHeader()->findField(fields::CONTENT_DESCRIPTION); + shared_ptr cd = + getHeader()->findField(fields::CONTENT_DESCRIPTION); + if (cd) + { description = *cd->getValue (); } - catch (exceptions::no_such_field&) + else { // No description available. } diff --git a/src/header.cpp b/src/header.cpp index 8e04cadc..2dc07b8f 100644 --- a/src/header.cpp +++ b/src/header.cpp @@ -171,14 +171,10 @@ shared_ptr 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); - } + return (*pos); } diff --git a/src/htmlTextPart.cpp b/src/htmlTextPart.cpp index 0aabbdc4..e97161cb 100644 --- a/src/htmlTextPart.cpp +++ b/src/htmlTextPart.cpp @@ -135,27 +135,13 @@ void htmlTextPart::findEmbeddedParts(const bodyPart& part, { shared_ptr 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 ctf = + part.getHeader()->findField(fields::CONTENT_TYPE); + + if (ctf) { - const shared_ptr ctf = part.getHeader()->ContentType(); type = *ctf->getValue (); } - catch (exceptions::no_such_field) + else { // No "Content-type" field: assume "application/octet-stream". } @@ -206,21 +194,25 @@ void htmlTextPart::parse(shared_ptr message, shared_ptr getBody()->getContents()->clone(); - try - { - const shared_ptr ctf = - textPart->getHeader()->findField (fields::CONTENT_TYPE); + // Find charset + shared_ptr ctf = + textPart->getHeader()->findField (fields::CONTENT_TYPE); - m_charset = ctf->getCharset(); + if (ctf) + { + try + { + m_charset = ctf->getCharset(); + } + catch (exceptions::no_such_parameter) + { + // No "charset" parameter. + } } - catch (exceptions::no_such_field) + else { // No "Content-type" field. } - catch (exceptions::no_such_parameter) - { - // No "charset" parameter. - } // 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 message, shared_ptr ctf = - part.getHeader()->findField(fields::CONTENT_TYPE); + const shared_ptr ctf = + part.getHeader()->findField(fields::CONTENT_TYPE); + if (ctf) + { const mediaType type = *ctf->getValue (); if (type.getType() == mediaTypes::MULTIPART && @@ -299,10 +291,11 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren { const shared_ptr p = part.getBody()->getPartAt(i); - try + const shared_ptr ctf = + p->getHeader()->findField(fields::CONTENT_TYPE); + + if (ctf) { - const shared_ptr ctf = - p->getHeader()->findField(fields::CONTENT_TYPE); const mediaType type = *ctf->getValue (); @@ -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. } diff --git a/src/mdn/receivedMDNInfos.cpp b/src/mdn/receivedMDNInfos.cpp index 1c523be7..53b2281e 100644 --- a/src/mdn/receivedMDNInfos.cpp +++ b/src/mdn/receivedMDNInfos.cpp @@ -110,18 +110,23 @@ void receivedMDNInfos::extract() header fields; fields.parse(oss.str()); - try { m_omid = *fields.OriginalMessageId()->getValue (); } - catch (exceptions::no_such_field&) { /* Ignore */ } + shared_ptr omid = + fields.findFieldValue (fields::ORIGINAL_MESSAGE_ID); - try { m_disp = *fields.Disposition()->getValue (); } - catch (exceptions::no_such_field&) { /* Ignore */ } + if (omid) + m_omid = *omid; - try - { - text t = *fields.findField("Received-content-MIC")->getValue (); - m_contentMIC = t.generate(); - } - catch (exceptions::no_such_field&) { /* Ignore */ } + shared_ptr disp = + fields.findFieldValue (fields::DISPOSITION); + + if (disp) + m_disp = *disp; + + shared_ptr contentMIC = + fields.findFieldValue ("Received-content-MIC"); + + if (contentMIC) + m_contentMIC = contentMIC->generate(); } } } diff --git a/src/messageParser.cpp b/src/messageParser.cpp index 41be3803..5fe219f3 100644 --- a/src/messageParser.cpp +++ b/src/messageParser.cpp @@ -63,8 +63,11 @@ void messageParser::parse(shared_ptr msg) #ifndef VMIME_BUILDING_DOC #define TRY_FIELD(var, type, name) \ - try { var = *msg->getHeader()->findField(name)->getValue (); } \ - catch (exceptions::no_such_field) { } + { \ + shared_ptr fldValue = msg->getHeader()->findFieldValue (name); \ + if (fldValue) \ + var = *fldValue; \ + } TRY_FIELD(m_from, mailbox, fields::FROM); @@ -79,22 +82,20 @@ void messageParser::parse(shared_ptr msg) #endif // VMIME_BUILDING_DOC // Date - try + shared_ptr recv = msg->getHeader()->findField(fields::RECEIVED); + + if (recv) { - const headerField& recv = *msg->getHeader()->findField(fields::RECEIVED); - m_date = recv.getValue ()->getDate(); + m_date = recv->getValue ()->getDate(); } - catch (vmime::exceptions::no_such_field&) + else { - try - { - const headerField& date = *msg->getHeader()->findField(fields::DATE); - m_date = *date.getValue (); - } - catch (vmime::exceptions::no_such_field&) - { + shared_ptr date = msg->getHeader()->findField(fields::DATE); + + if (date) + m_date = *date->getValue (); + else m_date = datetime::now(); - } } // Attachments @@ -120,13 +121,12 @@ void messageParser::findTextParts(shared_ptr msg, shared_ptr getHeader()->findField (fields::CONTENT_TYPE); + shared_ptr ctf = + msg->getHeader()->findField (fields::CONTENT_TYPE); - const mediaType ctfType = - *ctf.getValue (); + if (ctf) + { + const mediaType ctfType = *ctf->getValue (); if (ctfType.getType() == mediaTypes::TEXT) { @@ -134,7 +134,7 @@ void messageParser::findTextParts(shared_ptr msg, shared_ptr msg, shared_ptr { const shared_ptr p = part->getBody()->getPartAt(i); - try - { - const contentTypeField& ctf = - *p->getHeader()->findField (fields::CONTENT_TYPE); + shared_ptr ctf = + p->getHeader()->findField (fields::CONTENT_TYPE); - const mediaType type = *ctf.getValue (); + if (ctf) + { + const mediaType type = *ctf->getValue (); contentDisposition disp; // default should be inline if (type.getType() == mediaTypes::TEXT) { - try - { - shared_ptr cdf = p->getHeader()-> - findField (fields::CONTENT_DISPOSITION); + shared_ptr cdf = p->getHeader()-> + findField (fields::CONTENT_DISPOSITION); + if (cdf) + { disp = *cdf->getValue (); } - catch (exceptions::no_such_field&) + else { // No "Content-Disposition" field, assume default } @@ -195,7 +195,7 @@ bool messageParser::findSubTextParts(shared_ptr msg, shared_ptr textParts.push_back(p); } } - catch (exceptions::no_such_field&) + else { // No "Content-type" field. } diff --git a/src/misc/importanceHelper.cpp b/src/misc/importanceHelper.cpp index 8066cc5f..b13f7466 100644 --- a/src/misc/importanceHelper.cpp +++ b/src/misc/importanceHelper.cpp @@ -39,25 +39,13 @@ void importanceHelper::resetImportance(shared_ptr msg) void importanceHelper::resetImportanceHeader(shared_ptr
hdr) { - try - { - shared_ptr fld = hdr->findField("X-Priority"); - hdr->removeField(fld); - } - catch (exceptions::no_such_field) - { - // Ignore - } + shared_ptr fld; - try - { - shared_ptr 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 hdr) { // Try "X-Priority" field - try + shared_ptr fld = hdr->findField("X-Priority"); + + if (fld) { - const shared_ptr fld = hdr->findField("X-Priority"); const string value = fld->getValue ()->getWholeBuffer(); int n = IMPORTANCE_NORMAL; @@ -93,12 +82,13 @@ importanceHelper::Importance importanceHelper::getImportanceHeader(shared_ptr findField("Importance"); + + if (fld) { - const shared_ptr fld = hdr->findField("Importance"); const string value = utility::stringUtils::toLower(utility::stringUtils::trim (fld->getValue ()->getWholeBuffer())); @@ -109,7 +99,7 @@ importanceHelper::Importance importanceHelper::getImportanceHeader(shared_ptr msg, utility::progressListener* progress) { // Extract expeditor - mailbox expeditor; + shared_ptr fromMbox = + msg->getHeader()->findFieldValue (fields::FROM); - try - { - const mailbox& mbox = - *msg->getHeader()->findField(fields::FROM)->getValue (); - - expeditor = mbox; - } - catch (exceptions::no_such_field&) - { + if (!fromMbox) throw exceptions::no_expeditor(); - } + + mailbox expeditor = *fromMbox; // Extract sender + shared_ptr senderMbox = + msg->getHeader()->findFieldValue (fields::SENDER); + mailbox sender; - try - { - const mailbox& mbox = - *msg->getHeader()->findField(fields::SENDER)->getValue (); - - 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 (); + // -- "To" field + shared_ptr addresses = + msg->getHeader()->findFieldValue (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 (); + // -- "Cc" field + addresses = + msg->getHeader()->findFieldValue (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 (); + // -- "Bcc" field + addresses = + msg->getHeader()->findFieldValue (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 diff --git a/src/plainTextPart.cpp b/src/plainTextPart.cpp index e1959af1..bdb76c4d 100644 --- a/src/plainTextPart.cpp +++ b/src/plainTextPart.cpp @@ -75,21 +75,24 @@ void plainTextPart::parse(shared_ptr /* message */, { m_text = vmime::clone(textPart->getBody()->getContents()); - try - { - const contentTypeField& ctf = - *textPart->getHeader()->findField (fields::CONTENT_TYPE); + shared_ptr ctf = + textPart->getHeader()->findField (fields::CONTENT_TYPE); - m_charset = ctf.getCharset(); + if (ctf) + { + try + { + m_charset = ctf->getCharset(); + } + catch (exceptions::no_such_parameter&) + { + // No "charset" parameter. + } } - catch (exceptions::no_such_field&) + else { // No "Content-type" field. } - catch (exceptions::no_such_parameter&) - { - // No "charset" parameter. - } } diff --git a/tests/misc/importanceHelperTest.cpp b/tests/misc/importanceHelperTest.cpp index 9a4b86f7..53c5c679 100644 --- a/tests/misc/importanceHelperTest.cpp +++ b/tests/misc/importanceHelperTest.cpp @@ -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")); } diff --git a/vmime/header.hpp b/vmime/header.hpp index b073e8cb..96548b48 100644 --- a/vmime/header.hpp +++ b/vmime/header.hpp @@ -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 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 shared_ptr findField(const string& fieldName) const @@ -116,6 +120,26 @@ public: return dynamicCast (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 + shared_ptr findFieldValue(const string& fieldName) const + { + shared_ptr field = findField(fieldName); + + if (field) + return dynamicCast (field->getValue()); + else + return null; + } + /** Find all fields that match the specified name. * If no field is found, an empty vector is returned. *