65.9K
CodeProject 正在变化。 阅读更多。
Home

AMMimeUtils

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.24/5 (10投票s)

2001年3月23日

viewsIcon

142767

downloadIcon

1587

一篇文章,介绍如何在不使用 MFC 的情况下解码 Base64 和 Quoted-Printable 文本。

引言

The Code Project 上已经有其他文章介绍了如何解码 Base64 和 Quoted-Printable,但它们都使用了 MFC。我需要一些不使用 MFC 的代码,所以我编写了 AMMimeUtils。

我编写这些类是因为我正在处理接收和发送电子邮件和 Usenet 消息。几乎所有的电子邮件消息和附件都经过 Base64 或 Quoted-Printable 编码。Usenet 消息中的附件通常使用 UU 编码,我还需要编写一个类来处理它,但这可能会在后续版本中实现。

当你收到电子邮件时,主题和其他头部字段也可能被编码,因此这段代码还包含一些用于解码这些字段的代码。不同的邮件程序以不同的方式编码主题。以下文本

Just a small text (for demo), and some more text...

可能看起来像

=?iso-8859-1?Q?Just a small text =28for demo=29, and some more text...?=

或者像

Just a small text =?iso-8859-1?Q?=28for demo=29?=, and some more text...

第一行很容易,因为我们可以看到整个字符串都使用 Quoted-Printable 编码(?Q? 部分表示 Quoted-Printable)。在第二行字符串中,只有一部分被编码,所以我们必须获取第一个未编码的部分,解码编码的部分,并获取最后一个未编码的部分,然后将这 3 个部分加在一起以获得最终的主题。

我创建了一个函数 char* MimeDecodeMailHeaderField(char *s); 来处理这个问题。如果你有一个名为 s 的字符串,包含你要解码的主题,只需像这样调用它

s = MimeDecodeMailHeaderField(s);

现在 s 包含了解码后的文本。

我有 2 个类 CBase64UtilsCQPUtils,用于 Base64 和 Quoted-Printable 的通用编码和解码。接口如下所示

//class to handle all base64 stuff...
class CBase64Utils
{
private:
  int ErrorCode;
public:
  int GetLastError() {return ErrorCode;};
  CBase64Utils();
  ~CBase64Utils();
  //caller must free the result, bufsize holds the decoded length
  char* Decode(char *input, int *bufsize);
  //caller must free the result, bufsize is the length of the input buffer
  char* Encode(char *input, int bufsize);
};

//class to handle quoted-printable stuff
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); //caller must free the result
  char* Encode(char *input); //caller must free the result
  CQPUtils();
  ~CQPUtils();
};

唯一的区别是 Decode()Encode() 函数。Quoted-Printable 始终是文本,因此它只接受一个参数,包含编码文本的字符串,并返回一个指向包含解码文本的新缓冲区的指针。Base64 可能是编码的二进制文件,因此它将返回缓冲区的长度放入 bufsize 变量中。然后可以将解码后的缓冲区保存为二进制文件。

如果解码某些内容,并且该变量为零,则一切正常,如果非零,则输入中存在错误,但你仍然会获得(可能)编码/解码的结果,两个类都有一个函数 GetLastError()

现在,这段代码只有在我编写它时需要的功能。将来,我可能会添加一些更好的错误处理。

如果你想了解更多关于 MIME 和电子邮件消息的信息,你可以查看

  • RFC 2045 - 多用途互联网邮件扩展 (MIME) 第一部分,互联网消息主体的格式
  • RFC 2046 - 多用途互联网邮件扩展 (MIME) 第二部分,互联网消息主体的格式
  • RFC 2044 - 多用途互联网邮件扩展 (MIME) 第三部分,互联网消息主体的格式
  • RFC 822 - ARPA 互联网文本消息格式标准
© . All rights reserved.