delphi - 简单的 MIME Base64 解码器

标签 delphi email base64 mime thunderbird

我正在寻找一种简单的方法,不需要使用 Indy 之类的东西来解码包含 Thunderbird 消息内容的 Base64。

示例:

WW91ciBtZXNzYWdlDQoNCiAgVG86ICAgICAgeHh4QHh4eC5jb20NCiAgU3ViamVjdDogSXh4eA0KICBTZW50OiAgICBUaHUsIDIyIE9jdCAyMDA5IDAxOjE0OjM0IC0wNDAwDQoNCmRpZCBub3QgcmVhY2ggdGhlIGZvbGxvd2luZyByZWNpcGllbnQocyk6DQoNCnh4eEBneHh4IG9uIFR1ZSwgMjcgT2N0IDIwMDkgMDE6NDA6NDQgLTA0MDANCiAgICBUaGUgZS1tYWlsIHN5c3RlbSB3YXMgdW5hYmxlIHRvIGRlbGl2ZXIgdGhlIG1lc3NhZ2UsIGJ1dCBkaWQgbm90DQpyZXBvcnQgYSBzcGVjaWZpYyByZWFzb24uICBDaGVjayB0aGUgYWRkcmVzcyBhbmQgdHJ5IGFnYWluLiAgSWYgaXQgc3RpbGwNCmZhaWxzLCBjb250YWN0IHlvdXIgc3lzdGVtIGFkbWluaXN0cmF0b3IuDQogICAgPCBDaW54eHguY29tICM1LjAuMCBzbXRwOyA1LjQuNyAtIERlbGl2ZXJ5IGV4cGlyZWQNCihtZXNzYWdlIHRvbyBvbGQpICd0aW1lb3V0JyAoZGVsaXZlcnkgYXR0ZW1wdHM6IDApPg==

变成: 您的留言

  To:      xxx@xxx.com
  Subject: Ixxx
  Sent:    Thu, 22 Oct 2009 01:14:34 -0400

did not reach the following recipient(s):

xxx@gxxx on Tue, 27 Oct 2009 01:40:44 -0400
    The e-mail system was unable to deliver the message, but did not
report a specific reason.  Check the address and try again.  If it still
fails, contact your system administrator.
    < Cinxxx.com #5.0.0 smtp; 5.4.7 - Delivery expired
(message too old) 'timeout' (delivery attempts: 0)>

编辑:MIME Base64 行的最大长度似乎是 76。我必须解码每个 76 位长的行,而不是一次解码整个消息。谢谢。

最佳答案

自 Delphi 6 起,Delphi 已包含 EncdDecd 单元,其中包含 DecodeString函数将包含 base64 文本的 Input 字符串解码为包含实际解码数据(可能是二进制)的 Result 字符串:

function DecodeString(const Input: string): string;

自 Delphi 2009 以来,它还包括 DecodeBase64Input AnsiString 解码为 TBytes 的二进制 Result 的函数:

function  DecodeBase64(const Input: AnsiString): TBytes;

除了 earlier Delphi/PHP base64 answer我现在编写了一个小型单元测试,显示 DecodeString 和 EncodeString 如何工作:

unit Base64TestCaseUnit;

interface

uses
  Classes, SysUtils, TestFrameWork, Generics.Collections;

{
 base64 test vectors: http://tools.ietf.org/html/rfc4648
   BASE64("") = ""
   BASE64("f") = "Zg=="
   BASE64("fo") = "Zm8="
   BASE64("foo") = "Zm9v"
   BASE64("foob") = "Zm9vYg=="
   BASE64("fooba") = "Zm9vYmE="
   BASE64("foobar") = "Zm9vYmFy"
}
const
  Key_ = '';
  Value_ = '';
  Key_f = 'f';
  Value_f = 'Zg==';
  Key_fo = 'fo';
  Value_fo = 'Zm8=';
  Key_foo = 'foo';
  Value_foo = 'Zm9v';
  Key_foob = 'foob';
  Value_foob = 'Zm9vYg==';
  Key_fooba = 'fooba';
  Value_fooba = 'Zm9vYmE=';
  Key_foobar = 'foobar';
  Value_foobar = 'Zm9vYmFy';
// binary test vector
  Key_binary = #1#2#3#4;
  Value_binary = 'AQIDBA==';

type
  TStringStringDictionary = TDictionary<string, string>;
  TBase64TestCase = class(TTestCase)
  strict private
    FBase64VectorsDictionary: TStringStringDictionary;
  strict protected
    procedure DecodeTestOneKey(const ExpectedKey: string); virtual;
    procedure EncodeTestOneKey(const ActualKey: string); virtual;
    property Base64VectorsDictionary: TStringStringDictionary read FBase64VectorsDictionary;
  protected
    procedure SetUp; override;
    procedure TearDown; override;
  published
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_DecodeString_Test_;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_DecodeString_Test_binary;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_DecodeString_Test_f;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_DecodeString_Test_fo;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_DecodeString_Test_foo;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_DecodeString_Test_foob;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_DecodeString_Test_fooba;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_DecodeString_Test_foobar;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_EncodeString_Test_;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_EncodeString_Test_binary;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_EncodeString_Test_f;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_EncodeString_Test_fo;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_EncodeString_Test_foo;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_EncodeString_Test_foob;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_EncodeString_Test_fooba;
    {$IFDEF CLR}[Test]{$ENDIF}
    procedure Base64_EncodeString_Test_foobar;
  end;

