本方案採雙程式協作模式,搭配外部防毒掃描器,構建「公用信箱 → 病毒掃描 → 祕密信箱」的郵件防護管道:
USER/PASS 進行認證STAT 取得信件數UIDL n 取得唯一 ID,作為本地檔名RETR n 下載完整郵件內容,存入 ./Messages/ 資料夾outputStream.println("UIDL " + msgNumber);
String uidl = validateOneLine(); // 格式:"+OK 38 402fb6da00000098"
pathFileName = dataPath + uidl;
DataOutputStream dataOut = new DataOutputStream(new FileOutputStream(pathFileName));
outputStream.println("RETR " + msgNumber);
validateOneLine(); // 忽略 +OK 回應
String msgLine = inputStream.readLine();
while (!msgLine.equals(".")) { // 單獨一行 "." 代表郵件結束
dataOut.writeBytes(msgLine + "\n");
msgLine = inputStream.readLine();
}
dataOut.close();
// 觸發下一封下載(模擬按鈕點擊)
Toolkit.getDefaultToolkit().getSystemEventQueue()
.postEvent(new ActionEvent(startButton, ActionEvent.ACTION_PERFORMED, "Start/Next"));
./Messages/ 所有檔案,逐一呼叫 forwardEmailMsg()sun.net.smtp.SmtpClient 發送郵件(SDK 1.4.2 內建但未公開文件化){001} 以利追蹤msgToDelete 向量,失敗者保留於工作資料夾DELE n 標記刪除,再送 QUIT 生效moveFile() 將已處理檔案移至 ./Archives/ 歸檔private boolean forwardEmailMsg(String recipient, String smtpServer,
String tag, String pathFileName) {
try {
SmtpClient smtp = new SmtpClient(smtpServer);
smtp.from(recipient); // 寄件人設為收件人(僅需合法格式)
smtp.to(recipient); // 真正收件人
PrintStream msg = smtp.startMessage();
// 讀取完整郵件內容(含標頭與本文)
StringBuffer message = new StringBuffer(readLines(pathFileName, null, null));
// 在 Subject: 後插入標記
int idx = message.indexOf("Subject: ") + 9;
message.insert(idx, tag);
msg.println(message.toString());
smtp.closeServer(); // 關閉連線並發送
return true;
} catch (Exception e) { /* 錯誤處理與 beep 提示 */ return false; }
}
private String readLines(String path, String firstLine, String lastLine) {
StringBuffer buf = new StringBuffer();
try (BufferedReader in = new BufferedReader(new FileReader(path))) {
String line; boolean saving = false;
while ((line = in.readLine()) != null) {
if (!saving && (firstLine == null || line.startsWith(firstLine))) saving = true;
if (saving) buf.append(line).append("\n");
if (lastLine != null && line.startsWith(lastLine)) break;
}
} catch (Exception e) { e.printStackTrace(); }
return buf.toString();
}
檔名範例:+OK 38 402fb6da00000098
+OK:伺服器回應狀態碼38:郵件在伺服器上的流水號(1-based,刪除較小編號會導致重新編號)402fb6da00000098:UIDL 唯一識別碼(同一帳號下不重複)程式從檔名擷取流水號,格式化為三位數 001~999 插入 Subject。
Messages、Archives 兩個資料夾java VirPro01a pop3.server user pass 下載郵件Messages 資料夾java VirPro01b pop3.server user pass smtp.server smtp.host 轉寄與清理Archives 避免磁碟滿載sun.net.smtp.SmtpClient,生產環境建議改用 JavaMail APIDELE 指令預設註解,需徹底測試後方可啟用,防止誤刪未成功轉寄的郵件