Author: sebb
Date: Mon Sep 23 00:48:46 2013
New Revision: 1525483

URL: http://svn.apache.org/r1525483
Log:
Use IMAP URL to simplify command line
Add selector support

Modified:
    commons/proper/net/trunk/src/main/java/examples/mail/IMAPImportMbox.java

Modified: 
commons/proper/net/trunk/src/main/java/examples/mail/IMAPImportMbox.java
URL: 
http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/examples/mail/IMAPImportMbox.java?rev=1525483&r1=1525482&r2=1525483&view=diff
==============================================================================
--- commons/proper/net/trunk/src/main/java/examples/mail/IMAPImportMbox.java 
(original)
+++ commons/proper/net/trunk/src/main/java/examples/mail/IMAPImportMbox.java 
Mon Sep 23 00:48:46 2013
@@ -21,6 +21,10 @@ import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
 
 import org.apache.commons.net.imap.IMAPClient;
 import org.apache.commons.net.imap.IMAPSClient;
@@ -29,8 +33,13 @@ import org.apache.commons.net.imap.IMAPS
  * This is an example program demonstrating how to use the IMAP[S]Client class.
  * This program connects to a IMAP[S] server and imports messages into the 
folder from an mbox file.
  * <p>
- * Usage: IMAPMail <imap[s] server hostname> <folder> <username> <password> 
<mboxfile> [secure protocol, e.g. TLS]
+ * Usage: IMAPImportMbox imap[s]://user:password@host[:port]/folder/path 
<mboxfile> [selectors]
  * <p>
+ * An example selector might be:
+ * <ul>
+ * <li>1,2,3,7-10</li>
+ * <li>-142986- : this is useful for retrieving messages by apmail number, 
which appears as From xyz-return-142986-apmail-...</li>
+ * <ul>
  */
 public final class IMAPImportMbox
 {
@@ -39,33 +48,93 @@ public final class IMAPImportMbox
 
     public static void main(String[] args) throws IOException
     {
-        if (args.length < 5)
+        if (args.length < 2)
         {
-            System.err.println(
-                "Usage: IMAPImportMbox <imap server hostname> <folder> 
<username> <password> <mboxfile> [TLS]");
+            System.err.println("Usage: IMAPImportMbox 
imap[s]://user:password@host[:port]/folder/path <mboxfile> [selectors]");
+            System.err.println("\tWhere: a selector is a list of 
numbers/number ranges - 1,2,3-10 - or a list of strings to match in the initial 
From line");
             System.exit(1);
         }
 
-        final String server   = args[0];
-        final String folder   = args[1];
-        final String username = args[2];
-        final String password = args[3];
-        final String file     = args[4];
-        final String proto = (args.length > 5) ? args[5] : null;
+        final URI uri      = URI.create(args[0]);
+        final String file  = args[1];
 
         final File mbox = new File(file);
         if (!mbox.isFile() || !mbox.canRead()) {
             throw new IOException("Cannot read mailbox file: " + mbox);
         }
 
-        IMAPClient imap;
+        final String userInfo = uri.getUserInfo();
+        if (userInfo == null) {
+            throw new IllegalArgumentException("Missing userInfo details");
+        }
+
+        String []userpass = userInfo.split(":");
+        if (userpass.length != 2) {
+            throw new IllegalArgumentException("Invalid userInfo details: '" + 
userpass + "'");            
+        }
+
+        String username = userpass[0];
+        String password = userpass[1];
+
+        String path = uri.getPath();
+        if (path == null || path.length() < 1) {
+            throw new IllegalArgumentException("Invalid folderPath: '" + path 
+ "'");
+        }
+        String folder = path.substring(1); // skip the leading /
+
+        List<String> contains = new ArrayList<String>(); // list of strings to 
find
+        BitSet msgNums = new BitSet(); // list of message numbers
+
+        for(int i = 2; i < args.length; i++) {
+            String arg = args[i];
+            if (arg.matches("\\d+(-\\d+)(,\\d+(-\\d+))*")) { // number,m-n
+                for(String entry :arg.split(",")) {
+                    String []parts = entry.split("-");
+                    if (parts.length == 2) { // m-n
+                        int low = Integer.parseInt(parts[0]);
+                        int high = Integer.parseInt(parts[1]);
+                        for(int j=low; j <= high; j++) {
+                            msgNums.set(j);
+                        }
+                    } else {
+                        msgNums.set(Integer.parseInt(entry));
+                    }
+                }
+            } else {
+                contains.add(arg); // not a number/number range
+            }
+        }
+
+        final IMAPClient imap;
 
-        if (proto != null) {
-            System.out.println("Using secure protocol: " + proto);
-            imap = new IMAPSClient(proto, true); // implicit
+        if ("imaps".equalsIgnoreCase(uri.getScheme())) {
+            System.out.println("Using secure protocol");
+            imap = new IMAPSClient(true); // implicit
+//        } else if ("null".equals(uri.getScheme())) {
+//            imap = new IMAPClient(){
+//                @Override
+//                public void connect(String host){ }
+//                @Override
+//                public boolean login(String user, String pass) {return true;}
+//                @Override
+//                public boolean logout() {return true;}
+//                @Override
+//                public void disconnect() {}
+//                @Override
+//                public void setSoTimeout(int t) {}
+//                @Override
+//                public boolean append(String mailboxName, String flags, 
String datetime, String message) {return true;}
+//            };
         } else {
             imap = new IMAPClient();
         }
+
+        String server = uri.getHost();
+        int port = uri.getPort();
+        if (port != -1) {
+            imap.setDefaultPort(port);
+        }
+
         System.out.println("Connecting to server " + server + " on " + 
imap.getDefaultPort());
 
         // We want to timeout if a response takes longer than 60 seconds
@@ -77,6 +146,8 @@ public final class IMAPImportMbox
             throw new RuntimeException("Could not connect to server.", e);
         }
 
+        int total = 0;
+        int loaded = 0;
         try {
             if (!imap.login(username, password)) {
                 System.err.println("Could not login to server. Check 
password.");
@@ -90,19 +161,28 @@ public final class IMAPImportMbox
 
             String line;
             StringBuilder sb = new StringBuilder();
+            boolean wanted = false; // Skip any leading rubbish
             while((line=br.readLine())!=null) {
                 if (line.startsWith("From ")) { // start of message; i.e. end 
of previous (if any)
-                    process(sb, imap, folder);
+                    if (process(sb, imap, folder)) { // process previous 
message (if any)
+                        loaded++;
+                    }
+                    wanted = wanted(total, line, msgNums, contains);
+                    total ++;
                     sb.setLength(0);
                 } else if (line.startsWith(">From ")) { // Unescape "From " in 
body text
                     line = line.substring(1);
                 }
                 // TODO process first Received: line to determine arrival date?
-                sb.append(line);
-                sb.append(CRLF);
+                if (wanted) {
+                    sb.append(line);
+                    sb.append(CRLF);
+                }
             }
             br.close();
-            process(sb, imap, folder); // end of last message (if any)
+            if (wanted && process(sb, imap, folder)) { // last message (if any)
+                loaded++;
+            }
         } catch (IOException e) {
             System.out.println(imap.getReplyString());
             e.printStackTrace();
@@ -112,11 +192,13 @@ public final class IMAPImportMbox
             imap.logout();
             imap.disconnect();
         }
+        System.out.println("Processed " + total + " messages, loaded " + 
loaded);
     }
 
-    private static void process(final StringBuilder sb, final IMAPClient imap, 
final String folder) throws IOException {
+    private static boolean process(final StringBuilder sb, final IMAPClient 
imap, final String folder) throws IOException {
         final int length = sb.length();
-        if (length > 2) {
+        boolean haveMessage = length > 2;
+        if (haveMessage) {
             System.out.println("Length " + length);
             sb.setLength(length-2); // drop trailing CRLF
             String msg = sb.toString();
@@ -124,5 +206,37 @@ public final class IMAPImportMbox
                 throw new IOException("Failed to import message: " + 
imap.getReplyString());
             }
         }
+        return haveMessage;
+    }
+
+    /**
+     * Is the message wanted?
+     * 
+     * @param msgNum the message number
+     * @param line the From line
+     * @param msgNums the list of wanted message numbers
+     * @param contains the list of strings to be contained
+     * @return true if the message is wanted
+     */
+    private static boolean wanted(int msgNum, String line, BitSet msgNums, 
List<String> contains) {
+        return (msgNums.isEmpty() && contains.isEmpty()) // no selectors 
+             || msgNums.get(msgNum) // matches message number
+             || listContains(contains, line); // contains string
+    }
+
+    /**
+     * Is at least one entry in the list contained in the string?
+     * @param contains the list of strings to look for
+     * @param string the String to check against
+     * @return true if at least one entry in the contains list is contained in 
the string
+     */
+    private static boolean listContains(List<String> contains, String string) {
+        for(String entry : contains) {
+            if (string.contains(entry)) {
+                return true;
+            }
+        }
+        return false;
     }
+
 }


Reply via email to