カテゴリー: JAVA

JAVA MAILを使用して、IMAP POP3からメールを取得するクラスです

 ここ2年ばかりPHPをやってきたのだけど、JAVAがやっぱりいいということで、JAVAをやるはめになりました。
ブログのタイトルは「PHP開発」ですが、昔に戻って、当分JAVAをやりそうです。
よろしく!

そんなことで、Java Mailを使ってメールボックスからメールを取得するクラスを作ってみました。
ご意見ご感想をお待ちしています。

package jp.compsys.common.util;

import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Address;
import javax.mail.Message.RecipientType;
import javax.mail.internet.MimeUtility;

import com.sun.mail.util.QPDecoderStream;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.Comparator;
import java.util.Properties;
import java.util.ArrayList;

/**
 * サーバからメールを取得するクラス.
 *
 * @author Computer System Corp tamura
 * @since 1.6
 * @version 1.0
 * @since 1.0
 */
public class MailReader implements Serializable
{
	private static final long serialVersionUID = -8161055025994457665L;
	private String server;
	private String protocol = "imap";
	private int port = 143;
	private String userId;
	private String password;

	private int pageNo = 0;
	private int recordCount = 0;
	private int maxPageNo = 0;

	private Session session;
	private Store store;
	private Folder folder;

	/**
	 * MailReaderのコンストラクタ.
	 * @param server 	接続するサーバ名またはIPアドレス
	 * @param port   	接続するポート番号
	 * @param userId	接続するユーザID
	 * @param password 	接続するパスワード
	 * @since			1.6
	 */
	public MailReader(String server, int port, String userId, String password)
	{
		this.server = server;
		this.protocol="imap";
		this.port = port;
		this.userId = userId;
		this.password = password;
/*
		this.protocol="pop3";
		this.port = -1;
*/
	}

	/**
	 * メールの内容を取得する。.
	 * @param	msgnum メッセージ番号
	 * @return	MailItemのインスタンスを返す。取得できない場合はnullを返す。
	 */
	public MailItem getMail(int msgnum)
	{
		MailItem mailItem = new MailItem();
		if(!open())	return null;
		try
		{
			folder = store.getFolder("INBOX");
			folder.open(Folder.READ_ONLY);
			if (!folder.exists())
			{
				close();
				return null;
			}
			Message m = folder.getMessage(msgnum);
			messageEdit(m, mailItem);
			Part p = m;
			partSet(p, mailItem);
		} catch (MessagingException ex)
		{
			mailItem = null;
			ex.printStackTrace();
		} catch (IOException ex)
		{
			mailItem = null;
			ex.printStackTrace();
		}
		close();
		return mailItem;
	}

	/**
	 * メールの一覧を取得(mailList)した後の実際の取得ページ番号を取得する。
	 * mailListメソッドを実行した後でなければ正しい値を返さない。.
	 */
	public int getPageNo()
	{
		return pageNo;
	}

	/**
	 * メールの一覧を取得(mailList)した時の総メール数を取得する。
	 * mailListメソッドを実行した後でなければ正しい値を返さない.
	 */
	public int getRecordCount()
	{
		return recordCount;
	}

	/**
	 * メールの一覧を取得(mailList)した時の最大ページ数を取得する。
	 * mailListメソッドを実行した後でなければ正しい値を返さない.
	 */
	public int getMaxPageNo()
	{
		return maxPageNo;
	}

	/**
	 * メールサーバに接続する。.
	 * @return	true:成功 false:失敗
	 */
	private boolean open()
	{
		Properties properties = System.getProperties();
		session = Session.getInstance(properties, null);
		try
		{
			store = session.getStore(protocol);
			store.connect(server, port, userId, password);
			return true;
		} catch (MessagingException ex)
		{
			ex.printStackTrace();
			return false;
		}
	}
	/**
	 * メールサーバとの接続をクローズする
	 */
	private void close()
	{
		if (null != store)
		{
			try
			{
				store.close();
			} catch (MessagingException ex)
			{
			}
		}
	}

