通过Java Mail访问Gmail唯一邮件ID

时间:2014-07-28 14:27:23

标签: groovy javamail imap gmail-api

我试图通过JavaMail获取唯一的消息ID,这样我以后就可以识别没有特定IMAP文件夹上下文的邮件。我到目前为止编写的代码如下:

def fp = new FetchProfile()

fp.add(FetchProfile.Item.ENVELOPE)
fp.add(FetchProfile.Item.FLAGS)
fp.add(FetchProfile.Item.CONTENT_INFO)
fp.add(javax.mail.UIDFolder.FetchProfileItem.UID)
fp.add("X-mailer")
fp.add("X-GM-MSGID") // Attribute for retrieving the ID in the fetch (?)

uIDFolder.fetch(iMAPmessages, fp);

iMAPmessages.each { msg ->
   println msg.dump()
}

这导致以下输出(对于一条消息):

<com.sun.mail.imap.IMAPMessage@14c04449 
  bs=com.sun.mail.imap.protocol.BODYSTRUCTURE@5ac31f43
  envelope=com.sun.mail.imap.protocol.ENVELOPE@40399642 
  items=[:] 
  receivedDate=Mon Jul 28 12:18:38 MSK 2014 
  size=3147 
  peek=false 
  uid=991 
  modseq=-1  
  sectionId=null 
  type=null 
  subject=null   
  description=null 
  headersLoaded=false 
  loadedHeaders=[X-GM-MSGID:X-GM-MSGID, X-MAILER:X-mailer] 
  dh=null 
  content=null 
  contentStream=null 
  headers=javax.mail.internet.InternetHeaders@4b7e7ff
  flags=com.sun.mail.imap.protocol.FLAGS@20 
  modified=false 
  saved=true 
  cachedContent=null 
  strict=true 
  msgnum=372 
  expunged=false 
  folder=INBOX 
  session=javax.mail.Session@4f0dc86c>

信封:

<com.sun.mail.imap.protocol.ENVELOPE@34ea0af2 
  msgno=371 
  date=Sun Jul 27 17:46:08 MSK 2014 
  subject=Re: Require 
  from=[From <from@gmail.com>]
  sender=[sender <sender@gmail.com>] 
  replyTo=[From <from@gmail.com>] 
  to=[receiver <receiver@gmail.com>, =?ISO-8859-1?Q?Johan_W=E4ngl=F6f?= <example@gmail.com>] 
  cc=null 
  bcc=null 
  inReplyTo=<CAHr+Gay-ZX0U-pFuwQUMziyECTOVrLNn-XLtc643DYXwgtdDFQ@mail.gmail.com>
  messageId=<CAHr+GawnCxaT476K8Rm1MeQNPx8HOfL+VqM0ThMydfTNR12rBg@mail.gmail.com>>

添加到获取配置文件的最后一个属性是用于获取唯一ID(https://developers.google.com/gmail/imap_extensions#access_to_the_gmail_unique_message_id_x-gm-msgid)的特殊属性。

据我所知,这些消息不包含唯一的消息ID。我做错了什么?

跟踪IMAP会话

* 372 FETCH (UID 991 RFC822.SIZE 3147 INTERNALDATE "28-Jul-2014 08:18:38 +0000" FLAGS (\Seen) ENVELOPE ("Mon, 28 Jul 2014 10:18:38 +0200" "Hej du" (("Emil Tholin" NIL "emtholin" "gmail.com")) (("Emil Tholin" NIL "emtholin" "gmail.com")) (("Emil Tholin" NIL "emtholin" "gmail.com")) (("Emil Tholin" NIL "emtholin" "gmail.com")) NIL NIL NIL "<CADsZLRxveuyQX5gXVHvr8ca57yCLopJEc+TpuL2GS-57Kq+yqg@mail.gmail.com>") BODYSTRUCTURE ((("TEXT" "PLAIN" ("CHARSET" "UTF-8") NIL NIL "7BIT" 13 1 NIL NIL NIL)("TEXT" "HTML" ("CHARSET" "UTF-8") NIL NIL "7BIT" 34 1 NIL NIL NIL) "ALTERNATIVE" ("BOUNDARY" "001a11c1250ef810aa04ff3c91b5") NIL NIL)("TEXT" "PLAIN" ("CHARSET" "US-ASCII" "NAME" "rygg.txt") NIL NIL "BASE64" 2138 0 NIL ("ATTACHMENT" ("FILENAME" "rygg.txt")) NIL) "MIXED" ("BOUNDARY" "001a11c1250ef810af04ff3c91b7") NIL NIL) BODY[HEADER.FIELDS (X-mailer X-GM-MSGID)] {4}
)
A4 OK Success
A5 CLOSE
A5 OK Returned to authenticated state. (Success)
DEBUG IMAPS: added an Authenticated connection -- size: 1
specificFolderHeaders() - Closing the mail connection
A6 LOGOUT
* BYE LOGOUT Requested
A6 OK 73 good day (Success)
DEBUG IMAPS: IMAPStore connection dead
DEBUG IMAPS: IMAPStore cleanup, force false
DEBUG IMAPS: IMAPStore cleanup done

2 个答案:

答案 0 :(得分:1)

答案 1 :(得分:1)

比尔击中头部,但我只是想分享我遇到的小问题。

我在问题中发布的代码没有太大变化:

def messages = []

def fp = new FetchProfile()
fp.add(FetchProfile.Item.ENVELOPE)
fp.add(FetchProfile.Item.FLAGS)
fp.add(javax.mail.UIDFolder.FetchProfileItem.UID)
fp.add("X-mailer")

//Google specific attributes
fp.add(GmailFolder.FetchProfileItem.MSGID)
fp.add(GmailFolder.FetchProfileItem.THRID)

uIDFolder.fetch(iMAPmessages, fp);

iMAPmessages.each { msg ->
  GmailMessage gmsg = (GmailMessage) msg
  println Long.toHexString(gmsg.getMsgId().toLong()) //Eureka!
}

花费一些时间才能做到正确的部分是使用授权令牌正确连接到gimap:

def connect(mailAccount) {

  if (mailAccount.provider == "Gmail") {
    Properties props = new Properties();
    props.put("mail.store.protocol", "gimaps");
    props.put("mail.gimaps.sasl.enable", "true"); // Note the "gimaps"
    props.put("mail.gimaps.sasl.mechanisms", "XOAUTH2");
    props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, mailAccount.token);
    Session session = Session.getDefaultInstance(props, null);

    final String emptyPassword = ""; // Since we authorize with token
    GmailStore store = (GmailStore) session.getStore("gimaps");
    store.connect(
        "imap.gmail.com",
        993,
        mailAccount.emailAddress,
        emptyPassword);
    return store;
  }
  else {
    OAuth2Authenticator.initialize();
    def store = OAuth2Authenticator.connectToImap(
        "imap.gmail.com",
        993,
        mailAccount.emailAddress,
        mailAccount.token,
        false); // Debug flag

    return store;
  }
}

为其他提供商使用单独的商店用于Gmail地址和整洁的OAuth2Authenticator(https://code.google.com/p/google-mail-oauth2-tools/source/browse/trunk/java/com/google/code/samples/oauth2/OAuth2Authenticator.java?r=3)效果很好。