Program: Processing a Multipart MIME Message
Example 31 uses the MIME package to process a multipart MIME message and print the component parts to standard output. The message this program contains is essentially identical to the message created in
Example 29. Although we’ve kept the example simple for demonstration purposes, notice that a recursive approach to processing MIME parts works well for multipart messages. Source for this program is in
MultipartMimeMessageDecomposition.cpp in the
examples\mime directory.
NOTE: Sample programs are located in the examples directory created for your installation. For more information, see Installing and Building Your SourcePro Products and Building Your Applications.
Example 31 – Processing a multipart MIME message
#include <rw/mime/RWMimePart.h>
#includwe <rw/mime/RWMimeMultipart.h>
#include <rw/mime/RWMimeContentTransferEncodingHeader.h>
#include <rw/mime/RWMimeParseError.h>
#include <rw/mime/RWMimeUtils.h>
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
// This is roughly equivalent to the message generated in
// the BasicMimeMessageComposition example.
const RWCString messageStr(
"MIME-Version: 1.0\r\n"
"To: <developer@yourcompany.com>\r\n"
"From: <developer@roguewave.com>\r\n"
"Subject: Sample MIME Multipart Message from Rogue Wave\r\n"
"Content-Type: multipart/mixed; \r\n"
" boundary=\"_=_next_part_279429471_=_\"\r\n"
"\r\n"
"This is a MIME 1.0 compliant message.\r\n"
"\r\n"
"If you are able to see this message, your\r\n"
"user agent is not MIME compliant. You will\r\n"
"need an alternative mail viewer to read this\r\n"
"message in its entirety.\r\n"
"\r\n"
"--_=_next_part_279429471_=_\r\n"
"Content-Type: text/plain\r\n"
"\r\n"
"This is a part in a (multipart) message generated with the Rogue Wave "
"SourcePro Net product.\r\n"
"\r\n"
"All of the parts of this message are identical, however they've been "
"encoded for transport using different methods.\r\n"
"\r\n"
"--_=_next_part_279429471_=_\r\n"
"Content-Type: text/plain\r\n"
"Content-Transfer-Encoding: base64\r\n"
"\r\n"
"VGhpcyBpcyBhIHBhcnQgaW4gYSAobXVsdGlwYXJ0KSBtZXNzYWdlIGdlbmVyYXRlZCB3aXRo\r\n"
"IHRoZSBSb2d1ZSBXYXZlIFNvdXJjZVBybyBOZXQgcHJvZHVjdC4NCg0KQWxsIG9mIHRoZSBw\r\n"
"YXJ0cyBvZiB0aGlzIG1lc3NhZ2UgYXJlIGlkZW50aWNhbCwgaG93ZXZlciB0aGV5J3ZlIGJl\r\n"
"ZW4gZW5jb2RlZCBmb3IgdHJhbnNwb3J0IHVzaW5nIGRpZmZlcmVudCBtZXRob2RzLg0K\r\n"
"--_=_next_part_279429471_=_\r\n"
"Content-Type: text/plain\r\n"
"Content-Transfer-Encoding: quoted-printable\r\n"
"\r\n"
"This is a part in a (multipart) message generated with the Rogue Wave Sour=\r\n"
"cePro Net product.\r\n"
"\r\n"
"All of the parts of this message are identical, however they've been encod=\r\n"
"ed for transport using different methods.\r\n"
"\r\n"
"--_=_next_part_279429471_=_--\r\n"); //1
void decomposePart(const RWMimePart& part, const RWCString& indent = "");
{
cout << indent << "MIME Message Extraction" << endl << endl;
// Show header information for the part.
cout << indent << "...Headers" << endl << endl;
for (size_t pos = 0; pos < part.getHeaderCount(); ++pos) //3
{
RWMimeHeader header = part.getHeader(pos); //4
cout << indent << header.asString() << endl; //5
}
// Check and see if this is a multipart part, if it is, then
// we'll break it apart, decode, and show the contents of
// each part separately.
if (part.isMultipart()) //6
{
// It is a multipart, extract each part, and pass it to
// this function to be printed to the screen.
cout << indent << "EXTRACTING MULTIPART BODY" << endl;
RWMimeMultipart multipart = part; //7
for (size_t pos = 0; pos < multipart.getPartCount(); ++pos) //8
{
cout << endl << indent << "Extracting Part " << pos+1 << " (of "
<< multipart.getPartCount() << ")..." << endl << endl;
decomposePart(multipart.getPart(pos), indent+" "); //9
}
}
else
{
RWCString body = part.getBody(); //10
// Decode the body of the part (if it's encoded) if it
// isn't, then we can assume that it is already in 7-bit
// text.
size_t pos =
part.findHeader(RWMimeContentTransferEncodingHeader::Label); //11
if (pos != RW_NPOS)
{
// The part is encoded. Let's decode it.
try
{
RWMimeContentTransferEncodingHeader header =
part.getHeader(pos); //12
body = RWMimeUtils::decode(body, header.getEncoding()); //13
}
catch(const RWMimeParseError& error)
{
cerr << endl << indent << RWCString("[ERROR] ")+error.why() << endl;
}
}
// Convert trailing CRLF characters to local new line
// conventions (and add an indention for output purposes.)
RWCString linebreak = RWCString("\n")+indent;
body = RWMimeUtils::replaceLineDelimiter(body, linebreak); //14
// Display the body of the part.
cout << endl << indent << "...Body" << endl << endl << indent<< body
<< endl; //15
}
}
int main(void)
{
// Create a RWMimePart object.
RWMimePart message;
// Extract the message from the string.
message.fromString(messageStr);
decomposePart(message);
return 0;
}
This program produces the following output (note that the longer lines are wrapped here):
MIME Message Extraction
...Headers
MIME-Version: 1.0
To: <developer@yourcompany.com>
From: <developer@roguewave.com>
Subject: Sample MIME Multipart Message from Rogue Wave
Content-Type: multipart/mixed; boundary="_=_next_part_279429471_=_"
EXTRACTING MULTIPART BODY
Extracting Part 1 (of 3)...
MIME Message Extraction
...Headers
Content-Type: text/plain
...Body
This is a part in a (multipart) message generated with the Rogue Wave
SourcePro Net product.
All of the parts of this message are identical, however they've been
encoded for transport using different methods.
Extracting Part 2 (of 3)...
MIME Message Extraction
...Headers
Content-Type: text/plain
Content-Transfer-Encoding: base64
...Body
This is a part in a (multipart) message generated with the Rogue Wave
SourcePro Net product.
All of the parts of this message are identical, however they've been
encoded for transport using different methods.
Extracting Part 3 (of 3)...
MIME Message Extraction
...Headers
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable
...Body
This is a part in a (multipart) message generated with the Rogue Wave
SourcePro Net product.
All of the parts of this message are identical, however they've been
encoded for transport using different methods.