I work on university project in java. I have to download attachments from new emails using GMAIL API.
I successfully connected to gmail account using OAuth 2.0 authorization.
private static final List<String> SCOPES = Collections.singletonList(GmailScopes.GMAIL_READONLY);
I tried to get unseen mails using
ListMessagesResponse listMessageResponse = service.users().messages().list(user).setQ("is:unseen").execute();
listMessageResponse is not null but when I call method .getResultSizeEstimate() it returns 0 also I tried to convert listMessageResponse to List < Message > (I guess this is more usable) using
List<Message> list = listMessageResponse.getMessages();
But list launches NullPointerException
Then tried to get each attachment with
for(Message m : list) { List<MessagePart> part = m.getPayload().getParts(); for(MessagePart p: part) { if(p.getFilename()!=null && p.getFilename().length()>0) { System.out.println(p.getFilename()); // Just to check attachment filename } } }
Is my approach correct (if not how to fix it) and how should I download those attachments.
EDIT 1:
Fixed q parameter, I mistakenly wrote is:unseen instead of is:unread. Now app reaches unread mails successfully. (For example there was two unread mails and both successfully reached, I can get theirs IDs easy).
Now this part trows NullPointerException
List<MessagePart> part = m.getPayload().getParts();
Both messages have attachments and m is not null (I get ID with .getID())
Any ideas how to overcome this and download attachment?
EDIT 2:
Attachments Downloading part
for(MessagePart p : parts) { if ((p.getFilename() != null && p.getFilename().length() > 0)) { String filename = p.getFilename(); String attId = p.getBody().getAttachmentId(); MessagePartBody attachPart; FileOutputStream fileOutFile = null; try { attachPart = service.users().messages().attachments().get("me", p.getPartId(), attId).execute(); byte[] fileByteArray = Base64.decodeBase64(attachPart.getData()); fileOutFile = new FileOutputStream(filename); // Or any other dir fileOutFile.write(fileByteArray); fileOutFile.close(); }catch (IOException e) { System.out.println("IO Exception processing attachment: " + filename); } finally { if (fileOutFile != null) { try { fileOutFile.close(); } catch (IOException e) { // probably doesn't matter } } } } }
Downloading working like charm, tested app with different type of emails. Only thing left is to change label of unread message (that was reached by app) to read. Any tips how to do it?
And one tiny question: I want this app to fetch mails on every 10 minutes using TimerTask abstract class. Is there need for manual “closing” of connection with gmail or that’s done automatically after run() method iteration ends?
@Override public void run(){ // Some fancy code service.close(); // Something like that if even exists }
Advertisement
Answer
I don’t think ListMessagesResponse
ever becomes null. Even if there are no messages that match your query, at least resultSizeEstimate
will get populated in the resulting response: see Users.messages: list > Response.
I think you are using the correct approach, just that there is no message that matches your query. Actually, I never saw is:unseen
before. Did you mean is:unread
instead?
Update:
When using Users.messages: list only the id
and the threadId
of each message is populated, so you cannot access the message payload
. In order to get the full message resource, you have to use Users.messages: get
instead, as you can see in the referenced link:
Note that each message resource contains only an id and a threadId. Additional message details can be fetched using the messages.get method.
So in this case, after getting the list of messages, you have to iterate through the list, and do the following for each message in the list:
- Get the message
id
via m.getId(). - Once you have retrieved the message
id
, use it to call Gmail.Users.Messages.Get and get the full message resource. The retrieved message should have all fields populated, including payload, and you should be able to access the corresponding attachments.
Code sample:
List<Message> list = listMessageResponse.getMessages(); for(Message m : list) { Message message = service.users().messages().get(user, m.getId()).execute(); List<MessagePart> part = message.getPayload().getParts(); // Rest of code }