用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字
云代码 - java代码库

java邮件接收器 pop3协议

2012-11-16 作者: 程序猿style举报

[java]代码库

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.Date;

import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

import java.util.Properties;

/**
 * 邮件接收器,目前支持pop3协议。 能够接收文本、HTML和带有附件的邮件
 * 
 * 需要导入mail.jar
 */
public class MailReceiver {
	// 收邮件的参数配置
	private MailReceiverInfo receiverInfo;
	// 与邮件服务器连接后得到的邮箱
	private Store store;
	// 收件箱
	private Folder folder;
	// 收件箱中的邮件消息
	private Message[] messages;
	// 当前正在处理的邮件消息
	private Message currentMessage;

	private String currentEmailFileName;

	public MailReceiver(MailReceiverInfo receiverInfo) {
		this.receiverInfo = receiverInfo;
	}

	/**
	 * 收邮件
	 */
	public void receiveAllMail() throws Exception {
		if (this.receiverInfo == null) {
			throw new Exception("必须提供接收邮件的参数!");
		}
		// 连接到服务器
		if (this.connectToServer()) {
			// 打开收件箱
			if (this.openInBoxFolder()) {
				// 获取所有邮件
				this.getAllMail();
				this.closeConnection();
			} else {
				throw new Exception("打开收件箱失败!");
			}
		} else {
			throw new Exception("连接邮件服务器失败!");
		}
	}

	/**
	 * 登陆邮件服务器
	 */
	private boolean connectToServer() {
		// 判断是否需要身份认证
		MyAuthenticator authenticator = null;
		if (this.receiverInfo.isValidate()) {
			// 如果需要身份认证,则创建一个密码验证器
			authenticator = new MyAuthenticator(
					this.receiverInfo.getUserName(),
					this.receiverInfo.getPassword());
		}
		// 创建session
		Session session = Session.getInstance(
				this.receiverInfo.getProperties(), authenticator);

		// 创建store,建立连接
		try {
			this.store = session.getStore(this.receiverInfo.getProtocal());
		} catch (NoSuchProviderException e) {
			System.out.println("连接服务器失败!");
			return false;
		}

		System.out.println("connecting");
		try {
			this.store.connect();
		} catch (MessagingException e) {
			System.out.println("连接服务器失败!");
			return false;
		}
		System.out.println("连接服务器成功");
		return true;
	}

	/**
	 * 打开收件箱
	 */
	private boolean openInBoxFolder() {
		try {
			this.folder = store.getFolder("INBOX");
			// 只读
			folder.open(Folder.READ_ONLY);
			return true;
		} catch (MessagingException e) {
			System.err.println("打开收件箱失败!");
		}
		return false;
	}

	/**
	 * 断开与邮件服务器的连接
	 */
	private boolean closeConnection() {
		try {
			if (this.folder.isOpen()) {
				this.folder.close(true);
			}
			this.store.close();
			System.out.println("成功关闭与邮件服务器的连接!");
			return true;
		} catch (Exception e) {
			System.out.println("关闭和邮件服务器之间连接时出错!");
		}
		return false;
	}

	/**
	 * 获取messages中的所有邮件
	 * 
	 * @throws MessagingException
	 */
	private void getAllMail() throws MessagingException {
		// 从邮件文件夹获取邮件信息
		this.messages = this.folder.getMessages();
		System.out.println("总的邮件数目:" + messages.length);
		System.out.println("新邮件数目:" + this.getNewMessageCount());
		System.out.println("未读邮件数目:" + this.getUnreadMessageCount());
		// 将要下载的邮件的数量。
		int mailArrayLength = this.getMessageCount();
		System.out.println("一共有邮件" + mailArrayLength + "封");
		int errorCounter = 0; // 邮件下载出错计数器
		int successCounter = 0;
		for (int index = 0; index < mailArrayLength; index++) {
			try {
				this.currentMessage = (messages[index]); // 设置当前message
				System.out.println("正在获取第" + index + "封邮件......");
				this.showMailBasicInfo();
				getMail(); // 获取当前message
				System.out.println("成功获取第" + index + "封邮件");
				successCounter++;
			} catch (Throwable e) {
				errorCounter++;
				System.err.println("下载第" + index + "封邮件时出错");
			}
		}
		System.out.println("------------------");
		System.out.println("成功下载了" + successCounter + "封邮件");
		System.out.println("失败下载了" + errorCounter + "封邮件");
		System.out.println("------------------");
	}

