Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
* * * * * 2 votes

How to read your emails using Java

authentication streamwriter

  • Please log in to reply
13 replies to this topic

#1 Hurricane

Hurricane

    CC Newcomer

  • Member
  • PipPip
  • 22 posts

Posted 21 February 2011 - 10:54 AM

I found out a few days ago a way to login to your account on ANY email service using Java.
In this tutorial though, we'll be using gmail as our email service.

Prerequisites:
- Basic sockets

Guide:

Have you ever wondered how to extend your Java knowledge and do some really awesome programs? In this guide, we'll be creating our own program that reads our emails.
It won't have any fancy GUI as this is not a GUI tutorial. It will only teach you how to read emails. What you do with the read emails is your choice. :P

A very important note: THIS IS NOT A TUTORIAL ABOUT SENDING EMAILS. ONLY READING THEM.

Basicaly, most email services are using a protocal called POP3 (Post Office Protocal, Version 3), which contains a few instructions. For example, by sending "USER userNameHere@gmail.com" to the server and after that sending "PASS passwordHere" to the server, we'll be connected to the server. Pretty easy, ah? :D
In most servers, the port of the email service is 110. But of course, gmail is special and it uses port 995.

Usually, we'll need to create a regular socket to connect to the an email service, but gmail isn't regular. Gmail is using what's called "SSL" (Secured Sockets Layer). Instead of regular sockets, gmail is using secured sockets, because security in emails is VERY important (I wouldn't want anyone to know that I told me friend I stole a wallet a week ago, would you?).

How do I know that gmail is using SSL sockets?
It's simple, gmail tells us that in the following link:
Configuring other mail clients - Gmail Help

You can see a lot of information here. For example, the server we'll be connecting to is "pop.gmail.com". The port will be 995 and so on.

Let's go to the code now.
First, we'll declare a few global variables that will contain the server's DNS, the port, the username and the password:
String server = "pop.gmail.com";
int port = 995;
String username = "cool1337@gmail.com", password = "whatACoolPassword";
We'll also need to declare a few more global variables that will responsible for connecting to the server, and its input and output:
SSLSocket socket;
BufferedReader input;
PrintWriter output;
The input will be used to read input from the server. For example, if I'm asking the server to send me an email, the input will read it and print it on the screen (On the console in our program).

The output will be used to send messages to the server. For example, I can ask the server to send me an email.

Now, moving on to the constructor.
In our constructor, we'll be initiating our socket, our input and our output variables.

