為抑制垃圾郵件,主流郵件伺服器(網易、新浪等)均要求發信端進行身份驗證。BCB 6 自帶的 NMSMTP 控件雖簡單易用,但不支援 AUTH LOGIN 機制,導致無法直接用於需驗證的伺服器。
C: AUTH LOGIN
S: 334 dXNlcm5hbWU6 (Base64 "username:")
C: d3lxX2puX3NkX2Nu (Base64 用戶名)
S: 334 UGFzc3dvcmQ6 (Base64 "password:")
C: ******** (Base64 密碼)
S: 235 Authentication successful
核心點:所有認證數據均為 Base64 編碼,狀態碼 334 表示繼續,235 表示成功。
NMSMTP1->Connect() 建立 TCP 連線。OnConnect 事件中,利用繼承自 TPowerSocket 的 SendBuffer/Read/DataAvailable 手工完成 AUTH 交互。AnsiString TForm1::encode(AnsiString s) {
const char* table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int len = s.Length();
char* src = s.c_str();
AnsiString out;
for(int i=0; i<len-len%3; i+=3) {
out += table[src[i]>>2];
out += table[((src[i]&3)<<4) | (src[i+1]>>4)];
out += table[((src[i+1]&15)<<2) | (src[i+2]>>6)];
out += table[src[i+2]&63];
}
// 處理剩餘 1/2 字節,補 '='
// ...(完整代碼見原文)
return out;
}
void __fastcall TForm1::NMSMTP1Connect(TObject *Sender) {
AnsiString cmd, resp;
// 1. 發送 AUTH LOGIN
cmd = "AUTH LOGIN "; NMSMTP1->SendBuffer(...);
resp = WaitForReply(5);
if(resp.SubString(1,3)!="334") { Fail(); return; }
// 2. 發送用戶名
cmd = encode(Edit4->Text) + " "; NMSMTP1->SendBuffer(...);
resp = WaitForReply(5);
if(resp.SubString(1,3)!="334") { Fail(); return; }
// 3. 發送密碼
cmd = encode(Edit5->Text) + " "; NMSMTP1->SendBuffer(...);
resp = WaitForReply(5);
if(resp.SubString(1,3)!="235") { Fail(); return; }
// 成功
SendMail->Enabled = true;
}
在 Windows 2000 + BCB 6.0 環境下,分別測試網易、新浪郵箱,均能完成身份驗證並正常發送郵件。