1 JavaMail介绍
JavaMail,顾名思义,提供给开发者处理电子邮件相关的编程接口。它是Sun发布的用来处理email的API。它可以方便地执行一些常用的邮件传输。我们可以基于JavaMail开发出类似于Microsoft Outlook的应用程序。
虽然JavaMail是Sun的API之一,但它目前还没有被加在标准的java开发工具包中。
这就意味着你在使用前必须另外下载JavaMail文件。
JavaMail包中用于处理电子邮件的核心类是:Session,Message,Address,Authenticator,Transport,Store,Folder等。
2 没有安全加密设置的邮件读取
现在很多免费的邮箱没有进行安全加密设置 端口号 Smtp : 25 POP3 : 110, 通过JavaMail来实现邮件服务的收发,网上有很多很好的代码,实现起来也比较简单。
3 有SSL安全加密设置的邮件读取
一般的企业邮箱都会进行安全加密设置:
POP3服务器地址端口:995 支持SSL
SMTP服务器地址端口:465 或者 587 支持SSL(TSL)
465端口是SSL/TLS通讯协议的 内容一开始就被保护起来了 是看不到原文的。
587端口是STARTTLS协议的 属于TLS通讯协议 只是他是在STARTTLS命令执行后才对之后的原文进行保护的。
收邮件的代码如下:
主要的包如下:
import java.io.UnsupportedEncodingException;
import java.security.Security;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import com.sun.mail.pop3.POP3Folder;
//接收邮件的主方法
public void mainReceive() throws Exception {
// DummySSLSocketFactory 是一个网上现有的一个类,路径我放在com.mycom.receiveMail文件夹下
Security.setProperty( "ssl.SocketFactory.provider", "com.mycom.receiveMail.DummySSLSocketFactory");
final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
Properties props = System.getProperties();
props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
props.setProperty("mail.pop3.socketFactory.fallback", "false");
props.setProperty("mail.pop3.port", "995");
props.setProperty("mail.pop3.socketFactory.port", "995");
//以下步骤跟一般的JavaMail操作相同--建立一个邮件对话 mail.myCom.com 服务
Session session = Session.getInstance(props);
URLName urln = new URLName("pop3","mail.myCom.com",995,null,
'myUserNameLiwg', 'myUserPassLiwg');
Store store = session.getStore(urln);
Folder inbox = null;
//创建数据库连接----------主要用于每次收不重复的邮件--还有就是可以储存读取的邮件标题,内容等信息----------
ConnectionPool conpool=new ConnectionPool();
Connection conn=conpool.getDbCon("oracle.properties");
try {
store.connect();
inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_ONLY);
// 过滤已经下载过的邮件,而不用重复下载 利用邮件唯一的uid来实现,邮件服务器上的每一个邮件都有一个唯一标识 UID
// 每一个邮件在邮件服务器上都有一个唯一的UID标识属性。
Message[] messages=getNewMessages(inbox,conn);
if(messages!=null){
//解析收取到的邮件----把邮件相关的属性内容放在数据库中
insertMailInfo(messages,conn);
}
//提交数据库操作的事务
try{
conn.commit();
}catch(Exception e){
//回滚事务或给某些数据进行解锁
conn.rollback();
}
//关闭数据库-----------------
conn.close();
}catch (Exception ex){
ex.printStackTrace();
}
finally {
try {
inbox.close(false);
} catch (Exception e) {e.printStackTrace();}
try {
store.close();
} catch (Exception e) {e.printStackTrace();}
}
}
// 通过邮件的UID 来实现不重复接收邮件-- 主要代码如下
public List getNewMessages(Folder folder,Connection conn) throws Exception{
POP3Folder inbox = (POP3Folder) folder;
Message[] messages = inbox.getMessages();
Message[] messages2 = null;
List noReadList=new ArrayList();
//读取数据库中是否存在这样的UID,如何存在,跳过,如果不存在,读取,并在UID表中插入一条记录,通过数据库的一个UID表来实现存储和判断。
//用查询的方式来实现判断 不用遍历数组的方式。
for (int i = 0; i < messages.length; i++) {
MimeMessage mimeMessage = (MimeMessage) messages[i];
String uid = inbox.getUID(mimeMessage);
if(!isExistUID(uid,conn)){
//添加-当符合条件的邮件才会被添加进list列表中,
noReadList.add(messages[i]);
}
}
return noReadList;
}
//读取有效的邮件信息,并把邮件信息插入到数据库中
//插入邮件的有效信息到表中
public void insertMailInfo(Message[] messages,Connection conn) throws Exception{
for(int m=0;m<messages.length;m++) {
//邮件发送者的对象获取
String from = decodeText(messages[m].getFrom()[0].toString());
InternetAddress ia = new InternetAddress(from);
//邮件内容
StringBuffer bodytext = new StringBuffer();
//如果邮件有附件的时候
if (messages[m].getContent() instanceof Multipart) {
Multipart mp = (Multipart) messages[m].getContent();
// 2012-03-14 只进行1次循环,我跟过代码,一次循环,就可以得到我需要的内容,两次循环,内容会重复取。
for (int t = 0; t < 1; t++) {
BodyPart part = mp.getBodyPart(t);
bodytext.append(getMailContent(part));
}
} //如果邮件就是直接的邮件--html格式-直接打印邮件内容
else if(messages[m].isMimeType("text/html")){
//html--转换成 text 文本
//其中html2text方法是我写的专门处理html内容转成text内容的方法。WebFormatter是我建立的一个类,包含一个html到text文本转换的方法。
String htmlToText=WebFormatter.html2text(messages[m].getContent().toString());
bodytext.append(htmlToText);
}
//如果邮件就是直接的邮件--text--格式-直接打印邮件内容
else{
//直接的文本邮件
bodytext.append(messages[m].getContent());
}
// 邮件标题
String mailTitle= messages[m].getSubject();
//发送人的邮件地址
String fromMail= ia.getAddress();
//邮件正文内容
String mailContext=tempBody;
//得到邮件抄送人信息
String ccString=decodeText(getCCString(messages[m].getRecipients(Message.RecipientType.CC)));
}
在网上有现成的DummySSLSocketFactory类如下:
import com.sun.net.ssl.*;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
public class DummySSLSocketFactory extends SSLSocketFactory {
private SSLSocketFactory factory;
public DummySSLSocketFactory() {
try {
SSLContext sslcontext = SSLContext.getInstance( "TLS");
sslcontext.init( null, // No KeyManager required
new TrustManager[] { new DummyTrustManager()},
new java.security.SecureRandom());
factory = ( SSLSocketFactory) sslcontext.getSocketFactory();
} catch( Exception ex) {
ex.printStackTrace();
}
}
public static SocketFactory getDefault() {
return new DummySSLSocketFactory();
}
public Socket createSocket() throws IOException {
return factory.createSocket();
}
public Socket createSocket( Socket socket, String s, int i, boolean
flag)
throws IOException {
return factory.createSocket( socket, s, i, flag);
}
public Socket createSocket( InetAddress inaddr, int i,
InetAddress inaddr1, int j) throws IOException {
return factory.createSocket( inaddr, i, inaddr1, j);
}
public Socket createSocket( InetAddress inaddr, int i) throws
IOException {
return factory.createSocket( inaddr, i);
}
public Socket createSocket( String s, int i, InetAddress inaddr, int j)
throws IOException {
return factory.createSocket( s, i, inaddr, j);
}
public Socket createSocket( String s, int i) throws IOException {
return factory.createSocket( s, i);
}
public String[] getDefaultCipherSuites() {
return factory.getSupportedCipherSuites();
}
public String[] getSupportedCipherSuites() {
return factory.getSupportedCipherSuites();
}
}
// DummySSLSocketFactory的依赖类 如下:
import java.security.cert.X509Certificate;
import com.sun.net.ssl.X509TrustManager;
public class DummyTrustManager implements X509TrustManager{
public boolean isClientTrusted( X509Certificate[] cert) {
return true;
}
public boolean isServerTrusted( X509Certificate[] cert) {
return true;
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[ 0];
}
}