一、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)); //發送郵件
靈感來自博客:解決辦法