JAVA項目四:郵件發送客戶端

一、Java Mail API簡介

JavaMail API是讀取、撰寫、發送電子信息的可選包。我們可用它來建立如Eudora、Foxmail、MS Outlook Express一般的郵件用戶代理程序(Mail User Agent,簡稱MUA)。而不是像sendmail或者其它的郵件傳輸代理(Mail Transfer Agent,簡稱MTA)程序那樣可以傳送、遞送、轉發郵件。從另外一個角度來看,我們這些電子郵件用戶日常用MUA程序來讀寫郵件,而MUA依賴着MTA處理郵件的遞送。
JavaMail核心類:Session、Message、Address、Authenticator、Transport、Store、Folder。
Session類:定義了基本的郵件會話。就像Http會話那樣,我們進行收發郵件的工作都是基於這個會話的。Session對象利用了java.util.Properties對象獲得了郵件服務器、用戶名、密碼信息和整個應用程序都要使用到的共享信息。
Message類: SUN提供了Message類型來幫助開發者完成這項工作。由於Message是一個抽象類,大多數情況下,我們使用javax.mail.internet.MimeMessage這個子類,該類是使用MIME類型、MIME信息頭的郵箱信息。信息頭只能使用US-ASCII字符,而非ASCII字符將通過編碼轉換爲ASCII的方式使用
Address類:到這裏,我們已經建立了Session和Message,下面將介紹如何使用郵件地址類:Address。像Message一樣,Address類也是一個抽象類,所以我們將使用javax.mail.internet.InternetAddress這個子類。
Authenticator類:像java.net類那樣,JavaMail API通過使用授權者類(Authenticator)以用戶名、密碼的方式訪問那些受到保護的資源,在這裏“資源”就是指郵件服務器。在javax.mail包中可以找到這個JavaMail的授權者類(Authenticator)。
Transport類:在發送信息時,Transport類將被用到。這個類實現了發送信息的協議(通稱爲SMTP),此類是一個抽象類,我們可以使用這個類的靜態方法send()來發送消息:Transport.send(message);
Store和Folder類:接收郵件和發送郵件很類似都要用到Session。但是在獲得Session後,我們需要從Session中獲取特定類型的Store,然後連接到Store,這裏的Store代表了存儲郵件的郵件服務器。在連接Store的過程中,極有可能需要用到用戶名、密碼

ps:項目要用到jar包:activation.jar和mail.jar.

二、代碼實現

項目源碼下載地址:點我