	/**
	 * メールに含まれるメッセージや添付ファイルを取得する。.
	 */
	@SuppressWarnings("unchecked")
	public void partSet(Part p, MailItem m) throws MessagingException, IOException
	{
		MailContent mailContent = new MailContent();
		String disp = p.getDisposition();
		if (p.isMimeType("multipart/*"))
		{ // マルチパートの場合
			Multipart mp = (Multipart) p.getContent();
			int count = mp.getCount();
			for (int i = 0; i < count; i++)
			{
				partSet(mp.getBodyPart(i), m);
			}
			return;
		}
		else if (p.isMimeType("message/rfc822"))
		{ // メッセージの場合
			partSet((Part) p.getContent(), m);
			return;
		}
		else if (p.isMimeType("text/*"))
		{
			if(disp != null && disp.equalsIgnoreCase(Part.ATTACHMENT))
			{
				mailContent.attachmentFlg = true;
			}
			mailContent.header = p.getAllHeaders();
			mailContent.contentType = p.getContentType();
			mailContent.content = content2string(p.getContent());
			m.mailContents.add(mailContent);
			return;
		}
		// 添付ファイルの場合
		if (disp == null || disp.equalsIgnoreCase(Part.ATTACHMENT))
		{
			mailContent.contentBinaryFlg = true;
			mailContent.fileName = p.getFileName();
			if (mailContent.fileName != null)
			{
				mailContent.fileName = MimeUtility.decodeText(mailContent.fileName);
			}
			else
			{
				mailContent.fileName = "";
			}
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			try
			{
				p.writeTo(os);
				mailContent.content_binary = os.toByteArray();
			} catch (IOException e)
			{
				e.printStackTrace();
			}
			mailContent.header = p.getAllHeaders();
			mailContent.contentType = p.getContentType();
			mailContent.attachmentFlg=true;
			m.mailContents.add(mailContent);
		}
	}

	/**
	 * text/* に含まれるコンテンツを文字列として受け取る.
	 * @param	textコンテンツの内容
	 */
	private String content2string(Object obj) throws MessagingException
	{
		String ret = "";
		if (obj instanceof String)
		{
			return (String) obj;
		}
		else if (obj instanceof QPDecoderStream)
		{
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			QPDecoderStream qps = (QPDecoderStream) obj;
			while (true)
			{
				try
				{
					int c = qps.read();
					if (c == -1) break;
					os.write(c);
				} catch (IOException ex)
				{
					return ret;
				}
			}
			ret = os.toString();
		}
		else
		{
			throw new MessagingException("textのコンテンツファイルに未定義のものがあります");
		}
		return ret;
	}

	/**
	 * メールの一覧をぺジ単位に取得します。
	 * @param lineCount	1ページあたりの行数
	 * @param pageNo    取得したいページ
	 * @return	取得したメールの一覧を返します。メールがない場合はnullを返します。
	 */
	public ArrayList mailList(int lineCount, int pageNo)
	{
		this.pageNo = pageNo;
		recordCount = 0;
		maxPageNo = 0;
		ArrayList list = null;
		open();
		int start = 0;
		int end = 0;
		int cnt = 0;
		try
		{
			folder = store.getFolder("INBOX");
			if (!folder.exists())
			{
				close();
				return list;
			}
			folder.open(Folder.READ_ONLY);
			cnt = folder.getMessageCount();
			if (0 == cnt)
			{
				close();
				return list;
			}
			recordCount = cnt;
			maxPageNo = (int) Math.ceil((double) cnt / (double) lineCount);
			if (this.pageNo  maxPageNo) this.pageNo = maxPageNo;
			list = new ArrayList(cnt);
			Message mes[] = folder.getMessages();
			for (Message m : mes)
			{
				MailItem mailItem = new MailItem();
				messageEdit(m, mailItem);
//				一覧にメールの内容も取得したい場合はコメントをはずす かなり遅くなるのでやめたほうがいいです。
/*  			Part p = m;
				partSet(p, mailItem);
*/				list.add(mailItem);
			}
			folder.close(false);
		} catch (MessagingException ex)
		{
			ex.printStackTrace();
		} catch (Exception e)
		{
			e.printStackTrace();
		} finally
		{
		}
		close();
		Collections.sort(list, new Comparator()
		{
			public int compare(MailItem o1, MailItem o2)
			{
				return (o1.sentDate.compareTo(o2.sentDate) * (-1));
			}
		});
		start = (this.pageNo - 1) * lineCount;
		if (this.pageNo == maxPageNo)
		{
			end = start + ((cnt - 1) % lineCount);
		}
		else
		{
			end = start + lineCount - 1;
		}
		int i = -1;
		ArrayList retList = new ArrayList(end - start + 1);
		for (MailItem m : list)
		{
			i++;
			if (i  end) break;
			retList.add(m);
		}
		return retList;
	}

