本文提供兩種在 Applet 中發送電子郵件的方式:方式一 呼叫瀏覽器/系統預設郵件用戶端 (mailto: 協議);方式二 直接透過 Socket 連線 SMTP 伺服器發送。第二種方式需注意 Applet 沙箱限制 (需簽名或修改安全策略)。
利用 AppletContext.showDocument(URL) 開啟 mailto: 連結,由瀏覽器處理關聯應用程式 (Outlook, Foxmail, Thunderbird 等)。
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
public class EmailApplet extends Applet {
TextField tfEmail;
Button btnSend;
public void init() {
setLayout(new BorderLayout());
tfEmail = new TextField(30);
btnSend = new Button("寄信");
add("North", tfEmail);
add("South", btnSend);
}
@Override
public boolean action(Event e, Object arg) {
if ("寄信".equals(arg)) {
try {
String addr = tfEmail.getText().trim();
if (!addr.isEmpty()) {
URL url = new URL("mailto:" + addr);
getAppletContext().showDocument(url);
}
} catch (Exception ex) { ex.printStackTrace(); }
return true;
}
return super.action(e, arg);
}
}
優點:無沙箱限制、無需簽名、使用者熟悉介面可編輯完整郵件。
缺點:依賴用戶端環境、無法自動化批次寄送、無法控制郵件內容細節。
直接建立 Socket 連線至 SMTP 埠 (25/465/587),發送 SMTP 指令。必須將 Applet 打包為 JAR 並簽名,否則 Socket 連線會被安全管理員阻擋。
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.Socket;
import java.util.StringTokenizer;
public class SmtpApplet extends Applet implements ActionListener {
TextField tfTo, tfFrom, tfHost;
TextArea taBody;
Button btnSend, btnClear;
int smtpPort = 25;
public void init() {
// 從 HTML 讀取預設值與埠號
String portParam = getParameter("port");
if (portParam != null) smtpPort = Integer.parseInt(portParam);
// ... 介面建構略 (GridLayout 排版 To/From/Host/Body/Buttons)
btnSend.addActionListener(this);
btnClear.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == btnSend) sendMail();
else if (e.getSource() == btnClear) clearFields();
}
private void sendMail() {
String to = tfTo.getText().trim();
String from = tfFrom.getText().trim();
String host = tfHost.getText().trim();
String body = taBody.getText();
// 簡易 Email 格式驗證
if (!isValidEmail(from) || !isValidEmail(to)) {
showError("郵件地址格式錯誤");
return;
}
try (Socket s = new Socket(host, smtpPort);
PrintStream out = new PrintStream(s.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()))) {
readResponse(in); // 220
out.println("HELO " + getHostPart(from)); readResponse(in); // 250
out.println("MAIL FROM:<" + from + ">"); readResponse(in); // 250
out.println("RCPT TO:<" + to + ">"); readResponse(in); // 250
out.println("DATA"); readResponse(in); // 354
out.println("Subject: Applet Mail\r\n" + body);
out.println("."); readResponse(in); // 250
out.println("QUIT"); readResponse(in); // 221
showMessage("郵件發送成功!");
} catch (Exception ex) {
ex.printStackTrace();
showError("發送失敗:" + ex.getMessage());
}
}
private boolean isValidEmail(String email) {
return email.contains("@") && email.indexOf('@') != email.lastIndexOf('@') == false;
}
private String getHostPart(String email) {
return email.substring(email.indexOf('@') + 1);
}
private void readResponse(BufferedReader in) throws IOException {
String line;
while ((line = in.readLine()) != null) {
System.out.println("SMTP: " + line);
if (line.matches("^\\d{3} .*")) break; // 讀取單行回應碼
}
}
// clearFields, showError, showMessage 略
}
javac SmtpApplet.javajar cvf smtp.jar SmtpApplet.classkeytool -genkey -alias mykey -keystore mykeystore -validity 365jarsigner -keystore mykeystore smtp.jar mykeyApplet 已被瀏覽器淘汰,新專案請採用:
@Autowired JavaMailSender mailSender;
public void send(String to, String subject, String text) {
SimpleMailMessage msg = new SimpleMailMessage();
msg.setTo(to); msg.setSubject(subject); msg.setText(text);
mailSender.send(msg);
}