1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.FileReader;
23 import java.io.IOException;
24 import java.net.URI;
25 import java.util.ArrayList;
26 import java.util.BitSet;
27 import java.util.List;
28 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
30
31 import org.apache.commons.net.imap.IMAPClient;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 public final class IMAPImportMbox {
49
50 private static final String CRLF = "\r\n";
51 private static final Pattern PATFROM = Pattern.compile(">+From ");
52
53 private static String getDate(final String msg) {
54
55 final Pattern FROM_RE = Pattern.compile("From \\S+ +\\S+ (\\S+) ?(\\S+) (\\S+) (\\S+)");
56
57
58 String date = null;
59 final Matcher m = FROM_RE.matcher(msg);
60 if (m.lookingAt()) {
61 date = m.group(2) + "-" + m.group(1) + "-" + m.group(4) + " " + m.group(3) + " +0000";
62 }
63 return date;
64 }
65
66
67
68
69
70
71
72
73 private static boolean listContains(final List<String> contains, final String string) {
74 for (final String entry : contains) {
75 if (string.contains(entry)) {
76 return true;
77 }
78 }
79 return false;
80 }
81
82 public static void main(final String[] args) throws IOException {
83 if (args.length < 2) {
84 System.err.println("Usage: IMAPImportMbox imap[s]://user:password@host[:port]/folder/path <mboxfile> [selectors]");
85 System.err
86 .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");
87 System.exit(1);
88 }
89
90 final URI uri = URI.create(args[0]);
91 final String file = args[1];
92
93 final File mbox = new File(file);
94 if (!mbox.isFile() || !mbox.canRead()) {
95 throw new IOException("Cannot read mailbox file: " + mbox);
96 }
97
98 final String path = uri.getPath();
99 if (path == null || path.length() < 1) {
100 throw new IllegalArgumentException("Invalid folderPath: '" + path + "'");
101 }
102 final String folder = path.substring(1);
103
104 final List<String> contains = new ArrayList<>();
105 final BitSet msgNums = new BitSet();
106
107 for (int i = 2; i < args.length; i++) {
108 final String arg = args[i];
109 if (arg.matches("\\d+(-\\d+)?(,\\d+(-\\d+)?)*")) {
110 for (final String entry : arg.split(",")) {
111 final String[] parts = entry.split("-");
112 if (parts.length == 2) {
113 final int low = Integer.parseInt(parts[0]);
114 final int high = Integer.parseInt(parts[1]);
115 for (int j = low; j <= high; j++) {
116 msgNums.set(j);
117 }
118 } else {
119 msgNums.set(Integer.parseInt(entry));
120 }
121 }
122 } else {
123 contains.add(arg);
124 }
125 }
126
127
128
129
130 final IMAPClient imap = IMAPUtils.imapLogin(uri, 10000, null);
131
132 int total = 0;
133 int loaded = 0;
134 try {
135 imap.setSoTimeout(6000);
136
137 final BufferedReader br = new BufferedReader(new FileReader(file));
138
139 String line;
140 final StringBuilder sb = new StringBuilder();
141 boolean wanted = false;
142 while ((line = br.readLine()) != null) {
143 if (line.startsWith("From ")) {
144 if (process(sb, imap, folder, total)) {
145 loaded++;
146 }
147 sb.setLength(0);
148 total++;
149 wanted = wanted(total, line, msgNums, contains);
150 } else if (startsWith(line, PATFROM)) {
151 line = line.substring(1);
152 }
153
154 if (wanted) {
155 sb.append(line);
156 sb.append(CRLF);
157 }
158 }
159 br.close();
160 if (wanted && process(sb, imap, folder, total)) {
161 loaded++;
162 }
163 } catch (final IOException e) {
164 System.out.println("Error processing msg: " + total + " " + imap.getReplyString());
165 e.printStackTrace();
166 System.exit(10);
167 return;
168 } finally {
169 imap.logout();
170 imap.disconnect();
171 }
172 System.out.println("Processed " + total + " messages, loaded " + loaded);
173 }
174
175 private static boolean process(final StringBuilder sb, final IMAPClient imap, final String folder, final int msgNum) throws IOException {
176 final int length = sb.length();
177 final boolean haveMessage = length > 2;
178 if (haveMessage) {
179 System.out.println("MsgNum: " + msgNum + " Length " + length);
180 sb.setLength(length - 2);
181 final String msg = sb.toString();
182 if (!imap.append(folder, null, getDate(msg), msg)) {
183 throw new IOException("Failed to import message: " + msgNum + " " + imap.getReplyString());
184 }
185 }
186 return haveMessage;
187 }
188
189 private static boolean startsWith(final String input, final Pattern pat) {
190 final Matcher m = pat.matcher(input);
191 return m.lookingAt();
192 }
193
194
195
196
197
198
199
200
201
202
203 private static boolean wanted(final int msgNum, final String line, final BitSet msgNums, final List<String> contains) {
204 return msgNums.isEmpty() && contains.isEmpty()
205 || msgNums.get(msgNum)
206 || listContains(contains, line);
207 }
208
209 }