Javax Mail fetching is very slow - java

final Session session = Session.getDefaultInstance(new Properties());
try (Store store = session.getStore("imaps"))
{
store.connect("smtp.gmail.com", "email#gmail.com", "password");
try (Folder inbox = store.getFolder("Inbox"))
{
inbox.open(Folder.READ_WRITE);
for (final Message message : inbox.getMessages())
{
final Multipart multipart = (Multipart) message.getContent();
System.out.println(multipart.getBodyPart(0).getContent());
}
}
}
The fetching of each mail takes around 0.5 second.
So if i do a loop over all my mail and let's say i have around 100 it can take up to minutes. Is there something wrong with my code or the javaxmail works like that? I realise it open a connection per mail but this seem wrong. It should fetch all data once and then cache them.

Related

Use Java Gmail API to send an email with multiple (large) attachments

I am trying to use the Google Gmail API (Java) to create an email that contains multiple attachments. Using the code below, I am able to send multiple attachments that are embedded within a MimeMessage if the attachments total less than 5MB (Google's threshold for simple file upload).
com.google.api.services.gmailGmail service = (... defined above ...)
javax.mail.internet.MimeMessage message = (... defined above with attachments embedded ...)
// Send the email
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
mimeMessage.writeTo(buffer);
byte[] bytes = buffer.toByteArray();
String encodedEmail = Base64.encodeBase64URLSafeString(bytes);
Message message = new Message();
message.setRaw(encodedEmail);
message = service.users().messages().send("me", message).execute();
However, I am unable to figure out how to correctly attach multiple files to an email using the Gmail Java API. The method below looks promising, but it appears to only accept 1 File/InputStream (mediaContent).
Gmail.Users.Messages.Send send(userId, Message content, AbstractInputStreamContent mediaContent)
Anyone know how to correctly implement a multi-file upload using the API?
As you correctly stated, the maximum attachment size for Simple file upload is 5 MB
Conclusion:
You need to to use Multipart upload or Resumable upload.
A sample sending an email with a multipart upload:
public static MimeMessage createEmailWithAttachment(String to, String from, String subject,
String bodyText,String filePath) throws MessagingException{
File file = new File(filePath);
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
MimeMessage email = new MimeMessage(session);
Multipart multipart = new MimeMultipart();
InternetAddress tAddress = new InternetAddress(to);
InternetAddress fAddress = new InternetAddress(from);
email.setFrom(fAddress);
email.addRecipient(javax.mail.Message.RecipientType.TO, tAddress);
email.setSubject(subject);
if (file.exists()) {
source = new FileDataSource(filePath);
messageFilePart = new MimeBodyPart();
messageBodyPart = new MimeBodyPart();
try {
messageBodyPart.setText(bodyText);
messageFilePart.setDataHandler(new DataHandler(source));
messageFilePart.setFileName(file.getName());
multipart.addBodyPart(messageBodyPart);
multipart.addBodyPart(messageFilePart);
email.setContent(multipart);
} catch (MessagingException e) {
e.printStackTrace();
}
}else
email.setText(bodyText);
return email;
}
Here you can find many other useful samples for sending emails with the Gmail API in Java.
It turns out that my MimeMessage was generated correctly, however, if the attachments included in the MimeMessage are larger than 5MB, you need to use a different Gmail API send() method. The API docs are incredibly confusing because they appear to state that you need to make multiple calls to rest endpoints to upload multiple files. It turns out that the Gmail Java Api does all the for you based off the MimeMessage submitted.
Below is a code snippet that shows how to use the two methods: "simple upload" and "multipart upload".
com.google.api.services.gmailGmail service = (... defined above ...)
javax.mail.internet.MimeMessage message = (... defined above with attachments embedded ...)
/**
* Send email using Gmail API - dynamically uses simple or multipart send depending on attachments size
*
* #param mimeMessage MimeMessage (includes any attachments for the email)
* #param attachments the Set of files that were included in the MimeMessage (if any). Only used to calculate total size to see if we should use "simple" send or need to use multipart upload.
*/
void send(MimeMessage mimeMessage, #Nullable Set<File> attachments) throws Exception {
Message message = new Message();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
mimeMessage.writeTo(buffer);
// See if we need to use multipart upload
if (attachments!=null && computeTotalSizeOfAttachments(attachments) > BYTES_5MB) {
ByteArrayContent content = new ByteArrayContent("message/rfc822", buffer.toByteArray());
message = service.users().messages().send("me", null, content).execute();
// Otherwise, use "simple" send
} else {
String encodedEmail = Base64.encodeBase64URLSafeString(buffer.toByteArray());
message.setRaw(encodedEmail);
message = service.users().messages().send("me", message).execute();
}
System.out.println("Gmail Message: " + message.toPrettyString());
}

How to retrieve only 40-50 email like Gmail using Javamail?

I am trying to retrieve my inbox using javamail and I have done that but now problem arises when I try to load the code it take lot of time in reading all emails as it read the whole inbox but I want that only few emails should be fetched that are most recent.
Properties properties = new Properties();
String host = "pop.gmail.com";// change accordingly
properties.put("mail.pop3.host", host);
properties.put("mail.pop3.port", "995");
properties.put("mail.pop3.starttls.enable", "true");
Session emailSession = Session.getDefaultInstance(properties);
//create the POP3 store object and connect with the pop server
Store store = emailSession.getStore("pop3s");
store.connect(host, username, password);
//create the folder object and open it
Folder emailFolder = store.getFolder("INBOX");
emailFolder.open(Folder.READ_ONLY);
// retrieve the messages from the folder in an array and print it
Message[] messages = emailFolder.getMessages();
LOG.info("messages.length---" + messages.length);
for (int i = 0; i < messages.length; i++) {
Message message = messages[i];
leadJSONObject = new JSONObject();
LOG.info("Email Number " + (i + 1));
LOG.info("This log is executed successfully");
leadJSONObject.put("emailFrom", message.getFrom()[0].toString());
leadJSONObject.put("emailSubject", message.getSubject());
leadJSONObject.put("emailText", message.getContent().toString());
planJSONArray.put(leadJSONObject);
}
//close the store and folder objects
emailFolder.close(false);
store.close();
Please Help how can I read only few emails. Thanks in Advance.
You may want to count the messages, then retrieve only a part of the total , e.g for the 50 first messages (or less if there isn't enough):
int total = emailFolder.getMessageCount();
Message[] messages = emailFolder.getMessages(1,Math.min(total,50));
cf. the javadoc of javax.mail.Folder.

JavaMail - Issue with Multiple And Search Terms

I would like to fetch recent, unread emails with a specific subject in a particular folder from my gmail account. I am using JavaMail API as below but it returns 0 results. However if I just use subjectTerm alone, I see results. Please let me know where am I going wrong. Thank you.
Please note that I used messages[0] below instead of looping through messages array for code simplicity to paste it here.
public void openMailBox(String hostname, String username, String password, String folderName, String subject) throws MessagingException, GeneralSecurityException, IOException{
props = System.getProperties();
props.setProperty("mail.store.protocol", "imaps");
props.setProperty("mail.imaps.host", "imap.gmail.com");
props.setProperty("mail.imaps.port", "993");
props.setProperty("mail.imaps.ssl.enable", "true");
props.put("mail.imaps.ssl.socketFactory", new MailSSLSocketFactory());
session = Session.getInstance(props);
store = session.getStore();
store.connect(username, password);
folder = store.getFolder(folderName);
folder.open(Folder.READ_ONLY);
messages = folder.search(getSearchTerm(subject));
if (messages[0].isMimeType("multipart/*")){
Multipart multipart = (Multipart) messages[0].getContent();
for(int i=0;i<multipart.getCount();i++) {
BodyPart bodyPart = multipart.getBodyPart(0);
if (bodyPart.isMimeType("text/*")) {
msg = msg+bodyPart.getContent().toString();
}
}
}else{
msg = messages[0].getContent().toString();
}
System.out.println(msg);
folder.close(true);
store.close();
}
public SearchTerm getSearchTerm(String subject){
subjectTerm = new SubjectTerm(subject);
unseenFlagTerm = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
recentFlagTerm; = new FlagTerm(new Flags(Flags.Flag.RECENT), true);
return new AndTerm(subjectTerm, new AndTerm(unseenFlagTerm, recentFlagTerm));
}
}
What mail server are you using?
Some mail servers don't implement the RECENT flag in any useful way, so messages might not be marked RECENT. Try leaving out the RECENT term and see if you get more results.
If that doesn't help, add code to dump out the flags for all messages and then post the JavaMail debug output that shows the flags for all messages along with the search request and response.
Note also that some IMAP servers don't fully or correctly implement the SEARCH command and so can't handle the kind of search you're doing.
Finally, note that you don't need to set the socketFactory property unless you're using MailSSLSocketFactory in a more interesting way than you've show in your example code above.

Reading mails sent from GMail

I am using JavaMail to read mail in my Android app. I have tried to cover all combinations i.e Mail sent/received on/from Custom Server/Gmail ID/Live ID.
The problem occurs with SOME of the mails sent from GMail WITH Attachment. I am able to receive the attachment, but the content returns javax.mail.internet.MimeMultipart#44f2e698
Here's the code used to receive and read messages:
Properties props = System.getProperties();
props.setProperty("mail.store.protocol", "imap");
try {
/* Create the session and get the store for read the mail. */
Session session = Session.getInstance(props, null);
Store store = session.getStore("imaps");
store.connect("imap.gmail.com", Username, Password);
/* Mention the folder name which you want to read. */
Folder inbox = store.getFolder("INBOX");
System.out.println("No of Unread Messages : " + inbox.getUnreadMessageCount());
/* Open the inbox using store. */
inbox.open(Folder.READ_ONLY);
Message messages[] = inbox.getMessages();
Log.d("Inbox", "Message Count: "+inbox.getMessageCount());
for (int i = messages.length - 1 ; i > 0; --i) {
Log.i("ContentType", "ContentType: "+messages[i].getContentType());
Object msgContent = messages[i].getContent();
String content = "";
/* Check if content is pure text/html or in parts */
if (msgContent instanceof Multipart) {
Multipart multipart = (Multipart) msgContent;
Log.e("BodyPart", "MultiPartCount: "+multipart.getCount());
for (int j = 0; j < multipart.getCount(); j++) {
BodyPart bodyPart = multipart.getBodyPart(j);
String disposition = bodyPart.getDisposition();
if (disposition != null && (disposition.equalsIgnoreCase("ATTACHMENT"))) { // BodyPart.ATTACHMENT doesn't work for gmail
System.out.println("Mail have some attachment");
DataHandler handler = bodyPart.getDataHandler();
System.out.println("file name : " + handler.getName());
}
else {
System.out.println("Content: "+bodyPart.getContent());
content= bodyPart.getContent().toString();
}
}
}
else
content= messages[i].getContent().toString();
What I know about the problematic mails:
getFrom also return the name i.e it comes in this format FirstName LastName &ltemailID#gmail.com&gt
MultiPart contains 2 BodyParts:
BodyPart 1 returns the content as javax.mail.internet.MimeMultipart#44f2e698
BodyPart 2 returns the correct name for attachment
BodyPart 1 returns the content as
javax.mail.internet.MimeMultipart#44f2e698
Try calling getBodyPart on the MimeMultiPart
That probably returns a MimeBodyPart you can call getContent() on
http://docs.oracle.com/javaee/5/api/javax/mail/internet/MimeBodyPart.html#content
You're probably only handling the simplest case of a text message with attachments. MIME allows much more. You need to learn about the difference between multipart/mixed, multipart/alternative, multipart/related, and multipart/signed. The JavaMail FAQ has more information on handling attachments and the msgshow.java demo program included with the JavaMail download bundle shows how to process messages with nested multiparts.

How to read mbox email messages using mstor

I am using mstor to read the mbox email messages, but i am not able to connect to the store using the urlName name which i m passing, by default its connecting to other
location on my macbine.Do i need to create the store using mstor JCR before proceed to connect to the store?
Session session = Session.getDefaultInstance(new Properties());
Store store = session.getStore(new URLName("mstor:C:/mailbox/MyStore/Inbox"));
store.connect();
Folder inbox = store.getDefaultFolder().getFolder("inbox");
inbox.open(Folder.READ_ONLY);
Message m = inbox.getMessage(0);
Any suggetions are helpful
Thanks in advance..
//Set the Properties as shown below:
Properties properties = new Properties();
this.properties.setProperty("mail.store.protocol", "mstor");
this.properties.setProperty("mstor.mbox.metadataStrategy", "none");
this.properties.setProperty("mstor.mbox.cacheBuffers", "disabled");
this.properties.setProperty("mstor.cache.disabled", "true");
this.properties.setProperty("mstor.mbox.bufferStrategy", "mapped");
this.properties.setProperty("mstor.metadata", "disabled");
//Also mstor count for messages start from 1 and not 0. so change it to 1.
Store store = session.getStore(new URLName("mstor:C:/mailbox/MyStore/Inbox"));
store.connect();
Folder inbox = store.getDefaultFolder().getFolder("inbox");
inbox.open(Folder.READ_ONLY);
Message m = inbox.getMessage(1);

Categories