78 |
*/ |
*/ |
79 |
protected static final String US_ASCII = "US-ASCII"; |
protected static final String US_ASCII = "US-ASCII"; |
80 |
|
|
81 |
/** |
/** |
82 |
* The default IMAP port. |
* The default IMAP port. |
83 |
*/ |
*/ |
84 |
protected static final int DEFAULT_PORT = 143; |
protected static final int DEFAULT_PORT = 143; |
85 |
|
|
86 |
/** |
/** |
87 |
* The socket used for communication with the server. |
* The socket used for communication with the server. |
133 |
{ |
{ |
134 |
this(host, port, -1, -1, false); |
this(host, port, -1, -1, false); |
135 |
} |
} |
136 |
|
|
137 |
/** |
/** |
138 |
* Creates a new connection. |
* Creates a new connection. |
139 |
* @param host the name of the host to connect to |
* @param host the name of the host to connect to |
140 |
* @param port the port to connect to |
* @param port the port to connect to |
141 |
*/ |
*/ |
142 |
public IMAPConnection(String host, int port, |
public IMAPConnection(String host, int port, |
143 |
int connectionTimeout, int timeout, boolean debug) |
int connectionTimeout, int timeout, boolean debug) |
144 |
throws UnknownHostException, IOException |
throws UnknownHostException, IOException |
145 |
{ |
{ |
146 |
this.debug = debug; |
this.debug = debug; |
147 |
// TODO connectionTimeout |
// TODO connectionTimeout |
148 |
|
|
149 |
if (port<0) |
if (port < 0) |
150 |
port = DEFAULT_PORT; |
port = DEFAULT_PORT; |
151 |
|
|
152 |
// Set up socket |
// Set up socket |
153 |
socket = new Socket(host, port); |
socket = new Socket(host, port); |
154 |
if (timeout>0) |
if (timeout > 0) |
155 |
socket.setSoTimeout(timeout); |
socket.setSoTimeout(timeout); |
156 |
|
|
157 |
InputStream in = socket.getInputStream(); |
InputStream in = socket.getInputStream(); |
158 |
in = new BufferedInputStream(in); |
in = new BufferedInputStream(in); |
159 |
this.in = new IMAPResponseTokenizer(in); |
this.in = new IMAPResponseTokenizer(in); |
160 |
OutputStream out = socket.getOutputStream(); |
OutputStream out = socket.getOutputStream(); |
161 |
out = new BufferedOutputStream(out); |
out = new BufferedOutputStream(out); |
162 |
this.out = new CRLFOutputStream(out); |
this.out = new CRLFOutputStream(out); |
163 |
|
|
164 |
asyncResponses = new ArrayList(); |
asyncResponses = new ArrayList(); |
165 |
alerts = new ArrayList(); |
alerts = new ArrayList(); |
166 |
} |
} |
167 |
|
|
168 |
/** |
/** |
176 |
/** |
/** |
177 |
* Returns a new tag for a command. |
* Returns a new tag for a command. |
178 |
*/ |
*/ |
179 |
protected String newTag() { |
protected String newTag() |
180 |
|
{ |
181 |
return new StringBuffer(TAG_PREFIX).append(++tagIndex).toString(); |
return new StringBuffer(TAG_PREFIX).append(++tagIndex).toString(); |
182 |
} |
} |
183 |
|
|
184 |
/** |
/** |
185 |
* Sends the specified IMAP tagged command to the server. |
* Sends the specified IMAP tagged command to the server. |
186 |
*/ |
*/ |
187 |
protected void sendCommand(String tag, String command) |
protected void sendCommand(String tag, String command) throws IOException |
|
throws IOException |
|
188 |
{ |
{ |
189 |
if (debug) |
if (debug) |
190 |
{ |
{ |
191 |
Logger logger = Logger.getInstance(); |
Logger logger = Logger.getInstance(); |
192 |
logger.log("imap", "> "+tag+" "+command); |
logger.log("imap", "> " + tag + " " + command); |
193 |
} |
} |
194 |
String cmd = new StringBuffer(tag) |
String cmd = new StringBuffer(tag).append(' ').append(command).toString(); |
|
.append(' ') |
|
|
.append(command) |
|
|
.toString(); |
|
195 |
out.write(cmd); |
out.write(cmd); |
196 |
out.writeln(); |
out.writeln(); |
197 |
out.flush(); |
out.flush(); |
198 |
} |
} |
199 |
|
|
200 |
/** |
/** |
203 |
* @return true if OK was received, or false if NO was received |
* @return true if OK was received, or false if NO was received |
204 |
* @exception IOException if BAD was received or an I/O error occurred |
* @exception IOException if BAD was received or an I/O error occurred |
205 |
*/ |
*/ |
206 |
protected boolean invokeSimpleCommand(String command) |
protected boolean invokeSimpleCommand(String command) throws IOException |
|
throws IOException |
|
207 |
{ |
{ |
208 |
String tag = newTag(); |
String tag = newTag(); |
209 |
sendCommand(tag, command); |
sendCommand(tag, command); |
210 |
while (true) |
while (true) |
211 |
{ |
{ |
212 |
IMAPResponse response = readResponse(); |
IMAPResponse response = readResponse(); |
214 |
if (tag.equals(response.getTag())) |
if (tag.equals(response.getTag())) |
215 |
{ |
{ |
216 |
processAlerts(response); |
processAlerts(response); |
217 |
if (id==OK) |
if (id == OK) |
218 |
return true; |
return true; |
219 |
else if (id==NO) |
else if (id == NO) |
220 |
return false; |
return false; |
221 |
else |
else |
222 |
throw new IMAPException(id, response.getText()); |
throw new IMAPException(id, response.getText()); |
223 |
} |
} |
224 |
else if (response.isUntagged()) |
else if (response.isUntagged()) |
225 |
asyncResponses.add(response); |
asyncResponses.add(response); |
226 |
else |
else |
227 |
throw new IMAPException(id, response.getText()); |
throw new IMAPException(id, response.getText()); |
228 |
} |
} |
237 |
* <li>An untagged error response</li> |
* <li>An untagged error response</li> |
238 |
* <li>A continuation response</li> |
* <li>A continuation response</li> |
239 |
*/ |
*/ |
240 |
protected IMAPResponse readResponse() |
protected IMAPResponse readResponse() throws IOException |
|
throws IOException |
|
241 |
{ |
{ |
242 |
IMAPResponse response = in.next(); |
IMAPResponse response = in.next(); |
243 |
if (debug) |
if (debug) |
244 |
{ |
{ |
245 |
Logger logger = Logger.getInstance(); |
Logger logger = Logger.getInstance(); |
246 |
if (ansiDebug) |
if (ansiDebug) |
247 |
logger.log("imap", "< "+response.toANSIString()); |
logger.log("imap", "< " + response.toANSIString()); |
248 |
else |
else |
249 |
logger.log("imap", "< "+response.toString()); |
logger.log("imap", "< " + response.toString()); |
250 |
} |
} |
251 |
return response; |
return response; |
252 |
} |
} |
256 |
private void processAlerts(IMAPResponse response) |
private void processAlerts(IMAPResponse response) |
257 |
{ |
{ |
258 |
List code = response.getResponseCode(); |
List code = response.getResponseCode(); |
259 |
if (code!=null && code.contains(ALERT)) |
if (code != null && code.contains(ALERT)) |
260 |
alerts.add(response.getText()); |
alerts.add(response.getText()); |
261 |
} |
} |
262 |
|
|
263 |
boolean alertsPending() |
boolean alertsPending() |
264 |
{ |
{ |
265 |
return (alerts.size()>0); |
return (alerts.size() > 0); |
266 |
} |
} |
267 |
|
|
268 |
String[] getAlerts() |
String[]getAlerts() |
269 |
{ |
{ |
270 |
String[] a = new String[alerts.size()]; |
String[]a = new String[alerts.size()]; |
271 |
alerts.toArray(a); |
alerts.toArray(a); |
272 |
alerts.clear(); // flush |
alerts.clear(); // flush |
273 |
return a; |
return a; |
274 |
} |
} |
275 |
|
|
278 |
/** |
/** |
279 |
* Returns a list of the capabilities of the IMAP server. |
* Returns a list of the capabilities of the IMAP server. |
280 |
*/ |
*/ |
281 |
public List capability() |
public List capability() throws IOException |
|
throws IOException |
|
282 |
{ |
{ |
283 |
String tag = newTag(); |
String tag = newTag(); |
284 |
sendCommand(tag, CAPABILITY); |
sendCommand(tag, CAPABILITY); |
285 |
while (true) |
while (true) |
286 |
{ |
{ |
287 |
IMAPResponse response = readResponse(); |
IMAPResponse response = readResponse(); |
289 |
if (tag.equals(response.getTag())) |
if (tag.equals(response.getTag())) |
290 |
{ |
{ |
291 |
processAlerts(response); |
processAlerts(response); |
292 |
if (id==OK) |
if (id == OK) |
293 |
{ |
{ |
294 |
// The capability "list" is actually contained in the response |
// The capability "list" is actually contained in the response |
295 |
// text. |
// text. |
296 |
String text = response.getText(); |
String text = response.getText(); |
297 |
List capabilities = new ArrayList(); |
List capabilities = new ArrayList(); |
298 |
int si = text.indexOf(' '); |
int si = text.indexOf(' '); |
299 |
while (si!=-1) |
while (si != -1) |
300 |
{ |
{ |
301 |
capabilities.add(text.substring(0, si)); |
capabilities.add(text.substring(0, si)); |
302 |
text = text.substring(si+1); |
text = text.substring(si + 1); |
303 |
si = text.indexOf(' '); |
si = text.indexOf(' '); |
304 |
} |
} |
305 |
if (text.length()>0) |
if (text.length() > 0) |
306 |
capabilities.add(text); |
capabilities.add(text); |
307 |
return capabilities; |
return capabilities; |
308 |
} |
} |
309 |
else |
else |
321 |
* If a change in mailbox state is detected, a new mailbox status is |
* If a change in mailbox state is detected, a new mailbox status is |
322 |
* returned, otherwise this method returns null. |
* returned, otherwise this method returns null. |
323 |
*/ |
*/ |
324 |
public MailboxStatus noop() |
public MailboxStatus noop() throws IOException |
|
throws IOException |
|
325 |
{ |
{ |
326 |
String tag = newTag(); |
String tag = newTag(); |
327 |
sendCommand(tag, NOOP); |
sendCommand(tag, NOOP); |
328 |
boolean changed = false; |
boolean changed = false; |
329 |
MailboxStatus ms = new MailboxStatus(); |
MailboxStatus ms = new MailboxStatus(); |
330 |
Iterator asyncIterator = asyncResponses.iterator(); |
Iterator asyncIterator = asyncResponses.iterator(); |
334 |
// Process any asynchronous responses first |
// Process any asynchronous responses first |
335 |
if (asyncIterator.hasNext()) |
if (asyncIterator.hasNext()) |
336 |
{ |
{ |
337 |
response = (IMAPResponse)asyncIterator.next(); |
response = (IMAPResponse) asyncIterator.next(); |
338 |
asyncIterator.remove(); |
asyncIterator.remove(); |
339 |
} |
} |
340 |
else |
else |
341 |
response = readResponse(); |
response = readResponse(); |
342 |
String id = response.getID(); |
String id = response.getID(); |
343 |
if (response.isUntagged()) |
if (response.isUntagged()) |
344 |
{ |
{ |
347 |
else if (tag.equals(response.getTag())) |
else if (tag.equals(response.getTag())) |
348 |
{ |
{ |
349 |
processAlerts(response); |
processAlerts(response); |
350 |
if (id==OK) |
if (id == OK) |
351 |
return changed ? ms : null; |
return changed ? ms : null; |
352 |
else |
else |
353 |
throw new IMAPException(id, response.getText()); |
throw new IMAPException(id, response.getText()); |
362 |
* See RFC 2595 for details. |
* See RFC 2595 for details. |
363 |
* @return true if successful, false otherwise |
* @return true if successful, false otherwise |
364 |
*/ |
*/ |
365 |
public boolean starttls() |
public boolean starttls() throws IOException |
|
throws IOException |
|
366 |
{ |
{ |
367 |
try |
try |
368 |
{ |
{ |
369 |
// Use SSLSocketFactory to negotiate a TLS session and wrap the |
// Use SSLSocketFactory to negotiate a TLS session and wrap the |
370 |
// current socket. |
// current socket. |
371 |
SSLSocketFactory factory = |
SSLSocketFactory factory = |
372 |
(SSLSocketFactory)SSLSocketFactory.getDefault(); |
(SSLSocketFactory) SSLSocketFactory.getDefault(); |
373 |
|
|
374 |
String tag = newTag(); |
String tag = newTag(); |
375 |
sendCommand(tag, STARTTLS); |
sendCommand(tag, STARTTLS); |
376 |
while (true) |
while (true) |
377 |
{ |
{ |
378 |
IMAPResponse response = readResponse(); |
IMAPResponse response = readResponse(); |
379 |
if (response.isTagged() && tag.equals(response.getTag())) |
if (response.isTagged() && tag.equals(response.getTag())) |
380 |
{ |
{ |
381 |
processAlerts(response); |
processAlerts(response); |
382 |
String id = response.getID(); |
String id = response.getID(); |
383 |
if (id==OK) |
if (id == OK) |
384 |
break; // negotiate TLS |
break; // negotiate TLS |
385 |
else if (id==BAD) |
else if (id == BAD) |
386 |
return false; |
return false; |
387 |
} |
} |
388 |
else |
else |
389 |
asyncResponses.add(response); |
asyncResponses.add(response); |
390 |
} |
} |
391 |
|
|
392 |
socket = factory.createSocket(socket, |
socket = factory.createSocket(socket, |
393 |
socket.getInetAddress().getHostName(), |
socket.getInetAddress().getHostName(), |
394 |
socket.getPort(), |
socket.getPort(), true); |
395 |
true); |
|
396 |
|
InputStream in = socket.getInputStream(); |
397 |
InputStream in = socket.getInputStream(); |
in = new BufferedInputStream(in); |
398 |
in = new BufferedInputStream(in); |
this.in = new IMAPResponseTokenizer(in); |
399 |
this.in = new IMAPResponseTokenizer(in); |
OutputStream out = socket.getOutputStream(); |
400 |
OutputStream out = socket.getOutputStream(); |
out = new BufferedOutputStream(out); |
401 |
out = new BufferedOutputStream(out); |
this.out = new CRLFOutputStream(out); |
|
this.out = new CRLFOutputStream(out); |
|
402 |
return true; |
return true; |
403 |
} |
} |
404 |
catch (ClassNotFoundException e) |
catch(ClassNotFoundException e) |
405 |
{ |
{ |
406 |
return false; // No javax.net classes in runtime |
return false; // No javax.net classes in runtime |
407 |
} |
} |
408 |
} |
} |
409 |
|
|
413 |
* @param password the authentication credentials |
* @param password the authentication credentials |
414 |
* @return true if authentication was successful, false otherwise |
* @return true if authentication was successful, false otherwise |
415 |
*/ |
*/ |
416 |
public boolean login(String username, String password) |
public boolean login(String username, String password) throws IOException |
|
throws IOException |
|
417 |
{ |
{ |
418 |
StringBuffer cmd = new StringBuffer(LOGIN); |
StringBuffer cmd = new StringBuffer(LOGIN); |
419 |
cmd.append(' '); |
cmd.append(' '); |
420 |
cmd.append(quote(username)); |
cmd.append(quote(username)); |
421 |
cmd.append(' '); |
cmd.append(' '); |
422 |
cmd.append(quote(password)); |
cmd.append(quote(password)); |
423 |
return invokeSimpleCommand(cmd.toString()); |
return invokeSimpleCommand(cmd.toString()); |
424 |
} |
} |
425 |
|
|
426 |
/** |
/** |
427 |
* Authenticates the connection using the specified SASL mechanism, |
* Authenticates the connection using the specified SASL mechanism, |
428 |
* username, and password. |
* username, and password. |
429 |
* @param mechanism a SASL authentication mechanism, e.g. LOGIN, PLAIN, |
* @param mechanism a SASL authentication mechanism, e.g. LOGIN, PLAIN, |
432 |
* @param password the authentication credentials |
* @param password the authentication credentials |
433 |
* @return true if authentication was successful, false otherwise |
* @return true if authentication was successful, false otherwise |
434 |
*/ |
*/ |
435 |
public boolean authenticate(String mechanism, String username, String password) |
public boolean authenticate(String mechanism, String username, |
436 |
throws IOException |
String password) throws IOException |
437 |
{ |
{ |
438 |
try |
try |
439 |
{ |
{ |
440 |
String[] m = new String[] { mechanism }; |
String[]m = new String[] |
441 |
CallbackHandler ch = new SaslCallbackHandler(username, password); |
{ |
442 |
// Avoid lengthy callback procedure for GNU Crypto |
mechanism}; |
443 |
Properties p = new Properties(); |
CallbackHandler ch = new SaslCallbackHandler(username, password); |
444 |
p.put("gnu.crypto.sasl.username", username); |
// Avoid lengthy callback procedure for GNU Crypto |
445 |
p.put("gnu.crypto.sasl.password", password); |
Properties p = new Properties(); |
446 |
SaslClient sasl = Sasl.createSaslClient(m, null, "smtp", |
p.put("gnu.crypto.sasl.username", username); |
447 |
socket.getInetAddress().getHostName(), p, ch); |
p.put("gnu.crypto.sasl.password", password); |
448 |
|
SaslClient sasl = Sasl.createSaslClient(m, null, "smtp", |
449 |
StringBuffer cmd = new StringBuffer(AUTHENTICATE); |
socket.getInetAddress(). |
450 |
cmd.append(' '); |
getHostName(), p, ch); |
451 |
cmd.append(mechanism); |
|
452 |
if (sasl.hasInitialResponse()) |
StringBuffer cmd = new StringBuffer(AUTHENTICATE); |
453 |
{ |
cmd.append(' '); |
454 |
cmd.append(' '); |
cmd.append(mechanism); |
455 |
byte[] init = sasl.evaluateChallenge(new byte[0]); |
if (sasl.hasInitialResponse()) |
456 |
cmd.append(new String(init, US_ASCII)); |
{ |
457 |
} |
cmd.append(' '); |
458 |
String tag = newTag(); |
byte[]init = sasl.evaluateChallenge(new byte[0]); |
459 |
sendCommand(tag, cmd.toString()); |
cmd.append(new String(init, US_ASCII)); |
460 |
while (true) |
} |
461 |
{ |
String tag = newTag(); |
462 |
IMAPResponse response = readResponse(); |
sendCommand(tag, cmd.toString()); |
463 |
if (tag.equals(response.getTag())) |
while (true) |
464 |
{ |
{ |
465 |
processAlerts(response); |
IMAPResponse response = readResponse(); |
466 |
String id = response.getID(); |
if (tag.equals(response.getTag())) |
467 |
if (id==OK) |
{ |
468 |
{ |
processAlerts(response); |
469 |
String qop = (String)sasl.getNegotiatedProperty(Sasl.QOP); |
String id = response.getID(); |
470 |
if ("auth-int".equalsIgnoreCase(qop) |
if (id == OK) |
471 |
|| "auth-conf".equalsIgnoreCase(qop)) |
{ |
472 |
{ |
String qop = (String) sasl.getNegotiatedProperty(Sasl.QOP); |
473 |
InputStream in = socket.getInputStream(); |
if ("auth-int".equalsIgnoreCase(qop) |
474 |
in = new BufferedInputStream(in); |
|| "auth-conf".equalsIgnoreCase(qop)) |
475 |
in = new SaslInputStream(sasl, in); |
{ |
476 |
this.in = new IMAPResponseTokenizer(in); |
InputStream in = socket.getInputStream(); |
477 |
OutputStream out = socket.getOutputStream(); |
in = new BufferedInputStream(in); |
478 |
out = new BufferedOutputStream(out); |
in = new SaslInputStream(sasl, in); |
479 |
out = new SaslOutputStream(sasl, out); |
this.in = new IMAPResponseTokenizer(in); |
480 |
this.out = new CRLFOutputStream(out); |
OutputStream out = socket.getOutputStream(); |
481 |
} |
out = new BufferedOutputStream(out); |
482 |
return true; |
out = new SaslOutputStream(sasl, out); |
483 |
} |
this.out = new CRLFOutputStream(out); |
484 |
else if (id==NO) |
} |
485 |
return false; |
return true; |
486 |
else if (id==BAD) |
} |
487 |
throw new IMAPException(id, response.getText()); |
else if (id == NO) |
488 |
} |
return false; |
489 |
else if (response.isContinuation()) |
else if (id == BAD) |
490 |
{ |
throw new IMAPException(id, response.getText()); |
491 |
try |
} |
492 |
{ |
else if (response.isContinuation()) |
493 |
byte[] c0 = response.getText().getBytes(US_ASCII); |
{ |
494 |
byte[] c1 = BASE64.decode(c0); // challenge |
try |
495 |
byte[] r0 = sasl.evaluateChallenge(c1); |
{ |
496 |
byte[] r1 = BASE64.encode(r0); // response |
byte[]c0 = response.getText().getBytes(US_ASCII); |
497 |
out.write(r1); |
byte[]c1 = BASE64.decode(c0); // challenge |
498 |
out.write(0x0d); |
byte[]r0 = sasl.evaluateChallenge(c1); |
499 |
out.flush(); |
byte[]r1 = BASE64.encode(r0); // response |
500 |
} |
out.write(r1); |
501 |
catch (SaslException e) |
out.writeln(); |
502 |
{ |
out.flush(); |
503 |
// Error in SASL challenge evaluation - cancel exchange |
} |
504 |
out.write(0x2a); |
catch(SaslException e) |
505 |
out.write(0x0d); |
{ |
506 |
out.flush(); |
// Error in SASL challenge evaluation - cancel exchange |
507 |
} |
out.write(0x2a); |
508 |
} |
out.writeln(); |
509 |
else |
out.flush(); |
510 |
asyncResponses.add(response); |
} |
511 |
} |
} |
512 |
} |
else |
513 |
catch (SaslException e) |
asyncResponses.add(response); |
514 |
{ |
} |
515 |
return false; // No provider for mechanism |
} |
516 |
} |
catch(SaslException e) |
517 |
catch (ClassNotFoundException e) |
{ |
518 |
{ |
return false; // No provider for mechanism |
519 |
return false; // No javax.security.sasl classes |
} |
520 |
} |
catch(ClassNotFoundException e) |
521 |
} |
{ |
522 |
|
return false; // No javax.security.sasl classes |
523 |
|
} |
524 |
|
} |
525 |
|
|
526 |
/** |
/** |
527 |
* Login to the connection using the CRAM-MD5 authorization extension. |
* Login to the connection using the CRAM-MD5 authorization extension. |
528 |
* This method is fully documented in RFC 2195. |
* This method is fully documented in RFC 2195. |
564 |
System.arraycopy(digest, 0, r1, r0.length+1, digest.length); |
System.arraycopy(digest, 0, r1, r0.length+1, digest.length); |
565 |
byte[] r2 = BASE64.encode(r1); |
byte[] r2 = BASE64.encode(r1); |
566 |
out.write(r2); |
out.write(r2); |
567 |
out.write(0x0d); |
out.writeln(); |
568 |
out.flush(); |
out.flush(); |
569 |
} |
} |
570 |
catch (NoSuchAlgorithmException e) |
catch (NoSuchAlgorithmException e) |
571 |
{ |
{ |
572 |
// No MD5 algorithm provider - cancel exchange |
// No MD5 algorithm provider - cancel exchange |
573 |
out.write(0x2a); |
out.write(0x2a); |
574 |
out.write(0x0d); |
out.writeln(); |
575 |
out.flush(); |
out.flush(); |
576 |
} |
} |
577 |
} |
} |
629 |
* Logout this connection. |
* Logout this connection. |
630 |
* Underlying network resources will be freed. |
* Underlying network resources will be freed. |
631 |
*/ |
*/ |
632 |
public void logout() |
public void logout() throws IOException |
|
throws IOException |
|
633 |
{ |
{ |
634 |
String tag = newTag(); |
String tag = newTag(); |
635 |
sendCommand(tag, LOGOUT); |
sendCommand(tag, LOGOUT); |
636 |
while (true) |
while (true) |
637 |
{ |
{ |
638 |
IMAPResponse response = readResponse(); |
IMAPResponse response = readResponse(); |
640 |
{ |
{ |
641 |
processAlerts(response); |
processAlerts(response); |
642 |
String id = response.getID(); |
String id = response.getID(); |
643 |
if (id==OK) |
if (id == OK) |
644 |
{ |
{ |
645 |
socket.close(); |
socket.close(); |
646 |
return; |
return; |
647 |
} |
} |
648 |
else |
else |
649 |
throw new IMAPException(id, response.getText()); |
throw new IMAPException(id, response.getText()); |
650 |
} |
} |
651 |
else |
else |
652 |
asyncResponses.add(response); |
asyncResponses.add(response); |
659 |
* @param mailbox the mailbox name |
* @param mailbox the mailbox name |
660 |
* @return a MailboxStatus containing the state of the selected mailbox |
* @return a MailboxStatus containing the state of the selected mailbox |
661 |
*/ |
*/ |
662 |
public MailboxStatus select(String mailbox) |
public MailboxStatus select(String mailbox) throws IOException |
|
throws IOException |
|
663 |
{ |
{ |
664 |
return selectImpl(mailbox, SELECT); |
return selectImpl(mailbox, SELECT); |
665 |
} |
} |
670 |
* @param mailbox the mailbox name |
* @param mailbox the mailbox name |
671 |
* @return a MailboxStatus containing the state of the selected mailbox |
* @return a MailboxStatus containing the state of the selected mailbox |
672 |
*/ |
*/ |
673 |
public MailboxStatus examine(String mailbox) |
public MailboxStatus examine(String mailbox) throws IOException |
|
throws IOException |
|
674 |
{ |
{ |
675 |
return selectImpl(mailbox, EXAMINE); |
return selectImpl(mailbox, EXAMINE); |
676 |
} |
} |
679 |
throws IOException |
throws IOException |
680 |
{ |
{ |
681 |
String tag = newTag(); |
String tag = newTag(); |
682 |
sendCommand(tag, new StringBuffer(command) |
sendCommand(tag, |
683 |
.append(' ') |
new StringBuffer(command).append(' '). |
684 |
.append(quote(UTF7imap.encode(mailbox))) |
append(quote(UTF7imap.encode(mailbox))).toString()); |
|
.toString()); |
|
685 |
MailboxStatus ms = new MailboxStatus(); |
MailboxStatus ms = new MailboxStatus(); |
686 |
while (true) |
while (true) |
687 |
{ |
{ |
695 |
else if (tag.equals(response.getTag())) |
else if (tag.equals(response.getTag())) |
696 |
{ |
{ |
697 |
processAlerts(response); |
processAlerts(response); |
698 |
if (id==OK) |
if (id == OK) |
699 |
{ |
{ |
700 |
List rc = response.getResponseCode(); |
List rc = response.getResponseCode(); |
701 |
if (rc.size()>0 && rc.get(0)==READ_WRITE) |
if (rc.size() > 0 && rc.get(0) == READ_WRITE) |
702 |
ms.readWrite = true; |
ms.readWrite = true; |
703 |
return ms; |
return ms; |
704 |
} |
} |
711 |
} |
} |
712 |
|
|
713 |
protected boolean updateMailboxStatus(MailboxStatus ms, |
protected boolean updateMailboxStatus(MailboxStatus ms, |
714 |
String id, IMAPResponse response) |
String id, IMAPResponse response) |
715 |
throws IOException |
throws IOException |
716 |
{ |
{ |
717 |
if (id==OK) |
if (id == OK) |
718 |
{ |
{ |
719 |
boolean changed = false; |
boolean changed = false; |
720 |
List rc = response.getResponseCode(); |
List rc = response.getResponseCode(); |
721 |
int len = (rc==null) ? 0 : rc.size(); |
int len = (rc == null) ? 0 : rc.size(); |
722 |
for (int i=0; i<len; i++) |
for (int i = 0; i < len; i++) |
723 |
{ |
{ |
724 |
Object ocmd = rc.get(i); |
Object ocmd = rc.get(i); |
725 |
if (ocmd instanceof String) |
if (ocmd instanceof String) |
726 |
{ |
{ |
727 |
String cmd = (String)ocmd; |
String cmd = (String) ocmd; |
728 |
if (i+1<len) |
if (i + 1 < len) |
729 |
{ |
{ |
730 |
Object oparam = rc.get(i+1); |
Object oparam = rc.get(i + 1); |
731 |
if (oparam instanceof String) |
if (oparam instanceof String) |
732 |
{ |
{ |
733 |
String param = (String)oparam; |
String param = (String) oparam; |
734 |
try |
try |
735 |
{ |
{ |
736 |
if (cmd==UNSEEN) |
if (cmd == UNSEEN) |
737 |
{ |
{ |
738 |
ms.firstUnreadMessage = Integer.parseInt(param); |
ms.firstUnreadMessage = Integer.parseInt(param); |
739 |
i++; |
i++; |
740 |
changed = true; |
changed = true; |
741 |
} |
} |
742 |
else if (cmd==UIDVALIDITY) |
else if (cmd == UIDVALIDITY) |
743 |
{ |
{ |
744 |
ms.uidValidity = Integer.parseInt(param); |
ms.uidValidity = Integer.parseInt(param); |
745 |
i++; |
i++; |
746 |
changed = true; |
changed = true; |
747 |
} |
} |
748 |
} |
} |
749 |
catch (NumberFormatException e) |
catch(NumberFormatException e) |
750 |
{ |
{ |
751 |
throw new ProtocolException("Illegal "+cmd+" value: "+ |
throw new ProtocolException("Illegal " + cmd + |
752 |
param); |
" value: " + param); |
753 |
} |
} |
754 |
} |
} |
755 |
else if (oparam instanceof List) |
else if (oparam instanceof List) |
756 |
{ |
{ |
757 |
if (cmd==PERMANENTFLAGS) |
if (cmd == PERMANENTFLAGS) |
758 |
{ |
{ |
759 |
ms.permanentFlags = (List)oparam; |
ms.permanentFlags = (List) oparam; |
760 |
i++; |
i++; |
761 |
changed = true; |
changed = true; |
762 |
} |
} |
766 |
} |
} |
767 |
return changed; |
return changed; |
768 |
} |
} |
769 |
else if (id==EXISTS) |
else if (id == EXISTS) |
770 |
{ |
{ |
771 |
ms.messageCount = response.getCount(); |
ms.messageCount = response.getCount(); |
772 |
return true; |
return true; |
773 |
} |
} |
774 |
else if (id==RECENT) |
else if (id == RECENT) |
775 |
{ |
{ |
776 |
ms.newMessageCount = response.getCount(); |
ms.newMessageCount = response.getCount(); |
777 |
return true; |
return true; |
778 |
} |
} |
779 |
else if (id==FLAGS) |
else if (id == FLAGS) |
780 |
{ |
{ |
781 |
ms.flags = response.getResponseCode(); |
ms.flags = response.getResponseCode(); |
782 |
return true; |
return true; |
790 |
* @param mailbox the mailbox name |
* @param mailbox the mailbox name |
791 |
* @return true if the mailbox was successfully created, false otherwise |
* @return true if the mailbox was successfully created, false otherwise |
792 |
*/ |
*/ |
793 |
public boolean create(String mailbox) |
public boolean create(String mailbox) throws IOException |
|
throws IOException |
|
794 |
{ |
{ |
795 |
return invokeSimpleCommand(new StringBuffer(CREATE) |
return invokeSimpleCommand(new StringBuffer(CREATE).append(' '). |
796 |
.append(' ') |
append(quote(UTF7imap.encode(mailbox))). |
797 |
.append(quote(UTF7imap.encode(mailbox))) |
toString()); |
|
.toString()); |
|
798 |
} |
} |
799 |
|
|
800 |
/** |
/** |
802 |
* @param mailbox the mailbox name |
* @param mailbox the mailbox name |
803 |
* @return true if the mailbox was successfully deleted, false otherwise |
* @return true if the mailbox was successfully deleted, false otherwise |
804 |
*/ |
*/ |
805 |
public boolean delete(String mailbox) |
public boolean delete(String mailbox) throws IOException |
|
throws IOException |
|
806 |
{ |
{ |
807 |
return invokeSimpleCommand(new StringBuffer(DELETE) |
return invokeSimpleCommand(new StringBuffer(DELETE).append(' '). |
808 |
.append(' ') |
append(quote(UTF7imap.encode(mailbox))). |
809 |
.append(quote(UTF7imap.encode(mailbox))) |
toString()); |
|
.toString()); |
|
810 |
} |
} |
811 |
|
|
812 |
/** |
/** |
815 |
* @param target the target mailbox name |
* @param target the target mailbox name |
816 |
* @return true if the mailbox was successfully renamed, false otherwise |
* @return true if the mailbox was successfully renamed, false otherwise |
817 |
*/ |
*/ |
818 |
public boolean rename(String source, String target) |
public boolean rename(String source, String target) throws IOException |
|
throws IOException |
|
819 |
{ |
{ |
820 |
return invokeSimpleCommand(new StringBuffer(RENAME) |
return invokeSimpleCommand(new StringBuffer(RENAME).append(' '). |
821 |
.append(' ') |
append(quote(UTF7imap.encode(source))). |
822 |
.append(quote(UTF7imap.encode(source))) |
append(' '). |
823 |
.append(' ') |
append(quote(UTF7imap.encode(target))). |
824 |
.append(quote(UTF7imap.encode(target))) |
toString()); |
|
.toString()); |
|
825 |
} |
} |
826 |
|
|
827 |
/** |
/** |
830 |
* @param mailbox the mailbox name |
* @param mailbox the mailbox name |
831 |
* @return true if the mailbox was successfully subscribed, false otherwise |
* @return true if the mailbox was successfully subscribed, false otherwise |
832 |
*/ |
*/ |
833 |
public boolean subscribe(String mailbox) |
public boolean subscribe(String mailbox) throws IOException |
|
throws IOException |
|
834 |
{ |
{ |
835 |
return invokeSimpleCommand(new StringBuffer(SUBSCRIBE) |
return invokeSimpleCommand(new StringBuffer(SUBSCRIBE).append(' '). |
836 |
.append(' ') |
append(quote(UTF7imap.encode(mailbox))). |
837 |
.append(quote(UTF7imap.encode(mailbox))) |
toString()); |
|
.toString()); |
|
838 |
} |
} |
839 |
|
|
840 |
/** |
/** |
843 |
* @param mailbox the mailbox name |
* @param mailbox the mailbox name |
844 |
* @return true if the mailbox was successfully unsubscribed, false otherwise |
* @return true if the mailbox was successfully unsubscribed, false otherwise |
845 |
*/ |
*/ |
846 |
public boolean unsubscribe(String mailbox) |
public boolean unsubscribe(String mailbox) throws IOException |
|
throws IOException |
|
847 |
{ |
{ |
848 |
return invokeSimpleCommand(new StringBuffer(UNSUBSCRIBE) |
return invokeSimpleCommand(new StringBuffer(UNSUBSCRIBE).append(' '). |
849 |
.append(' ') |
append(quote(UTF7imap.encode(mailbox))). |
850 |
.append(quote(UTF7imap.encode(mailbox))) |
toString()); |
|
.toString()); |
|
851 |
} |
} |
852 |
|
|
853 |
/** |
/** |
857 |
* defined |
* defined |
858 |
* @param mailbox a mailbox name, possibly including IMAP wildcards |
* @param mailbox a mailbox name, possibly including IMAP wildcards |
859 |
*/ |
*/ |
860 |
public ListEntry[] list(String reference, String mailbox) |
public ListEntry[] list(String reference, String mailbox) throws IOException |
|
throws IOException |
|
861 |
{ |
{ |
862 |
return listImpl(LIST, reference, mailbox); |
return listImpl(LIST, reference, mailbox); |
863 |
} |
} |
866 |
* Returns a subset of subscribed names. |
* Returns a subset of subscribed names. |
867 |
* @see #list |
* @see #list |
868 |
*/ |
*/ |
869 |
public ListEntry[] lsub(String reference, String mailbox) |
public ListEntry[] lsub(String reference, String mailbox) throws IOException |
|
throws IOException |
|
870 |
{ |
{ |
871 |
return listImpl(LSUB, reference, mailbox); |
return listImpl(LSUB, reference, mailbox); |
872 |
} |
} |
873 |
|
|
874 |
protected ListEntry[] listImpl(String command, String reference, |
protected ListEntry[] listImpl(String command, String reference, |
875 |
String mailbox) |
String mailbox) throws IOException |
|
throws IOException |
|
876 |
{ |
{ |
877 |
if (reference==null) |
if (reference == null) |
878 |
reference = ""; |
reference = ""; |
879 |
if (mailbox==null) |
if (mailbox == null) |
880 |
mailbox = ""; |
mailbox = ""; |
881 |
String tag = newTag(); |
String tag = newTag(); |
882 |
sendCommand(tag, new StringBuffer(command) |
sendCommand(tag, |
883 |
.append(' ') |
new StringBuffer(command).append(' '). |
884 |
.append(quote(UTF7imap.encode(reference))) |
append(quote(UTF7imap.encode(reference))).append(' '). |
885 |
.append(' ') |
append(quote(UTF7imap.encode(mailbox))).toString()); |
|
.append(quote(UTF7imap.encode(mailbox))) |
|
|
.toString()); |
|
886 |
List acc = new ArrayList(); |
List acc = new ArrayList(); |
887 |
while (true) |
while (true) |
888 |
{ |
{ |
894 |
{ |
{ |
895 |
List code = response.getResponseCode(); |
List code = response.getResponseCode(); |
896 |
String text = response.getText(); |
String text = response.getText(); |
897 |
|
|
898 |
// Populate entry attributes with the interned versions |
// Populate entry attributes with the interned versions |
899 |
// of the response code. |
// of the response code. |
900 |
// NB IMAP servers do not necessarily pay attention to case. |
// NB IMAP servers do not necessarily pay attention to case. |
903 |
boolean noselect = false; |
boolean noselect = false; |
904 |
boolean marked = false; |
boolean marked = false; |
905 |
boolean unmarked = false; |
boolean unmarked = false; |
906 |
for (int i=0; i<alen; i++) |
for (int i = 0; i < alen; i++) |
907 |
{ |
{ |
908 |
String attribute = (String)code.get(i); |
String attribute = (String) code.get(i); |
909 |
if (attribute.equalsIgnoreCase(LIST_NOINFERIORS)) |
if (attribute.equalsIgnoreCase(LIST_NOINFERIORS)) |
910 |
noinferiors = true; |
noinferiors = true; |
911 |
else if (attribute.equalsIgnoreCase(LIST_NOSELECT)) |
else if (attribute.equalsIgnoreCase(LIST_NOSELECT)) |
912 |
noselect = true; |
noselect = true; |
913 |
else if (attribute.equalsIgnoreCase(LIST_MARKED)) |
else if (attribute.equalsIgnoreCase(LIST_MARKED)) |
914 |
marked = true; |
marked = true; |
915 |
else if (attribute.equalsIgnoreCase(LIST_UNMARKED)) |
else if (attribute.equalsIgnoreCase(LIST_UNMARKED)) |
916 |
unmarked = true; |
unmarked = true; |
917 |
} |
} |
918 |
int si = text.indexOf(' '); |
int si = text.indexOf(' '); |
919 |
char delimiter='\u0000'; |
char delimiter = '\u0000'; |
920 |
String d = text.substring(0, si); |
String d = text.substring(0, si); |
921 |
if (d.equalsIgnoreCase(NIL)) |
if (d.equalsIgnoreCase(NIL)) |
922 |
delimiter = stripQuotes(d).charAt(0); |
delimiter = stripQuotes(d).charAt(0); |
923 |
String mbox = stripQuotes(text.substring(si+1)); |
String mbox = stripQuotes(text.substring(si + 1)); |
924 |
mbox = UTF7imap.decode(mbox); |
mbox = UTF7imap.decode(mbox); |
925 |
ListEntry entry = new ListEntry(mbox, delimiter, noinferiors, |
ListEntry entry = new ListEntry(mbox, delimiter, noinferiors, |
926 |
noselect, marked, unmarked); |
noselect, marked, unmarked); |
927 |
acc.add(entry); |
acc.add(entry); |
928 |
} |
} |
929 |
else |
else |
932 |
else if (tag.equals(response.getTag())) |
else if (tag.equals(response.getTag())) |
933 |
{ |
{ |
934 |
processAlerts(response); |
processAlerts(response); |
935 |
if (id==OK) |
if (id == OK) |
936 |
{ |
{ |
937 |
ListEntry[] entries = new ListEntry[acc.size()]; |
ListEntry[]entries = new ListEntry[acc.size()]; |
938 |
acc.toArray(entries); |
acc.toArray(entries); |
939 |
return entries; |
return entries; |
940 |
} |
} |
949 |
/** |
/** |
950 |
* Requests the status of the specified mailbox. |
* Requests the status of the specified mailbox. |
951 |
*/ |
*/ |
952 |
public MailboxStatus status(String mailbox, String[] statusNames) |
public MailboxStatus status(String mailbox, String[]statusNames) |
953 |
throws IOException |
throws IOException |
954 |
{ |
{ |
955 |
String tag = newTag(); |
String tag = newTag(); |
956 |
StringBuffer buffer = new StringBuffer(STATUS) |
StringBuffer buffer = |
957 |
.append(' ') |
new StringBuffer(STATUS).append(' '). |
958 |
.append(quote(UTF7imap.encode(mailbox))) |
append(quote(UTF7imap.encode(mailbox))).append(' ').append('('); |
959 |
.append(' ') |
for (int i = 0; i < statusNames.length; i++) |
|
.append('('); |
|
|
for (int i=0; i<statusNames.length; i++) |
|
960 |
{ |
{ |
961 |
if (i>0) |
if (i > 0) |
962 |
buffer.append(' '); |
buffer.append(' '); |
963 |
buffer.append(statusNames[i]); |
buffer.append(statusNames[i]); |
964 |
} |
} |
971 |
String id = response.getID(); |
String id = response.getID(); |
972 |
if (response.isUntagged()) |
if (response.isUntagged()) |
973 |
{ |
{ |
974 |
if (id==STATUS) |
if (id == STATUS) |
975 |
{ |
{ |
976 |
List code = response.getResponseCode(); |
List code = response.getResponseCode(); |
977 |
int last = code.size()-1; |
int last = code.size() - 1; |
978 |
for (int i=0; i<last; i+=2) |
for (int i = 0; i < last; i += 2) |
979 |
{ |
{ |
980 |
try |
try |
981 |
{ |
{ |
982 |
String statusName = ((String)code.get(i)).intern(); |
String statusName = ((String) code.get(i)).intern(); |
983 |
int value = Integer.parseInt((String)code.get(i+1)); |
int value = Integer.parseInt((String) code.get(i + 1)); |
984 |
if (statusName==MESSAGES) |
if (statusName == MESSAGES) |
985 |
ms.messageCount = value; |
ms.messageCount = value; |
986 |
else if (statusName==RECENT) |
else if (statusName == RECENT) |
987 |
ms.newMessageCount = value; |
ms.newMessageCount = value; |
988 |
else if (statusName==UIDNEXT) |
else if (statusName == UIDNEXT) |
989 |
ms.uidNext = value; |
ms.uidNext = value; |
990 |
else if (statusName==UIDVALIDITY) |
else if (statusName == UIDVALIDITY) |
991 |
ms.uidValidity = value; |
ms.uidValidity = value; |
992 |
else if (statusName==UNSEEN) |
else if (statusName == UNSEEN) |
993 |
ms.firstUnreadMessage = value; |
ms.firstUnreadMessage = value; |
994 |
} |
} |
995 |
catch (NumberFormatException e) |
catch(NumberFormatException e) |
996 |
{ |
{ |
997 |
throw new IMAPException(id, "Invalid code: "+code); |
throw new IMAPException(id, "Invalid code: " + code); |
998 |
} |
} |
999 |
} |
} |
1000 |
} |
} |
1004 |
else if (tag.equals(response.getTag())) |
else if (tag.equals(response.getTag())) |
1005 |
{ |
{ |
1006 |
processAlerts(response); |
processAlerts(response); |
1007 |
if (id==OK) |
if (id == OK) |
1008 |
return ms; |
return ms; |
1009 |
else |
else |
1010 |
throw new IMAPException(id, response.getText()); |
throw new IMAPException(id, response.getText()); |
1023 |
* @param content the message body (including headers) |
* @param content the message body (including headers) |
1024 |
* @return true if successful, false if error in flags/text |
* @return true if successful, false if error in flags/text |
1025 |
*/ |
*/ |
1026 |
public boolean append(String mailbox, String[] flags, byte[] content) |
public boolean append(String mailbox, String[]flags, byte[]content) |
1027 |
throws IOException |
throws IOException |
1028 |
{ |
{ |
1029 |
String tag = newTag(); |
String tag = newTag(); |
1030 |
StringBuffer buffer = new StringBuffer(APPEND) |
StringBuffer buffer = |
1031 |
.append(' ') |
new StringBuffer(APPEND).append(' '). |
1032 |
.append(quote(UTF7imap.encode(mailbox))) |
append(quote(UTF7imap.encode(mailbox))).append(' '); |
1033 |
.append(' '); |
if (flags != null) |
|
if (flags!=null) |
|
1034 |
{ |
{ |
1035 |
buffer.append('('); |
buffer.append('('); |
1036 |
for (int i=0; i<flags.length; i++) |
for (int i = 0; i < flags.length; i++) |
1037 |
{ |
{ |
1038 |
if (i>0) |
if (i > 0) |
1039 |
buffer.append(' '); |
buffer.append(' '); |
1040 |
buffer.append(flags[i]); |
buffer.append(flags[i]); |
1041 |
} |
} |
1049 |
IMAPResponse response = readResponse(); |
IMAPResponse response = readResponse(); |
1050 |
if (!response.isContinuation()) |
if (!response.isContinuation()) |
1051 |
throw new IMAPException(response.getID(), response.getText()); |
throw new IMAPException(response.getID(), response.getText()); |
1052 |
out.write(content); // write the message body |
out.write(content); // write the message body |
1053 |
out.write(0x0a); |
out.writeln(); |
|
out.write(0x0d); // write CRLF |
|
1054 |
out.flush(); |
out.flush(); |
1055 |
while (true) |
while (true) |
1056 |
{ |
{ |
1057 |
response = readResponse(); |
response = readResponse(); |
1058 |
String id = response.getID(); |
String id = response.getID(); |
1059 |
if (tag.equals(response.getTag())) { |
if (tag.equals(response.getTag())) |
1060 |
|
{ |
1061 |
processAlerts(response); |
processAlerts(response); |
1062 |
if (id==OK) |
if (id == OK) |
1063 |
return true; |
return true; |
1064 |
else if (id==NO) |
else if (id == NO) |
1065 |
return false; |
return false; |
1066 |
else |
else |
1067 |
throw new IMAPException(id, response.getText()); |
throw new IMAPException(id, response.getText()); |
1076 |
/** |
/** |
1077 |
* Request a checkpoint of the currently selected mailbox. |
* Request a checkpoint of the currently selected mailbox. |
1078 |
*/ |
*/ |
1079 |
public void check() |
public void check() throws IOException |
|
throws IOException |
|
1080 |
{ |
{ |
1081 |
invokeSimpleCommand(CHECK); |
invokeSimpleCommand(CHECK); |
1082 |
} |
} |
1086 |
* and close the mailbox. |
* and close the mailbox. |
1087 |
* @return true if successful, false if no mailbox was selected |
* @return true if successful, false if no mailbox was selected |
1088 |
*/ |
*/ |
1089 |
public boolean close() |
public boolean close() throws IOException |
|
throws IOException |
|
1090 |
{ |
{ |
1091 |
return invokeSimpleCommand(CLOSE); |
return invokeSimpleCommand(CLOSE); |
1092 |
} |
} |
1095 |
* Permanently removes all messages that have the \Delete flag set. |
* Permanently removes all messages that have the \Delete flag set. |
1096 |
* @return the numbers of the messages expunged |
* @return the numbers of the messages expunged |
1097 |
*/ |
*/ |
1098 |
public int[] expunge() |
public int[] expunge() throws IOException |
|
throws IOException |
|
1099 |
{ |
{ |
1100 |
String tag = newTag(); |
String tag = newTag(); |
1101 |
sendCommand(tag, EXPUNGE); |
sendCommand(tag, EXPUNGE); |
1102 |
List numbers = new ArrayList(); |
List numbers = new ArrayList(); |
1103 |
while (true) |
while (true) |
1104 |
{ |
{ |
1106 |
String id = response.getID(); |
String id = response.getID(); |
1107 |
if (response.isUntagged()) |
if (response.isUntagged()) |
1108 |
{ |
{ |
1109 |
if (id==EXPUNGE) |
if (id == EXPUNGE) |
1110 |
numbers.add(new Integer(response.getCount())); |
numbers.add(new Integer(response.getCount())); |
1111 |
else |
else |
1112 |
asyncResponses.add(response); |
asyncResponses.add(response); |
1114 |
else if (tag.equals(response.getTag())) |
else if (tag.equals(response.getTag())) |
1115 |
{ |
{ |
1116 |
processAlerts(response); |
processAlerts(response); |
1117 |
if (id==OK) |
if (id == OK) |
1118 |
{ |
{ |
1119 |
int len = numbers.size(); |
int len = numbers.size(); |
1120 |
int[] mn = new int[len]; |
int[] mn = new int[len]; |
1121 |
for (int i=0; i<len; i++) |
for (int i = 0; i < len; i++) |
1122 |
mn[i] = ((Integer)numbers.get(i)).intValue(); |
mn[i] = ((Integer) numbers.get(i)).intValue(); |
1123 |
return mn; |
return mn; |
1124 |
} |
} |
1125 |
else |
else |
1134 |
* Searches the currently selected mailbox for messages matching the |
* Searches the currently selected mailbox for messages matching the |
1135 |
* specified criteria. |
* specified criteria. |
1136 |
*/ |
*/ |
1137 |
public int[] search(String charset, String[] criteria) |
public int[] search(String charset, String[]criteria) throws IOException |
|
throws IOException |
|
1138 |
{ |
{ |
1139 |
String tag = newTag(); |
String tag = newTag(); |
1140 |
StringBuffer buffer = new StringBuffer(SEARCH); |
StringBuffer buffer = new StringBuffer(SEARCH); |
1141 |
buffer.append(' '); |
buffer.append(' '); |
1142 |
if (charset!=null) |
if (charset != null) |
1143 |
{ |
{ |
1144 |
buffer.append(charset); |
buffer.append(charset); |
1145 |
buffer.append(' '); |
buffer.append(' '); |
1146 |
} |
} |
1147 |
for (int i=0; i<criteria.length; i++) |
for (int i = 0; i < criteria.length; i++) |
1148 |
{ |
{ |
1149 |
if (i>0) |
if (i > 0) |
1150 |
buffer.append(' '); |
buffer.append(' '); |
1151 |
buffer.append(criteria[i]); |
buffer.append(criteria[i]); |
1152 |
} |
} |
1158 |
String id = response.getID(); |
String id = response.getID(); |
1159 |
if (response.isUntagged()) |
if (response.isUntagged()) |
1160 |
{ |
{ |
1161 |
if (id==SEARCH) |
if (id == SEARCH) |
1162 |
{ |
{ |
1163 |
String text = response.getText(); |
String text = response.getText(); |
1164 |
try |
try |
1165 |
{ |
{ |
1166 |
int si = text.indexOf(' '); |
int si = text.indexOf(' '); |
1167 |
while (si!=-1) |
while (si != -1) |
1168 |
{ |
{ |
1169 |
list.add(new Integer(text.substring(0, si))); |
list.add(new Integer(text.substring(0, si))); |
1170 |
text = text.substring(si+1); |
text = text.substring(si + 1); |
1171 |
si = text.indexOf(' '); |
si = text.indexOf(' '); |
1172 |
} |
} |
1173 |
list.add(new Integer(text)); |
list.add(new Integer(text)); |
1174 |
} |
} |
1175 |
catch (NumberFormatException e) |
catch(NumberFormatException e) |
1176 |
{ |
{ |
1177 |
throw new IMAPException(id, "Expecting number: "+text); |
throw new IMAPException(id, "Expecting number: " + text); |
1178 |
} |
} |
1179 |
} |
} |
1180 |
else |
else |
1183 |
else if (tag.equals(response.getTag())) |
else if (tag.equals(response.getTag())) |
1184 |
{ |
{ |
1185 |
processAlerts(response); |
processAlerts(response); |
1186 |
if (id==OK) |
if (id == OK) |
1187 |
{ |
{ |
1188 |
int len = list.size(); |
int len = list.size(); |
1189 |
int[] mn = new int[len]; |
int[] mn = new int[len]; |
1190 |
for (int i=0; i<len; i++) |
for (int i = 0; i < len; i++) |
1191 |
mn[i] = ((Integer)list.get(i)).intValue(); |
mn[i] = ((Integer) list.get(i)).intValue(); |
1192 |
return mn; |
return mn; |
1193 |
} |
} |
1194 |
else |
else |
1203 |
* Retrieves data associated with messages in the mailbox. |
* Retrieves data associated with messages in the mailbox. |
1204 |
* @param messages the message numbers |
* @param messages the message numbers |
1205 |
*/ |
*/ |
1206 |
public MessageStatus[] fetch(int[] messages, String[] fetchCommands) |
public MessageStatus[] fetch(int[]messages, String[]fetchCommands) |
1207 |
throws IOException |
throws IOException |
1208 |
{ |
{ |
1209 |
String tag = newTag(); |
String tag = newTag(); |
1210 |
StringBuffer buffer = new StringBuffer(FETCH); |
StringBuffer buffer = new StringBuffer(FETCH); |
1211 |
buffer.append(' '); |
buffer.append(' '); |
1212 |
for (int i=0; i<messages.length; i++) |
for (int i = 0; i < messages.length; i++) |
1213 |
{ |
{ |
1214 |
if (i>0) |
if (i > 0) |
1215 |
buffer.append(','); |
buffer.append(','); |
1216 |
buffer.append(messages[i]); |
buffer.append(messages[i]); |
1217 |
} |
} |
1218 |
buffer.append(' '); |
buffer.append(' '); |
1219 |
buffer.append('('); |
buffer.append('('); |
1220 |
for (int i=0; i<fetchCommands.length; i++) |
for (int i = 0; i < fetchCommands.length; i++) |
1221 |
{ |
{ |
1222 |
if (i>0) |
if (i > 0) |
1223 |
buffer.append(' '); |
buffer.append(' '); |
1224 |
buffer.append(fetchCommands[i]); |
buffer.append(fetchCommands[i]); |
1225 |
} |
} |
1232 |
String id = response.getID(); |
String id = response.getID(); |
1233 |
if (response.isUntagged()) |
if (response.isUntagged()) |
1234 |
{ |
{ |
1235 |
if (id==FETCH) |
if (id == FETCH) |
1236 |
{ |
{ |
1237 |
int msgnum = response.getCount(); |
int msgnum = response.getCount(); |
1238 |
List code = response.getResponseCode(); |
List code = response.getResponseCode(); |
1245 |
else if (tag.equals(response.getTag())) |
else if (tag.equals(response.getTag())) |
1246 |
{ |
{ |
1247 |
processAlerts(response); |
processAlerts(response); |
1248 |
if (id==OK) |
if (id == OK) |
1249 |
{ |
{ |
1250 |
MessageStatus[] statuses = new MessageStatus[list.size()]; |
MessageStatus[]statuses = new MessageStatus[list.size()]; |
1251 |
list.toArray(statuses); |
list.toArray(statuses); |
1252 |
return statuses; |
return statuses; |
1253 |
} |
} |
1266 |
* @param flags message flags to set |
* @param flags message flags to set |
1267 |
* @return a list of message-number to current flags |
* @return a list of message-number to current flags |
1268 |
*/ |
*/ |
1269 |
public MessageStatus[] store(int[] messages, |
public MessageStatus[] store(int[]messages, |
1270 |
String flagCommand, |
String flagCommand, |
1271 |
String[] flags) |
String[]flags) throws IOException |
|
throws IOException |
|
1272 |
{ |
{ |
1273 |
String tag = newTag(); |
String tag = newTag(); |
1274 |
StringBuffer buffer = new StringBuffer(STORE); |
StringBuffer buffer = new StringBuffer(STORE); |
1275 |
buffer.append(' '); |
buffer.append(' '); |
1276 |
for (int i=0; i<messages.length; i++) |
for (int i = 0; i < messages.length; i++) |
1277 |
{ |
{ |
1278 |
if (i>0) |
if (i > 0) |
1279 |
buffer.append(','); |
buffer.append(','); |
1280 |
buffer.append(messages[i]); |
buffer.append(messages[i]); |
1281 |
} |
} |
1283 |
buffer.append(flagCommand); |
buffer.append(flagCommand); |
1284 |
buffer.append(' '); |
buffer.append(' '); |
1285 |
buffer.append('('); |
buffer.append('('); |
1286 |
for (int i=0; i<flags.length; i++) |
for (int i = 0; i < flags.length; i++) |
1287 |
{ |
{ |
1288 |
if (i>0) |
if (i > 0) |
1289 |
buffer.append(' '); |
buffer.append(' '); |
1290 |
buffer.append(flags[i]); |
buffer.append(flags[i]); |
1291 |
} |
} |
1301 |
int msgnum = response.getCount(); |
int msgnum = response.getCount(); |
1302 |
List code = response.getResponseCode(); |
List code = response.getResponseCode(); |
1303 |
// 2 different styles returned by server: FETCH or FETCH FLAGS |
// 2 different styles returned by server: FETCH or FETCH FLAGS |
1304 |
if (id==FETCH) |
if (id == FETCH) |
1305 |
{ |
{ |
1306 |
MessageStatus mf = new MessageStatus(msgnum, code); |
MessageStatus mf = new MessageStatus(msgnum, code); |
1307 |
list.add(mf); |
list.add(mf); |
1308 |
} |
} |
1309 |
else if (id==FETCH_FLAGS) |
else if (id == FETCH_FLAGS) |
1310 |
{ |
{ |
1311 |
List base = new ArrayList(); |
List base = new ArrayList(); |
1312 |
base.add(FLAGS); |
base.add(FLAGS); |
1320 |
else if (tag.equals(response.getTag())) |
else if (tag.equals(response.getTag())) |
1321 |
{ |
{ |
1322 |
processAlerts(response); |
processAlerts(response); |
1323 |
if (id==OK) |
if (id == OK) |
1324 |
{ |
{ |
1325 |
MessageStatus[] mf = new MessageStatus[list.size()]; |
MessageStatus[]mf = new MessageStatus[list.size()]; |
1326 |
list.toArray(mf); |
list.toArray(mf); |
1327 |
return mf; |
return mf; |
1328 |
} |
} |
1339 |
* @param messages the message numbers |
* @param messages the message numbers |
1340 |
* @param mailbox the destination mailbox |
* @param mailbox the destination mailbox |
1341 |
*/ |
*/ |
1342 |
public boolean copy(int[] messages, String mailbox) |
public boolean copy(int[]messages, String mailbox) throws IOException |
|
throws IOException |
|
1343 |
{ |
{ |
1344 |
if (messages==null || messages.length<1) |
if (messages == null || messages.length < 1) |
1345 |
return true; |
return true; |
1346 |
StringBuffer buffer = new StringBuffer(COPY) |
StringBuffer buffer = new StringBuffer(COPY).append(' '); |
1347 |
.append(' '); |
for (int i = 0; i < messages.length; i++) |
|
for (int i=0; i<messages.length; i++) |
|
1348 |
{ |
{ |
1349 |
if (i>0) |
if (i > 0) |
1350 |
buffer.append(','); |
buffer.append(','); |
1351 |
buffer.append(messages[i]); |
buffer.append(messages[i]); |
1352 |
} |
} |
1353 |
buffer.append(' ') |
buffer.append(' ').append(quote(UTF7imap.encode(mailbox))); |
|
.append(quote(UTF7imap.encode(mailbox))); |
|
1354 |
return invokeSimpleCommand(buffer.toString()); |
return invokeSimpleCommand(buffer.toString()); |
1355 |
} |
} |
1356 |
|
|
1357 |
// -- Utility methods -- |
// -- Utility methods -- |
1358 |
|
|
1359 |
/** |
/** |
1360 |
* Remove the quotes from each end of a string literal. |
* Remove the quotes from each end of a string literal. |
1361 |
*/ |
*/ |
1362 |
static String stripQuotes(String text) |
static String stripQuotes(String text) |
1363 |
{ |
{ |
1364 |
if (text.charAt(0)=='"') |
if (text.charAt(0) == '"') |
1365 |
{ |
{ |
1366 |
int len = text.length(); |
int len = text.length(); |
1367 |
if (text.charAt(len-1)=='"') |
if (text.charAt(len - 1) == '"') |
1368 |
return text.substring(1, len-1); |
return text.substring(1, len - 1); |
1369 |
} |
} |
1370 |
return text; |
return text; |
1371 |
} |
} |
1375 |
*/ |
*/ |
1376 |
static String quote(String text) |
static String quote(String text) |
1377 |
{ |
{ |
1378 |
if (text.length()==0 || text.indexOf(' ')!=-1) |
if (text.length() == 0 || text.indexOf(' ') != -1) |
1379 |
{ |
{ |
1380 |
StringBuffer buffer = new StringBuffer(); |
StringBuffer buffer = new StringBuffer(); |
1381 |
buffer.append('"'); |
buffer.append('"'); |