You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2014/11/29 00:47:06 UTC
svn commit: r1642376 -
/commons/proper/net/trunk/src/main/java/examples/mail/IMAPExportMbox.java
Author: sebb
Date: Fri Nov 28 23:47:05 2014
New Revision: 1642376
URL: http://svn.apache.org/r1642376
Log:
General tidyup and enhancements
Modified:
commons/proper/net/trunk/src/main/java/examples/mail/IMAPExportMbox.java
Modified: commons/proper/net/trunk/src/main/java/examples/mail/IMAPExportMbox.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/examples/mail/IMAPExportMbox.java?rev=1642376&r1=1642375&r2=1642376&view=diff
==============================================================================
--- commons/proper/net/trunk/src/main/java/examples/mail/IMAPExportMbox.java (original)
+++ commons/proper/net/trunk/src/main/java/examples/mail/IMAPExportMbox.java Fri Nov 28 23:47:05 2014
@@ -67,26 +67,62 @@ public final class IMAPExportMbox
{
private static final String CRLF = "\r\n";
+ private static final String LF = "\n";
+ private static final String EOL_DEFAULT = System.getProperty("line.separator");
private static final Pattern PATFROM = Pattern.compile(">*From "); // unescaped From_
// e.g. INTERNALDATE "27-Oct-2013 07:43:24 +0000"
private static final Pattern PATID =
Pattern.compile(".*INTERNALDATE \"(\\d\\d-\\w{3}-\\d{4} \\d\\d:\\d\\d:\\d\\d [+-]\\d+)\"");
+ private static final int CONNECT_TIMEOUT = 10; // Seconds
+ private static final int READ_TIMEOUT = 10;
+
public static void main(String[] args) throws IOException
{
- if (args.length < 2)
+ int connect_timeout = CONNECT_TIMEOUT;
+ int read_timeout = READ_TIMEOUT;
+
+ int argIdx = 0;
+ String eol = EOL_DEFAULT;
+ boolean printHash = false;
+
+ for(argIdx = 0; argIdx < args.length; argIdx++) {
+ if (args[argIdx].equals("-c")) {
+ connect_timeout = Integer.parseInt(args[++argIdx]);
+ } else if (args[argIdx].equals("-c")) {
+ connect_timeout = Integer.parseInt(args[++argIdx]);
+ } else if (args[argIdx].equals("-LF")) {
+ eol = LF;
+ } else if (args[argIdx].equals("-CRLF")) {
+ eol = CRLF;
+ } else if (args[argIdx].equals("-.")) {
+ printHash = true;
+ } else {
+ break;
+ }
+
+ }
+
+ int argCount = args.length - argIdx;
+
+ if (argCount < 2)
{
- System.err.println("Usage: IMAPExportMbox imap[s]://user:password@host[:port]/folder/path <mboxfile> [sequence-set] [itemnames]");
+ System.err.println("Usage: IMAPExportMbox [-LF|-CRLF] [-c n] [-r n] [#] imap[s]://user:password@host[:port]/folder/path <mboxfile> [sequence-set] [itemnames]");
+ System.err.println("\t-LF | -CRLF set end-of-line to LF or CRLF (default is the line.separator system property)");
+ System.err.println("\t-c connect timeout in seconds (default 10)");
+ System.err.println("\t-r read timeout in seconds (default 10)");
+ System.err.println("\t-. print a . for each complete message received");
+ System.err.println("\tthe mailboxfile is where the messages are stored; use '-' to write to standard output");
System.err.println("\ta sequence-set is a list of numbers/number ranges e.g. 1,2,3-10,20:* - default 1:*");
System.err.println("\titemnames are the message data item name(s) e.g. BODY.PEEK[HEADER.FIELDS (SUBJECT)] or a macro e.g. ALL - default (INTERNALDATE BODY.PEEK[])");
System.exit(1);
}
- final URI uri = URI.create(args[0]);
- final String file = args[1];
- final String sequenceSet = args.length > 2 ? args[2] : "1:*";
- final String itemNames = args.length > 3 ? args[3] : "(INTERNALDATE BODY.PEEK[])";
+ final URI uri = URI.create(args[argIdx++]);
+ final String file = args[argIdx++];
+ final String sequenceSet = argCount > 2 ? args[argIdx++] : "1:*";
+ final String itemNames = argCount > 3 ? args[argIdx++] : "(INTERNALDATE BODY.PEEK[])";
final File mbox = "-".equals(file) ? null : new File(file);
@@ -99,37 +135,57 @@ public final class IMAPExportMbox
// suppress login details
final PrintCommandListener listener = new PrintCommandListener(System.out, true);
+ final MboxListener chunkListener = mbox == null? null : new MboxListener(mbox, eol, printHash);
+
// Connect and login
- final IMAPClient imap = IMAPUtils.imapLogin(uri, 10000, listener);
+ final IMAPClient imap = IMAPUtils.imapLogin(uri, connect_timeout * 1000, listener);
- MboxListener chunkListener = new MboxListener(mbox);
try {
- imap.setSoTimeout(6000);
+ imap.setSoTimeout(read_timeout * 1000);
if (!imap.select(folder)){
- throw new RuntimeException("Could not select folder: " + folder);
+ throw new IOException("Could not select folder: " + folder);
}
- imap.removeProtocolCommandListener(listener); // no longer needed
+ if (mbox != null) {
+ imap.removeProtocolCommandListener(listener); // We use the chunk listener instead
+ imap.setChunkListener(chunkListener);
+ } // else the command listener displays the full output without processing
- imap.setChunkListener(chunkListener);
if (!imap.fetch(sequenceSet, itemNames)) {
- chunkListener.close();
+ if (chunkListener != null) {
+ chunkListener.close();
+ }
throw new IOException("FETCH " + sequenceSet + " " + itemNames+ " failed with " + imap.getReplyString());
}
+ if (printHash) {
+ System.err.println();
+ }
+
// remains of response
for(String line :imap.getReplyStrings()) {
System.out.println(line);
}
- chunkListener.close();
+ if (chunkListener != null) {
+ chunkListener.close();
+ }
+ } catch (IOException ioe) {
+ String count = chunkListener == null ? "?" : Integer.toString(chunkListener.total);
+ System.err.println("FETCH " + sequenceSet + " " + itemNames + " failed after processing " + count + " complete messages ");
+ throw ioe;
} finally {
+ if (chunkListener != null) {
+ chunkListener.close();
+ }
imap.logout();
imap.disconnect();
}
- System.out.println("Processed " + chunkListener.total + " messages.");
+ if (chunkListener != null) {
+ System.out.println("Processed " + chunkListener.total + " messages.");
+ }
}
private static boolean startsWith(String input, Pattern pat) {
@@ -141,35 +197,28 @@ public final class IMAPExportMbox
private BufferedWriter bw;
volatile int total = 0;
- private final File mbox;
+ private final String eol;
private final SimpleDateFormat DATE_FORMAT // for mbox From_ lines
= new SimpleDateFormat("EEE MMM dd HH:mm:ss YYYY");
// e.g. INTERNALDATE "27-Oct-2013 07:43:24 +0000"
private final SimpleDateFormat IDPARSE // for parsing INTERNALDATE
= new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss Z");
+ private final boolean printHash;
- MboxListener(File mbox) {
- this.mbox=mbox;
+ MboxListener(File mbox, String eol, boolean printHash) throws IOException {
+ this.eol = eol;
+ this.printHash = printHash;
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
+ if (mbox.exists()) {
+ throw new IOException("mailbox file: " + mbox + " already exists!");
+ } else {
+ System.out.println("Creating: " + mbox);
+ }
+ this.bw = new BufferedWriter(new FileWriter(mbox));
}
public boolean chunkReceived(IMAP imap) {
- if (mbox == null) {
- return true;
- }
- if (bw == null) {
- try {
- if (mbox.exists()) {
- throw new IOException("mailbox file: " + mbox + " already exists!");
- } else {
- System.out.println("Creating: " + mbox);
- }
- bw = new BufferedWriter(new FileWriter(mbox));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
final String[] replyStrings = imap.getReplyStrings();
Date received = new Date();
final String firstLine = replyStrings[0];
@@ -182,28 +231,32 @@ public final class IMAPExportMbox
System.err.println(e);
}
} else {
+ System.err.println("No timestamp found in: " + firstLine + " - using current time");
}
String replyTo = "MAILER-DAEMON"; // default
for(int i=1; i< replyStrings.length - 1; i++) {
final String line = replyStrings[i];
- String[] parts = line.split(" ", 2);
- if ("Return-Path:".equals(parts[0])) {
+ if (line.startsWith("Return-Path: ")) {
+ String[] parts = line.split(" ", 2);
replyTo = parts[1];
- replyTo = replyTo.substring(1,replyTo.length()-2); // drop <> wrapper
+ if (replyTo.startsWith("<")) {
+ replyTo = replyTo.substring(1,replyTo.length()-1); // drop <> wrapper
+ } else {
+ System.err.println("Unexpected Return-path:" + line+ " in " + firstLine);
+ }
break;
}
}
try {
- total++;
// Add initial mbox header line
bw.append("From ");
bw.append(replyTo);
bw.append(' ');
bw.append(DATE_FORMAT.format(received));
- bw.append(CRLF);
+ bw.append(eol);
// Debug
- bw.append("X-IMAP-Response: ").append(firstLine).append(CRLF);
+ bw.append("X-IMAP-Response: ").append(firstLine).append(eol);
// Skip first and last lines
for(int i=1; i< replyStrings.length - 1; i++) {
final String line = replyStrings[i];
@@ -211,18 +264,22 @@ public final class IMAPExportMbox
bw.append('>'); // Escape a From_ line
}
bw.append(line);
- bw.append(CRLF);
+ bw.append(eol);
}
// The last line ends with the trailing closing ")" which needs to be stripped
String lastLine = replyStrings[replyStrings.length-1];
final int lastLength = lastLine.length();
if (lastLength > 1) { // there's some content, we need to save it
bw.append(lastLine, 0, lastLength-1);
- bw.append(CRLF);
+ bw.append(eol);
}
- bw.append(CRLF); // blank line between entries
+ bw.append(eol); // blank line between entries
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new RuntimeException(e); // chunkReceived cannot throw a checked Exception
+ }
+ total++;
+ if (printHash) {
+ System.err.print(".");
}
return true;
}