??xml version="1.0" encoding="utf-8" standalone="yes"?>
JavaMail使用了Sessioncȝ概念来保存诸如SMTPL和认证的信息Q主要想法是Z会话QSessionsQ在Java虚拟Z可以被隔,q可以阻止恶意代码窃取其他用户在其他会话中的信息Q这些信息可能包括用户名和密码等认证信息.你所要发送的邮g保存在一个Message对象?而这个Message对象则是׃所构造的session实例来创?br /> 要得C个特定的session对象,可以通过一下代?
//讄session的属?br /> Properties pro = new Properties();
pro.put("mail.transport.protocol", "smtp");
pro.put("mail.smtp.auth", "true");
pro.put("mail.smtp.host", "smtp.126.com");
pro.put("mail.host", "126.com");
//讄认证?br /> PopupAuthenticator pop = new PopupAuthenticator();
pop.performCheck("My Name", "My Password");//你的帐户和密?br />
//得到session
Session mailSession = Session.getInstance(pro, pop);
要注意的?Z避免垃圾邮g,大多数的smtp服务器需要认?SMTP认证(SMTP AUTH)需要用户名和密码来发送邮?因此,必须在session的初始化参数中设|一个认证者(AuthenticatorQ来q回所需的认证证?具体代码必须p己来实现:
class PopupAuthenticator extends Authenticator {
String username = null;
String password = null;
public PopupAuthenticator() {}
public PasswordAuthentication performCheck(String user, String pass) {
username = user;
password = pass;
return getPasswordAuthentication();
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
}
接着,可以用之前得到的session来构造Message对象:
Message msg = new MimeMessage(mailSession);
在用会话创Z一个MimeMessage?我们需要来填充q个消息.首先是设|表头信?Messagecd义了邮gpȝ中用的属?由名?值对l成,使用q些名字-值可以指定邮件表头信?Javamail提供了一pdapi用于讄常见的邮件表?其中在涉及地址的操作时,我们用InternetAddress来进行封?
msg.setFrom(new InternetAddress ("acmilan@126.com");
msg.setSubject("Hello");
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("intermilan@126.com", false));
msg.setText("I will beat u");
msg.setSentDate(new Date());
//发送消?br /> Transport.send(msg);
对Transportcȝ调用会LN当的会话,q找出如何发送消息,管q样做看上去有些不直观。当我们完成q一步的时候,我们的邮件就已经发送出M。此Ӟ我们q需要添加代码来捕获三种JavaMail可能抛出的异常,它们是AddressException、MessagingException和UnsupportedEncodingException. 但这是最基本的用JavaMail发送邮件的Ҏ?br /> 有时候我们还需要给邮gd附g.再回C前对Message的讨Z,Message对象同样定义了邮件的内容,它可以定义一个消息内?也可以定义多个消息内?消息内容(通常指的是附?都将由DataHandle下的cL处理.Message对象由Multipartl成,一个Multipart可含有多个BodyPart,q些BodyPart用来保存文本信息和附g.
MimeMultipart multipart = new MimeMultipart();
BodyPart msgBodyPart = new MimeBodyPart();//用来攄文本内容
msgBodyPart.setContent(message, "text/plain");
BodyPart attBodyPart = new MimeBodyPart();//用来攄附g
DataSource ds = new FileDataSource(new File("c:/td.txt"));
attBodyPart.setDataHandler(new DataHandler(ds));//讄DataHandler
attBodyPart.setFileName("bsbs.txt");//附g的显C名?br /> multipart.addBodyPart(msgBodyPart);
multipart.addBodyPart(attBodyPart);
msg.setContent(multipart);
Transport.send(msg);
最?我们来看看如何发送HTML格式的邮?文本的格式必ȝ应的讄为text/html,邮g中的囄以附g形式加蝲,另外q要指定一个内部ID以供调用;
MimeMultipart multipart = new MimeMultipart();
BodyPart msgBodyPart = new MimeBodyPart();
//讄格式?text/html"
msgBodyPart.setContent("<H1>Hi! From HtmlJavaMail</H1> <img src=\"cid:logo\"/>", "text/html");
BodyPart embedImage = new MimeBodyPart();
DataSource ds = new URLDataSource(new URL(" embedImage.setDataHandler(new DataHandler(ds));
//讄表头的内部ID,注意,所讄内容必须与前文对?在此?前文的引用ؓ<img src=\"cid:logo\"/>,因此Content-ID表头对应
//的应该是<logo>
embedImage.setHeader("Content-ID", "<logo>");
multipart.addBodyPart(msgBodyPart);
multipart.addBodyPart(embedImage);
msg.setContent(multipart);
q样,一HTML格式的邮件便完成?br /> Transport.send(msg);
?邮g的收?br /> 同样,W一步还是要获得服务器的名字.我们q是以网易ؓ?
接收邮g包含两个协议Q即POP3和IMAP。POP3是老协议,它提供一个单一收信,以存放一定顺序的邮g信息。IMAP相对比较斎ͼ它ؓ邮g提供q接C个层ơ关pȝ文g入口Q其中一个入口即为收信箱。当然还有其它可以用的协议QPOP3和IMAP只是其中一U安全性很好的协议。JavaMail这些协议提gؓ一U邮件仓?Store)的概念,q一仓库为文件等U的集合。这U提炼意味着仓库包含很多内容Q但我们只需要弄清楚在一个服务文件夹中浏览与D邮g信息的过E,而实际处理邮件协议的d则通过JavaMail调用Provider来完?不同的协议对应不同的provider?br /> JavaMail的Provider操作服务于POP3和IMAPQ你也可以将另外的Providers嵌入到JavaMail API以处理其它诸如NNTP或本地存储邮件的协议。在Sun主页上列斚w的第三方Providers?br /> 在Javamail?store和foldercL用来存储和接受消?store由具体的session得到,它用可带参数的connectҎ与服务器q接,folder则和File有点cM,可以其比作windows下的文g?客户由storecM取得folder,再对folderq行操作--q入特定的folder,dfolder中的消息.
Session session;
Store store = null;
Folder folder = null;
Folder inboxfolder = null;
Properties props = System.getProperties();
props.setProperty("mail.pop3s.rsetbeforequit", "true");//q样d邮g时服务器不会删除原有的邮?br /> props.setProperty("mail.pop3.rsetbeforequit", "true");
session = Session.getInstance(props, null);
store = session.getStore("pop3");//通过"pop3"得到适当的provider
store.connect(emailserver, emailuser, emailpassword);
folder = store.getDefaultFolder();//得到默认的顶U文件夹
每一Folder可以包含很多其它的文件夹,通过getFolderҎ来浏览特定文件夹。INBOX是邮件服务器表示的主文g夹保留的名称,pop3和imap存储都会提供一个INBOX文g?
inboxfolder = folder.getFolder("INBOX");
inboxfolder.open(Folder.READ_ONLY);//只读模式
Message[] msgs = inboxfolder.getMessages();
需要注意的?此时真正的消息对象ƈ没有存储到数l?msgs)?数组保存的只是这些消息对象的引用,只有在调用了具体的Message.getXX()Ҏ?E序才会再次q接服务器ƈ取得真正的结?如果要进行对邮g的筛选工?不停的调用每个消息对象的getXXҎ无疑会媄响性能.因此我们可以用FetchProfilecL预先抓取感兴的部分内容(如各表头内容),q就不需要每ơ调用getXXҎ旉再连接服务器?
FetchProfile fp = new FetchProfile();
fp.add("Subject");//卛_d主题信息
inboxfolder.fetch(msgs, fp);//预读取每个消息的主题
for (int j = 0 ;j <msgs.length; j++) {
if (msgs[j].getSubject().startsWith("^_^")) {//只对标题?^_^"的邮件进行操?br /> .......
}
接下?可以调用Message的各U方法对邮gq行操作?对不同格式的邮g,具体的操作当然也略微不同.一个做法是Ҏ个具体的BodyPartq行操作,通过下列的递归Ҏ可以获得每个BodyPart的引?br /> private void extractPart(final Part part) throws MessagingException,IOException {
if(part.getContent() instanceof Multipart) {
Multipart mp=(Multipart)part.getContent();
for (int i = 0; i < mp.getCount(); i++) {
extractPart(mp.getBodyPart(i));
}
return;
}
Part的getContentTypeҎ可以为我们对光取何U方法处理提供依?br /> part.getContentType().startsWith("text/plain").....
如果是以"text/plain"或?text/html"开?通常我们可以直接取出其内?br /> bodytext = (String) part.getContent();
如果两者都不是,我们其视之为附?通过IO来d:
InputStream in = part.getInputStream();//dpart中的附g
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int count = 0;
while ( (count = in.read(buffer)) >= 0) {
bos.write(buffer, 0, count);
}
in.close();
接下?可以对进行操作了.
那么,关于Javamail的研I也p行到q儿?
参考文?
DJ Walker-Morgan Getting the mail in: receiving in JavaMail
Sending email in Java: There's more than one way
赵强,乔新亮 J2EE应用开?/p>