package com.hnust.frame;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Date;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class SendAttachmentMailFrame extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private JTextArea ta_attachment;
    private JTextArea ta_text;
    private JTextField tf_title;
    private JTextField tf_send;
    private JTextField tf_receive;
    private JPasswordField tf_password;
    /**
     * Session類是定義了一個基本會話,是Java Mail API最高層入口類。所有其他類都是經由這個Session才得以生效。
     * Session對象從java.util.Properties對象中獲取信息,
     * 如郵件發送服務器、接收郵件協議、發送郵件協議、用戶名、密碼及整個應用程序中共享的其他信息
     * */
    private Session session;
    private String sendHost = "localhost";
    private String sendProtocol="smtp";
    private String filePathAndName = null;

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    SendAttachmentMailFrame frame = new SendAttachmentMailFrame();
                    frame.init();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public SendAttachmentMailFrame() {
        super();
        setTitle("發送帶附件的郵件");
        getContentPane().setLayout(null); //設置佈局爲空佈局
        setBounds(200, 200, 480, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JLabel label = new JLabel();
        label.setForeground(new Color(0, 0, 255));
        label.setFont(new Font("", Font.BOLD, 22));
        label.setText("@發送帶附件的郵件@");
        label.setBounds(123, 10, 230, 24);
        getContentPane().add(label);

        final JLabel label_1 = new JLabel();
        label_1.setText("收件人地址:");
        label_1.setBounds(22, 42, 85, 18);
        getContentPane().add(label_1);

        tf_receive = new JTextField();
        tf_receive.setBounds(113, 40, 287, 22);
        getContentPane().add(tf_receive);

        final JLabel label_2 = new JLabel();
        label_2.setText("發件人郵箱:");
        label_2.setBounds(22, 68, 78, 18);
        getContentPane().add(label_2);

        tf_send = new JTextField();
        tf_send.setBounds(113, 66, 287, 22);
        getContentPane().add(tf_send);

        final JLabel label_2_1 = new JLabel();
        label_2_1.setText("郵箱密碼:");
        label_2_1.setBounds(30, 95, 78, 18);
        getContentPane().add(label_2_1);

        tf_password = new JPasswordField();
        tf_password.setBounds(113, 95, 278, 18);
        getContentPane().add(tf_password);

        final JLabel label_3 = new JLabel();
        label_3.setText("主    題:");
        label_3.setBounds(32, 125, 66, 18);
        getContentPane().add(label_3);

        tf_title = new JTextField();
        tf_title.setBounds(113, 125, 287, 22);
        getContentPane().add(tf_title);

        final JLabel label_4 = new JLabel();
        label_4.setText("正    文:");
        label_4.setBounds(34, 150, 66, 18);
        getContentPane().add(label_4);

        //創建一個空的(無視口的視圖)JScrollPane,需要時水平和垂直滾動條都可顯示
        final JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(113, 150, 287, 76);
        getContentPane().add(scrollPane);

        ta_text = new JTextArea();
        //創建一個視口(如果有必要)並設置其視圖
        scrollPane.setViewportView(ta_text);

        final JButton btn_send = new JButton();
        btn_send.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                String fromAddr = tf_send.getText().trim();
                String toAddr = tf_receive.getText().trim();// 真實存在的目標郵件地址
                String title = tf_title.getText().trim();
                String text = ta_text.getText().trim();
                try {
                  sendMessage(fromAddr, toAddr, title, text);   //發送消息
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        });
        btn_send.setText("發    送");
        btn_send.setBounds(225, 300, 85, 28);
        getContentPane().add(btn_send);//添加發送按鈕到容器

        final JButton btn_exit = new JButton();
        btn_exit.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                System.exit(0);
            }
        });
        btn_exit.setText("退    出");
        btn_exit.setBounds(316, 300, 84, 28);
        getContentPane().add(btn_exit);

        final JButton button = new JButton();   //添加附件按鈕
        button.addActionListener(new ActionListener() { //點擊事件
            public void actionPerformed(final ActionEvent e) {
                JFileChooser fileChooser = new JFileChooser(); // 創建文件對話框
                int returnValue = fileChooser.showOpenDialog(null);// 打開文件選擇對話框
                if (returnValue == JFileChooser.APPROVE_OPTION) { // 判斷是否選擇了文件
                    File file = fileChooser.getSelectedFile(); // 獲得文件對象
                    if (file.length() / 1024.0 / 1024 > 50.0) {
                        JOptionPane.showMessageDialog(null, "請選擇小於等於50MB的文件。");
                        return;
                    }
                    filePathAndName = file.getAbsolutePath();// 獲得文件的完整路徑和文件名
                    ta_attachment.append(file.getName());// 顯示附件文件的名稱
                }
            }
        });
        button.setText("添加附件");
        button.setBounds(113, 300, 106, 28);
        getContentPane().add(button);

        final JLabel label_5 = new JLabel();
        label_5.setText("附    件:");
        label_5.setBounds(32, 230, 66, 18);
        getContentPane().add(label_5);

        //創建一個空的(無視口的視圖)JScrollPane,需要時水平和垂直滾動條都可顯示
        final JScrollPane scrollPane_1 = new JScrollPane();
        scrollPane_1.setBounds(112, 230, 287, 63);
        getContentPane().add(scrollPane_1);

        ta_attachment = new JTextArea();
        //創建一個視口(如果有必要)並設置其視圖
        scrollPane_1.setViewportView(ta_attachment);
    }
    public void init() throws Exception {
        /**
         * Session對象利用Properties對象獲得了郵件發送服務器、接收郵件協議、發送郵件協議、用戶名、密碼等整個應用程序都要使用到的共享信息
         * */
        Properties props = new Properties();
        /**
         *  put()方法將指定 key 映射到此哈希表中的指定 value。鍵和值都不可以爲 null。 
            通過使用與原來的鍵相同的鍵調用 get 方法,可以獲取相應的值
         * */
        props.put("mail.transport.protocol", sendProtocol);//發送協議
        props.put("mail.smtp.class", "com.sun.mail.smtp.SMTPTransport");
        props.put("mail.smtp.host", "127.0.0.1");//本機地址和域名綁定。否則會出錯 詳見:http://www.cnblogs.com/zhongzheng123/p/5869554.html
        session = Session.getDefaultInstance(props);
    }
    /**
     * @param fromAddr 發送方地址
     * @param toAddr 接收方地址
     * @param title 主題
     * @param text 文本內容
     * @throws Exception 異常
     */
    public void sendMessage(String fromAddr,String toAddr,String title,String text) throws Exception {
        //Message類封裝的郵件信息,提供了訪問和設置郵件內容的方法
        Message msg = new MimeMessage(session);// 創建Message對象
        /**
         * 建立了Session和Message對象之後,使用郵件地址Address抽象類的子類:javax.mail.internetAddress 
         * */
        InternetAddress[] toAddrs = InternetAddress.parse(toAddr,false);// 接收方地址
        msg.setRecipients(Message.RecipientType.TO, toAddrs);// 指定接收方
        msg.setSentDate(new Date());// 設置發送日期
        msg.setSubject(title);// 設置主題
        msg.setFrom(new InternetAddress(fromAddr));// 設置發送地址

        Multipart multipart = new MimeMultipart();// 可以添加複雜內容的Multipart對象(Multipart抽象類是保存電子郵件內容的容器)
        MimeBodyPart mimeBodyPartText = new MimeBodyPart();// 添加正文的MimeBodyPart對象
        mimeBodyPartText.setText(text);// 指定正文
        multipart.addBodyPart(mimeBodyPartText);// 添加到Multipart對象上
        if (filePathAndName!=null && !filePathAndName.equals("")){
            MimeBodyPart mimeBodyPartAdjunct = new MimeBodyPart();// 添加附件的MimeBodyPart對象
            FileDataSource fileDataSource = new FileDataSource(filePathAndName);// 創建附件的FileDataSource對象
            mimeBodyPartAdjunct.setDataHandler(new DataHandler(fileDataSource));// 指定數據
            mimeBodyPartAdjunct.setDisposition(Part.ATTACHMENT);// 指定添加的內容是附件
            String name = fileDataSource.getName();
            mimeBodyPartAdjunct.setFileName(MimeUtility.encodeText(name, "GBK", null));// 指定附件文件的名稱
            multipart.addBodyPart(mimeBodyPartAdjunct);// 添加到Multipart對象上
        }
        msg.setContent(multipart);// 設置郵件內容
        String server = "smtp.163.com";  //設置SMTP服務器(220.181.12.15)
        String username = tf_send.getText();  //獲取發送方的郵箱用戶名
        String password = new String(tf_password.getPassword());    //獲取發送方的郵箱密碼
        /**
         * Transport類根據指定的郵件發送協議(通常是SMTP),通過指定的郵件發送服務器來發送郵件。
         * Transport類是抽象類,他提供了一個靜態方法send(Message)來發送郵件
         * */       
        Transport transport = session.getTransport();  
        transport.connect(server, username, password);  //連接服務器
        transport.sendMessage(msg, msg.getRecipients(Message.RecipientType.TO)); //發送郵件
        filePathAndName = null;
        JOptionPane.showMessageDialog(null, "郵件發送成功。");
    }
}

運行效果:

三、遇到的問題

1、Could not connect to SMTP host: localhost, port: 25;

問題原因:SMTP服務主機沒有正確配置
解決辦法:配置正確的SMTP服務主機,保證服務連接上

 String server = "smtp.163.com";  //設置SMTP服務器(220.181.12.15)
        String username = tf_send.getText();  //獲取發送方的郵箱用戶名
        String password = new String(tf_password.getPassword());    //獲取發送方的郵箱密碼
        /**
         * Transport類根據指定的郵件發送協議(通常是SMTP),通過指定的郵件發送服務器來發送郵件。
         * Transport類是抽象類,他提供了一個靜態方法send(Message)來發送郵件
         * */       
        Transport transport = session.getTransport();  
        transport.connect(server, username, password);  //連接服務器
        transport.sendMessage(msg, msg.getRecipients(Message.RecipientType.TO)); //發送郵件

靈感來自博客:解決辦法

2、郵箱要開啓SMTP服務,否則會導致無法發送郵件或者郵件會被存入垃圾箱。百度一下就能找到郵箱開啓SMTP的方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章