前回はpop3でYahooメールの受信箱を巡回して特定メールを読みだすプログラムを書きましたが、受信箱の中のメールをすべて走査する仕組みだったため、受信箱にいっぱいメールがあると時間がかかります。
調べてみると、IMAPというプロトコルであればサーバ側でメールの検索が行えるとのこと。処理時間や通信量の削減が期待できそうなので、さっそくテストコードを書いてみました。
IMAPサーバへの接続設定は下表になります。
設定項目 | 入力内容 |
---|---|
受信メール(IMAP)サーバー) | imap.mail.yahoo.co.jp |
受信メール(IMAP)ポート番号 | 993 |
アカウント名、または、ログイン名 | Yahoo! JAPAN ID |
パスワード | Yahoo! JAPAN IDのパスワード |
IMAPサーバへの接続はPOPサーバへの接続の時とあまり変わりません。メール検索条件であるSearchTermオブジェクトを生成して、メッセージを取得しているところが今回のポイントです。
- Subjectに “の日記” が含まれていること。
- 受信日が本日であること。(時分秒の指定は無視されるため、EQ(一致)、 new Date()で機能します)
- Fromに “no-reply@plaza.rakuten.co.jp” が含まれていること。
今回はこの3つの条件で、記事投稿用メールアドレスについてのメールかどうかを判定しています。
// https://mvnrepository.com/artifact/com.sun.mail/javax.mail
@Grab(group='com.sun.mail', module='javax.mail', version='1.6.2')
import javax.mail.Folder
import javax.mail.Message
import javax.mail.Session
import javax.mail.Store
import javax.mail.URLName
import javax.mail.search.AndTerm
import javax.mail.search.ComparisonTerm
import javax.mail.search.FromStringTerm
import javax.mail.search.ReceivedDateTerm
import javax.mail.search.SearchTerm
import javax.mail.search.SubjectTerm
String host = 'imap.mail.yahoo.co.jp'
String user = '******'
String pass = '******'
String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
Properties properties = System.properties
properties.setProperty('mail.imap.socketFactory.class', SSL_FACTORY)
properties.setProperty('mail.imap.ssl.trust', '*')
Session session = Session.getDefaultInstance(properties)
URLName urln = new URLName('imap', host, 993, null, user, pass)
Store store = session.getStore(urln)
store.connect()
Folder inbox = store.getFolder("INBOX")
inbox.open(Folder.READ_ONLY)
SearchTerm[] stlst = [
new SubjectTerm('日の日記'),
new ReceivedDateTerm(ComparisonTerm.EQ, new Date()),
new FromStringTerm('no-reply@plaza.rakuten.co.jp')
]
SearchTerm st = new AndTerm(stlst)
inbox.search(st).each { Message msg->
println("Subject : ${msg.getSubject()}")
println(" From : ${msg.getFrom()}")
println(" ReplyTo : ${msg.getReplyTo()}")
}
inbox.close()
store.close()
検索条件は抽象クラスSearchTermを継承した条件クラスのオブジェクトを生成し、単体あるいは組み合わせて指定します。私自身、すこし手こずったので全体像をメモしておきます。
ちなみに日本語で検索するのは思ったように動きませんでした。コツがあるのかもしれません。
抽象 | クラス | メモ |
---|---|---|
○ | javax.mail.search.SearchTerm | |
○ | AddressTerm | |
FromTerm | fromに指定Addressが存在するか。ざっくり絞り込むならFromStringTerm の方が向いていそう。 | |
RecipientTerm | recipientに指定Addressが存在するか。ざっくり絞り込むならRecipientStringTermの方が向いていそう。 | |
○ | ComparisonTerm | 比較条件の抽象クラス |
○ | DateTerm | 日付比較 |
ReceivedDateTerm | 受信日で絞り込む。条件は ComparisonTerm で定義されているものを指定。日付はDate型で指定するが時分秒は無視される。 | |
SentDateTerm | ||
○ | IntegerComparisonTerm | 数値比較 |
MessageNumberTerm | ||
SizeTerm | ||
FlagTerm | メッセージのフラグ状態で抽出する。フラグの種類はjavax.mail.Flagsで定義されている。 | |
ModifiedSinceTerm | ||
OlderTerm | ||
YoungerTerm | ||
○ | StringTerm | 指定の文字列が含まれているか。 |
○ | AddressStringTerm | |
FromStringTerm | ||
RecipientStringTerm | ||
BodyTerm | ||
HeaderTerm | ||
MessageIDTerm | ||
SubjectTerm | ||
AndTerm | 2つ以上の条件オブジェクトをAND結合する。 | |
OrTerm | 2つ以上の条件オブジェクトをOR結合する。 | |
NotTerm | 指定した条件オブジェクトの論理を反転する。 |