How to extend javax.mail for custom POP3 commands?

  • Thread starter Matthew Strawbridge
  • Start date
M

Matthew Strawbridge

Hi,

I've written a spam filter that happily uses the standard javax.mail
classes to get message headers from the server (so I can do some
simple filtering). This is all via POP3.

I want to extend this so that if a message has been viewed, but not
deleted, then it should be treated as "safe". The difficulty I am
having is identifying whether or not a message has been read already.

Now I know that there is no guarantee that a POP3 server will tell you
whether or not a mail has been read, but that many servers set the
appropriate headers so that msg.isSet(Flags.Flag.SEEN) is true.
Unfortunately, my ISP (demon) takes a different approach.

As described on
http://www.demon.net/helpdesk/products/mail/sdps-tech.shtml they have
added an extra POP3 command "*ENV n", where n is the message number,
and returns a response "OK" for unread or "RD" for read messages.

My question is how can I best send this raw command to the POP3 server
and parse the response? I got a bit lost in the javax.mail docs - what
(if anything) do I need to extend to get some access to input and
output streams, or should I be using a different library entirely (I
think there are some mail classes in the Jakarta commons)?

Thanks for your help,
Matthew

PS There is no IMAP support, so I have to use POP3.
 
R

Roedy Green

My question is how can I best send this raw command to the POP3 server
and parse the response? I got a bit lost in the javax.mail docs - what
(if anything) do I need to extend to get some access to input and
output streams, or should I be using a different library entirely (I
think there are some mail classes in the Jakarta commons)?

I suggest you decompile the JavaMail classes, if it is not illegal,
and see if how the lower level methods use the socket, and see if it
exposed anywhere. You simply want to do a raw socket write/read.
Your only problem is finding a handle to that socket that is logged
into the pop3 port.

In a pinch you could relogin on a separate socket with id/password
bubblegum done manually.

Turn Debug on so you can watch the protocol.
 
A

AC

There may be better ways to do this than sending 'raw' commands to the pop3
server but you asked how to do it, so here's you answer...

Communicating with the POP3 server is just a matter of creating a socket and
sending the strings described in STD53
(ftp://ftp.rfc-editor.org/in-notes/std/std53.txt - worth a read, very well
written and easy to understand), you'll find all the available POP3 commands
here.

The following code should do the job (it could do with tidying up). The
System.out.println() statements are only there to help illustrate the
communication. I'm not a demon customer so I haven't been able to test it...

import java.io.*;
import java.net.*;

public class Pop3 {

public static void main(String[] args) {
try {

String serverAddress = "pop3.demon.co.uk";
int port = 110; // standard pop3 port

String username = "your_email_username";
String password = "your_email_password";

Socket s = new Socket(serverAddress, port);
BufferedReader in = new BufferedReader(new
InputStreamReader(s.getInputStream()));
PrintWriter out = new PrintWriter(s.getOutputStream(), true);

// This will receive the welcome message
System.out.println(in.readLine());

// Login
out.println("USER " + username);
System.out.println(in.readLine());
out.println("PASS " + password);
System.out.println(in.readLine());

// Send *ENV command with message number
int msgNum = 0;
out.println("*ENV " + msgNum);
// You should only need to read in 1 char here, R for read or O for not
read (according to demon)
char response = (char)in.read();
boolean messageRead = (response == 'R' ? true : false);
System.out.println("Message " + msgNum + " has" + (messageRead ? " " : "
not ") + "been read");

// You really don't need to communicate with the server any longer so
// you can quit now (you should really be using the QUIT command, but
// to avoid having to code for multi-line responses just close the socket)
in.close();
out.close();
} catch (Exception e) {}
}
}
 
A

AC

BTW, it may be the case that the first 2 characters returned by the *ENV
command are NOT OK or RD as demon have said. The first line of POP3
responses in STD0053 always return a + or a -, so you may need to add an
'in.read();' statement to lose the +/- when getting the response to the env
command:

in.read(); // ignore the + or -
char response = (char)in.read(); // Get the R or O

AC


AC said:
There may be better ways to do this than sending 'raw' commands to the pop3
server but you asked how to do it, so here's you answer...

Communicating with the POP3 server is just a matter of creating a socket and
sending the strings described in STD53
(ftp://ftp.rfc-editor.org/in-notes/std/std53.txt - worth a read, very well
written and easy to understand), you'll find all the available POP3 commands
here.

The following code should do the job (it could do with tidying up). The
System.out.println() statements are only there to help illustrate the
communication. I'm not a demon customer so I haven't been able to test it...

import java.io.*;
import java.net.*;

public class Pop3 {

public static void main(String[] args) {
try {

String serverAddress = "pop3.demon.co.uk";
int port = 110; // standard pop3 port

String username = "your_email_username";
String password = "your_email_password";

Socket s = new Socket(serverAddress, port);
BufferedReader in = new BufferedReader(new
InputStreamReader(s.getInputStream()));
PrintWriter out = new PrintWriter(s.getOutputStream(), true);

// This will receive the welcome message
System.out.println(in.readLine());

// Login
out.println("USER " + username);
System.out.println(in.readLine());
out.println("PASS " + password);
System.out.println(in.readLine());

// Send *ENV command with message number
int msgNum = 0;
out.println("*ENV " + msgNum);
// You should only need to read in 1 char here, R for read or O for not
read (according to demon)
char response = (char)in.read();
boolean messageRead = (response == 'R' ? true : false);
System.out.println("Message " + msgNum + " has" + (messageRead ? " " : "
not ") + "been read");

// You really don't need to communicate with the server any longer so
// you can quit now (you should really be using the QUIT command, but
// to avoid having to code for multi-line responses just close the socket)
in.close();
out.close();
} catch (Exception e) {}
}
}


Matthew Strawbridge said:
Hi,

I've written a spam filter that happily uses the standard javax.mail
classes to get message headers from the server (so I can do some
simple filtering). This is all via POP3.

I want to extend this so that if a message has been viewed, but not
deleted, then it should be treated as "safe". The difficulty I am
having is identifying whether or not a message has been read already.

Now I know that there is no guarantee that a POP3 server will tell you
whether or not a mail has been read, but that many servers set the
appropriate headers so that msg.isSet(Flags.Flag.SEEN) is true.
Unfortunately, my ISP (demon) takes a different approach.

As described on
http://www.demon.net/helpdesk/products/mail/sdps-tech.shtml they have
added an extra POP3 command "*ENV n", where n is the message number,
and returns a response "OK" for unread or "RD" for read messages.

My question is how can I best send this raw command to the POP3 server
and parse the response? I got a bit lost in the javax.mail docs - what
(if anything) do I need to extend to get some access to input and
output streams, or should I be using a different library entirely (I
think there are some mail classes in the Jakarta commons)?

Thanks for your help,
Matthew

PS There is no IMAP support, so I have to use POP3.
 
R

Roedy Green

Communicating with the POP3 server is just a matter of creating a socket and
sending the strings described in STD53
(ftp://ftp.rfc-editor.org/in-notes/std/std53.txt - worth a read, very well
written and easy to understand), you'll find all the available POP3 commands
here.

For more hints see
http://mindprod.com/jgloss/pop3.html
http://mindprod.com/jgloss/javamail.html
http://mindprod.com/jgloss/mailserver.html
http://mindprod.com/jgloss/smtp.html
http://mindprod.com/jgloss/email.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top