	/**
	 * メッセージに含まれるヘダー情報を取得編集する。
	 * @param m javax.mail.Message
	 * @param mailItem 編集対象
	 */
	private void messageEdit(Message m, MailItem mailItem)
	{
		try
		{
			mailItem.messageNo = m.getMessageNumber();
			mailItem.sentDate = m.getSentDate();
			mailItem.receivedDate = m.getReceivedDate();
			mailItem.subject = m.getSubject();
			Flags flags = m.getFlags();
			String[] userFlg = flags.getUserFlags();
			{
				if (m.isSet(Flags.Flag.ANSWERED))
				{
					mailItem.systemFlg.add("ANSWERED");
				}
				if (m.isSet(Flags.Flag.DELETED))
				{
					mailItem.systemFlg.add("DELETED");
				}
				if (m.isSet(Flags.Flag.DRAFT))
				{
					mailItem.systemFlg.add("DRAFT");
				}
				if (m.isSet(Flags.Flag.FLAGGED))
				{
					mailItem.systemFlg.add("FLAGGED");
				}
				if (m.isSet(Flags.Flag.RECENT))
				{
					mailItem.systemFlg.add("RECENT");
				}
				if (m.isSet(Flags.Flag.SEEN))
				{
					mailItem.systemFlg.add("SEEN");
				}
				if (m.isSet(Flags.Flag.USER))
				{
					mailItem.systemFlg.add("USER");
				}
			}
			if (null != userFlg)
			{
				for (int i = 0; i < userFlg.length; i++)
				{
					mailItem.userFlg.add(userFlg[i]);
				}
			}
			if (null != m.getFrom())
			{
				for (Address a : m.getFrom())
				{
					mailItem.from.add(MimeUtility.decodeText(a.toString()));
				}

			}
			if (null != m.getReplyTo())
			{
				for (Address a : m.getReplyTo())
				{
					mailItem.replyTo.add(MimeUtility.decodeText(a.toString()));
				}
			}
			if (null != m.getRecipients(RecipientType.TO))
			{
				for (Address a : m.getRecipients(RecipientType.TO))
				{
					mailItem.to.add(MimeUtility.decodeText(a.toString()));
				}
			}
			if (null != m.getRecipients(RecipientType.CC))
			{
				for (Address a : m.getRecipients(RecipientType.CC))
				{
					mailItem.cc.add(MimeUtility.decodeText(a.toString()));
				}
			}
			if (null != m.getRecipients(RecipientType.BCC))
			{
				for (Address a : m.getRecipients(RecipientType.BCC))
				{
					mailItem.bcc.add(MimeUtility.decodeText(a.toString()));
				}
			}
		} catch (UnsupportedEncodingException ex)
		{
			ex.printStackTrace();
		} catch (MessagingException ex)
		{
			ex.printStackTrace();
		} finally
		{
		}

	}

}
全自動マージャン卓
10万円未満で買える
折りたたんで収納


会社に1台

AMAZON