	/**
	 * 显示邮件的基本信息
	 */
	private void showMailBasicInfo() throws Exception {
		showMailBasicInfo(this.currentMessage);
	}

	private void showMailBasicInfo(Message message) throws Exception {
		System.out.println("-------- 邮件ID:" + this.getMessageId()
				+ " ---------");
		System.out.println("From:" + this.getFrom());
		System.out.println("To:" + this.getTOAddress());
		System.out.println("CC:" + this.getCCAddress());
		System.out.println("BCC:" + this.getBCCAddress());
		System.out.println("Subject:" + this.getSubject());
		System.out.println("发送时间::" + this.getSentDate());
		System.out.println("是新邮件?" + this.isNew());
		System.out.println("要求回执?" + this.getReplySign());
		System.out.println("包含附件?" + this.isContainAttach());
		System.out.println("------------------------------");
	}

	/**
	 * 获得邮件的收件人,抄送,和密送的地址和姓名,根据所传递的参数的不同 "to"----收件人 "cc"---抄送人地址 "bcc"---密送人地址
	 */
	private String getTOAddress() throws Exception {
		return getMailAddress("TO", this.currentMessage);
	}

	private String getCCAddress() throws Exception {
		return getMailAddress("CC", this.currentMessage);
	}

	private String getBCCAddress() throws Exception {
		return getMailAddress("BCC", this.currentMessage);
	}

	/**
	 * 获得邮件地址
	 * 
	 * @param type
	 *            类型,如收件人、抄送人、密送人
	 * @param mimeMessage
	 *            邮件消息
	 * @return
	 * @throws Exception
	 */
	private String getMailAddress(String type, Message mimeMessage)
			throws Exception {
		String mailaddr = "";
		String addtype = type.toUpperCase();
		InternetAddress[] address = null;
		if (addtype.equals("TO") || addtype.equals("CC")
				|| addtype.equals("BCC")) {
			if (addtype.equals("TO")) {
				address = (InternetAddress[]) mimeMessage
						.getRecipients(Message.RecipientType.TO);
			} else if (addtype.equals("CC")) {
				address = (InternetAddress[]) mimeMessage
						.getRecipients(Message.RecipientType.CC);
			} else {
				address = (InternetAddress[]) mimeMessage
						.getRecipients(Message.RecipientType.BCC);
			}
			if (address != null) {
				for (int i = 0; i < address.length; i++) {
					// 先获取邮件地址
					String email = address[i].getAddress();
					if (email == null) {
						email = "";
					} else {
						email = MimeUtility.decodeText(email);
					}
					// 再取得个人描述信息
					String personal = address[i].getPersonal();
					if (personal == null) {
						personal = "";
					} else {
						personal = MimeUtility.decodeText(personal);
					}
					// 将个人描述信息与邮件地址连起来
					String compositeto = personal + "<" + email + ">";
					// 多个地址时,用逗号分开
					mailaddr += "," + compositeto;
				}
				mailaddr = mailaddr.substring(1);
			}
		} else {
			throw new Exception("错误的地址类型!!");
		}
		return mailaddr;
	}

	/**
	 * 获得发件人的地址和姓名
	 * 
	 * @throws Exception
	 */
	private String getFrom() throws Exception {
		return getFrom(this.currentMessage);
	}

