首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Applet 發送 Email 兩種實作:啟動郵件用戶端 vs 直連 SMTP

     編輯:Java 程式設計入門

本文提供兩種在 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);
    }
}

優點:無沙箱限制、無需簽名、使用者熟悉介面可編輯完整郵件。
缺點:依賴用戶端環境、無法自動化批次寄送、無法控制郵件內容細節。

方式二:直連 SMTP 伺服器 (需簽名 Applet)

直接建立 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 略
}

部署簽名 Applet 步驟

  1. 編譯類別:javac SmtpApplet.java
  2. 建立 JAR:jar cvf smtp.jar SmtpApplet.class
  3. 產生金鑰:keytool -genkey -alias mykey -keystore mykeystore -validity 365
  4. 簽名 JAR:jarsigner -keystore mykeystore smtp.jar mykey
  5. HTML 引用:
    
        
    
  6. 瀏覽器載入時會提示信任簽名,用戶同意後方可建立 Socket 連線。

現代替代方案建議

Applet 已被瀏覽器淘汰,新專案請採用:

  • 前端 + 後端 API:前端 (React/Vue) 呼叫後端 REST API (Spring Boot / Node.js),後端使用 JavaMail API (Jakarta Mail) 發送郵件。
  • JavaMail 範例:
    @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);
    }
  • 後端可整合 SMTP 伺服器 (Gmail, SendGrid, Amazon SES, 企業 Exchange) 支援 SSL/TLS、認證、HTML 郵件、附件。

安全性提醒

  • 直連 SMTP 暴露伺服器位址與埠號於客戶端程式碼,易遭濫用。
  • 生產環境應禁止客戶端直連 SMTP,統一由受信任後端服務發送。
  • 若必須客戶端發送,請使用 OAuth2 權杖或一次性 API 金鑰,並限制發送頻率與收件域名。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved