Introduction
There are already other articles here on The Code Project that shows how to decode Base64 and Quoted-Printable, but they all use MFC. I needed some code that didn't use MFC, so I wrote AMMimeUtils.
I wrote these classes because I was working with receiving and sending emails and Usenet messages. Almost all email messages and attachments are either Base64 or Quoted-Printable encoded. Attachments in Usenet messages are often UU encoded, I still need to write a class to handle this, but it might come in a later version.
When you get an email, the subject and other header fields might also be encoded, so this code also includes some code to decode these fields. Different mail programs encode the subject in different ways. The following text:
Just a small text (for demo), and some more text...
can look both like
=?iso-8859-1?Q?Just a small text =28for demo=29, and some more text...?=
or like
Just a small text =?iso-8859-1?Q?=28for demo=29?=, and some more text...
The first line is easy, because we can see that the entire string is encoded with Quoted-Printable (the ?Q? part means Quoted-Printable). In the second string, it's only a part of it that's encoded, so we have to get the first non-encoded part, decode the encoded part, and get the last non-encoded part, and add the 3 parts together to get the final subject.
I made a function char* MimeDecodeMailHeaderField(char *s);
to handle this. If you have a string called s
containing the subject you want to decode, simply call it like this:
s = MimeDecodeMailHeaderField(s);
Now s
contains the decoded text.
I have 2 classes CBase64Utils
and CQPUtils
for general encoding and decoding of Base64 and Quoted-Printable. The interface looks like:
class CBase64Utils
{
private:
int ErrorCode;
public:
int GetLastError() {return ErrorCode;};
CBase64Utils();
~CBase64Utils();
char* Decode(char *input, int *bufsize);
char* Encode(char *input, int bufsize);
};
class CQPUtils
{
private:
char* ExpandBuffer(char *buffer, int UsedSize,
int *BufSize, bool SingleChar = true);
int ErrorCode;
public:
int GetLastError() {return ErrorCode;};
char* Decode(char *input);
char* Encode(char *input);
CQPUtils();
~CQPUtils();
};
The only difference is the Decode()
and Encode()
functions. Quoted-Printable is always text, therefore it only takes one parameter, the string containing encoded text, and returns a pointer to a new buffer containing the decoded text. Base64 might be an encoded binary file, so it puts the length of the returned buffer in the bufsize
variable. Then it's possible to save the decoded buffer as a binary file.
Both classes have a function GetLastError()
, if you decode something, and this variable is zero, everything is fine, if it's non-zero there was an error in the input, but you still get the (maybe) encoded/decoded result.
Right now, this code only has functions for what I needed when I wrote it. In the future, it I might add some better error handling.
If you want to know more about MIME and email messages, you can take a look at:
- RFC 2045 - Multipurpose Internet Mail Extensions (MIME) Part One, Format of Internet Message Bodies
- RFC 2046 - Multipurpose Internet Mail Extensions (MIME) Part Two, Format of Internet Message Bodies
- RFC 2044 - Multipurpose Internet Mail Extensions (MIME) Part Three, Format of Internet Message Bodies
- RFC 822 - STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES