Java tutorial
/* * Copyright (c) 2004 David Flanagan. All rights reserved. * This code is from the book Java Examples in a Nutshell, 3nd Edition. * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose, * including teaching and use in open-source projects. * You may distribute it non-commercially as long as you retain this notice. * For a commercial use license, or to purchase the book, * please visit http://www.davidflanagan.com/javaexamples3. */ //package je3.net; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * A simple utility program for deleting messages from a POP3 mailbox based on * message size and Subject line. Don't run this program unless you understand * what it is doing. It deletes e-mail without downloading it: YOU MAY * PERMANENTLY LOSE DATA! * * Typical usage: 1) Look at the subject lines for the big messages you've got * java PopClean -host host -user user -pass pass -size 100000 * * 2) Create a regular expression to match viral subject lines, and use it to * delete large matching messages java PopClean -host h -user u -pass p -delete * -size 100000 \ -subject 'Thank you!|Re: Your application' This will ask for * confirmation before proceeding. * * 3) If you're confident that all big messages are virus-infected, then you can * skip the -subject argument and delete on size alone java PopClean -host h * -user u -pass p -delete -size 100000 This will ask for confirmation before * proceeding. */ public class PopClean { static Socket s = null; // The connection to the server static BufferedReader in = null; // To read lines from the server static PrintWriter out = null; // To write to the server static boolean debug = false; // Are we in debug mode? public static void main(String args[]) { try { String hostname = null, username = null, password = null; int port = 110; int sizelimit = -1; String subjectPattern = null; Pattern pattern = null; Matcher matcher = null; boolean delete = false; boolean confirm = true; // Handle command-line arguments for (int i = 0; i < args.length; i++) { if (args[i].equals("-user")) username = args[++i]; else if (args[i].equals("-pass")) password = args[++i]; else if (args[i].equals("-host")) hostname = args[++i]; else if (args[i].equals("-port")) port = Integer.parseInt(args[++i]); else if (args[i].equals("-size")) sizelimit = Integer.parseInt(args[++i]); else if (args[i].equals("-subject")) subjectPattern = args[++i]; else if (args[i].equals("-debug")) debug = true; else if (args[i].equals("-delete")) delete = true; else if (args[i].equals("-force")) // don't confirm confirm = false; } // Verify them if (hostname == null || username == null || password == null || sizelimit == -1) usage(); // Make sure the pattern is a valid regexp if (subjectPattern != null) { pattern = Pattern.compile(subjectPattern); matcher = pattern.matcher(""); } // Say what we are going to do System.out .println("Connecting to " + hostname + " on port " + port + " with username " + username + "."); if (delete) { System.out.println("Will delete all messages longer than " + sizelimit + " bytes"); if (subjectPattern != null) System.out.println("that have a subject matching: [" + subjectPattern + "]"); } else { System.out.println("Will list subject lines for messages " + "longer than " + sizelimit + " bytes"); if (subjectPattern != null) System.out.println("that have a subject matching: [" + subjectPattern + "]"); } // If asked to delete, ask for confirmation unless -force is given if (delete && confirm) { System.out.println(); System.out.print("Do you want to proceed (y/n) [n]: "); System.out.flush(); BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); String response = console.readLine(); if (!response.equals("y")) { System.out.println("No messages deleted."); System.exit(0); } } // Connect to the server, and set up streams s = new Socket(hostname, port); in = new BufferedReader(new InputStreamReader(s.getInputStream())); out = new PrintWriter(new OutputStreamWriter(s.getOutputStream())); // Read the welcome message from the server, confirming it is OK. System.out.println("Connected: " + checkResponse()); // Now log in send("USER " + username); // Send username, wait for response send("PASS " + password); // Send password, wait for response System.out.println("Logged in"); // Check how many messages are waiting, and report it String stat = send("STAT"); StringTokenizer t = new StringTokenizer(stat); System.out.println(t.nextToken() + " messages in mailbox."); System.out.println("Total size: " + t.nextToken()); // Get a list of message numbers and sizes send("LIST"); // Send LIST command, wait for OK response. // Now read lines from the server until we get . by itself List msgs = new ArrayList(); String line; for (;;) { line = in.readLine(); if (line == null) throw new IOException("Unexpected EOF"); if (line.equals(".")) break; msgs.add(line); } // Now loop through the lines we read one at a time. // Each line should specify the message number and its size. int nummsgs = msgs.size(); for (int i = 0; i < nummsgs; i++) { String m = (String) msgs.get(i); StringTokenizer st = new StringTokenizer(m); int msgnum = Integer.parseInt(st.nextToken()); int msgsize = Integer.parseInt(st.nextToken()); // If the message is too small, ignore it. if (msgsize <= sizelimit) continue; // If we're listing messages, or matching subject lines // find the subject line for this message String subject = null; if (!delete || pattern != null) { subject = getSubject(msgnum); // get the subject line // If we couldn't find a subject, skip the message if (subject == null) continue; // If this subject does not match the pattern, then // skip the message if (pattern != null) { matcher.reset(subject); if (!matcher.matches()) continue; } // If we are listing, list this message if (!delete) { System.out.println("Subject " + msgnum + ": " + subject); continue; // so we never delete it } } // If we were asked to delete, then delete the message if (delete) { send("DELE " + msgnum); if (pattern == null) System.out.println("Deleted message " + msgnum); else System.out.println("Deleted message " + msgnum + ": " + subject); } } // When we're done, log out and shutdown the connection shutdown(); } catch (Exception e) { // If anything goes wrong print exception and show usage System.err.println(e); usage(); // Always try to shutdown nicely so the server doesn't hang on us shutdown(); } } // Explain how to use the program public static void usage() { System.err.println("java PopClean <options>"); System.err.println("Options are:\n" + "-host <hostname> # Required\n" + "-port <port> # Optional; default is 110\n" + "-user <username> # Required\n" + "-pass <password> # Required and sent as cleartext; APOP not supported\n" + "-size <limit> # Message size in bytes. Shorter messages are ignored.\n" + "-subject <regexp> # Optional java.util.regex.Pattern regular expression\n" + " # only messages with a matching Subject line are deleted\n" + "-delete # Delete messages; the default is just to list them\n" + "-force # Don't ask for confirmation before deleting\n" + "-debug # Display POP3 protocol requests and responses\n"); System.exit(1); } // Send a POP3 command to the server and return its response public static String send(String cmd) throws IOException { if (debug) System.out.println(">>>" + cmd); out.print(cmd); // Send command out.print("\r\n"); // and line terminator. out.flush(); // Send it now! String response = checkResponse(); // Get the response. if (debug) System.out.println("<<<+OK " + response); return response; } // Wait for a response and make sure it is an "OK" response. public static String checkResponse() throws IOException { String response; for (;;) { response = in.readLine(); if (response == null) throw new IOException("Server unexpectedly closed connection"); else if (response.startsWith("-ERR")) throw new IOException("Error from server: " + response); else if (response.startsWith("+OK")) return response.substring(3); } } // Ask the server to send the headers of the numbered message. // Look through them for the Subject header and return its content. public static String getSubject(int msgnum) throws IOException { send("TOP " + msgnum + " 0"); String subject = null, line; for (;;) { line = in.readLine(); if (line == null) throw new IOException("Unexpected EOF"); if (line.startsWith("Subject: ")) subject = line.substring(9); if (line.equals(".")) break; } return subject; } // Disconnect nicely from the POP server. // This method is called for normal termination and exceptions. public static void shutdown() { try { if (out != null) { send("QUIT"); out.close(); } if (in != null) in.close(); if (s != null) s.close(); } catch (IOException e) { } } }