1 22 23 package gnu.mail.providers.imap4; 24 25 import java.io.IOException ; 26 import java.io.OutputStream ; 27 import java.net.ProtocolException ; 28 import java.net.Socket ; 29 import java.net.UnknownHostException ; 30 import java.util.ArrayList ; 31 import java.util.Collections ; 32 import java.util.HashMap ; 33 import java.util.Iterator ; 34 import java.util.List ; 35 import java.util.Map ; 36 import javax.mail.Session ; 37 38 44 public class IMAPConnection implements IMAPConstants 45 { 46 47 public static void main(String [] args) { 49 try { 50 IMAPConnection c = new IMAPConnection("localhost", 143); 51 c.setDebug(true); 52 if (!c.login("test", "imaptest")) { 54 Session.log("bad login"); 55 c.logout(); 56 System.exit(1); 57 } 58 ListEntry[] le = c.list(null, "*"); 60 for (int i=0; i<le.length; i++) { 61 System.out.println(le[i]); 62 } 63 MailboxStatus fs = c.select("INBOX"); 65 System.out.println("INBOX has "+fs.messageCount+" messages"); 66 int[] messages = new int[] { 2 }; 68 String [] fetchCommands = new String [] { "BODY.PEEK[]" }; 69 MessageStatus[] ms = c.fetch(messages, fetchCommands); 70 for (int i=0; i<ms.length; i++) { 71 System.out.println("Message "+ms[i].messageNumber+" properties:"); 72 System.out.println(ms[i].properties); 73 } 74 c.close(); 76 c.logout(); 78 } catch (IOException e) { 79 e.printStackTrace(System.err); 80 } 81 } 83 protected static final String TAG_PREFIX = "A"; 85 86 protected static final String DEFAULT_ENCODING = "US-ASCII"; 87 88 91 protected Socket socket; 92 93 96 protected IMAPResponseTokenizer in; 97 98 101 protected OutputStream out; 102 103 106 private int tagIndex = 0; 107 108 111 private boolean debug = false; 112 113 116 public IMAPConnection(String host, int port) 117 throws UnknownHostException , IOException 118 { 119 socket = new Socket (host, port); 120 in = new IMAPResponseTokenizer(socket.getInputStream()); 121 out = socket.getOutputStream(); 122 } 123 124 127 public void setDebug(boolean flag) 128 { 129 debug = flag; 130 } 131 132 135 protected String newTag() { 136 return new StringBuffer (TAG_PREFIX).append(++tagIndex).toString(); 137 } 138 139 142 protected void sendCommand(String tag, String command) 143 throws IOException 144 { 145 Session.log("> "+tag+" "+command); 146 byte[] bytes = new StringBuffer (tag) 147 .append(' ') 148 .append(command) 149 .append('\r') 150 .append('\n') 151 .toString() 152 .getBytes(DEFAULT_ENCODING); 153 out.write(bytes); 154 } 155 156 162 protected boolean invokeSimpleCommand(String command) 163 throws IOException 164 { 165 String tag = newTag(); 166 sendCommand(tag, command); 167 while (true) 168 { 169 IMAPResponse response = readResponse(); 170 if (response.isTagged()) { 171 String id = response.getID(); 172 if (id==OK) 173 return true; 174 else if (id==NO) 175 return false; 176 else 177 throw new IMAPException(id, response.getText()); 178 } 179 } 180 } 181 182 183 191 protected IMAPResponse readResponse() 192 throws IOException 193 { 194 IMAPResponse response = in.next(); 195 Session.log("< "+response.toString()); 196 return response; 197 } 198 199 205 public boolean login(String username, String password) 206 throws IOException 207 { 208 return invokeSimpleCommand(new StringBuffer (LOGIN) 209 .append(' ') 210 .append(username) 211 .append(' ') 212 .append(password) 213 .toString()); 214 } 215 216 220 public void logout() 221 throws IOException 222 { 223 String tag = newTag(); 224 sendCommand(tag, LOGOUT); 225 while (true) 226 { 227 IMAPResponse response = readResponse(); 228 String id = response.getID(); 229 if (id==OK) 230 { 231 socket.close(); 232 return; 233 } 234 } 235 } 236 237 243 public MailboxStatus select(String mailbox) 244 throws IOException 245 { 246 return selectImpl(mailbox, SELECT); 247 } 248 249 255 public MailboxStatus examine(String mailbox) 256 throws IOException 257 { 258 return selectImpl(mailbox, EXAMINE); 259 } 260 261 protected MailboxStatus selectImpl(String mailbox, String command) 262 throws IOException 263 { 264 String tag = newTag(); 265 sendCommand(tag, new StringBuffer (command) 266 .append(' ') 267 .append(mailbox) 268 .toString()); 269 MailboxStatus ms = new MailboxStatus(); 270 while (true) 271 { 272 IMAPResponse response = readResponse(); 273 String id = response.getID(); 274 if (response.isUntagged()) 275 { 276 if (id==OK) 277 { 278 List rc = response.getResponseCode(); 279 int len = rc.size(); 280 for (int i=0; i<len; i++) 281 { 282 Object ocmd = rc.get(i); 283 if (ocmd instanceof String ) 284 { 285 String cmd = (String )ocmd; 286 if (i+1<len) 287 { 288 Object oparam = rc.get(i+1); 289 if (oparam instanceof String ) 290 { 291 String param = (String )oparam; 292 try 293 { 294 if (cmd==UNSEEN) 295 { 296 ms.firstUnreadMessage = Integer.parseInt(param); 297 i++; 298 } 299 else if (cmd==UIDVALIDITY) 300 { 301 ms.uidValidity = Integer.parseInt(param); 302 i++; 303 } 304 } 305 catch (NumberFormatException e) 306 { 307 throw new ProtocolException ("Illegal "+cmd+" value: "+ 308 param); 309 } 310 } 311 else if (oparam instanceof List ) 312 { 313 if (cmd==PERMANENTFLAGS) 314 { 315 ms.permanentFlags = (List )oparam; 316 i++; 317 } 318 } 319 } 320 } 321 } 322 } 323 else if (id==EXISTS) 324 ms.messageCount = response.getCount(); 325 else if (id==RECENT) 326 ms.newMessageCount = response.getCount(); 327 else if (id==FLAGS) 328 ms.flags = response.getResponseCode(); 329 } 330 else if (tag.equals(response.getTag())) 331 { 332 if (id==OK) 333 { 334 List rc = response.getResponseCode(); 335 if (rc.size()>0 && rc.get(0)==READ_WRITE) 336 ms.readWrite = true; 337 return ms; 338 } 339 else 340 throw new IMAPException(id, response.getText()); 341 } 342 } 343 } 344 345 350 public boolean create(String mailbox) 351 throws IOException 352 { 353 return invokeSimpleCommand(new StringBuffer (CREATE) 354 .append(' ') 355 .append(mailbox) 356 .toString()); 357 } 358 359 364 public boolean delete(String mailbox) 365 throws IOException 366 { 367 return invokeSimpleCommand(new StringBuffer (DELETE) 368 .append(' ') 369 .append(mailbox) 370 .toString()); 371 } 372 373 379 public boolean rename(String source, String target) 380 throws IOException 381 { 382 return invokeSimpleCommand(new StringBuffer (RENAME) 383 .append(' ') 384 .append(source) 385 .append(' ') 386 .append(target) 387 .toString()); 388 } 389 390 396 public boolean subscribe(String mailbox) 397 throws IOException 398 { 399 return invokeSimpleCommand(new StringBuffer (SUBSCRIBE) 400 .append(' ') 401 .append(mailbox) 402 .toString()); 403 } 404 405 411 public boolean unsubscribe(String mailbox) 412 throws IOException 413 { 414 return invokeSimpleCommand(new StringBuffer (UNSUBSCRIBE) 415 .append(' ') 416 .append(mailbox) 417 .toString()); 418 } 419 420 427 public ListEntry[] list(String reference, String mailbox) 428 throws IOException 429 { 430 return listImpl(LIST, reference, mailbox); 431 } 432 433 437 public ListEntry[] lsub(String reference, String mailbox) 438 throws IOException 439 { 440 return listImpl(LSUB, reference, mailbox); 441 } 442 443 protected ListEntry[] listImpl(String command, String reference, 444 String mailbox) 445 throws IOException 446 { 447 if (reference==null || reference.length()==0) 448 reference = "\"\""; 449 if (mailbox==null || mailbox.length()==0) 450 mailbox = "\"\""; 451 String tag = newTag(); 452 sendCommand(tag, new StringBuffer (command) 453 .append(' ') 454 .append(reference) 455 .append(' ') 456 .append(mailbox) 457 .toString()); 458 List acc = new ArrayList (); 459 while (true) 460 { 461 IMAPResponse response = readResponse(); 462 String id = response.getID(); 463 if (response.isUntagged()) 464 { 465 if (id==LIST) 466 { 467 List code = response.getResponseCode(); 468 String text = response.getText(); 469 ListEntry entry = new ListEntry(); 470 entry.attributes = code; 471 int si = text.indexOf(' '); 472 String delimiter = text.substring(0, si).intern(); 473 if (delimiter==NIL) 474 entry.delimiter='\u0000'; 475 else 476 entry.delimiter = stripQuotes(delimiter).charAt(0); 477 entry.mailbox = stripQuotes(text.substring(si+1)); 478 acc.add(entry); 479 } 480 } 481 else if (response.isTagged()) 482 { 483 if (id==OK) 484 { 485 ListEntry[] entries = new ListEntry[acc.size()]; 486 acc.toArray(entries); 487 return entries; 488 } 489 else 490 throw new IMAPException(id, response.getText()); 491 } 492 } 493 } 494 495 498 public MailboxStatus status(String mailbox, String [] statusNames) 499 throws IOException 500 { 501 String tag = newTag(); 502 StringBuffer buffer = new StringBuffer (STATUS) 503 .append(' ') 504 .append(mailbox) 505 .append(' ') 506 .append('('); 507 for (int i=0; i<statusNames.length; i++) 508 { 509 if (i>0) 510 buffer.append(' '); 511 buffer.append(statusNames[i]); 512 } 513 buffer.append(')'); 514 sendCommand(tag, buffer.toString()); 515 MailboxStatus ms = new MailboxStatus(); 516 while (true) 517 { 518 IMAPResponse response = readResponse(); 519 String id = response.getID(); 520 if (response.isUntagged()) 521 { 522 if (id==STATUS) 523 { 524 List code = response.getResponseCode(); 525 int last = code.size()-1; 526 for (int i=0; i<last; i+=2) 527 { 528 try 529 { 530 String statusName = ((String )code.get(i)).intern(); 531 int value = Integer.parseInt((String )code.get(i+1)); 532 if (statusName==MESSAGES) 533 ms.messageCount = value; 534 else if (statusName==RECENT) 535 ms.newMessageCount = value; 536 else if (statusName==UIDNEXT) 537 ms.uidNext = value; 538 else if (statusName==UIDVALIDITY) 539 ms.uidValidity = value; 540 else if (statusName==UNSEEN) 541 ms.firstUnreadMessage = value; 542 } 543 catch (NumberFormatException e) 544 { 545 throw new IMAPException(id, "Invalid code: "+code); 546 } 547 } 548 } 549 } 550 else if (response.isTagged()) 551 { 552 if (id==OK) 553 return ms; 554 else 555 throw new IMAPException(id, response.getText()); 556 } 557 } 558 } 559 560 569 public boolean append(String mailbox, String [] flags, byte[] content) 570 throws IOException 571 { 572 String tag = newTag(); 573 StringBuffer buffer = new StringBuffer (APPEND) 574 .append(' ') 575 .append(mailbox) 576 .append(' '); 577 if (flags!=null) 578 { 579 buffer.append('('); 580 for (int i=0; i<flags.length; i++) 581 { 582 if (i>0) 583 buffer.append(' '); 584 buffer.append(flags[i]); 585 } 586 buffer.append(')'); 587 buffer.append(' '); 588 } 589 buffer.append('{'); 590 buffer.append(content.length); 591 buffer.append('}'); 592 sendCommand(tag, buffer.toString()); 593 out.write(content); while (true) 595 { 596 IMAPResponse response = readResponse(); 597 if (response.isTagged()) { 598 String id = response.getID(); 599 if (id==OK) 600 return true; 601 else if (id==NO) 602 return false; 603 else 604 throw new IMAPException(id, response.getText()); 605 } 606 } 607 } 608 609 612 public void check() 613 throws IOException 614 { 615 invokeSimpleCommand(CHECK); 616 } 617 618 623 public boolean close() 624 throws IOException 625 { 626 return invokeSimpleCommand(CLOSE); 627 } 628 629 633 public int[] expunge() 634 throws IOException 635 { 636 String tag = newTag(); 637 sendCommand(tag, EXPUNGE); 638 List numbers = new ArrayList (); 639 while (true) 640 { 641 IMAPResponse response = readResponse(); 642 String id = response.getID(); 643 if (response.isUntagged()) 644 { 645 if (id==EXPUNGE) 646 numbers.add(new Integer (response.getCount())); 647 } 648 else if (response.isTagged()) 649 { 650 if (id==OK) 651 { 652 int[] mn = new int[numbers.size()]; 653 for (int i=0; i<mn.length; i++) 654 mn[i] = ((Integer )numbers.get(i)).intValue(); 655 return mn; 656 } 657 else 658 throw new IMAPException(id, response.getText()); 659 } 660 } 661 } 662 663 public void search() 664 throws IOException 665 { 666 } 668 669 673 public MessageStatus[] fetch(int[] messages, String [] fetchCommands) 674 throws IOException 675 { 676 String tag = newTag(); 677 StringBuffer buffer = new StringBuffer (FETCH); 678 buffer.append(' '); 679 for (int i=0; i<messages.length; i++) 680 { 681 if (i>0) 682 buffer.append(','); 683 buffer.append(messages[i]); 684 } 685 buffer.append(' '); 686 buffer.append('('); 687 for (int i=0; i<fetchCommands.length; i++) 688 { 689 if (i>0) 690 buffer.append(' '); 691 buffer.append(fetchCommands[i]); 692 } 693 buffer.append(')'); 694 sendCommand(tag, buffer.toString()); 695 List list = new ArrayList (messages.length); 696 while (true) 697 { 698 IMAPResponse response = readResponse(); 699 String id = response.getID(); 700 if (response.isUntagged()) 701 { 702 if (id==FETCH) 703 { 704 MessageStatus status = new MessageStatus(response.getCount()); 705 List code = response.getResponseCode(); 706 addKeys(code, status); 707 status.content = response.content; 708 list.add(status); 709 } 710 } 711 else if (response.isTagged()) 712 { 713 if (id==OK) 714 { 715 MessageStatus[] statuses = new MessageStatus[list.size()]; 716 list.toArray(statuses); 717 return statuses; 718 } 719 else 720 throw new IMAPException(id, response.getText()); 721 } 722 } 723 } 724 725 void addKeys(List code, MessageStatus status) 726 { 727 int len = code.size(); 728 for (int i=0; i<len; i++) 729 { 730 Object key = code.get(i); 731 if (key instanceof String ) 732 { 733 Object value = null; 734 if ((i+1)<len) 735 { 736 value = code.get(i+1); 737 i++; 738 } 739 status.put((String )key, value); 740 } 741 else if (key instanceof List ) 742 { 743 addKeys((List )key, status); 744 } 745 } 746 } 747 748 755 public MessageStatus[] store(int[] messages, 756 String flagCommand, 757 String [] flags) 758 throws IOException 759 { 760 String tag = newTag(); 761 StringBuffer buffer = new StringBuffer (STORE); 762 buffer.append(' '); 763 for (int i=0; i<messages.length; i++) 764 { 765 if (i>0) 766 buffer.append(','); 767 buffer.append(messages[i]); 768 } 769 buffer.append(' '); 770 buffer.append(flagCommand); 771 buffer.append(' '); 772 buffer.append('('); 773 for (int i=0; i<flags.length; i++) 774 { 775 if (i>0) 776 buffer.append(' '); 777 buffer.append(flags[i]); 778 } 779 buffer.append(')'); 780 sendCommand(tag, buffer.toString()); 781 List list = new ArrayList (messages.length); 782 while (true) 783 { 784 IMAPResponse response = readResponse(); 785 String id = response.getID(); 786 if (response.isUntagged()) 787 { 788 if (id==FETCH) 790 { 791 MessageStatus mf = new MessageStatus(response.getCount()); 792 List code = response.getResponseCode(); 793 int len = code.size(); 794 for (int i=0; i<len; i++) 795 { 796 Object key = code.get(i); 797 if (key instanceof String && (i+1)<len) 798 { 799 Object value = code.get(i+1); 800 if (value instanceof List ) 801 { 802 mf.put((String )key, value); 803 i++; 804 } 805 } 806 } 807 list.add(mf); 808 } 809 else if (id==FETCH_FLAGS) 810 { 811 MessageStatus mf = new MessageStatus(response.getCount()); 812 mf.put(FLAGS, response.getResponseCode()); 813 list.add(mf); 814 } 815 } 816 else if (response.isTagged()) 817 { 818 if (id==OK) 819 { 820 MessageStatus[] mf = new MessageStatus[list.size()]; 821 list.toArray(mf); 822 return mf; 823 } 824 else 825 throw new IMAPException(id, response.getText()); 826 } 827 } 828 } 829 830 835 public boolean copy(int[] messages, String mailbox) 836 throws IOException 837 { 838 if (messages==null || messages.length<1) 839 return true; 840 StringBuffer buffer = new StringBuffer (COPY) 841 .append(' '); 842 for (int i=0; i<messages.length; i++) 843 { 844 if (i>0) 845 buffer.append(','); 846 buffer.append(messages[i]); 847 } 848 buffer.append(' ').append(mailbox); 849 return invokeSimpleCommand(buffer.toString()); 850 } 851 852 854 static String stripQuotes(String text) 855 { 856 if (text.charAt(0)=='"') 857 { 858 int len = text.length(); 859 if (text.charAt(len-1)=='"') 860 return text.substring(1, len-1); 861 } 862 return text; 863 } 864 865 } 866 | Popular Tags |