	private String getFrom(Message mimeMessage) throws Exception {
		InternetAddress[] address = (InternetAddress[]) mimeMessage.getFrom();
		// 获得发件人的邮箱
		String from = address[0].getAddress();
		if (from == null) {
			from = "";
		}
		// 获得发件人的描述信息
		String personal = address[0].getPersonal();
		if (personal == null) {
			personal = "";
		}
		// 拼成发件人完整信息
		String fromaddr = personal + "<" + from + ">";
		return fromaddr;
	}

	/**
	 * 获取messages中message的数量
	 * 
	 * @return
	 */
	private int getMessageCount() {
		return this.messages.length;
	}

	/**
	 * 获得收件箱中新邮件的数量
	 * 
	 * @return
	 * @throws MessagingException
	 */
	private int getNewMessageCount() throws MessagingException {
		return this.folder.getNewMessageCount();
	}

	/**
	 * 获得收件箱中未读邮件的数量
	 * 
	 * @return
	 * @throws MessagingException
	 */
	private int getUnreadMessageCount() throws MessagingException {
		return this.folder.getUnreadMessageCount();
	}

	/**
	 * 获得邮件主题
	 */
	private String getSubject() throws MessagingException {
		return getSubject(this.currentMessage);
	}

	private String getSubject(Message mimeMessage) throws MessagingException {
		String subject = "";
		try {
			// 将邮件主题解码
			subject = MimeUtility.decodeText(mimeMessage.getSubject());
			if (subject == null) {
				subject = "";
			}
		} catch (Exception exce) {
		}
		return subject;
	}

	/**
	 * 获得邮件发送日期
	 */
	private Date getSentDate() throws Exception {
		return getSentDate(this.currentMessage);
	}

	private Date getSentDate(Message mimeMessage) throws Exception {
		return mimeMessage.getSentDate();
	}

	/**
	 * 判断此邮件是否需要回执,如果需要回执返回"true",否则返回"false"
	 */
	private boolean getReplySign() throws MessagingException {
		return getReplySign(this.currentMessage);
	}

	private boolean getReplySign(Message mimeMessage) throws MessagingException {
		boolean replysign = false;
		String needreply[] = mimeMessage
				.getHeader("Disposition-Notification-To");
		if (needreply != null) {
			replysign = true;
		}
		return replysign;
	}

	/**
	 * 获得此邮件的Message-ID
	 */
	private String getMessageId() throws MessagingException {
		return getMessageId(this.currentMessage);
	}

	private String getMessageId(Message mimeMessage) throws MessagingException {
		return ((MimeMessage) mimeMessage).getMessageID();
	}

	/**
	 * 判断此邮件是否已读,如果未读返回返回false,反之返回true
	 */
	private boolean isNew() throws MessagingException {
		return isNew(this.currentMessage);
	}

	private boolean isNew(Message mimeMessage) throws MessagingException {
		boolean isnew = false;
		Flags flags = mimeMessage.getFlags();
		Flags.Flag[] flag = flags.getSystemFlags();
		for (int i = 0; i < flag.length; i++) {
			if (flag[i] == Flags.Flag.SEEN) {
				isnew = true;
				break;
			}
		}
		return isnew;
	}

	/**
	 * 判断此邮件是否包含附件
	 */
	private boolean isContainAttach() throws Exception {
		return isContainAttach(this.currentMessage);
	}

	private boolean isContainAttach(Part part) throws Exception {
		boolean attachflag = false;
		if (part.isMimeType("multipart/*")) {
			// 如果邮件体包含多部分
			Multipart mp = (Multipart) part.getContent();
			// 遍历每部分
			for (int i = 0; i < mp.getCount(); i++) {
				// 获得每部分的主体
				BodyPart bodyPart = mp.getBodyPart(i);
				String disposition = bodyPart.getDisposition();
				if ((disposition != null)
						&& ((disposition.equals(Part.ATTACHMENT)) || (disposition
								.equals(Part.INLINE)))) {
					attachflag = true;
				} else if (bodyPart.isMimeType("multipart/*")) {
					attachflag = isContainAttach((Part) bodyPart);
				} else {
					String contype = bodyPart.getContentType();
					if (contype.toLowerCase().indexOf("application") != -1) {
						attachflag = true;
					}
					if (contype.toLowerCase().indexOf("name") != -1) {
						attachflag = true;
					}
				}
			}
		} else if (part.isMimeType("message/rfc822")) {
			attachflag = isContainAttach((Part) part.getContent());
		}
		return attachflag;
	}

	/**
	 * 获得当前邮件
	 */
	private void getMail() throws Exception {
		try {
			this.saveMessageAsFile(currentMessage);
			this.parseMessage(currentMessage);
		} catch (IOException e) {
			throw new IOException("保存邮件出错,检查保存路径");
		} catch (MessagingException e) {
			throw new MessagingException("邮件转换出错");
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception("未知错误");
		}
	}

