呃,好吧,我只寫過三個JavaMail的程序。
都是批量郵件守護程序。決定總結一下,希望非常幸運找到這篇文章的人不會再對這個困惑。
必須明白的基礎知識
- STMP協議是如何工作的
協議的標準在這里 http://www.ietf.org/rfc/rfc2821.txt?number=2821
下面是扼要說明(http://www.freesoft.org/CIE/Topics/94.htm ):
Simple Mail Transfer Protocol (SMTP), documented in RFC
821, is Internet’s standard host-to-host mail transport protocol and
traditionally operates over TCP, port 25. In other words, a UNIX user
can type telnet hostname 25 and connect with an SMTP server, if one is
present.
SMTP uses a style of asymmetric request-response protocol popular in
the early 1980s, and still seen occasionally, most often in mail
protocols. The protocol is designed to be equally useful to either a
computer or a human, though not too forgiving of the human. From the
server’s viewpoint, a clear set of commands is provided and
well-documented in the RFC. For the human, all the commands are clearly
terminated by newlines and a HELP command lists all of them. From the
sender’s viewpoint, the command replies always take the form of text
lines, each starting with a three-digit code identifying the result of
the operation, a continuation character to indicate another lines
following, and then arbitrary text information designed to be
informative to a human.
事實上,你可以像使用DOS命令一樣發送電子郵件。http://bbs.stcore.com/archiver/tid-8024.htm 當然因為各種原因,你的嘗試不可能成功。事實上SMTP工作的時候就是簡單的發送命令。取得認證,發送數據。得到反饋。確認退出這么簡單。
- SMTP中用于發送的數據
SMTP中發送的數據,遵從Multipurpose Internet Mail Extensions (MIME)標準,呃,我不得不說,這是這個星球上最重要的標準之一。所有的互聯網通信基本都是基于這個標準的演化。除了電子郵件,常見的應用還包括HTTP報文等(也就是所有網頁了),另外即使在20年后發展的XML,其2進制數據發送仍然實用的MIME中的編碼方式。
恩,這里就涉及到郵件附件如何處理的問題。恩,簡單地說就是BASE64編碼
Table 1: The Base64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
在這種編碼中,我們將字符或者二進制編碼以6個比特位為一組,替換成相應的字符形式。比如
100110111010001011101001
轉換結果就是
100110 -> 38
111010 -> 58
001011 -> 11
101001 -> 41
38 -> m
58 -> 6
11 -> L
41 -> p
m6Lp
于是,我們就可以以文本的方式編碼二進制流以及擴展ASCII字符,比如中文字符。
基礎知識完畢,下面是FAQ
Java發送電子郵件需要哪些軟件包
mail.jar 通常還會需要 activation.jar
下載地址
http://java.sun.com/products/javabeans/jaf/downloads/index.html
https://maven-repository.dev.java.net/nonav/repository/javax.mail/
如何發送郵件
關于:
- 如何發送郵件
- 如何發送帶有附件的郵件
- 如何發送中文郵件
- 郵件中文標題亂碼怎么辦
- 郵件附件亂碼怎么辦等等問題
請查看以下代碼
public static synchronized void sendMail(Properties settings)
throws Exception {
Properties props = new Properties();
props.put("mail.smtp.host", settings.get(StartCore.MAIL_SERVER));
props.put("mail.smtp.user", settings.get(StartCore.USER_NAME));
props.put("mail.smtp.auth", "true");
//SMTP服務器用戶驗證
Authenticator auth = new SMTPAuthenticator((String) settings
.get(StartCore.USER_NAME), (String) settings
.get(StartCore.PASSWORD));
Session session = Session.getDefaultInstance(props, auth);
if ("true".compareToIgnoreCase((String) settings.get("DEBUG")) == 0) {
session.setDebug(true);
}
//創建消息體
MimeMessage msg = new MimeMessage(session);
//設置發送人郵件
msg.setFrom(new InternetAddress((String) settings
.get(StartCore.USER_MAIL)));
//設置接收人郵件
address = new InternetAddress[] { new InternetAddress(rs
.getString("GRE_mail")) };
msg.setRecipients(Message.RecipientType.TO, address);
//設置主題,中文編碼
msg.setSubject(subject, "gbk");
msg.setSentDate(new Date());
String content = "郵件正文";
MimeBodyPart mbp1 = new MimeBodyPart();
mbp1.setText(content, "gbk");
//郵件附件
MimeBodyPart attachFilePart = new MimeBodyPart();
File file = new File("中文附件.txt");
FileDataSource fds = new FileDataSource(file.getName());
attachFilePart.setDataHandler(new DataHandler(fds));
sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
//解決中文附件名稱
attachFilePart.setFileName("=?gbk?B?"
+ enc.encode(file.getName().getBytes("gbk")) + "?=");
Multipart mp = new MimeMultipart();
mp.addBodyPart(mbp1);
mp.addBodyPart(attachFilePart);
msg.setContent(mp);
// send the message
msg.saveChanges();
Transport.send(msg);
}
這是上面用戶驗證用到的類
class SMTPAuthenticator extends javax.mail.Authenticator {
private String username;
private String password;
/**
* @param username
* @param password
*/
public SMTPAuthenticator(String username, String password) {
this.username = username;
this.password = password;
}
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
}
郵件發送出錯
What causes an
“javax.activation.UnsupportedDataTypeException: no object DCH for MIME
type xxx/xxxx javax.mail.MessagingException: IOException while sending
message;” to be sent and how do I fix this? [This happens for known
MIME types like text/htm
事實上這個是郵件發送時驗證組件設置不當引起的,這個組件配置方法如下
(http://java.sun.com/j2ee/1.4/docs/api/javax/activation/MailcapCommandMap.html)
The MailcapCommandMap looks in various places in the user’s system
for mailcap file entries. When requests are made to search for commands
in the MailcapCommandMap, it searches mailcap files in the following
order:
1) Programatically added entries to the MailcapCommandMap instance.
2) The file .mailcap in the user’s home directory.
3) The file /lib/mailcap.
4) The file or resources named META-INF/mailcap.
5) The file or resource named META-INF/mailcap.default (usually found only in the activation.jar file).
我選用了第四種方法,在生成的Jar文件中加入了 META-INF/mailcap.
#
# This is a very simple 'mailcap' file
#
image/gif;; x-java-view=com.sun.activation.viewers.ImageViewer
image/jpeg;; x-java-view=com.sun.activation.viewers.ImageViewer
text/*;; x-java-view=com.sun.activation.viewers.TextViewer
text/*;; x-java-edit=com.sun.activation.viewers.TextEditor
text/html;; x-java-content-handler=com.sun.mail.handlers.text_html
text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml
text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain
multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed
message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822