76

I want to access messages in Gmail from a Java application using JavaMail and IMAP. Why am I getting a SocketTimeoutException ?

Here is my code:

Properties props = System.getProperties();
props.setProperty("mail.imap.host", "imap.gmail.com");
props.setProperty("mail.imap.port", "993");
props.setProperty("mail.imap.connectiontimeout", "5000");
props.setProperty("mail.imap.timeout", "5000");

try {
    Session session = Session.getDefaultInstance(props, new MyAuthenticator());
    URLName urlName = new URLName("imap://MYUSERNAME@gmail.com:MYPASSWORD@imap.gmail.com");
    Store store = session.getStore(urlName);
    if (!store.isConnected()) {
        store.connect();
    }
} catch (NoSuchProviderException e) {
    e.printStackTrace();
    System.exit(1);
} catch (MessagingException e) {
    e.printStackTrace();
    System.exit(2);
}

I have set the timeout values so that it wouldn't take "forever" to timeout. Also, MyAuthenticator also has the username and password, which seems redundant with the URL. Is there another way to specify the protocol? (I didn't see it in the JavaDoc for IMAP.)

Zoran Jankov
  • 236
  • 2
  • 5
  • 18
Dave of San Ramon
  • 1,471
  • 1
  • 11
  • 8
  • 1
    If you want access GMail threads using JavaMail you might be interested in http://code.google.com/p/java-gmail-imap/ – Mark McLaren Aug 04 '11 at 14:46
  • 2
    Do any of these IMAP-based solutions work anymore *without* the need to "Allow less secure apps"? – jordanpg Dec 03 '15 at 01:31
  • Related: http://security.stackexchange.com/questions/66025/what-are-the-dangers-of-allowing-less-secure-apps-to-access-my-google-account – jordanpg Dec 03 '15 at 01:31

10 Answers10

71

Using imaps was a great suggestion. Neither of the answers provided just worked for me, so I googled some more and found something that worked. Here's how my code looks now.

Properties props = System.getProperties();
props.setProperty("mail.store.protocol", "imaps");
try {
  Session session = Session.getDefaultInstance(props, null);
  Store store = session.getStore("imaps");
  store.connect("imap.gmail.com", "<username>@gmail.com", "<password>");
  ...
} catch (NoSuchProviderException e) {
  e.printStackTrace();
  System.exit(1);
} catch (MessagingException e) {
  e.printStackTrace();
  System.exit(2);
}

This is nice because it takes the redundant Authenticator out of the picture. I'm glad this worked because the SSLNOTES.txt make my head spin.

Dave of San Ramon
  • 1,471
  • 1
  • 11
  • 8
8

You need to use the following properties for imaps:

props.setProperty("mail.imaps.host", "imap.gmail.com");
props.setProperty("mail.imaps.port", "993");
props.setProperty("mail.imaps.connectiontimeout", "5000");
props.setProperty("mail.imaps.timeout", "5000");

Notices it's "imaps", not "imap", since the protocol you're using is imaps (IMAP + SSL)

WhyNotHugo
  • 9,423
  • 6
  • 62
  • 70
6

In JavaMail, you can use imaps as the URL scheme to use IMAP over SSL. (See SSLNOTES.txt in your JavaMail distribution for more details.) For example, imaps://username%40gmail.com@imap.gmail.com/INBOX.

Similarly, use smtps to send emails via Gmail. e.g., smtps://username%40gmail.com@smtp.gmail.com/. Again, read SSLNOTES.txt for more details. Hope it helps!

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
3

Here is what worked for my team and I, given a classic account nickname@gmail.com and a business account employee@business.com :

            final Properties properties = new Properties();
            properties.put("mail.imap.ssl.enable", "true");

            imapSession = Session.getInstance(properties, null);
            imapSession.setDebug(false);
            imapStore = imapSession.getStore("imap");

            imapStore.connect("imap.gmail.com", USERNAME, "password");

with USERNAME = "nickname" in the classic case, and USERNAME = "employee@business.com" in the business account case.

In the classic case, don't forget to lower the account security here : https://www.google.com/settings/security/lesssecureapps

In both cases check in GMail Settings => Forwarding POP / IMAP if IMAP is enabled for the account.

Hope it helps!

To go further :

lboix
  • 969
  • 12
  • 14
  • What do you mean by "old JavaMail dependency"? I don't think this has anything to do with the JavaMail version, it's that you're connecting with IMAPS instead of OAUTH2. – jordanpg Dec 03 '15 at 01:29
3

You have to connect to GMail using SSL only. Setting the following properties will force that for you.

props.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.imap.socketFactory.fallback", "false");
Brian Matthews
  • 8,506
  • 7
  • 46
  • 68
  • I don't recommend this approach in general, because it overrides _all_ imap connections to be imaps. Sometimes choice is a good thing, especially if the program is to be used for connecting to just Gmail. However, if you think plain IMAP is outright wrong, then this approach is acceptable. :-) – C. K. Young Sep 14 '08 at 09:31
  • ...used for connecting to _more than_ just Gmail, I meant. :-P – C. K. Young Sep 14 '08 at 09:31
2

If you'd like more sample code on using JavaMail with Gmail (e.g. converting Gmail labels to IMAP folder names, or using IMAP IDLE), do check out my program GmailAssistant on SourceForge.

Zach Scrivena
  • 29,073
  • 11
  • 63
  • 73
1

I used following properties to get the store and It works well.

"mail.imaps.host" : "imap.gmail.com"
"mail.store.protocol" : "imaps"
"mail.imaps.port" : "993"

Fu Cheng
  • 3,385
  • 1
  • 21
  • 24
1

Check http://g4j.sourceforge.net/. There is a minimal gmail client built using this API.

Adisesha
  • 5,200
  • 1
  • 32
  • 43
0
URLName server = new URLName("imaps://<gmail-user-name>:<gmail-pass>@imap.gmail.com/INBOX");
ngrashia
  • 9,869
  • 5
  • 43
  • 58
0

You need to have JSSE installed to use SSL with Java

hd1
  • 33,938
  • 5
  • 80
  • 91