	/**
	 * 保存邮件源文件
	 */
	private void saveMessageAsFile(Message message) {
		try {
			// 将邮件的ID中尖括号中的部分做为邮件的文件名
			String oriFileName = getInfoBetweenBrackets(this.getMessageId(
					message).toString());
			// 设置文件后缀名。若是附件则设法取得其文件后缀名作为将要保存文件的后缀名,
			// 若是正文部分则用.htm做后缀名
			String emlName = oriFileName;
			String fileNameWidthExtension = this.receiverInfo.getEmailDir()
					+ oriFileName + this.receiverInfo.getEmailFileSuffix();
			File storeFile = new File(fileNameWidthExtension);
			for (int i = 0; storeFile.exists(); i++) {
				emlName = oriFileName + i;
				fileNameWidthExtension = this.receiverInfo.getEmailDir()
						+ emlName + this.receiverInfo.getEmailFileSuffix();
				storeFile = new File(fileNameWidthExtension);
			}
			this.currentEmailFileName = emlName;
			System.out.println("邮件消息的存储路径: " + fileNameWidthExtension);
			// 将邮件消息的内容写入ByteArrayOutputStream流中
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			message.writeTo(baos);
			// 读取邮件消息流中的数据
			StringReader in = new StringReader(baos.toString());
			// 存储到文件
			saveFile(fileNameWidthExtension, in);
		} catch (MessagingException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * 解析邮件
	 */
	private void parseMessage(Message message) throws IOException,
			MessagingException {
		Object content = message.getContent();
		// 处理多部分邮件
		if (content instanceof Multipart) {
			handleMultipart((Multipart) content);
		} else {
			handlePart(message);
		}
	}

	/*
	 * 解析Multipart
	 */
	private void handleMultipart(Multipart multipart)
			throws MessagingException, IOException {
		for (int i = 0, n = multipart.getCount(); i < n; i++) {
			handlePart(multipart.getBodyPart(i));
		}
	}

	/*
	 * 解析指定part,从中提取文件
	 */
	private void handlePart(Part part) throws MessagingException, IOException {
		String disposition = part.getDisposition();
		String contentType = part.getContentType();
		String fileNameWidthExtension = "";
		// 获得邮件的内容输入流
		InputStreamReader sbis = new InputStreamReader(part.getInputStream());
		// 没有附件的情况
		if (disposition == null) {
			if ((contentType.length() >= 10)
					&& (contentType.toLowerCase().substring(0, 10)
							.equals("text/plain"))) {
				fileNameWidthExtension = this.receiverInfo.getAttachmentDir()
						+ this.currentEmailFileName + ".txt";
			} else if ((contentType.length() >= 9) // Check if html
					&& (contentType.toLowerCase().substring(0, 9)
							.equals("text/html"))) {
				fileNameWidthExtension = this.receiverInfo.getAttachmentDir()
						+ this.currentEmailFileName + ".html";
			} else if ((contentType.length() >= 9) // Check if html
					&& (contentType.toLowerCase().substring(0, 9)
							.equals("image/gif"))) {
				fileNameWidthExtension = this.receiverInfo.getAttachmentDir()
						+ this.currentEmailFileName + ".gif";
			} else if ((contentType.length() >= 11)
					&& contentType.toLowerCase().substring(0, 11)
							.equals("multipart/*")) {
				// System.out.println("multipart body: " + contentType);
				handleMultipart((Multipart) part.getContent());
			} else { // Unknown type
				// System.out.println("Other body: " + contentType);
				fileNameWidthExtension = this.receiverInfo.getAttachmentDir()
						+ this.currentEmailFileName + ".txt";
			}
			// 存储内容文件
			System.out.println("保存邮件内容到:" + fileNameWidthExtension);
			saveFile(fileNameWidthExtension, sbis);

			return;
		}

		// 各种有附件的情况
		String name = "";
		if (disposition.equalsIgnoreCase(Part.ATTACHMENT)) {
			name = getFileName(part);
			// System.out.println("Attachment: " + name + " : "
			// + contentType);
			fileNameWidthExtension = this.receiverInfo.getAttachmentDir()
					+ name;
		} else if (disposition.equalsIgnoreCase(Part.INLINE)) {
			name = getFileName(part);
			// System.out.println("Inline: " + name + " : "
			// + contentType);
			fileNameWidthExtension = this.receiverInfo.getAttachmentDir()
					+ name;
		} else {
			// System.out.println("Other: " + disposition);
		}
		// 存储各类附件
		if (!fileNameWidthExtension.equals("")) {
			System.out.println("保存邮件附件到:" + fileNameWidthExtension);
			saveFile(fileNameWidthExtension, sbis);
		}
	}

	private String getFileName(Part part) throws MessagingException,
			UnsupportedEncodingException {
		String fileName = part.getFileName();
		fileName = MimeUtility.decodeText(fileName);
		String name = fileName;
		if (fileName != null) {
			int index = fileName.lastIndexOf("/");
			if (index != -1) {
				name = fileName.substring(index + 1);
			}
		}
		return name;
	}

	/**
	 * 保存文件内容
	 * 
	 * @param fileName
	 *            文件名
	 * @param input
	 *            输入流
	 * @throws IOException
	 */
	private void saveFile(String fileName, Reader input) throws IOException {

		// 为了放置文件名重名,在重名的文件名后面天上数字
		File file = new File(fileName);
		// 先取得文件名的后缀
		int lastDot = fileName.lastIndexOf(".");
		String extension = fileName.substring(lastDot);
		fileName = fileName.substring(0, lastDot);
		for (int i = 0; file.exists(); i++) {
			//  如果文件重名,则添加i
			file = new File(fileName + i + extension);
		}
		// 从输入流中读取数据,写入文件输出流
		FileWriter fos = new FileWriter(file);
		BufferedWriter bos = new BufferedWriter(fos);
		BufferedReader bis = new BufferedReader(input);
		int aByte;
		while ((aByte = bis.read()) != -1) {
			bos.write(aByte);
		}
		// 关闭流
		bos.flush();
		bos.close();
		bis.close();
	}

	/**
	 * 获得尖括号之间的字符
	 * 
	 * @param str
	 * @return
	 * @throws Exception
	 */
	private String getInfoBetweenBrackets(String str) throws Exception {
		int i, j; // 用于标识字符串中的"<"和">"的位置
		if (str == null) {
			str = "error";
			return str;
		}
		i = str.lastIndexOf("<");
		j = str.lastIndexOf(">");
		if (i != -1 && j != -1) {
			str = str.substring(i + 1, j);
		}
		return str;
	}

	public static void main(String[] args) throws Exception {
		MailReceiverInfo receiverInfo = new MailReceiverInfo();
		receiverInfo.setMailServerHost("pop.163.com");
		receiverInfo.setMailServerPort("110");
		receiverInfo.setValidate(true);
		receiverInfo.setUserName("***");
		receiverInfo.setPassword("***");
		receiverInfo.setAttachmentDir("C:/temp/mail/");
		receiverInfo.setEmailDir("C:/temp/mail/");

		MailReceiver receiver = new MailReceiver(receiverInfo);
		receiver.receiveAllMail();
	}
}

/**
 * 收邮件的基本信息
 */
class MailReceiverInfo {
	// 邮件服务器的IP、端口和协议
	private String mailServerHost;
	private String mailServerPort = "110";
	private String protocal = "pop3";
	// 登陆邮件服务器的用户名和密码
	private String userName;
	private String password;
	// 保存邮件的路径
	private String attachmentDir = "C:/temp/";
	private String emailDir = "C:/temp/";
	private String emailFileSuffix = ".eml";
	// 是否需要身份验证
	private boolean validate = true;

	/**
	 * 获得邮件会话属性
	 */
	public Properties getProperties() {
		Properties p = new Properties();
		p.put("mail.pop3.host", this.mailServerHost);
		p.put("mail.pop3.port", this.mailServerPort);
		p.put("mail.pop3.auth", validate ? "true" : "false");
		return p;
	}

	public String getProtocal() {
		return protocal;
	}

	public void setProtocal(String protocal) {
		this.protocal = protocal;
	}

	public String getAttachmentDir() {
		return attachmentDir;
	}

	public void setAttachmentDir(String attachmentDir) {
		if (!attachmentDir.endsWith(File.separator)) {
			attachmentDir = attachmentDir + File.separator;
		}
		this.attachmentDir = attachmentDir;
	}

	public String getEmailDir() {
		return emailDir;
	}

	public void setEmailDir(String emailDir) {
		if (!emailDir.endsWith(File.separator)) {
			emailDir = emailDir + File.separator;
		}
		this.emailDir = emailDir;
	}

	public String getEmailFileSuffix() {
		return emailFileSuffix;
	}

	public void setEmailFileSuffix(String emailFileSuffix) {
		if (!emailFileSuffix.startsWith(".")) {
			emailFileSuffix = "." + emailFileSuffix;
		}
		this.emailFileSuffix = emailFileSuffix;
	}

	public String getMailServerHost() {
		return mailServerHost;
	}

	public void setMailServerHost(String mailServerHost) {
		this.mailServerHost = mailServerHost;
	}

	public String getMailServerPort() {
		return mailServerPort;
	}

	public void setMailServerPort(String mailServerPort) {
		this.mailServerPort = mailServerPort;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public boolean isValidate() {
		return validate;
	}

	public void setValidate(boolean validate) {
		this.validate = validate;
	}

}

/**
 * 邮件身份认证器,在发送邮件时使用
 */
class MyAuthenticator extends Authenticator {
	// 登陆发送邮件服务器的用户名
	private String userName;
	// 登陆发送邮件服务器的密码
	private String password;

	public MyAuthenticator(String userName, String password) {
		this.userName = userName;
		this.password = password;
	}

	/**
	 * 覆盖父类的该方法,获得密码认证器
	 */
	protected PasswordAuthentication getPasswordAuthentication() {
		return new PasswordAuthentication(userName, password);
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}
}


网友评论    (发表评论)


发表评论:

评论须知:

  • 1、评论每次加2分,每天上限为30;
  • 2、请文明用语,共同创建干净的技术交流环境;
  • 3、若被发现提交非法信息,评论将会被删除,并且给予扣分处理,严重者给予封号处理;
  • 4、请勿发布广告信息或其他无关评论,否则将会删除评论并扣分,严重者给予封号处理。


扫码下载

加载中,请稍后...

输入口令后可复制整站源码

加载中,请稍后...