implementation

uses
  EncdDecd;

procedure TBase64TestCase.Base64_DecodeString_Test_;
begin
  DecodeTestOneKey(Key_);
end;

procedure TBase64TestCase.Base64_DecodeString_Test_binary;
begin
  DecodeTestOneKey(Key_binary);
end;

procedure TBase64TestCase.Base64_DecodeString_Test_f;
begin
  DecodeTestOneKey(Key_f);
end;

procedure TBase64TestCase.Base64_DecodeString_Test_fo;
begin
  DecodeTestOneKey(Key_fo);
end;

procedure TBase64TestCase.Base64_DecodeString_Test_foo;
begin
  DecodeTestOneKey(Key_foo);
end;

procedure TBase64TestCase.Base64_DecodeString_Test_foob;
begin
  DecodeTestOneKey(Key_foob);
end;

procedure TBase64TestCase.Base64_DecodeString_Test_fooba;
begin
  DecodeTestOneKey(Key_fooba);
end;

procedure TBase64TestCase.Base64_DecodeString_Test_foobar;
begin
  DecodeTestOneKey(Key_foobar);
end;

procedure TBase64TestCase.SetUp;
begin
  FBase64VectorsDictionary := TStringStringDictionary.Create();
  FBase64VectorsDictionary.Add(Key_, Value_);
  FBase64VectorsDictionary.Add(Key_f, Value_f);
  FBase64VectorsDictionary.Add(Key_fo, Value_fo);
  FBase64VectorsDictionary.Add(Key_foo, Value_foo);
  FBase64VectorsDictionary.Add(Key_foob, Value_foob);
  FBase64VectorsDictionary.Add(Key_fooba, Value_fooba);
  FBase64VectorsDictionary.Add(Key_foobar, Value_foobar);
  FBase64VectorsDictionary.Add(Key_binary, Value_binary);
end;

procedure TBase64TestCase.TearDown;
begin
  FBase64VectorsDictionary.Free();
  FBase64VectorsDictionary := nil;
end;

procedure TBase64TestCase.Base64_EncodeString_Test_;
begin
  EncodeTestOneKey(Key_);
end;

procedure TBase64TestCase.Base64_EncodeString_Test_binary;
begin
  EncodeTestOneKey(Key_binary);
end;

procedure TBase64TestCase.Base64_EncodeString_Test_f;
begin
  EncodeTestOneKey(Key_f);
end;

procedure TBase64TestCase.Base64_EncodeString_Test_fo;
begin
  EncodeTestOneKey(Key_fo);
end;

procedure TBase64TestCase.Base64_EncodeString_Test_foo;
begin
  EncodeTestOneKey(Key_foo);
end;

procedure TBase64TestCase.Base64_EncodeString_Test_foob;
begin
  EncodeTestOneKey(Key_foob);
end;

procedure TBase64TestCase.Base64_EncodeString_Test_fooba;
begin
  EncodeTestOneKey(Key_fooba);
end;

procedure TBase64TestCase.Base64_EncodeString_Test_foobar;
begin
  EncodeTestOneKey(Key_foobar);
end;

procedure TBase64TestCase.DecodeTestOneKey(const ExpectedKey: string);
var
  ActualKey: string;
  ExpectedValue: string;
begin
  ExpectedValue := FBase64VectorsDictionary[ExpectedKey];
  ActualKey := DecodeString(ExpectedValue);
  Self.CheckEquals(ExpectedKey, ActualKey, Format('base64 decode of "%s" should be "%s"', [ExpectedValue, ExpectedKey]));
end;

procedure TBase64TestCase.EncodeTestOneKey(const ActualKey: string);
var
  ActualValue: string;
  ExpectedValue: string;
begin
  ExpectedValue := FBase64VectorsDictionary[ActualKey];
  ActualValue := EncodeString(ActualKey);
  Self.CheckEquals(ExpectedValue, ActualValue, Format('base64 of "%s" should be "%s"', [ActualKey, ExpectedValue]));
end;

initialization
  RegisterTest('', TBase64TestCase.Suite);
end.

关于delphi - 简单的 MIME Base64 解码器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6655056/

相关文章:

node.js - 将数据 URI 保存为图像?

linux - 我如何将我的 Windows 程序编译成与 Wine 一起运行的单个 Linux 二进制文件?

php - php 中的安全和 mail() 函数

email - 在 Laravel 中发送邮件时缺少 Illuminate\Support\Manager::createDriver() 的参数 1

php - Wp_mail 不适用于 css 类

node.js - 将 PGP 加密的二进制文件编码为 NodeJS 的 Base64

sorting - 如何对字符串列表中的数字进行排序?

delphi - 为什么@运算符返回的地址与GetProcAddress函数返回的地址不同

Delphi 7 - 如何使用标题从 ListView 中删除项目

C# AES Base64 加密(字符串)