一简介SMTP 的全称是Simple Mail Transfer Protocol即简单邮件传输协议用于邮件发送SMTP 认证简单地说就是要求必须在提供了账户名和密码之后才可以登录 SMTP 服务器
POP(Post Office Protocol )协议允许电子邮件客户端下载服务器上的邮件但是在客户端的操作(如移动邮件标记已读等)不会反馈到服务器上比如通过客户端收取了邮箱中的封邮件并移动到其他文件夹邮箱服务器上的这些邮件是没有同时被移动的
而IMAP(Internet Mail Access Protocol)提供webmail 与电子邮件客户端之间的双向通信客户端的操作都会反馈到服务器上对邮件进行的操作服务器上的邮件也会做相应的动作
同时IMAP像POP那样提供了方便的邮件下载服务让用户能进行离线阅读IMAP提供的摘要浏览功能可以让你在阅读完所有的邮件到达时间主题发件人大小等信息后才作出是否下载的决定此外IMAP 更好地支持了从多个不同设备中随时访问新邮件
总之IMAP 整体上为用户带来更为便捷和可靠的体验POP 更易丢失邮件或多次下载相同的邮件但 IMAP 通过邮件客户端与webmail 之间的双向同步功能很好地避免了这些问题
注若在web邮箱中设置了保存到已发送使用客户端POP服务发信时已发邮件也会自动同步到网页端已发送文件夹内
二利用SMTP协议发送邮件package comlikeemail;
import javaioFile;
import javaioUnsupportedEncodingException;
import javautilArrayList;
import javautilProperties;
import javaxactivationDataHandler;
import javaxactivationDataSource;
import javaxactivationFileDataSource;
import javaxmailAuthenticator;
import javaxmailBodyPart;
import javaxmailMessage;
import javaxmailMessagingException;
import javaxmailMultipart;
import javaxmailSession;
import javaxmailTransport;
import javaxmailinternetAddressException;
import javaxmailinternetInternetAddress;
import javaxmailinternetMimeBodyPart;
import javaxmailinternetMimeMessage;
import javaxmailinternetMimeMultipart;
/**
* @author like
* @Email k
* @CreateTime 下午::
*/
public class SMTPSendTest {
private static final int RECEIPT = ;
private static final String attachmentDir = ;
public static void sendEmail(Email emailInfo) throws UnsupportedEncodingException MessagingException {
Properties props = new Properties()
propsput(mailsmtphost emailInfogetSmtpServer())
propsput(mailsmtpport emailInfogetSmtpPort())
propsput(mailsmtpauth true)
Authenticator auth = new SMTPAuthenticator(emailInfogetUsername() emailInfogetPassword())
Session session = SessiongetInstance(props auth)
sessionsetDebug(false)
Message msg = new MimeMessage(session)
msgsetFrom(new InternetAddress(emailInfogetFrom() emailInfogetFromName()))
msgsetRecipients(MessageRecipientTypeTO getEmailRecipient(emailInfogetTO()))
msgsetRecipients(MessageRecipientTypeCC getEmailRecipient(emailInfogetCC()))
msgsetRecipients(MessageRecipientTypeBCC getEmailRecipient(emailInfogetBCC()))
if (emailInfogetReceipt() == RECEIPT) {
msgsetHeader(DispositionNotificationTo emailInfogetFrom())
}
msgsetSubject(emailInfogetSubject())
// 设置邮件内容(包括附件的HTML格式内容)
msgsetContent(getMultipart(emailInfogetContent() attachmentDir emailInfogetAttachment()))
msgsaveChanges()
Transportsend(msg)
}
/**
* 封装邮件地址
*
* @param address
* @return
* @throws AddressException
*/
private static InternetAddress[] getEmailRecipient(ArrayList<String> address) throws AddressException {
int toLen = ;
if (address != null) {
toLen = addresssize()
}
InternetAddress[] addressTo = new InternetAddress[toLen];
if (toLen != ) {
String m_st_email = ;
for (int i = ; i < toLen; i++) {
m_st_email = (String) addressget(i)
if (m_st_email != null)
addressTo[i] = new InternetAddress(m_st_emailtrim())
}
}
return addressTo;
}
private static Multipart getMultipart(String text String attachParentDir ArrayList<String> attachment) throws MessagingException {
// 混合型邮件内容
Multipart multi = new MimeMultipart(mixed)// 混合MIME消息
// 加入文本内容
multiaddBodyPart(createContent(text))
// 加入附件内容
for (int i = ; i < attachmentsize() i++) {
String attachmentI = (String) attachmentget(i)
// 附件的真是存储名称
String fileRealName = attachmentIsubstring(attachmentIindexOf(<) + )trim()
// 附件在邮件中的显示名称
String fileShowName = attachmentIsubstring( attachmentIindexOf(>))
multiaddBodyPart(createAttachment(fileShowName new File(attachParentDir + fileRealName)))// 嵌入附件
}
return multi;
}
/**
* 邮件附件的处理
*
* @param fileName
* 附件显示名称
* @param file
* 文件
* @return javaxmailBodyPart(javaMail的邮件内容)
* @throws MessagingException
*/
private static BodyPart createAttachment(String fileName File file) throws MessagingException {
BodyPart attach = new MimeBodyPart()
DataSource ds = new FileDataSource(file)
attachsetDataHandler(new DataHandler(ds))
try {
// 文件名重新编码解决乱码问题
attachsetFileName(new String(fileNamegetBytes() ISO))
} catch (UnsupportedEncodingException e) {
eprintStackTrace()
}
return attach;
}
/**
* 邮件文本内容的处理
*
* @param text
* 文本内容
* @return javaxmailBodyPart(javaMail的邮件内容)
* @throws MessagingException
*/
private static BodyPart createContent(String text) throws MessagingException {
BodyPart content = new MimeBodyPart()
// 邮件正文也是一种组合消息可以包含多个MimeBodyPart
Multipart relate = new MimeMultipart(related)
BodyPart html = new MimeBodyPart()
htmlsetContent(text text/html;charset=gbk)
relateaddBodyPart(html)
contentsetContent(relate)
return content;
}
}
邮件内容结构图
三POP协议接受邮件
package comlikeemail;
import javautilProperties;
import javaxmailAuthenticator;
import javaxmailFlags;
import javaxmailFolder;
import javaxmailMessage;
import javaxmailMessagingException;
import javaxmailSession;
import javaxmailStore;
import comsunmailpopPOPFolder;
/**
* POP协议虽然相较IMAP协议有明显劣势但仍然使用广泛而且并不是所有的邮件服务器都支持IMAP协议
* @author like
* @Email k
* @CreateTime 下午::
*/
public class OPTest {
public static void receive(String server int port String username String password boolean isDelete) throws MessagingException {
Properties props = SystemgetProperties()
Authenticator auth = new POPAuthenticator(username password)
Session session = SessiongetInstance(props auth)
sessionsetDebug(false)
Store store = sessiongetStore(POP)
nnect(server port username password)
//获得收件箱
POPFolder folder = (POPFolder) storegetFolder(INBOX)
try {
//读写方式打开
folderopen(FolderREAD_WRITE)
} catch (MessagingException ex) {
//制度方式打开
folderopen(FolderREAD_ONLY)
}
// int totalMessages = foldergetMessageCount()
Message m_message = null;
Message[] msgs = foldergetMessages()
for (int i = ; i < msgslength; i++) {
m_message = msgs[i];
String UID = foldergetUID(m_message)
if (haveReceived(UID)) {
// 插入数据库
// mailListadd(new RecvMailTask(m_message
// p_st_attachmentParentDir UID))
// 设置为已读IMAP协议支持POP协议不支持该功能
m_messagesetFlag(FlagsFlagSEEN true)
// POP协议可以删除
m_messagesetFlag(FlagsFlagDELETED isDelete)
}
}
}
/**
* POP协议的对邮件的操作和服务器不同步不能区分是否为已读邮件 如果接收后不删除服务器上的邮件下次仍然会接收该邮件
* 服务器会给每一封邮件一个独一无二的UID接收邮件时保存该UID到数据库作为下次接收时是否已经接收过该邮件的依据
* 有两种方式()每次接收先从数据库中读取所有的UID接收时判断是否包含当次接收邮件的UID
* 优点是只读一次数据库缺点是读出的UID数量可能会很多
* ()接收每一封邮件时把其UID作为参数查询数据库是否返回数据作为判断依据
*
* @param UID
* @return
*/
private static boolean haveReceived(String UID) {
//个人觉得第一种较好如果邮箱中邮件较多接收又较为频繁那么每次接收都会产生大量数据库连接次数
//第一种注意把取得的UID集放入到Set集合中用contains()方法直接判断
return true;
}