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

View File

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

View File

@ -36,20 +36,18 @@ bodyPartAttachment::bodyPartAttachment(shared_ptr <const bodyPart> part)
const mediaType bodyPartAttachment::getType() const 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". // No "Content-type" field: assume "application/octet-stream".
type = mediaType(mediaTypes::APPLICATION, return mediaType(mediaTypes::APPLICATION,
mediaTypes::APPLICATION_OCTET_STREAM); mediaTypes::APPLICATION_OCTET_STREAM);
} }
return type;
} }
@ -58,37 +56,47 @@ const word bodyPartAttachment::getName() const
word name; word name;
// Try the 'filename' parameter of 'Content-Disposition' field // Try the 'filename' parameter of 'Content-Disposition' field
try shared_ptr <const contentDispositionField> 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 // No 'Content-Disposition' field
} }
catch (exceptions::no_such_parameter&)
{
// No 'filename' parameter
}
// Try the 'name' parameter of 'Content-Type' field // Try the 'name' parameter of 'Content-Type' field
if (name.getBuffer().empty()) if (name.getBuffer().empty())
{ {
try shared_ptr <const contentTypeField> ctf = getContentType();
{
shared_ptr <parameter> prm = getContentType()->findParameter("name");
if (prm != NULL) if (ctf)
name = prm->getValue(); {
try
{
shared_ptr <const parameter> 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 // No 'Content-Type' field
} }
catch (exceptions::no_such_parameter&)
{
// No attachment name available
}
} }
return name; return name;
@ -99,14 +107,14 @@ const text bodyPartAttachment::getDescription() const
{ {
text description; text description;
try shared_ptr <const headerField> cd =
{ getHeader()->findField(fields::CONTENT_DESCRIPTION);
shared_ptr <const headerField> cd =
getHeader()->findField(fields::CONTENT_DESCRIPTION);
if (cd)
{
description = *cd->getValue <text>(); description = *cd->getValue <text>();
} }
catch (exceptions::no_such_field&) else
{ {
// No description available. // 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 // No field with this name can be found
if (pos == m_fields.end()) if (pos == m_fields.end())
{ return null;
throw exceptions::no_such_field();
}
// Else, return a reference to the existing field // Else, return a reference to the existing field
else return (*pos);
{
return (*pos);
}
} }

View File

@ -135,27 +135,13 @@ void htmlTextPart::findEmbeddedParts(const bodyPart& part,
{ {
shared_ptr <const bodyPart> p = part.getBody()->getPartAt(i); 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. // Content-Id field or a Content-Location field.
try if (p->getHeader()->hasField(fields::CONTENT_ID))
{
p->getHeader()->findField(fields::CONTENT_ID);
cidParts.push_back(p); cidParts.push_back(p);
}
catch (exceptions::no_such_field)
{
// No "Content-id" field.
}
try if (p->getHeader()->hasField(fields::CONTENT_LOCATION))
{
p->getHeader()->findField(fields::CONTENT_LOCATION);
locParts.push_back(p); locParts.push_back(p);
}
catch (exceptions::no_such_field)
{
// No "Content-Location" field.
}
findEmbeddedParts(*p, cidParts, locParts); findEmbeddedParts(*p, cidParts, locParts);
} }
@ -172,12 +158,14 @@ void htmlTextPart::addEmbeddedObject(const bodyPart& part, const string& id,
mediaType type; 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>(); type = *ctf->getValue <mediaType>();
} }
catch (exceptions::no_such_field) else
{ {
// No "Content-type" field: assume "application/octet-stream". // 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(); m_text = textPart->getBody()->getContents()->clone();
try // Find charset
{ shared_ptr <const contentTypeField> ctf =
const shared_ptr <const contentTypeField> ctf = textPart->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
textPart->getHeader()->findField <contentTypeField>(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. // No "Content-type" field.
} }
catch (exceptions::no_such_parameter)
{
// No "charset" parameter.
}
// Extract embedded objects. The algorithm is quite simple: for each previously // 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. // 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) bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& parent, const bodyPart& textPart)
{ {
// We search for the nearest "multipart/alternative" part. // We search for the nearest "multipart/alternative" part.
try const shared_ptr <const headerField> ctf =
{ part.getHeader()->findField(fields::CONTENT_TYPE);
const shared_ptr <const headerField> ctf =
part.getHeader()->findField(fields::CONTENT_TYPE);
if (ctf)
{
const mediaType type = *ctf->getValue <mediaType>(); const mediaType type = *ctf->getValue <mediaType>();
if (type.getType() == mediaTypes::MULTIPART && if (type.getType() == mediaTypes::MULTIPART &&
@ -299,10 +291,11 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
{ {
const shared_ptr <const bodyPart> p = part.getBody()->getPartAt(i); 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 shared_ptr <const headerField> ctf =
p->getHeader()->findField(fields::CONTENT_TYPE);
const mediaType type = *ctf->getValue <mediaType>(); const mediaType type = *ctf->getValue <mediaType>();
@ -313,7 +306,7 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
found = true; found = true;
} }
} }
catch (exceptions::no_such_field) else
{ {
// No "Content-type" field. // 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. // No "Content-type" field.
} }

View File

@ -110,18 +110,23 @@ void receivedMDNInfos::extract()
header fields; header fields;
fields.parse(oss.str()); fields.parse(oss.str());
try { m_omid = *fields.OriginalMessageId()->getValue <messageId>(); } shared_ptr <messageId> omid =
catch (exceptions::no_such_field&) { /* Ignore */ } fields.findFieldValue <messageId>(fields::ORIGINAL_MESSAGE_ID);
try { m_disp = *fields.Disposition()->getValue <disposition>(); } if (omid)
catch (exceptions::no_such_field&) { /* Ignore */ } m_omid = *omid;
try shared_ptr <disposition> disp =
{ fields.findFieldValue <disposition>(fields::DISPOSITION);
text t = *fields.findField("Received-content-MIC")->getValue <text>();
m_contentMIC = t.generate(); if (disp)
} m_disp = *disp;
catch (exceptions::no_such_field&) { /* Ignore */ }
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 #ifndef VMIME_BUILDING_DOC
#define TRY_FIELD(var, type, name) \ #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); TRY_FIELD(m_from, mailbox, fields::FROM);
@ -79,22 +82,20 @@ void messageParser::parse(shared_ptr <const message> msg)
#endif // VMIME_BUILDING_DOC #endif // VMIME_BUILDING_DOC
// Date // 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&) else
{ {
try shared_ptr <const headerField> date = msg->getHeader()->findField(fields::DATE);
{
const headerField& date = *msg->getHeader()->findField(fields::DATE); if (date)
m_date = *date.getValue <datetime>(); m_date = *date->getValue <datetime>();
} else
catch (vmime::exceptions::no_such_field&)
{
m_date = datetime::now(); m_date = datetime::now();
}
} }
// Attachments // Attachments
@ -120,13 +121,12 @@ void messageParser::findTextParts(shared_ptr <const bodyPart> msg, shared_ptr <c
mediaType type(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN); mediaType type(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN);
bool accept = false; bool accept = false;
try shared_ptr <const contentTypeField> ctf =
{ msg->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
const contentTypeField& ctf =
*msg->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
const mediaType ctfType = if (ctf)
*ctf.getValue <mediaType>(); {
const mediaType ctfType = *ctf->getValue <mediaType>();
if (ctfType.getType() == mediaTypes::TEXT) if (ctfType.getType() == mediaTypes::TEXT)
{ {
@ -134,7 +134,7 @@ void messageParser::findTextParts(shared_ptr <const bodyPart> msg, shared_ptr <c
accept = true; accept = true;
} }
} }
catch (exceptions::no_such_field&) else
{ {
// No "Content-type" field: assume "text/plain". // No "Content-type" field: assume "text/plain".
accept = true; 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); const shared_ptr <const bodyPart> p = part->getBody()->getPartAt(i);
try shared_ptr <const contentTypeField> ctf =
{ p->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
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 contentDisposition disp; // default should be inline
if (type.getType() == mediaTypes::TEXT) if (type.getType() == mediaTypes::TEXT)
{ {
try shared_ptr <const contentDispositionField> cdf = p->getHeader()->
{ findField <contentDispositionField>(fields::CONTENT_DISPOSITION);
shared_ptr <const contentDispositionField> cdf = p->getHeader()->
findField <contentDispositionField>(fields::CONTENT_DISPOSITION);
if (cdf)
{
disp = *cdf->getValue <contentDisposition>(); disp = *cdf->getValue <contentDisposition>();
} }
catch (exceptions::no_such_field&) else
{ {
// No "Content-Disposition" field, assume default // No "Content-Disposition" field, assume default
} }
@ -195,7 +195,7 @@ bool messageParser::findSubTextParts(shared_ptr <const bodyPart> msg, shared_ptr
textParts.push_back(p); textParts.push_back(p);
} }
} }
catch (exceptions::no_such_field&) else
{ {
// No "Content-type" field. // No "Content-type" field.
} }

View File

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

View File

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

View File

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

View File

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