郵件群發廣泛應用於電子商務行銷、企業通知、資訊訂閱。本文詳述使用 C++ Builder 整合 Indy 元件套件與 Access 2000 資料庫,實作支援 SMTP/ESMTP 認證的郵件群發系統。
核心角色:SMTP 寄信機 ↔ 收信機。指令/回應模式:MAIL FROM: <addr> → 250 OK。主要指令:HELO、MAIL FROM、RCPT TO、DATA、QUIT。
防垃圾郵件需求下,幾乎所有郵件服務商要求認證。ESMTP 新增 AUTH 指令,支援機制:
認證流程:連接 → AUTH LOGIN → 伺服器回應 Base64 "Username:" → 客戶端回應 Base64 帳號 → 伺服器回應 "Password:" → 客戶端回應 Base64 密碼 → 成功進入郵件傳送階段。
TIdSMTP + TIdMessage| TIdSMTP | 說明 |
|---|---|
| Host | SMTP 伺服器位址 (如 smtp.gmail.com) |
| Port | 通常 25、465(SSL)、587(STARTTLS) |
| AuthenticationType | atLogin 等 |
| UserId / Password | 帳號密碼 |
| Connect() / Disconnect() | 建立/關閉會話 |
| Send(TIdMessage*) | 發送郵件 |
| TIdMessage | 說明 |
|---|---|
| ContentType | 如 "text/html" (關鍵!否則正文變附件) |
| Subject | 主旨 |
| Body | 正文內容 |
| From->Name | 寄件人顯示名稱 |
| Recipients->EmailAddresses | 收件人清單 |
void __fastcall TForm1::N_OpenClick(TObject *Sender) {
AnsiString ConnStr;
try {
ADOTable1->Active = false;
OpenDialog1->InitialDir = ".\\";
OpenDialog1->Filter = "MDB檔案 (*.mdb)|*.mdb|所有檔案 (*.*)|*.*";
OpenDialog1->DefaultExt = "mdb";
if (OpenDialog1->Execute()) {
// 必須包含 Jet OLEDB:Database Password 與 Persist Security Info
ConnStr = "Provider=Microsoft.Jet.OLEDB.4.0; "
"Jet OLEDB:Database Password=" + MaskEdit1->Text.Trim() + "; "
"Data Source=" + OpenDialog1->FileName.Trim() + "; "
"Persist Security Info=True";
ADOTable1->ConnectionString = ConnStr.Trim();
ADOTable1->Active = true;
}
} catch (Exception &e) {
Application->ShowException(&e);
}
}
關鍵點:有密碼的 MDB 必須獨佔模式開啟,Persist Security Info=True 為必需。
void __fastcall TForm1::SEND_BTNClick(TObject *Sender) {
int recnum, k; AnsiString addr;
IdSMTP1->Host = ComboBoxaddr->Text.Trim();
IdSMTP1->Port = 25;
if (CheckBox_AUTH->Checked) {
IdSMTP1->AuthenticationType = atLogin;
IdSMTP1->UserId = Edit_name->Text.Trim();
IdSMTP1->Password = MaskEdit_pass->Text.Trim();
}
IdMessage1->ContentType = "text/html"; // 必須設定!
IdMessage1->Subject = Edit3->Text.Trim();
// ... 設定 Body、From 等 ...
ADOTable1->First();
recnum = ADOTable1->RecordCount;
for (k = 0; k <= recnum - 1; k++) {
addr = Trim(ADOTable1->FieldByName("Email")->AsString);
IdMessage1->Recipients->EmailAddresses = addr;
if (!IdSMTP1->Connected()) {
try { IdSMTP1->Connect(); }
catch (Exception &e) {
Application->MessageBox(e.Message.c_str(), "連接失敗", MB_ICONWARNING);
continue;
}
}
if (IdSMTP1->Connected()) {
try { IdSMTP1->Send(IdMessage1); }
catch (Exception &e) {
Application->MessageBox(e.Message.c_str(), "發送失敗", MB_ICONWARNING);
}
}
ADOTable1->Next();
}
Application->MessageBox("發送完成!", "郵件系統", MB_OK);
}
RCPT TO 多位址(逗號分隔)LOGIN 機制 Base64 非加密,生產環境建議:
TIdSSLIOHandlerSocketOpenSSL)