Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web

C++ 11 S/MIME: A Simple MIME Parser and Builder with Security Features

4.90/5 (19 votes)
3 Sep 2018CPOL 42.6K   558  
Easy to use simple parser with S/MIME Support. Version 2.

Introduction

This is version 2 of my simple MIME parser and builder which uses C++ 11 elements and Win32 API for quick stuff.

For S/MIME, the library now uses my AdES.

Includes a QP decoder from here.

Single Message Builder

C++
// Single Message
MIME2::CONTENT c;

c["MIME-Version"] = "1.0";
c["Content-Type"] = "text/plain";
c.SetData("Hello");

auto str = c.SerializeToVector();

Result:

MIME-Version: 1.0
Content-Type: text/plain

Hello

Some Binary Message

C++
MIME2::CONTENT c;
c["MIME-Version"] = "1.0";
c["Content-Type"] = "application/octet-stream";
c["Content-Transfer-Encoding"] = "base64";
c["Content-Disposition"] = "attachment; filename=\"hello.txt\"";
string out = MIME2::Char2Base64("Hello", 5);
c.SetData(out.c_str());

auto str = c.SerializeToVector();

Result:

MIME-Version: 1.0
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="hello.txt"

SGVsbG8=

Multipart Builder

C++
MIME2::CONTENTBUILDER cb;
MIME2::CONTENT e1;
MIME2::CONTENT e2;
e1["Content-Type"] = "text/plain";
e1.SetData("Hello\r\n\r\n");
e2["Content-Type"] = "text/html";
e2.SetData("<b>Hello</b>");

cb.Add(e1);
cb.Add(e2);

MIME2::CONTENT cc;
cb.Build(cc, "multipart/alternative");

auto str = cc.SerializeToVector();

Result:

MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="{79EAC9E2-BAF9-11CE-8C82-00AA004BA90B}"

--{79EAC9E2-BAF9-11CE-8C82-00AA004BA90B}
Content-Type: text/plain

Hello

--{79EAC9E2-BAF9-11CE-8C82-00AA004BA90B}
Content-Type: text/html

<b>Hello</b>

--{79EAC9E2-BAF9-11CE-8C82-00AA004BA90B}--

Parse Simple

C++
string str = 
R"(MIME-Version: 1.0
Content-Type: text/plain

Hello)";

    MIME2::CONTENT c;
    if (c.Parse(str.c_str()) != MIME2::MIMEERR::OK)
        return;

    auto a1 = c.hval("Content-Type"); // a1 = "text/plain"
    auto a2 = c.GetData(); // vector<char> with the data

Parse Multiple

C++
string str = "MIME-Version: 1.0\r\n\
Content-Type: multipart/alternative; boundary=\"{79EAC9E2-BAF9-11CE-8C82-00AA004BA90B}\"\r\n\r\n\
\r\n\
--{79EAC9E2-BAF9-11CE-8C82-00AA004BA90B}\r\n\
Content-Type: text/plain\r\n\
\r\n\
Hello\r\n\
\r\n\
--{79EAC9E2-BAF9-11CE-8C82-00AA004BA90B}\r\n\
Content-Type: text/html\r\n\
\r\n\
<b>Hello</b>\r\n\
\r\n\
--{79EAC9E2-BAF9-11CE-8C82-00AA004BA90B}--";

    MIME2::CONTENT c;
    if (c.Parse(str.c_str()) != MIME2::MIMEERR::OK)
        return;

    auto a1 = c.hval("Content-Type","boundary"); // a1 = the boundary
    if (a1.empty())
        return;

    vector<MIME2::CONTENT> Contents;
    MIMELIB::ParseMultipleContent(str.c_str(), a1.c_str(), Contents);

    // Should have 2
    vector<char> d;
    Contents[1].DecodeData(d); // Decodes from Base64 or Quoted-Printable
    // d = "<b>Hello</b>"

S/MIME

For S/MIME, the library now uses AdES. You must #define MIME_CMS to use S/MIME.

C++
MIMEERR Encrypt(CONTENT& c, std::vector<PCCERT_CONTEXT> certs, bool BinaryOutput = false);
MIMEERR Decrypt(CONTENT& c);
MIMEERR Sign(CONTENT& co, std::vector<PCCERT_CONTEXT> certs,
      std::vector<PCCERT_CONTEXT> addcerts, const wchar_t* TimeStampServer = 0,
      bool Attached = true, bool BinaryOutput = false);
MIMEERR Verify(vector<PCCERT_CONTEXT>* Certs = 0, AdES::CLEVEL* plev = 0);

HTTP Support

C++
vector<char> data = "HTTP 1/1 200 OK\r\n...."
c.Parse(data.data(),true); // true indicates a possible HTTP header
auto mh = c1.httphdr();    // Gets the header

Or build:

C++
c.AddHTTPHeader("HTTP 1/1 200 OK");

Have fun with it!

History

  • 03-09-2018: Version 2, cleaner interface and S/MIME usage through AdES
  • 02-08-2016: Added binary support for all sort of operations
  • 30-07-2016: Added Timestamp support and low level functions, builder for detached signatures
  • 23-07-2016: First release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)