POP3ExportMbox.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.apache.commons.net.examples.mail;

  18. import java.io.BufferedReader;
  19. import java.io.File;
  20. import java.io.FileOutputStream;
  21. import java.io.IOException;
  22. import java.io.OutputStreamWriter;
  23. import java.nio.charset.StandardCharsets;
  24. import java.text.SimpleDateFormat;
  25. import java.util.Date;
  26. import java.util.regex.Matcher;
  27. import java.util.regex.Pattern;

  28. import org.apache.commons.net.pop3.POP3Client;
  29. import org.apache.commons.net.pop3.POP3MessageInfo;
  30. import org.apache.commons.net.pop3.POP3SClient;

  31. /**
  32.  * This is an example program demonstrating how to use the POP3[S]Client class. This program connects to a POP3[S] server and writes the messages to an mbox
  33.  * file.
  34.  * <p>
  35.  * The code currently assumes that POP3Client decodes the POP3 data as iso-8859-1. The POP3 standard only allows for ASCII so in theory iso-8859-1 should be OK.
  36.  * However, it appears that actual POP3 implementations may return 8bit data that is outside the ASCII range; this may result in loss of data when the mailbox
  37.  * is created.
  38.  * <p>
  39.  * See main() method for usage details
  40.  */
  41. public final class POP3ExportMbox {

  42.     private static final Pattern PATFROM = Pattern.compile(">*From "); // unescaped From_

  43.     public static void main(final String[] args) {
  44.         int argIdx;
  45.         String file = null;
  46.         for (argIdx = 0; argIdx < args.length; argIdx++) {
  47.             if (!args[argIdx].equals("-F")) {
  48.                 break;
  49.             }
  50.             file = args[++argIdx];
  51.         }

  52.         final int argCount = args.length - argIdx;
  53.         if (argCount < 3) {
  54.             System.err.println("Usage: POP3Mail [-F file/directory] <server[:port]> <user> <password|-|*|VARNAME> [TLS [true=implicit]]");
  55.             System.exit(1);
  56.         }

  57.         final String[] arg0 = args[argIdx++].split(":");
  58.         final String server = arg0[0];
  59.         final String user = args[argIdx++];
  60.         String password = args[argIdx++];
  61.         // prompt for the password if necessary
  62.         try {
  63.             password = Utils.getPassword(user, password);
  64.         } catch (final IOException e1) {
  65.             System.err.println("Could not retrieve password: " + e1.getMessage());
  66.             return;
  67.         }

  68.         final String proto = argCount > 3 ? args[argIdx++] : null;
  69.         final boolean implicit = argCount > 4 && Boolean.parseBoolean(args[argIdx++]);

  70.         final POP3Client pop3;

  71.         if (proto != null) {
  72.             System.out.println("Using secure protocol: " + proto);
  73.             pop3 = new POP3SClient(proto, implicit);
  74.         } else {
  75.             pop3 = new POP3Client();
  76.         }

  77.         final int port;
  78.         if (arg0.length == 2) {
  79.             port = Integer.parseInt(arg0[1]);
  80.         } else {
  81.             port = pop3.getDefaultPort();
  82.         }
  83.         System.out.println("Connecting to server " + server + " on " + port);

  84.         // We want to timeout if a response takes longer than 60 seconds
  85.         pop3.setDefaultTimeout(60000);

  86.         try {
  87.             pop3.connect(server);
  88.         } catch (final IOException e) {
  89.             System.err.println("Could not connect to server.");
  90.             e.printStackTrace();
  91.             return;
  92.         }

  93.         try {
  94.             if (!pop3.login(user, password)) {
  95.                 System.err.println("Could not login to server.  Check password.");
  96.                 pop3.disconnect();
  97.                 return;
  98.             }

  99.             final POP3MessageInfo status = pop3.status();
  100.             if (status == null) {
  101.                 System.err.println("Could not retrieve status.");
  102.                 pop3.logout();
  103.                 pop3.disconnect();
  104.                 return;
  105.             }

  106.             System.out.println("Status: " + status);
  107.             final int count = status.number;
  108.             if (file != null) {
  109.                 System.out.println("Getting messages: " + count);
  110.                 final File mbox = new File(file);
  111.                 if (mbox.isDirectory()) {
  112.                     System.out.println("Writing dir: " + mbox);
  113.                     // Currently POP3Client uses iso-8859-1
  114.                     for (int i = 1; i <= count; i++) {
  115.                         try (final OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(new File(mbox, i + ".eml")),
  116.                                 StandardCharsets.ISO_8859_1)) {
  117.                             writeFile(pop3, fw, i);
  118.                         }
  119.                     }
  120.                 } else {
  121.                     System.out.println("Writing file: " + mbox);
  122.                     // Currently POP3Client uses iso-8859-1
  123.                     try (final OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(mbox), StandardCharsets.ISO_8859_1)) {
  124.                         for (int i = 1; i <= count; i++) {
  125.                             writeMbox(pop3, fw, i);
  126.                         }
  127.                     }
  128.                 }
  129.             }

  130.             pop3.logout();
  131.             pop3.disconnect();
  132.         } catch (final IOException e) {
  133.             e.printStackTrace();
  134.         }
  135.     }

  136.     private static boolean startsWith(final String input, final Pattern pat) {
  137.         final Matcher m = pat.matcher(input);
  138.         return m.lookingAt();
  139.     }

  140.     private static void writeFile(final POP3Client pop3, final OutputStreamWriter fw, final int i) throws IOException {
  141.         try (final BufferedReader r = (BufferedReader) pop3.retrieveMessage(i)) {
  142.             String line;
  143.             while ((line = r.readLine()) != null) {
  144.                 fw.write(line);
  145.                 fw.write("\n");
  146.             }
  147.         }
  148.     }

  149.     private static void writeMbox(final POP3Client pop3, final OutputStreamWriter fw, final int i) throws IOException {
  150.         final SimpleDateFormat DATE_FORMAT // for mbox From_ lines
  151.                 = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy");
  152.         final String replyTo = "MAILER-DAEMON"; // default
  153.         final Date received = new Date();
  154.         try (final BufferedReader r = (BufferedReader) pop3.retrieveMessage(i)) {
  155.             fw.append("From ");
  156.             fw.append(replyTo);
  157.             fw.append(' ');
  158.             fw.append(DATE_FORMAT.format(received));
  159.             fw.append("\n");
  160.             String line;
  161.             while ((line = r.readLine()) != null) {
  162.                 if (startsWith(line, PATFROM)) {
  163.                     fw.write(">");
  164.                 }
  165.                 fw.write(line);
  166.                 fw.write("\n");
  167.             }
  168.             fw.write("\n");
  169.         }
  170.     }
  171. }