The way you do this is as follows:
public EmailService() {
    try {
        SSLSocketFactory sslsocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
        socket = (SSLSocket)sslsocketFactory.createSocket(server, port);
        input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        
        // After each println you MUST flush the buffer, or it won't work properly.
        // The true argument makes an automatic flush after each println.
        output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Basicaly, you have to make a SSL sockets factory, and then create a new socket using the factory. Just notice that we're sending our server's DNS and the port as arguements.

After we got a socket, we take care of our input and output variables. Notice that after each time you send information to the server, the output's stream must be flushed, or it won't work properly. The true arguement in "new PrintWriter" makes an automatic flush each time you send information to the server.

Connecting to your account:
The POP3 protocol (The Post Office Protocal 3 protocol ^^) is a really simple protocol.
Basicaly, whenever the server sends the client any information, it sends an indicator, the indicates if the request can be made. The states are: "+OK" or "-ERR".
After the indicator, there's the corresponding message.
For example, if I'm trying to connect to my account, but the password is wrong, the server will send an "-ERR [AUTH] Username and password not accepted."
But if the password is correct, I'll be recieving the following message:
+OK Welcome.
Important note: After you connect to the server (Not to your account on gmail, to the server!), the server automaticly sends a greeting.

For gmail, the greeting is:
+OK Gpop ready for requests from 109.64.30.80 l3pf4092546fan.52
Each service should send a different greeting.

Now, for some code.

First of all, I made a new method that reads one line from the input stream.
public String readOneLine() throws IOException {
        return input.readLine();
    }
Now we'll be printing the greeting message and connect to our account on gmail, using the following code:
System.out.print("Greeting message: ");
        String response = readOneLine();
        System.out.println(response);
        
        // Username
        output.println("USER " + username);
        response = readOneLine();
        System.out.println(response);
        
        // Password
        output.println("PASS " + password);
        response = readOneLine();
        System.out.println(response);
Notice that after each request from the server, I'm printing the server's response.
The output of this code is:

Greeting message: +OK Gpop ready for requests from 109.64.30.80 c10pf8910277bkc.43
+OK send PASS
+OK Welcome.

Pretty awesome, isn't it? =D

More information about requests in POP3:
The way you ask requests from the server using POP3 protocol is very simple.
You're sending a command with a possible argument, and recieve a response for your request.
For example, you may type:
"USER username" and after that "PASS passowrd" and the server will check if such user exists. In any case, the server will response and send you an "+OK" message or an "-ERR" message.

There are several commands in POP3.
We'll be using USER, PASS and RETR.

Reading a message:
Now, after we're connected to gmail, it's time to finally read our first message.
We'll be using the RETR command to ask the server to give us a message.
The RETR commands takes an argument. The message number. The first message, the second message and so on.

The way you do it is as follows:
output.println("RETR 1");
(1 is message #1).
After you ask for a message, the server may send "+OK message follows" if there's no problem, or "-ERR Message number out of range." if there's an error (For example, if you want to read message #133333337).

After the server sends an okay message, the server sends a multiple lines. In POP3, every time multiple lines are sent, the final line contains only one character - a dot (.).

That's why, in the code, we'll be reading a line until the line is ".".
The code is as follows:
while (!response.equals(".")) {
    response = readOneLine();
    System.out.println(response);
}

An output for example would be:

+OK message follows
Delivered-To: baraklevy21@gmail.com
Received: by 10.216.21.194 with SMTP id r44cs510787wer;
Tue, 16 Mar 2010 05:43:57 -0700 (PDT)
Received: by 10.142.60.4 with SMTP id i4mr2437100wfa.296.1268743423931;
Tue, 16 Mar 2010 05:43:43 -0700 (PDT)
Return-Path: <noreply@goldmineptc.com>
Received: from buxhost06.buxhost.net (buxhost06.buxhost.net [208.64.125.194])
by mx.google.com with ESMTP id 36si13219142pxi.53.2010.03.16.05.43.42;
Tue, 16 Mar 2010 05:43:42 -0700 (PDT)
Received-SPF: neutral (google.com: 208.64.125.194 is neither permitted nor denied by best guess record for domain of noreply@goldmineptc.com) client-ip=208.64.125.194;
Authentication-Results: mx.google.com; spf=neutral (google.com: 208.64.125.194 is neither permitted nor denied by best guess record for domain of noreply@goldmineptc.com) smtp.mail=noreply@goldmineptc.com
Received: from nobody by buxhost06.buxhost.net with local (Exim 4.69)
(envelope-from <noreply@goldmineptc.com>)
id 1NrW7Y-0006Pa-JQ
for baraklevy21@gmail.com; Tue, 16 Mar 2010 13:43:16 +0100
To: baraklevy21@gmail.com
Subject: Welcome to Gold Mine PTC
Date: Tue, 16 Mar 2010 07:43:40 -0500
From: Gold Mine PTC <noreply@goldmineptc.com>
Message-ID: <002058df3d12326f8aaf5c8c68ee32a0@www.goldmineptc.com>
X-Priority: 3
X-Mailer: PHPMailer (phpmailer.sourceforge.net) [version 2.0.4]
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="b1_002058df3d12326f8aaf5c8c68ee32a0"
X-AntiAbuse: This header was added to track abuse, please include it with any abuse report
X-AntiAbuse: Primary Hostname - buxhost06.buxhost.net
X-AntiAbuse: Original Domain - gmail.com
X-AntiAbuse: Originator/Caller UID/GID - [99 99] / [47 12]
X-AntiAbuse: Sender Address Domain - goldmineptc.com


--b1_002058df3d12326f8aaf5c8c68ee32a0
Content-Type: text/plain; charset = "iso-8859-1"
Content-Transfer-Encoding: 8bit


Welcome to Gold Mine PTC
Please find your login details below.

Username: ***
Password: ***

Important!
To activate your account click the link below or copy/paste the link into your browser:
***

Kind regards,
Support Gold Mine PTC



--b1_002058df3d12326f8aaf5c8c68ee32a0
Content-Type: text/html; charset = "iso-8859-1"
Content-Transfer-Encoding: 8bit


<HTML>
<HEAD></HEAD>
<BODY>
<table width=600 border=0 cellpadding=0 cellspacing=0>
<tr style='background:#000000; color:white; font-family:Lucida Sans Unicode;' valign=top align=left><td style='padding:10px;'>
<div style='font-size:26px;'>Gold Mine PTC</div>
<div style='font-size:16px;'>Easy Money!</div>
</td></tr>
<tr><td style='padding:5px; border-right:1px solid #000000; border-left:1px solid #000000;'>
<br />
Welcome to Gold Mine PTC<br />
Please find your login details below.<br />
<br />
Username: <b>***</b><br />
Password: <b>***</b><br />
<br />
<font color=darkorange><i><u>Important!</u></i></font><br />
To activate your account click the link below or copy/paste the link into your browser:<br />
<a href='http://www.goldmineptc.com/pages/login/confirm/U4***6a7a'>http://www.goldmineptc.com/pages/login/confirm/U468***6a7a</a><br />
<br />
Kind regards,<br />
Support Gold Mine PTC<br />

<br>
</td></tr>
<tr><td style='font-size:11px; color:white; padding:5px; background:#000000;'><b>Important!</b> To reply to this message, please open a <a style='color:white;' href='http://www.goldmineptc.com/pages/contact'><u>support ticket</u></a>.<br>Also want to start a PTC business like Gold Mine PTC? <a style='color:white;' href='http://www.buxhost.com'><u>www.buxhost.com</u></a></td></tr>
</table>
</BODY>
</HTML>




--b1_002058df3d12326f8aaf5c8c68ee32a0--

.


The entire code is as follows:
import java.io.*;
import javax.net.ssl.*;
import java.net.UnknownHostException;

public class EmailService {
    String server = "pop.gmail.com";
    int port = 995;
    String username = "c00001@gmail.com", password = "awesome1337";
    
    SSLSocket socket;
    BufferedReader input;
    PrintWriter output;
    
    public static void main(String[] args) {
        new EmailService();
    }
    
    public EmailService() {
        try {
            SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
            socket = (SSLSocket)sslsocketfactory.createSocket(server, port);
            input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            
            // After each println you MUST flush the buffer, or it won't work properly.
            // The true argument makes an automatic flush after each println.
            output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
            connect();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public void connect() throws IOException {
        System.out.print("Greeting message: ");
        String response = readOneLine();
        System.out.println(response);
        
        // Username
        output.println("USER " + username);
        response = readOneLine();
        System.out.println(response);
        
        // Password
        output.println("PASS " + password);
        response = readOneLine();
        System.out.println(response);
        
        output.println("RETR 1");
        while (!response.equals(".")) {
            response = readOneLine();
            System.out.println(response);
        }
    }
    
    public String readOneLine() throws IOException {
        return input.readLine();
    }
}

I hope you enjoyed the tutorial, and mostly learned more about sockets and about practical programming!

Barack.
  • 2

#2 An Alien

An Alien

    CC Addict

  • Senior Member
  • PipPipPipPipPip
  • 322 posts
  • Programming Language:Java
  • Learning:C, Java, PHP, Python, JavaScript, Lisp, Transact-SQL, Others

Posted 25 February 2011 - 04:31 PM

Is it safe to use?
  • 0

#3 Alexander

Alexander

    YOL9

  • Moderator
  • 3963 posts
  • Location:Vancouver, Eh! Cleverness: 200
  • Programming Language:C, C++, PHP, Assembly

Posted 25 February 2011 - 09:41 PM

Is it safe to use?

It looks like it would work fine, nothing too complex going on that you should be worried about.

Thank you Hurricane for the tutorial!
  • 0

All new problems require investigation, and so if errors are problems, try to learn as much as you can and report back.


#4 Hurricane

Hurricane

    CC Newcomer

  • Member
  • PipPip
  • 22 posts

Posted 26 February 2011 - 02:45 AM

No problem. :D

What do you mean by "safe-to-use"? Do you think it contains a virus or something? I posted the entire code and you can see that it doesn't contain anything risky.
  • 0

#5 An Alien

An Alien

    CC Addict

  • Senior Member
  • PipPipPipPipPip
  • 322 posts
  • Programming Language:Java
  • Learning:C, Java, PHP, Python, JavaScript, Lisp, Transact-SQL, Others

Posted 26 February 2011 - 09:59 AM

No, not like virus or anything, but I was thinking of holes or something that might allow someone else to steal your password and stuff. It's too advanced for me so I don't understand it a bit, lol. But I might try using it.
  • 0

#6 Hurricane

Hurricane

    CC Newcomer

  • Member
  • PipPip
  • 22 posts

Posted 26 February 2011 - 12:37 PM

Oh I see. Well that's why I said you need some basic sockets knowledge first. :P
  • 0

#7 An Alien

An Alien

    CC Addict

  • Senior Member
  • PipPipPipPipPip
  • 322 posts
  • Programming Language:Java
  • Learning:C, Java, PHP, Python, JavaScript, Lisp, Transact-SQL, Others

Posted 12 March 2011 - 09:27 PM

I want to make a program where it takes info from emails, processes/formats it and then saves that for viewing later, but I can't even do this yet!
  • 0

#8 baseball435

baseball435

    CC Newcomer

  • Member
  • PipPip
  • 14 posts

Posted 08 January 2012 - 07:00 PM

I want to make a program where it takes info from emails, processes/formats it and then saves that for viewing later, but I can't even do this yet!


That would be easy haha. As for the "is it safe", of course it is. Just don't give the code out if you have your username and password in it. And if you make it a jar file, don't give it to anyone either because someone could just decompile it and read your credentials
  • 0

#9 SankarAnandaKumar

SankarAnandaKumar

    CC Lurker

  • Just Joined
  • Pip
  • 1 posts

Posted 31 May 2013 - 04:25 AM

Hi,

 

A very nice article to start with. I liked it so much and was trying little bit more on this topic in my eclipse. How to read/retrieve a message dynamically? As in, I don't want to hardcode the values for RETR command like output.println("RETR 1");

But I wanted to write something like this output.println("RETR x");  where 'x' is a variable. Please suggest if there is a way to do this! Many Thanks in advance!!!

 

Regards,

Sankar Ananda Kumar

 


  • 0

#10 Polymath

Polymath

    CC Lurker

  • New Member
  • Pip
  • 8 posts

Posted 18 April 2014 - 07:05 PM

I will try this and get back to you.


  • 0

#11 Hurricane

Hurricane

    CC Newcomer

  • Member
  • PipPip
  • 22 posts

Posted 19 April 2014 - 04:22 AM

Hi,

 

A very nice article to start with. I liked it so much and was trying little bit more on this topic in my eclipse. How to read/retrieve a message dynamically? As in, I don't want to hardcode the values for RETR command like output.println("RETR 1");

But I wanted to write something like this output.println("RETR x");  where 'x' is a variable. Please suggest if there is a way to do this! Many Thanks in advance!!!

 

Regards,

Sankar Ananda Kumar

 

You could simply type:

output.println("RETR " + x);

where x is an integer.


  • 0

Download Nova! An addictive and innovative app for Android: play.google.com/store/apps/details?id=com.droplay.nova


#12 Ritwik I the programmer

Ritwik I the programmer

    CC Addict

  • Advanced Member
  • PipPipPipPipPip
  • 244 posts
  • Programming Language:Java
  • Learning:Java, C++, Python

Posted 01 May 2014 - 06:52 AM

Is their any way to stop the reader from printing the attachments in an email? Or at least print them after decoding?(latter option will be a little out of range of my skill-set, I think.)


  • 0

I can believe, but why should I?






Also tagged with one or more of these keywords: authentication, streamwriter