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.imap; 019 020import java.io.IOException; 021 022/** 023 * The IMAPClient class provides the basic functionalities found in an 024 * IMAP client. 025 */ 026public class IMAPClient extends IMAP 027{ 028 029 private static final char DQUOTE = '"'; 030 private static final String DQUOTE_S = "\""; 031 032 // --------- commands available in all states 033 034 /** 035 * Send a CAPABILITY command to the server. 036 * @return {@code true} if the command was successful,{@code false} if not. 037 * @exception IOException If a network I/O error occurs 038 */ 039 public boolean capability() throws IOException 040 { 041 return doCommand (IMAPCommand.CAPABILITY); 042 } 043 044 /** 045 * Send a NOOP command to the server. This is useful for keeping 046 * a connection alive since most IMAP servers will timeout after 10 047 * minutes of inactivity. 048 * @return {@code true} if the command was successful,{@code false} if not. 049 * @exception IOException If a network I/O error occurs. 050 */ 051 public boolean noop() throws IOException 052 { 053 return doCommand (IMAPCommand.NOOP); 054 } 055 056 /** 057 * Send a LOGOUT command to the server. To fully disconnect from the server 058 * you must call disconnect(). 059 * A logout attempt is valid in any state. If 060 * the client is in the not authenticated or authenticated state, it enters the 061 * logout on a successful logout. 062 * @return {@code true} if the command was successful,{@code false} if not. 063 * @exception IOException If a network I/O error occurs. 064 */ 065 public boolean logout() throws IOException 066 { 067 return doCommand (IMAPCommand.LOGOUT); 068 } 069 070 // --------- commands available in the not-authenticated state 071 // STARTTLS skipped - see IMAPSClient. 072 // AUTHENTICATE skipped - see AuthenticatingIMAPClient. 073 074 /** 075 * Login to the IMAP server with the given username and password. You 076 * must first connect to the server with 077 * {@link org.apache.commons.net.SocketClient#connect connect } 078 * before attempting to login. A login attempt is only valid if 079 * the client is in the NOT_AUTH_STATE. 080 * After logging in, the client enters the AUTH_STATE. 081 * 082 * @param username The account name being logged in to. 083 * @param password The plain text password of the account. 084 * @return True if the login attempt was successful, false if not. 085 * @exception IOException If a network I/O error occurs in the process of 086 * logging in. 087 */ 088 public boolean login(String username, String password) throws IOException 089 { 090 if (getState() != IMAP.IMAPState.NOT_AUTH_STATE) 091 { 092 return false; 093 } 094 095 if (!doCommand(IMAPCommand.LOGIN, username + " " + password)) 096 { 097 return false; 098 } 099 100 setState(IMAP.IMAPState.AUTH_STATE); 101 102 return true; 103 } 104 105 // --------- commands available in the authenticated state 106 107 /** 108 * Send a SELECT command to the server. 109 * @param mailboxName The mailbox name to select. 110 * @return {@code true} if the command was successful,{@code false} if not. 111 * @exception IOException If a network I/O error occurs. 112 */ 113 public boolean select(String mailboxName) throws IOException 114 { 115 return doCommand (IMAPCommand.SELECT, mailboxName); 116 } 117 118 /** 119 * Send an EXAMINE command to the server. 120 * @param mailboxName The mailbox name to examine. 121 * @return {@code true} if the command was successful,{@code false} if not. 122 * @exception IOException If a network I/O error occurs. 123 */ 124 public boolean examine(String mailboxName) throws IOException 125 { 126 return doCommand (IMAPCommand.EXAMINE, mailboxName); 127 } 128 129 /** 130 * Send a CREATE command to the server. 131 * @param mailboxName The mailbox name to create. 132 * @return {@code true} if the command was successful,{@code false} if not. 133 * @exception IOException If a network I/O error occurs. 134 */ 135 public boolean create(String mailboxName) throws IOException 136 { 137 return doCommand (IMAPCommand.CREATE, mailboxName); 138 } 139 140 /** 141 * Send a DELETE command to the server. 142 * @param mailboxName The mailbox name to delete. 143 * @return {@code true} if the command was successful,{@code false} if not. 144 * @exception IOException If a network I/O error occurs. 145 */ 146 public boolean delete(String mailboxName) throws IOException 147 { 148 return doCommand (IMAPCommand.DELETE, mailboxName); 149 } 150 151 /** 152 * Send a RENAME command to the server. 153 * @param oldMailboxName The existing mailbox name to rename. 154 * @param newMailboxName The new mailbox name. 155 * @return {@code true} if the command was successful,{@code false} if not. 156 * @exception IOException If a network I/O error occurs. 157 */ 158 public boolean rename(String oldMailboxName, String newMailboxName) throws IOException 159 { 160 return doCommand (IMAPCommand.RENAME, oldMailboxName + " " + newMailboxName); 161 } 162 163 /** 164 * Send a SUBSCRIBE command to the server. 165 * @param mailboxName The mailbox name to subscribe to. 166 * @return {@code true} if the command was successful,{@code false} if not. 167 * @exception IOException If a network I/O error occurs. 168 */ 169 public boolean subscribe(String mailboxName) throws IOException 170 { 171 return doCommand (IMAPCommand.SUBSCRIBE, mailboxName); 172 } 173 174 /** 175 * Send a UNSUBSCRIBE command to the server. 176 * @param mailboxName The mailbox name to unsubscribe from. 177 * @return {@code true} if the command was successful,{@code false} if not. 178 * @exception IOException If a network I/O error occurs. 179 */ 180 public boolean unsubscribe(String mailboxName) throws IOException 181 { 182 return doCommand (IMAPCommand.UNSUBSCRIBE, mailboxName); 183 } 184 185 /** 186 * Send a LIST command to the server. 187 * @param refName The reference name. 188 * @param mailboxName The mailbox name. 189 * @return {@code true} if the command was successful,{@code false} if not. 190 * @exception IOException If a network I/O error occurs. 191 */ 192 public boolean list(String refName, String mailboxName) throws IOException 193 { 194 return doCommand (IMAPCommand.LIST, refName + " " + mailboxName); 195 } 196 197 /** 198 * Send an LSUB command to the server. 199 * @param refName The reference name. 200 * @param mailboxName The mailbox name. 201 * @return {@code true} if the command was successful,{@code false} if not. 202 * @exception IOException If a network I/O error occurs. 203 */ 204 public boolean lsub(String refName, String mailboxName) throws IOException 205 { 206 return doCommand (IMAPCommand.LSUB, refName + " " + mailboxName); 207 } 208 209 /** 210 * Send a STATUS command to the server. 211 * @param mailboxName The reference name. 212 * @param itemNames The status data item names. 213 * @return {@code true} if the command was successful,{@code false} if not. 214 * @exception IOException If a network I/O error occurs. 215 */ 216 public boolean status(String mailboxName, String[] itemNames) throws IOException 217 { 218 if (itemNames == null || itemNames.length < 1) { 219 throw new IllegalArgumentException("STATUS command requires at least one data item name"); 220 } 221 222 StringBuilder sb = new StringBuilder(); 223 sb.append(mailboxName); 224 225 sb.append(" ("); 226 for ( int i = 0; i < itemNames.length; i++ ) 227 { 228 if (i > 0) { 229 sb.append(" "); 230 } 231 sb.append(itemNames[i]); 232 } 233 sb.append(")"); 234 235 return doCommand (IMAPCommand.STATUS, sb.toString()); 236 } 237 238 /** 239 * Send an APPEND command to the server. 240 * @param mailboxName The mailbox name. 241 * @param flags The flag parenthesized list (optional). 242 * @param datetime The date/time string (optional). 243 * @param message The message to append. 244 * @return {@code true} if the command was successful,{@code false} if not. 245 * @exception IOException If a network I/O error occurs. 246 * @since 3.4 247 */ 248 public boolean append(String mailboxName, String flags, String datetime, String message) throws IOException 249 { 250 StringBuilder args = new StringBuilder(mailboxName); 251 if (flags != null) { 252 args.append(" ").append(flags); 253 } 254 if (datetime != null) { 255 args.append(" "); 256 if (datetime.charAt(0) == DQUOTE) { 257 args.append(datetime); 258 } else { 259 args.append(DQUOTE).append(datetime).append(DQUOTE); 260 } 261 } 262 args.append(" "); 263 // String literal (probably not used much - it at all) 264 if (message.startsWith(DQUOTE_S) && message.endsWith(DQUOTE_S)) { 265 args.append(message); 266 return doCommand (IMAPCommand.APPEND, args.toString()); 267 } 268 args.append('{').append(message.length()).append('}'); // length of message 269 final int status = sendCommand(IMAPCommand.APPEND, args.toString()); 270 return IMAPReply.isContinuation(status) // expecting continuation response 271 && IMAPReply.isSuccess(sendData(message)); // if so, send the data 272 } 273 274 /** 275 * Send an APPEND command to the server. 276 * @param mailboxName The mailbox name. 277 * @param flags The flag parenthesized list (optional). 278 * @param datetime The date/time string (optional). 279 * @return {@code true} if the command was successful,{@code false} if not. 280 * @exception IOException If a network I/O error occurs. 281 * @deprecated (3.4) Does not work; the message body is not optional. 282 * Use {@link #append(String, String, String, String)} instead. 283 */ 284 @Deprecated 285 public boolean append(String mailboxName, String flags, String datetime) throws IOException 286 { 287 String args = mailboxName; 288 if (flags != null) { 289 args += " " + flags; 290 } 291 if (datetime != null) { 292 if (datetime.charAt(0) == '{') { 293 args += " " + datetime; 294 } else { 295 args += " {" + datetime + "}"; 296 } 297 } 298 return doCommand (IMAPCommand.APPEND, args); 299 } 300 301 /** 302 * Send an APPEND command to the server. 303 * @param mailboxName The mailbox name. 304 * @return {@code true} if the command was successful,{@code false} if not. 305 * @exception IOException If a network I/O error occurs. 306 * @deprecated (3.4) Does not work; the message body is not optional. 307 * Use {@link #append(String, String, String, String)} instead. 308 */ 309 @Deprecated 310 public boolean append(String mailboxName) throws IOException 311 { 312 return append(mailboxName, null, null); 313 } 314 315 // --------- commands available in the selected state 316 317 /** 318 * Send a CHECK command to the server. 319 * @return {@code true} if the command was successful,{@code false} if not. 320 * @exception IOException If a network I/O error occurs. 321 */ 322 public boolean check() throws IOException 323 { 324 return doCommand (IMAPCommand.CHECK); 325 } 326 327 /** 328 * Send a CLOSE command to the server. 329 * @return {@code true} if the command was successful,{@code false} if not. 330 * @exception IOException If a network I/O error occurs. 331 */ 332 public boolean close() throws IOException 333 { 334 return doCommand (IMAPCommand.CLOSE); 335 } 336 337 /** 338 * Send an EXPUNGE command to the server. 339 * @return {@code true} if the command was successful,{@code false} if not. 340 * @exception IOException If a network I/O error occurs. 341 */ 342 public boolean expunge() throws IOException 343 { 344 return doCommand (IMAPCommand.EXPUNGE); 345 } 346 347 /** 348 * Send a SEARCH command to the server. 349 * @param charset The charset (optional). 350 * @param criteria The search criteria. 351 * @return {@code true} if the command was successful,{@code false} if not. 352 * @exception IOException If a network I/O error occurs. 353 */ 354 public boolean search(String charset, String criteria) throws IOException 355 { 356 String args = ""; 357 if (charset != null) { 358 args += "CHARSET " + charset; 359 } 360 args += criteria; 361 return doCommand (IMAPCommand.SEARCH, args); 362 } 363 364 /** 365 * Send a SEARCH command to the server. 366 * @param criteria The search criteria. 367 * @return {@code true} if the command was successful,{@code false} if not. 368 * @exception IOException If a network I/O error occurs. 369 */ 370 public boolean search(String criteria) throws IOException 371 { 372 return search(null, criteria); 373 } 374 375 /** 376 * Send a FETCH command to the server. 377 * 378 * @param sequenceSet The sequence set to fetch (e.g. 1:4,6,11,100:*) 379 * @param itemNames The item names for the FETCH command. (e.g. BODY.PEEK[HEADER.FIELDS (SUBJECT)]) 380 * If multiple item names are requested, these must be enclosed in parentheses, e.g. "(UID FLAGS BODY.PEEK[])" 381 * @return {@code true} if the command was successful,{@code false} if not. 382 * @exception IOException If a network I/O error occurs. 383 * @see #getReplyString() 384 * @see #getReplyStrings() 385 */ 386 public boolean fetch(String sequenceSet, String itemNames) throws IOException 387 { 388 return doCommand (IMAPCommand.FETCH, sequenceSet + " " + itemNames); 389 } 390 391 /** 392 * Send a STORE command to the server. 393 * @param sequenceSet The sequence set to update (e.g. 2:5) 394 * @param itemNames The item name for the STORE command (i.e. [+|-]FLAGS[.SILENT]) 395 * @param itemValues The item values for the STORE command. (e.g. (\Deleted) ) 396 * @return {@code true} if the command was successful,{@code false} if not. 397 * @exception IOException If a network I/O error occurs. 398 */ 399 public boolean store(String sequenceSet, String itemNames, String itemValues) 400 throws IOException 401 { 402 return doCommand (IMAPCommand.STORE, sequenceSet + " " + itemNames + " " + itemValues); 403 } 404 405 /** 406 * Send a COPY command to the server. 407 * @param sequenceSet The sequence set to fetch. 408 * @param mailboxName The mailbox name. 409 * @return {@code true} if the command was successful,{@code false} if not. 410 * @exception IOException If a network I/O error occurs. 411 */ 412 public boolean copy(String sequenceSet, String mailboxName) throws IOException 413 { 414 return doCommand (IMAPCommand.COPY, sequenceSet + " " + mailboxName); 415 } 416 417 /** 418 * Send a UID command to the server. 419 * @param command The command for UID. 420 * @param commandArgs The arguments for the command. 421 * @return {@code true} if the command was successful,{@code false} if not. 422 * @exception IOException If a network I/O error occurs. 423 */ 424 public boolean uid(String command, String commandArgs) throws IOException 425 { 426 return doCommand (IMAPCommand.UID, command + " " + commandArgs); 427 } 428 429 /** 430 * The status data items defined in RFC 3501. 431 */ 432 public enum STATUS_DATA_ITEMS 433 { 434 /** The number of messages in the mailbox. */ 435 MESSAGES, 436 /** The number of messages with the \Recent flag set. */ 437 RECENT, 438 /** The next unique identifier value of the mailbox. */ 439 UIDNEXT, 440 /** The unique identifier validity value of the mailbox. */ 441 UIDVALIDITY, 442 /** The number of messages which do not have the \Seen flag set. */ 443 UNSEEN; 444 } 445 446 /** 447 * The search criteria defined in RFC 3501. 448 */ 449 public enum SEARCH_CRITERIA 450 { 451 /** All messages in the mailbox. */ 452 ALL, 453 /** Messages with the \Answered flag set. */ 454 ANSWERED, 455 /** 456 * Messages that contain the specified string in the envelope 457 * structure's BCC field. 458 */ 459 BCC, 460 /** 461 * Messages whose internal date (disregarding time and timezone) 462 * is earlier than the specified date. 463 */ 464 BEFORE, 465 /** 466 * Messages that contain the specified string in the body of the 467 * message. 468 */ 469 BODY, 470 /** 471 * Messages that contain the specified string in the envelope 472 * structure's CC field. 473 */ 474 CC, 475 /** Messages with the \Deleted flag set. */ 476 DELETED, 477 /** Messages with the \Draft flag set. */ 478 DRAFT, 479 /** Messages with the \Flagged flag set. */ 480 FLAGGED, 481 /** 482 * Messages that contain the specified string in the envelope 483 * structure's FROM field. 484 */ 485 FROM, 486 /** 487 * Messages that have a header with the specified field-name (as 488 * defined in [RFC-2822]) and that contains the specified string 489 * in the text of the header (what comes after the colon). If the 490 * string to search is zero-length, this matches all messages that 491 * have a header line with the specified field-name regardless of 492 * the contents. 493 */ 494 HEADER, 495 /** Messages with the specified keyword flag set. */ 496 KEYWORD, 497 /** 498 * Messages with an [RFC-2822] size larger than the specified 499 * number of octets. 500 */ 501 LARGER, 502 /** 503 * Messages that have the \Recent flag set but not the \Seen flag. 504 * This is functionally equivalent to "(RECENT UNSEEN)". 505 */ 506 NEW, 507 /** Messages that do not match the specified search key. */ 508 NOT, 509 /** 510 * Messages that do not have the \Recent flag set. This is 511 * functionally equivalent to "NOT RECENT" (as opposed to "NOT 512 * NEW"). 513 */ 514 OLD, 515 /** 516 * Messages whose internal date (disregarding time and timezone) 517 * is within the specified date. 518 */ 519 ON, 520 /** Messages that match either search key. */ 521 OR, 522 /** Messages that have the \Recent flag set. */ 523 RECENT, 524 /** Messages that have the \Seen flag set. */ 525 SEEN, 526 /** 527 * Messages whose [RFC-2822] Date: header (disregarding time and 528 * timezone) is earlier than the specified date. 529 */ 530 SENTBEFORE, 531 /** 532 * Messages whose [RFC-2822] Date: header (disregarding time and 533 * timezone) is within the specified date. 534 */ 535 SENTON, 536 /** 537 * Messages whose [RFC-2822] Date: header (disregarding time and 538 * timezone) is within or later than the specified date. 539 */ 540 SENTSINCE, 541 /** 542 * Messages whose internal date (disregarding time and timezone) 543 * is within or later than the specified date. 544 */ 545 SINCE, 546 /** 547 * Messages with an [RFC-2822] size smaller than the specified 548 * number of octets. 549 */ 550 SMALLER, 551 /** 552 * Messages that contain the specified string in the envelope 553 * structure's SUBJECT field. 554 */ 555 SUBJECT, 556 /** 557 * Messages that contain the specified string in the header or 558 * body of the message. 559 */ 560 TEXT, 561 /** 562 * Messages that contain the specified string in the envelope 563 * structure's TO field. 564 */ 565 TO, 566 /** 567 * Messages with unique identifiers corresponding to the specified 568 * unique identifier set. Sequence set ranges are permitted. 569 */ 570 UID, 571 /** Messages that do not have the \Answered flag set. */ 572 UNANSWERED, 573 /** Messages that do not have the \Deleted flag set. */ 574 UNDELETED, 575 /** Messages that do not have the \Draft flag set. */ 576 UNDRAFT, 577 /** Messages that do not have the \Flagged flag set. */ 578 UNFLAGGED, 579 /** Messages that do not have the specified keyword flag set. */ 580 UNKEYWORD, 581 /** Messages that do not have the \Seen flag set. */ 582 UNSEEN; 583 } 584 585 /** 586 * The message data item names for the FETCH command defined in RFC 3501. 587 */ 588 public enum FETCH_ITEM_NAMES 589 { 590 /** Macro equivalent to: (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE). */ 591 ALL, 592 /** Macro equivalent to: (FLAGS INTERNALDATE RFC822.SIZE). */ 593 FAST, 594 /** Macro equivalent to: (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY). */ 595 FULL, 596 /** Non-extensible form of BODYSTRUCTURE or the text of a particular body section. */ 597 BODY, 598 /** The [MIME-IMB] body structure of the message. */ 599 BODYSTRUCTURE, 600 /** The envelope structure of the message. */ 601 ENVELOPE, 602 /** The flags that are set for this message. */ 603 FLAGS, 604 /** The internal date of the message. */ 605 INTERNALDATE, 606 /** A prefix for RFC-822 item names. */ 607 RFC822, 608 /** The unique identifier for the message. */ 609 UID; 610 } 611 612} 613/* kate: indent-width 4; replace-tabs on; */