1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.net.imap;
19
20 import java.io.BufferedReader;
21 import java.io.BufferedWriter;
22 import java.io.EOFException;
23 import java.io.InputStreamReader;
24 import java.io.IOException;
25 import java.io.OutputStreamWriter;
26 import java.util.ArrayList;
27 import java.util.List;
28
29 import org.apache.commons.net.SocketClient;
30 import org.apache.commons.net.io.CRLFLineReader;
31
32
33
34
35
36
37 public class IMAP extends SocketClient
38 {
39
40 public static final int DEFAULT_PORT = 143;
41
42 public enum IMAPState
43 {
44
45 DISCONNECTED_STATE,
46
47 NOT_AUTH_STATE,
48
49 AUTH_STATE,
50
51 LOGOUT_STATE;
52 }
53
54
55
56
57
58 protected static final String __DEFAULT_ENCODING = "ISO-8859-1";
59
60 private IMAPState __state;
61 protected BufferedWriter __writer;
62
63 protected BufferedReader _reader;
64 private int _replyCode;
65 private final List<String> _replyLines;
66
67 private final char[] _initialID = { 'A', 'A', 'A', 'A' };
68
69
70
71
72
73 public IMAP()
74 {
75 setDefaultPort(DEFAULT_PORT);
76 __state = IMAPState.DISCONNECTED_STATE;
77 _reader = null;
78 __writer = null;
79 _replyLines = new ArrayList<String>();
80 createCommandSupport();
81 }
82
83
84
85
86
87
88 private void __getReply() throws IOException
89 {
90 __getReply(true);
91 }
92
93
94
95
96
97
98
99
100 private void __getReply(boolean wantTag) throws IOException
101 {
102 _replyLines.clear();
103 String line = _reader.readLine();
104
105 if (line == null) {
106 throw new EOFException("Connection closed without indication.");
107 }
108
109 _replyLines.add(line);
110
111 if (wantTag) {
112 while(IMAPReply.isUntagged(line)) {
113 int literalCount = IMAPReply.literalCount(line);
114 while (literalCount >= 0) {
115 line=_reader.readLine();
116 if (line == null) {
117 throw new EOFException("Connection closed without indication.");
118 }
119 _replyLines.add(line);
120 literalCount -= (line.length() + 2);
121 }
122 line = _reader.readLine();
123 if (line == null) {
124 throw new EOFException("Connection closed without indication.");
125 }
126 _replyLines.add(line);
127 }
128
129 _replyCode = IMAPReply.getReplyCode(line);
130 } else {
131 _replyCode = IMAPReply.getUntaggedReplyCode(line);
132 }
133
134 fireReplyReceived(_replyCode, getReplyString());
135 }
136
137
138
139
140
141 @Override
142 protected void _connectAction_() throws IOException
143 {
144 super._connectAction_();
145 _reader =
146 new CRLFLineReader(new InputStreamReader(_input_,
147 __DEFAULT_ENCODING));
148 __writer =
149 new BufferedWriter(new OutputStreamWriter(_output_,
150 __DEFAULT_ENCODING));
151 int tmo = getSoTimeout();
152 if (tmo <= 0) {
153 setSoTimeout(connectTimeout);
154 }
155 __getReply(false);
156 if (tmo <= 0) {
157 setSoTimeout(tmo);
158 }
159 setState(IMAPState.NOT_AUTH_STATE);
160 }
161
162
163
164
165
166
167
168 protected void setState(IMAP.IMAPState state)
169 {
170 __state = state;
171 }
172
173
174
175
176
177
178
179 public IMAP.IMAPState getState()
180 {
181 return __state;
182 }
183
184
185
186
187
188
189
190
191
192 @Override
193 public void disconnect() throws IOException
194 {
195 super.disconnect();
196 _reader = null;
197 __writer = null;
198 _replyLines.clear();
199 setState(IMAPState.DISCONNECTED_STATE);
200 }
201
202
203
204
205
206
207
208
209
210
211 private int sendCommandWithID(String commandID, String command, String args) throws IOException
212 {
213 StringBuilder __commandBuffer = new StringBuilder();
214 if (commandID != null)
215 {
216 __commandBuffer.append(commandID);
217 __commandBuffer.append(' ');
218 }
219 __commandBuffer.append(command);
220
221 if (args != null)
222 {
223 __commandBuffer.append(' ');
224 __commandBuffer.append(args);
225 }
226 __commandBuffer.append(SocketClient.NETASCII_EOL);
227
228 String message = __commandBuffer.toString();
229 __writer.write(message);
230 __writer.flush();
231
232 fireCommandSent(command, message);
233
234 __getReply();
235 return _replyCode;
236 }
237
238
239
240
241
242
243
244
245 public int sendCommand(String command, String args) throws IOException
246 {
247 return sendCommandWithID(generateCommandID(), command, args);
248 }
249
250
251
252
253
254
255
256
257 public int sendCommand(String command) throws IOException
258 {
259 return sendCommand(command, null);
260 }
261
262
263
264
265
266
267
268
269
270 public int sendCommand(IMAPCommand command, String args) throws IOException
271 {
272 return sendCommand(command.getIMAPCommand(), args);
273 }
274
275
276
277
278
279
280
281
282
283 public boolean doCommand(IMAPCommand command, String args) throws IOException
284 {
285 return IMAPReply.isSuccess(sendCommand(command, args));
286 }
287
288
289
290
291
292
293
294
295
296 public int sendCommand(IMAPCommand command) throws IOException
297 {
298 return sendCommand(command, null);
299 }
300
301
302
303
304
305
306
307
308 public boolean doCommand(IMAPCommand command) throws IOException
309 {
310 return IMAPReply.isSuccess(sendCommand(command));
311 }
312
313
314
315
316
317
318
319 public int sendData(String command) throws IOException
320 {
321 return sendCommandWithID(null, command, null);
322 }
323
324
325
326
327
328
329 public String[] getReplyStrings()
330 {
331 return _replyLines.toArray(new String[_replyLines.size()]);
332 }
333
334
335
336
337
338
339
340
341 public String getReplyString()
342 {
343 StringBuilder buffer = new StringBuilder(256);
344 for (String s : _replyLines)
345 {
346 buffer.append(s);
347 buffer.append(SocketClient.NETASCII_EOL);
348 }
349
350 return buffer.toString();
351 }
352
353
354
355
356
357 protected String generateCommandID()
358 {
359 String res = new String (_initialID);
360
361 boolean carry = true;
362 for (int i = _initialID.length-1; carry && i>=0; i--)
363 {
364 if (_initialID[i] == 'Z')
365 {
366 _initialID[i] = 'A';
367 }
368 else
369 {
370 _initialID[i]++;
371 carry = false;
372 }
373 }
374 return res;
375 }
376 }
377