View Javadoc
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  
18  package org.apache.commons.net.examples.mail;
19  
20  import java.io.BufferedReader;
21  import java.io.File;
22  import java.io.FileOutputStream;
23  import java.io.IOException;
24  import java.io.OutputStreamWriter;
25  import java.nio.charset.StandardCharsets;
26  import java.text.SimpleDateFormat;
27  import java.util.Date;
28  import java.util.regex.Matcher;
29  import java.util.regex.Pattern;
30  
31  import org.apache.commons.net.pop3.POP3Client;
32  import org.apache.commons.net.pop3.POP3MessageInfo;
33  import org.apache.commons.net.pop3.POP3SClient;
34  
35  /**
36   * 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
37   * file.
38   * <p>
39   * 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.
40   * 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
41   * is created.
42   * <p>
43   * See main() method for usage details
44   */
45  public final class POP3ExportMbox {
46  
47      private static final Pattern PATFROM = Pattern.compile(">*From "); // unescaped From_
48  
49      public static void main(final String[] args) {
50          int argIdx;
51          String file = null;
52          for (argIdx = 0; argIdx < args.length; argIdx++) {
53              if (!args[argIdx].equals("-F")) {
54                  break;
55              }
56              file = args[++argIdx];
57          }
58  
59          final int argCount = args.length - argIdx;
60          if (argCount < 3) {
61              System.err.println("Usage: POP3Mail [-F file/directory] <server[:port]> <user> <password|-|*|VARNAME> [TLS [true=implicit]]");
62              System.exit(1);
63          }
64  
65          final String[] arg0 = args[argIdx++].split(":");
66          final String server = arg0[0];
67          final String user = args[argIdx++];
68          String password = args[argIdx++];
69          // prompt for the password if necessary
70          try {
71              password = Utils.getPassword(user, password);
72          } catch (final IOException e1) {
73              System.err.println("Could not retrieve password: " + e1.getMessage());
74              return;
75          }
76  
77          final String proto = argCount > 3 ? args[argIdx++] : null;
78          final boolean implicit = argCount > 4 && Boolean.parseBoolean(args[argIdx++]);
79  
80          final POP3Client pop3;
81  
82          if (proto != null) {
83              System.out.println("Using secure protocol: " + proto);
84              pop3 = new POP3SClient(proto, implicit);
85          } else {
86              pop3 = new POP3Client();
87          }
88  
89          final int port;
90          if (arg0.length == 2) {
91              port = Integer.parseInt(arg0[1]);
92          } else {
93              port = pop3.getDefaultPort();
94          }
95          System.out.println("Connecting to server " + server + " on " + port);
96  
97          // We want to timeout if a response takes longer than 60 seconds
98          pop3.setDefaultTimeout(60000);
99  
100         try {
101             pop3.connect(server);
102         } catch (final IOException e) {
103             System.err.println("Could not connect to server.");
104             e.printStackTrace();
105             return;
106         }
107 
108         try {
109             if (!pop3.login(user, password)) {
110                 System.err.println("Could not login to server.  Check password.");
111                 pop3.disconnect();
112                 return;
113             }
114 
115             final POP3MessageInfo status = pop3.status();
116             if (status == null) {
117                 System.err.println("Could not retrieve status.");
118                 pop3.logout();
119                 pop3.disconnect();
120                 return;
121             }
122 
123             System.out.println("Status: " + status);
124             final int count = status.number;
125             if (file != null) {
126                 System.out.println("Getting messages: " + count);
127                 final File mbox = new File(file);
128                 if (mbox.isDirectory()) {
129                     System.out.println("Writing dir: " + mbox);
130                     // Currently POP3Client uses iso-8859-1
131                     for (int i = 1; i <= count; i++) {
132                         try (final OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(new File(mbox, i + ".eml")),
133                                 StandardCharsets.ISO_8859_1)) {
134                             writeFile(pop3, fw, i);
135                         }
136                     }
137                 } else {
138                     System.out.println("Writing file: " + mbox);
139                     // Currently POP3Client uses iso-8859-1
140                     try (final OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(mbox), StandardCharsets.ISO_8859_1)) {
141                         for (int i = 1; i <= count; i++) {
142                             writeMbox(pop3, fw, i);
143                         }
144                     }
145                 }
146             }
147 
148             pop3.logout();
149             pop3.disconnect();
150         } catch (final IOException e) {
151             e.printStackTrace();
152         }
153     }
154 
155     private static boolean startsWith(final String input, final Pattern pat) {
156         final Matcher m = pat.matcher(input);
157         return m.lookingAt();
158     }
159 
160     private static void writeFile(final POP3Client pop3, final OutputStreamWriter fw, final int i) throws IOException {
161         try (final BufferedReader r = (BufferedReader) pop3.retrieveMessage(i)) {
162             String line;
163             while ((line = r.readLine()) != null) {
164                 fw.write(line);
165                 fw.write("\n");
166             }
167         }
168     }
169 
170     private static void writeMbox(final POP3Client pop3, final OutputStreamWriter fw, final int i) throws IOException {
171         final SimpleDateFormat DATE_FORMAT // for mbox From_ lines
172                 = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy");
173         final String replyTo = "MAILER-DAEMON"; // default
174         final Date received = new Date();
175         try (final BufferedReader r = (BufferedReader) pop3.retrieveMessage(i)) {
176             fw.append("From ");
177             fw.append(replyTo);
178             fw.append(' ');
179             fw.append(DATE_FORMAT.format(received));
180             fw.append("\n");
181             String line;
182             while ((line = r.readLine()) != null) {
183                 if (startsWith(line, PATFROM)) {
184                     fw.write(">");
185                 }
186                 fw.write(line);
187                 fw.write("\n");
188             }
189             fw.write("\n");
190         }
191     }
192 }