001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.net.examples.mail;
019
020import java.io.BufferedReader;
021import java.io.File;
022import java.io.FileOutputStream;
023import java.io.IOException;
024import java.io.OutputStreamWriter;
025import java.nio.charset.StandardCharsets;
026import java.text.SimpleDateFormat;
027import java.util.Date;
028import java.util.regex.Matcher;
029import java.util.regex.Pattern;
030
031import org.apache.commons.net.pop3.POP3Client;
032import org.apache.commons.net.pop3.POP3MessageInfo;
033import org.apache.commons.net.pop3.POP3SClient;
034
035/**
036 * 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
037 * file.
038 * <p>
039 * 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.
040 * 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 is
041 * created.
042 * <p>
043 * See main() method for usage details
044 */
045public final class POP3ExportMbox {
046
047    private static final Pattern PATFROM = Pattern.compile(">*From "); // unescaped From_
048
049    public static void main(final String[] args) {
050        int argIdx;
051        String file = null;
052        for (argIdx = 0; argIdx < args.length; argIdx++) {
053            if (!args[argIdx].equals("-F")) {
054                break;
055            }
056            file = args[++argIdx];
057        }
058
059        final int argCount = args.length - argIdx;
060        if (argCount < 3) {
061            System.err.println("Usage: POP3Mail [-F file/directory] <server[:port]> <username> <password|-|*|VARNAME> [TLS [true=implicit]]");
062            System.exit(1);
063        }
064
065        final String arg0[] = args[argIdx++].split(":");
066        final String server = arg0[0];
067        final String username = args[argIdx++];
068        String password = args[argIdx++];
069        // prompt for the password if necessary
070        try {
071            password = Utils.getPassword(username, password);
072        } catch (final IOException e1) {
073            System.err.println("Could not retrieve password: " + e1.getMessage());
074            return;
075        }
076
077        final String proto = argCount > 3 ? args[argIdx++] : null;
078        final boolean implicit = argCount > 4 && Boolean.parseBoolean(args[argIdx++]);
079
080        final POP3Client pop3;
081
082        if (proto != null) {
083            System.out.println("Using secure protocol: " + proto);
084            pop3 = new POP3SClient(proto, implicit);
085        } else {
086            pop3 = new POP3Client();
087        }
088
089        final int port;
090        if (arg0.length == 2) {
091            port = Integer.parseInt(arg0[1]);
092        } else {
093            port = pop3.getDefaultPort();
094        }
095        System.out.println("Connecting to server " + server + " on " + port);
096
097        // We want to timeout if a response takes longer than 60 seconds
098        pop3.setDefaultTimeout(60000);
099
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(username, 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            return;
153        }
154    }
155
156    private static boolean startsWith(final String input, final Pattern pat) {
157        final Matcher m = pat.matcher(input);
158        return m.lookingAt();
159    }
160
161    private static void writeFile(final POP3Client pop3, final OutputStreamWriter fw, final int i) throws IOException {
162        try (final BufferedReader r = (BufferedReader) pop3.retrieveMessage(i)) {
163            String line;
164            while ((line = r.readLine()) != null) {
165                fw.write(line);
166                fw.write("\n");
167            }
168        }
169    }
170
171    private static void writeMbox(final POP3Client pop3, final OutputStreamWriter fw, final int i) throws IOException {
172        final SimpleDateFormat DATE_FORMAT // for mbox From_ lines
173                = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy");
174        final String replyTo = "MAILER-DAEMON"; // default
175        final Date received = new Date();
176        try (final BufferedReader r = (BufferedReader) pop3.retrieveMessage(i)) {
177            fw.append("From ");
178            fw.append(replyTo);
179            fw.append(' ');
180            fw.append(DATE_FORMAT.format(received));
181            fw.append("\n");
182            String line;
183            while ((line = r.readLine()) != null) {
184                if (startsWith(line, PATFROM)) {
185                    fw.write(">");
186                }
187                fw.write(line);
188                fw.write("\n");
189            }
190            fw.write("\n");
191        }
192    }
193}