利用 C++Builder 內建的 NMPOP3 元件 (屬於 Indy / NetMasters 套件),可快速建構功能完整的 POP3 郵件接收客戶端。本文提供從介面設計、元件配置、核心事件處理到進階功能 (附件、刪除、列表) 的完整實作指南。
| 分頁 | 元件 | Name | 關鍵屬性/用途 |
|---|---|---|---|
| 分頁 1: 連線設定 | TEdit | edServer | POP3 伺服器位址 (如 pop.gmail.com) |
| TEdit | edPort | Text="110" (標準 POP3 埠),SSL 為 995 | |
| TEdit | edUser | 使用者帳號 | |
| TEdit | edPass | Password=True (密碼遮罩) | |
| TButton | btnConnect | Caption="連接" | |
| TButton | btnDisconnect | Caption="斷開連接" | |
| 分頁 2: 郵件內容 | TEdit | edMsgNum | 郵件編號 (輸入/顯示) |
| TEdit | edFrom | 寄件者 | |
| TEdit | edSubject | 主旨 | |
| TEdit | edSize | 大小 (Bytes) | |
| TEdit | edMsgId | Message-ID | |
| TMemo | mmBody | 郵件本文 (純文字/HTML) | |
| TMemo | mmHeaders | 完整郵件標頭 | |
| 分頁 2 (按鈕區) | TButton | btnDelete | Caption="刪除" (標記刪除) |
| TButton | btnRetrieve | Caption="取回郵件" (下載完整內容) | |
| TButton | btnSummary | Caption="郵件資訊" (僅下載標頭/摘要) | |
| 分頁 3: 郵件列表 | TButton | btnList | Caption="郵件列表" (取得清單) |
| TButton | btnClearList | Caption="清除列表" | |
| TMemo | mmList | 顯示列表 (編號/大小) | |
| TStatusBar | sbStatus | 底部狀態列 (SimplePanel=True) |
NMPOP31) — POP3 協議客戶端核心。void __fastcall TForm1::btnConnectClick(TObject *Sender) {
NMPOP31->AttachFilePath = "."; // 附件儲存目錄 (當前目錄)
NMPOP31->DeleteOnRead = false; // 讀取後不自動刪除伺服器郵件
NMPOP31->ReportLevel = Status_Basic; // 狀態回報等級
NMPOP31->TimeOut = 20000; // 逾時 20 秒
NMPOP31->Host = edServer->Text; // 伺服器位址
NMPOP31->Port = StrToInt(edPort->Text); // 埠號
NMPOP31->UserID = edUser->Text; // 帳號
NMPOP31->Password = edPass->Text; // 密碼
NMPOP31->Connect(); // 發起連線
// 連線成功後 OnConnect 事件會更新郵件數量
}
void __fastcall TForm1::btnDisconnectClick(TObject *Sender) {
NMPOP31->Disconnect();
}
// 刪除郵件 (標記刪除,QUIT 時生效)
void __fastcall TForm1::btnDeleteClick(TObject *Sender) {
int msgNum = StrToIntDef(edMsgNum->Text, 0);
if (msgNum > 0) NMPOP31->DeleteMailMessage(msgNum);
}
// 取回完整郵件 (含本文、附件、標頭)
void __fastcall TForm1::btnRetrieveClick(TObject *Sender) {
int msgNum = StrToIntDef(edMsgNum->Text, 0);
if (msgNum == 0) return;
NMPOP31->GetMailMessage(msgNum); // 觸發 OnRetrieveStart/End
// 事件完成後,MailMessage 屬性填充完成
edFrom->Text = NMPOP31->MailMessage->From;
edSubject->Text = NMPOP31->MailMessage->Subject;
edMsgId->Text = NMPOP31->MailMessage->MessageId;
edSize->Text = IntToStr(NMPOP31->MailMessage->Size);
mmHeaders->Lines->Assign(NMPOP31->MailMessage->Head);
mmBody->Lines->Assign(NMPOP31->MailMessage->Body);
// 處理附件
if (!NMPOP31->MailMessage->Attachments->Text.IsEmpty()) {
ShowMessage("附件清單:\n" + NMPOP31->MailMessage->Attachments->Text);
// 附件已自動儲存至 AttachFilePath 目錄
}
}
// 僅取回摘要 (標頭 + 大小,不下載本文/附件,速度快)
void __fastcall TForm1::btnSummaryClick(TObject *Sender) {
int msgNum = StrToIntDef(edMsgNum->Text, 0);
if (msgNum == 0) return;
NMPOP31->GetSummary(msgNum);
edFrom->Text = NMPOP31->Summary->From;
edSubject->Text = NMPOP31->Summary->Subject;
edMsgId->Text = NMPOP31->Summary->MessageId;
edSize->Text = IntToStr(NMPOP31->Summary->Bytes);
// Summary 無 Body 與 Attachments
}
// 取得郵件清單 (編號 + 大小)
void __fastcall TForm1::btnListClick(TObject *Sender) {
NMPOP31->List(); // 觸發 OnList 事件逐筆回傳
}
void __fastcall TForm1::btnClearListClick(TObject *Sender) {
mmList->Clear();
}
// 連線成功
void __fastcall TForm1::NMPOP31Connect(TObject *Sender) {
sbStatus->SimpleText = "已連線至 " + NMPOP31->Host;
// 更新郵件總數 (連線成功後自動取得)
LabelCount->Caption = "郵件總數: " + IntToStr(NMPOP31->MailCount);
}
// 連線失敗
void __fastcall TForm1::NMPOP31ConnectionFailed(TObject *Sender) {
ShowMessage("連線失敗!請檢查伺服器、埠號、帳號密碼。");
}
// 需要連線時 (離線操作觸發)
void __fastcall TForm1::NMPOP31ConnectionRequired(TObject *Sender, bool &Handled) {
if (MessageBox(Handle, "需要連線至伺服器,是否立即連線?", "連線請求", MB_YESNO | MB_ICONQUESTION) == IDYES) {
Handled = true;
btnConnectClick(this); // 觸發連線
}
}
// 斷開連線
void __fastcall TForm1::NMPOP31Disconnect(TObject *Sender) {
sbStatus->SimpleText = "已斷線";
}
// 伺服器名稱解析完成
void __fastcall TForm1::NMPOP31HostResolved(TObject *Sender) {
sbStatus->SimpleText = "主機名稱解析完成";
}
// 無效主機名
void __fastcall TForm1::NMPOP31InvalidHost(TObject *Sender, AnsiString &NewHost, bool &Handled) {
if (InputQuery("無效主機", "請輸入正確的 POP3 伺服器位址:", NewHost)) {
NMPOP31->Host = NewHost;
Handled = true;
}
}
// 郵件列表項目接收 (List 命令回傳)
void __fastcall TForm1::NMPOP31List(TObject *Sender, int Msg, int Size) {
if (Msg < 2) mmList->Clear(); // 第一筆前清空
mmList->Lines->Add("編號: " + IntToStr(Msg) + " 大小: " + IntToStr(Size) + " Bytes");
}
// 列表傳輸進度
void __fastcall TForm1::NMPOP31ListPacketRecvd(TObject *Sender) {
sbStatus->SimpleText = "已接收 " + IntToStr(NMPOP31->BytesRecvd) + " / " + IntToStr(NMPOP31->BytesTotal) + " Bytes";
}
// 郵件取回開始/結束
void __fastcall TForm1::NMPOP31RetrieveStart(TObject *Sender) {
Screen->Cursor = crHourGlass;
sbStatus->SimpleText = "正在取回郵件...";
}
void __fastcall TForm1::NMPOP31RetrieveEnd(TObject *Sender) {
Screen->Cursor = crDefault;
sbStatus->SimpleText = "郵件取回完成";
}
// 一般狀態回報
void __fastcall TForm1::NMPOP31Status(TObject *Sender, const AnsiString &Status) {
sbStatus->SimpleText = Status;
}
// 操作成功/失敗
void __fastcall TForm1::NMPOP31Success(TObject *Sender) {
sbStatus->SimpleText = "操作成功";
}
void __fastcall TForm1::NMPOP31Failure(TObject *Sender) {
ShowMessage("操作失敗!");
sbStatus->SimpleText = "操作失敗";
}
// 重設刪除標記 (RSET 命令)
void __fastcall TForm1::NMPOP31Reset(TObject *Sender) {
ShowMessage("已重設刪除標記");
}
DeleteMailMessage 只發送 DELE 命令標記刪除。必須正常 Disconnect() (發送 QUIT) 伺服器才會真正刪除。若程式異常結束或網路中斷未送 QUIT,標記會被清除 (等同 RSET)。GetMailMessage 下載完整內容較慢。列表頁面建議僅用 List() + GetSummary() 顯示摘要,使用者點選再 GetMailMessage。TIdDecoderMIME。AttachFilePath 目錄必須存在且可寫入。附件檔名衝突會覆蓋,建議自行管理檔名。NMPOP3 屬於舊版 NetMasters/Indy 8/9 時代元件。C++Builder 10.x+ 內建 Indy 10,提供 TIdPOP3、TIdMessage、TIdSSLIOHandlerSocketOpenSSL,支援完整 SSL/TLS、Unicode、MIME 多部分解析、非同步操作。新專案請直接使用 Indy 10 元件,架構更清晰、維護性更高。