2011-02-15 19:37:35 +00:00
|
|
|
package zutil.net;
|
2008-12-05 15:13:26 +00:00
|
|
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
|
import java.io.PrintStream;
|
|
|
|
|
import java.net.Socket;
|
|
|
|
|
import java.net.UnknownHostException;
|
|
|
|
|
|
|
|
|
|
import javax.net.SocketFactory;
|
|
|
|
|
import javax.net.ssl.SSLSocketFactory;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A simple class that connects and logs in to a POP3
|
|
|
|
|
* server and then can read and delete messages.
|
|
|
|
|
* INFO: http://pages.prodigy.net/michael_santovec/pop3telnet.htm
|
|
|
|
|
*
|
|
|
|
|
* @author Ziver
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public class POP3Client {
|
|
|
|
|
public static boolean DEBUG = false;
|
|
|
|
|
public static final int POP3_PORT = 110;
|
|
|
|
|
public static final int POP3_SSL_PORT = 995;
|
|
|
|
|
|
|
|
|
|
private BufferedReader in;
|
|
|
|
|
private PrintStream out;
|
|
|
|
|
private Socket socket;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Connect to a POP3 server without username
|
|
|
|
|
*
|
|
|
|
|
* @param host The hostname of the server
|
|
|
|
|
* @throws UnknownHostException
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public POP3Client(String host) throws UnknownHostException, IOException{
|
|
|
|
|
this(host, POP3_PORT, null, null, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Connect to a POP3 server with username and password
|
|
|
|
|
*
|
|
|
|
|
* @param host The hostname of the server
|
|
|
|
|
* @param user The username
|
|
|
|
|
* @param password the password
|
|
|
|
|
* @throws UnknownHostException
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public POP3Client(String host, String user, String password) throws UnknownHostException, IOException{
|
|
|
|
|
this(host, POP3_PORT, user, password, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Connects to a POP3 server with username and password and SSL
|
|
|
|
|
*
|
|
|
|
|
* @param host The hostname of the server
|
|
|
|
|
* @param user The username
|
|
|
|
|
* @param password the password
|
|
|
|
|
* @param ssl If SSL should be used
|
|
|
|
|
* @throws UnknownHostException
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public POP3Client(String host, String user, String password, boolean ssl) throws UnknownHostException, IOException{
|
|
|
|
|
this(host, (ssl ? POP3_SSL_PORT : POP3_PORT), user, password, ssl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Connects to a POP3 server with username and password and
|
|
|
|
|
* SSL and with costume port.
|
|
|
|
|
*
|
|
|
|
|
* @param host The hostname of the server
|
|
|
|
|
* @param port The port number to connect to on the server
|
|
|
|
|
* @param user The username
|
|
|
|
|
* @param password the password
|
|
|
|
|
* @param ssl If SSL should be used
|
|
|
|
|
* @throws UnknownHostException
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public POP3Client(String host, int port, String user, String password, boolean ssl) throws UnknownHostException, IOException{
|
|
|
|
|
if(ssl) connectSSL(host, port);
|
|
|
|
|
else connect(host, port);
|
|
|
|
|
|
|
|
|
|
if(user != null){
|
|
|
|
|
login(user, password);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Connects to the server
|
|
|
|
|
*
|
|
|
|
|
* @param host The hostname of the server
|
|
|
|
|
* @param port The port to connect to on the server
|
|
|
|
|
* @throws UnknownHostException
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
private void connect(String host, int port) throws UnknownHostException, IOException{
|
|
|
|
|
socket = new Socket(host, port);
|
|
|
|
|
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
|
|
|
|
out = new PrintStream(socket.getOutputStream());
|
|
|
|
|
|
|
|
|
|
readCommand(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Connects to the server with SSL.
|
|
|
|
|
* http://www.exampledepot.com/egs/javax.net.ssl/Client.html
|
|
|
|
|
*
|
|
|
|
|
* @param host The hostname of the server
|
|
|
|
|
* @param port The port to connect to on the server
|
|
|
|
|
* @throws UnknownHostException
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
private void connectSSL(String host, int port) throws UnknownHostException, IOException{
|
|
|
|
|
SocketFactory socketFactory = SSLSocketFactory.getDefault();
|
|
|
|
|
socket = socketFactory.createSocket(host, port);
|
|
|
|
|
|
|
|
|
|
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
|
|
|
|
out = new PrintStream(socket.getOutputStream());
|
|
|
|
|
|
|
|
|
|
readCommand(DEBUG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Logs in to the POP3 server with the username and password if the password is set
|
|
|
|
|
*
|
|
|
|
|
* @param user The user name
|
|
|
|
|
* @param password The password or null if no password is required
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
private void login(String user, String password) throws IOException{
|
|
|
|
|
sendCommand("USER "+user);
|
|
|
|
|
if(password != null){
|
|
|
|
|
sendNoReplyCommand("PASS "+password, false);
|
|
|
|
|
if(DEBUG)System.out.println("PASS ***");
|
|
|
|
|
readCommand(DEBUG);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the number of messages that is on the server
|
|
|
|
|
*
|
|
|
|
|
* @return Message count
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public int getMessageCount() throws IOException{
|
|
|
|
|
String msg = sendCommand("STAT", DEBUG);
|
|
|
|
|
return Integer.parseInt(
|
|
|
|
|
msg.substring(
|
|
|
|
|
msg.indexOf(' ')+1,
|
|
|
|
|
msg.indexOf(' ', msg.indexOf(' ')+1)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Retrieves the message with the given id.
|
|
|
|
|
*
|
|
|
|
|
* @param id The id of the message to get
|
|
|
|
|
* @return The message
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public String getMessage(int id) throws IOException{
|
|
|
|
|
sendCommand("RETR "+id);
|
|
|
|
|
return readMultipleLines(DEBUG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the title of the message
|
|
|
|
|
*
|
|
|
|
|
* @param id The message id
|
|
|
|
|
* @return The title
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public String getMessageTitle(int id) throws IOException{
|
|
|
|
|
String tmp = getMessageHeader(id);
|
|
|
|
|
String tmp2 = tmp.toLowerCase();
|
|
|
|
|
if(tmp2.contains("subject:")){
|
|
|
|
|
return tmp.substring(
|
|
|
|
|
tmp2.indexOf("subject:")+8,
|
|
|
|
|
tmp2.indexOf('\n',
|
|
|
|
|
tmp2.indexOf("subject:")));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the header of the given message id.
|
|
|
|
|
*
|
|
|
|
|
* @param id The id of the message to get
|
|
|
|
|
* @return The message
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public String getMessageHeader(int id) throws IOException{
|
|
|
|
|
sendCommand("TOP "+id+" 0");
|
|
|
|
|
return readMultipleLines(DEBUG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Deletes the message with the given id
|
|
|
|
|
*
|
|
|
|
|
* @param id The id of the message to be deleted
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public void delete(int id) throws IOException{
|
|
|
|
|
sendCommand("DELE "+id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//*********************** IO Stuff *********************************************
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sends the given line to the server and returns a status integer
|
|
|
|
|
*
|
|
|
|
|
* @param cmd The command to send
|
|
|
|
|
* @return The return code from the server
|
|
|
|
|
* @throws IOException if the cmd fails
|
|
|
|
|
*/
|
|
|
|
|
private boolean sendCommand(String cmd) throws IOException{
|
|
|
|
|
return parseReturnCode(sendCommand(cmd, DEBUG));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sends the given line to the server and returns the last line
|
|
|
|
|
*
|
|
|
|
|
* @param cmd The command to send
|
|
|
|
|
* @param print To print out the received lines
|
|
|
|
|
* @return Last String line from the server
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
private String sendCommand(String cmd, boolean print) throws IOException{
|
|
|
|
|
sendNoReplyCommand(cmd, print);
|
|
|
|
|
return readCommand(print);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sends a given command and don't cares about the reply
|
|
|
|
|
*
|
|
|
|
|
* @param cmd The command
|
|
|
|
|
* @param print If it should print to System.out
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
private void sendNoReplyCommand(String cmd, boolean print) throws IOException{
|
|
|
|
|
out.println(cmd);
|
|
|
|
|
if(print)System.out.println(cmd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reads on line from the command channel
|
|
|
|
|
*
|
|
|
|
|
* @param print If the method should print the input line
|
|
|
|
|
* @return The input line
|
|
|
|
|
* @throws IOException if the server returns a error code
|
|
|
|
|
*/
|
|
|
|
|
private String readCommand(boolean print) throws IOException{
|
|
|
|
|
String tmp = in.readLine();
|
|
|
|
|
if(print)System.out.println(tmp);
|
|
|
|
|
if( !parseReturnCode(tmp) ) throw new IOException(tmp);
|
|
|
|
|
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reads from the server until there are a line with
|
|
|
|
|
* only one '.'
|
|
|
|
|
*
|
|
|
|
|
* @param print To print out the received lines
|
|
|
|
|
* @return String with the text
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
private String readMultipleLines(boolean print) throws IOException{
|
|
|
|
|
StringBuffer msg = new StringBuffer();
|
|
|
|
|
String tmp = in.readLine();
|
|
|
|
|
while(!tmp.equals(".")){
|
|
|
|
|
msg.append(tmp);
|
|
|
|
|
msg.append('\n');
|
|
|
|
|
tmp = in.readLine();
|
|
|
|
|
if(print)System.out.println(tmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return msg.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses the return line from the server and returns the status code
|
|
|
|
|
*
|
|
|
|
|
* @param msg The message from the server
|
|
|
|
|
* @return Returns true if return code is OK false if it is ERR
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
private boolean parseReturnCode(String msg){
|
|
|
|
|
int endpos = (msg.indexOf(' ')<0 ? msg.length() : msg.indexOf(' '));
|
|
|
|
|
return msg.substring(0, endpos).equals("+OK");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//*********************************************************************************
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* All the delete marked messages are unmarkt
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public void reset() throws IOException{
|
|
|
|
|
sendCommand("RSET", DEBUG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* All the changes(DELETE) are performed and then the connection is closed
|
|
|
|
|
*
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public void close() throws IOException{
|
|
|
|
|
sendCommand("QUIT", DEBUG);
|
|
|
|
|
in.close();
|
|
|
|
|
out.close();
|
|
|
|
|
socket.close();
|
|
|
|
|
}
|
|
|
|
|
}
|