Jump to content

How to read your emails using Java

- - - - -

  • Please log in to reply
7 replies to this topic

#1
Hurricane

Hurricane

    Newbie

  • Members
  • PipPip
  • 20 posts
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:

Quote

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:

Quote

+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
An Alien

An Alien

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 260 posts
Is it safe to use?

#3
Alexander

Alexander

    It's Science!

  • Moderators
  • 4,118 posts
  • Location:Vancouver, Eh! Cleverness: 200

An Alien said:

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!
Be sure to read the updated FAQ! || Health is achieved through the same 10,000 steps.
If a suggested code/method fails, informing us is less important than telling us why or what errors occurred.

#4
Hurricane

Hurricane

    Newbie

  • Members
  • PipPip
  • 20 posts
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.

#5
An Alien

An Alien

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 260 posts
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.

#6
Hurricane

Hurricane

    Newbie

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

#7
An Alien

An Alien

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 260 posts
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!

#8
baseball435

baseball435

    Newbie

  • Members
  • PipPip
  • 14 posts

An Alien said:

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




2 user(s) are reading this topic

0 members, 2 guests, 0 anonymous users