Coverage report

  %line %branch
org.apache.commons.net.pop3.POP3Client
0% 
0% 

 1  
 /*
 2  
  * Copyright 2001-2005 The Apache Software Foundation
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.apache.commons.net.pop3;
 17  
 
 18  
 import java.io.IOException;
 19  
 import java.io.Reader;
 20  
 import java.security.MessageDigest;
 21  
 import java.security.NoSuchAlgorithmException;
 22  
 import java.util.Enumeration;
 23  
 import java.util.StringTokenizer;
 24  
 import org.apache.commons.net.io.DotTerminatedMessageReader;
 25  
 
 26  
 /***
 27  
  * The POP3Client class implements the client side of the Internet POP3
 28  
  * Protocol defined in RFC 1939.  All commands are supported, including
 29  
  * the APOP command which requires MD5 encryption.  See RFC 1939 for
 30  
  * more details on the POP3 protocol.
 31  
  * <p>
 32  
  * Rather than list it separately for each method, we mention here that
 33  
  * every method communicating with the server and throwing an IOException
 34  
  * can also throw a
 35  
  * {@link org.apache.commons.net.MalformedServerReplyException}
 36  
  * , which is a subclass
 37  
  * of IOException.  A MalformedServerReplyException will be thrown when
 38  
  * the reply received from the server deviates enough from the protocol
 39  
  * specification that it cannot be interpreted in a useful manner despite
 40  
  * attempts to be as lenient as possible.
 41  
  * <p>
 42  
  * <p>
 43  
  * @author Daniel F. Savarese
 44  
  * @see POP3MessageInfo
 45  
  * @see org.apache.commons.net.io.DotTerminatedMessageReader
 46  
  * @see org.apache.commons.net.MalformedServerReplyException
 47  
  ***/
 48  
 
 49  0
 public class POP3Client extends POP3
 50  
 {
 51  
 
 52  
     private static POP3MessageInfo __parseStatus(String line)
 53  
     {
 54  
         int num, size;
 55  
         StringTokenizer tokenizer;
 56  
 
 57  0
         tokenizer = new StringTokenizer(line);
 58  
 
 59  0
         if (!tokenizer.hasMoreElements())
 60  0
             return null;
 61  
 
 62  0
         num = size = 0;
 63  
 
 64  
         try
 65  
         {
 66  0
             num = Integer.parseInt(tokenizer.nextToken());
 67  
 
 68  0
             if (!tokenizer.hasMoreElements())
 69  0
                 return null;
 70  
 
 71  0
             size = Integer.parseInt(tokenizer.nextToken());
 72  
         }
 73  0
         catch (NumberFormatException e)
 74  
         {
 75  0
             return null;
 76  0
         }
 77  
 
 78  0
         return new POP3MessageInfo(num, size);
 79  
     }
 80  
 
 81  
     private static POP3MessageInfo __parseUID(String line)
 82  
     {
 83  
         int num;
 84  
         StringTokenizer tokenizer;
 85  
 
 86  0
         tokenizer = new StringTokenizer(line);
 87  
 
 88  0
         if (!tokenizer.hasMoreElements())
 89  0
             return null;
 90  
 
 91  0
         num = 0;
 92  
 
 93  
         try
 94  
         {
 95  0
             num = Integer.parseInt(tokenizer.nextToken());
 96  
 
 97  0
             if (!tokenizer.hasMoreElements())
 98  0
                 return null;
 99  
 
 100  0
             line = tokenizer.nextToken();
 101  
         }
 102  0
         catch (NumberFormatException e)
 103  
         {
 104  0
             return null;
 105  0
         }
 106  
 
 107  0
         return new POP3MessageInfo(num, line);
 108  
     }
 109  
 
 110  
     /***
 111  
      * Login to the POP3 server with the given username and password.  You
 112  
      * must first connect to the server with
 113  
      * {@link org.apache.commons.net.SocketClient#connect  connect }
 114  
      * before attempting to login.  A login attempt is only valid if
 115  
      * the client is in the
 116  
      * {@link org.apache.commons.net.pop3.POP3#AUTHORIZATION_STATE AUTHORIZATION_STATE }
 117  
      * .  After logging in, the client enters the
 118  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 119  
      * .
 120  
      * <p>
 121  
      * @param username  The account name being logged in to.
 122  
      * @param password  The plain text password of the account.
 123  
      * @return True if the login attempt was successful, false if not.
 124  
      * @exception IOException If a network I/O error occurs in the process of
 125  
      *            logging in.
 126  
      ***/
 127  
     public boolean login(String username, String password) throws IOException
 128  
     {
 129  0
         if (getState() != AUTHORIZATION_STATE)
 130  0
             return false;
 131  
 
 132  0
         if (sendCommand(POP3Command.USER, username) != POP3Reply.OK)
 133  0
             return false;
 134  
 
 135  0
         if (sendCommand(POP3Command.PASS, password) != POP3Reply.OK)
 136  0
             return false;
 137  
 
 138  0
         setState(TRANSACTION_STATE);
 139  
 
 140  0
         return true;
 141  
     }
 142  
 
 143  
 
 144  
     /***
 145  
      * Login to the POP3 server with the given username and authentication
 146  
      * information.  Use this method when connecting to a server requiring
 147  
      * authentication using the APOP command.  Because the timestamp
 148  
      * produced in the greeting banner varies from server to server, it is
 149  
      * not possible to consistently extract the information.  Therefore,
 150  
      * after connecting to the server, you must call
 151  
      * {@link org.apache.commons.net.pop3.POP3#getReplyString getReplyString }
 152  
      *  and parse out the timestamp information yourself.
 153  
      * <p>
 154  
      * You must first connect to the server with
 155  
      * {@link org.apache.commons.net.SocketClient#connect  connect }
 156  
      * before attempting to login.  A login attempt is only valid if
 157  
      * the client is in the
 158  
      * {@link org.apache.commons.net.pop3.POP3#AUTHORIZATION_STATE AUTHORIZATION_STATE }
 159  
      * .  After logging in, the client enters the
 160  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 161  
      * .  After connecting, you must parse out the
 162  
      * server specific information to use as a timestamp, and pass that
 163  
      * information to this method.  The secret is a shared secret known
 164  
      * to you and the server.  See RFC 1939 for more details regarding
 165  
      * the APOP command.
 166  
      * <p>
 167  
      * @param username  The account name being logged in to.
 168  
      * @param timestamp  The timestamp string to combine with the secret.
 169  
      * @param secret  The shared secret which produces the MD5 digest when
 170  
      *        combined with the timestamp.
 171  
      * @return True if the login attempt was successful, false if not.
 172  
      * @exception IOException If a network I/O error occurs in the process of
 173  
      *            logging in.
 174  
      * @exception NoSuchAlgorithmException If the MD5 encryption algorithm
 175  
      *      cannot be instantiated by the Java runtime system.
 176  
      ***/
 177  
     public boolean login(String username, String timestamp, String secret)
 178  
     throws IOException, NoSuchAlgorithmException
 179  
     {
 180  
         int i;
 181  
         byte[] digest;
 182  
         StringBuffer buffer, digestBuffer;
 183  
         MessageDigest md5;
 184  
 
 185  0
         if (getState() != AUTHORIZATION_STATE)
 186  0
             return false;
 187  
 
 188  0
         md5 = MessageDigest.getInstance("MD5");
 189  0
         timestamp += secret;
 190  0
         digest = md5.digest(timestamp.getBytes());
 191  0
         digestBuffer = new StringBuffer(128);
 192  
 
 193  0
         for (i = 0; i < digest.length; i++)
 194  0
             digestBuffer.append(Integer.toHexString(digest[i] & 0xff));
 195  
 
 196  0
         buffer = new StringBuffer(256);
 197  0
         buffer.append(username);
 198  0
         buffer.append(' ');
 199  0
         buffer.append(digestBuffer.toString());
 200  
 
 201  0
         if (sendCommand(POP3Command.APOP, buffer.toString()) != POP3Reply.OK)
 202  0
             return false;
 203  
 
 204  0
         setState(TRANSACTION_STATE);
 205  
 
 206  0
         return true;
 207  
     }
 208  
 
 209  
 
 210  
     /***
 211  
      * Logout of the POP3 server.  To fully disconnect from the server
 212  
      * you must call
 213  
      * {@link org.apache.commons.net.pop3.POP3#disconnect  disconnect }.
 214  
      * A logout attempt is valid in any state.  If
 215  
      * the client is in the
 216  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 217  
      * , it enters the
 218  
      * {@link org.apache.commons.net.pop3.POP3#UPDATE_STATE UPDATE_STATE }
 219  
      *  on a successful logout.
 220  
      * <p>
 221  
      * @return True if the logout attempt was successful, false if not.
 222  
      * @exception IOException If a network I/O error occurs in the process
 223  
      *           of logging out.
 224  
      ***/
 225  
     public boolean logout() throws IOException
 226  
     {
 227  0
         if (getState() == TRANSACTION_STATE)
 228  0
             setState(UPDATE_STATE);
 229  0
         sendCommand(POP3Command.QUIT);
 230  0
         return (_replyCode == POP3Reply.OK);
 231  
     }
 232  
 
 233  
 
 234  
     /***
 235  
      * Send a NOOP command to the POP3 server.  This is useful for keeping
 236  
      * a connection alive since most POP3 servers will timeout after 10
 237  
      * minutes of inactivity.  A noop attempt will only succeed if
 238  
      * the client is in the
 239  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 240  
      * .
 241  
      * <p>
 242  
      * @return True if the noop attempt was successful, false if not.
 243  
      * @exception IOException If a network I/O error occurs in the process of
 244  
      *        sending the NOOP command.
 245  
      ***/
 246  
     public boolean noop() throws IOException
 247  
     {
 248  0
         if (getState() == TRANSACTION_STATE)
 249  0
             return (sendCommand(POP3Command.NOOP) == POP3Reply.OK);
 250  0
         return false;
 251  
     }
 252  
 
 253  
 
 254  
     /***
 255  
      * Delete a message from the POP3 server.  The message is only marked
 256  
      * for deletion by the server.  If you decide to unmark the message, you
 257  
      * must issuse a {@link #reset  reset } command.  Messages marked
 258  
      * for deletion are only deleted by the server on
 259  
      * {@link #logout  logout }.
 260  
      * A delete attempt can only succeed if the client is in the
 261  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 262  
      * .
 263  
      * <p>
 264  
      * @param messageId  The message number to delete.
 265  
      * @return True if the deletion attempt was successful, false if not.
 266  
      * @exception IOException If a network I/O error occurs in the process of
 267  
      *           sending the delete command.
 268  
      ***/
 269  
     public boolean deleteMessage(int messageId) throws IOException
 270  
     {
 271  0
         if (getState() == TRANSACTION_STATE)
 272  0
             return (sendCommand(POP3Command.DELE, Integer.toString(messageId))
 273  
                     == POP3Reply.OK);
 274  0
         return false;
 275  
     }
 276  
 
 277  
 
 278  
     /***
 279  
      * Reset the POP3 session.  This is useful for undoing any message
 280  
      * deletions that may have been performed.  A reset attempt can only
 281  
      * succeed if the client is in the
 282  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 283  
      * .
 284  
      * <p>
 285  
      * @return True if the reset attempt was successful, false if not.
 286  
      * @exception IOException If a network I/O error occurs in the process of
 287  
      *      sending the reset command.
 288  
      ***/
 289  
     public boolean reset() throws IOException
 290  
     {
 291  0
         if (getState() == TRANSACTION_STATE)
 292  0
             return (sendCommand(POP3Command.RSET) == POP3Reply.OK);
 293  0
         return false;
 294  
     }
 295  
 
 296  
     /***
 297  
      * Get the mailbox status.  A status attempt can only
 298  
      * succeed if the client is in the
 299  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 300  
      * .  Returns a POP3MessageInfo instance
 301  
      * containing the number of messages in the mailbox and the total
 302  
      * size of the messages in bytes.  Returns null if the status the
 303  
      * attempt fails.
 304  
      * <p>
 305  
      * @return A POP3MessageInfo instance containing the number of
 306  
      *         messages in the mailbox and the total size of the messages
 307  
      *         in bytes.  Returns null if the status the attempt fails.
 308  
      * @exception IOException If a network I/O error occurs in the process of
 309  
      *       sending the status command.
 310  
      ***/
 311  
     public POP3MessageInfo status() throws IOException
 312  
     {
 313  0
         if (getState() != TRANSACTION_STATE)
 314  0
             return null;
 315  0
         if (sendCommand(POP3Command.STAT) != POP3Reply.OK)
 316  0
             return null;
 317  0
         return __parseStatus(_lastReplyLine.substring(3));
 318  
     }
 319  
 
 320  
 
 321  
     /***
 322  
      * List an individual message.  A list attempt can only
 323  
      * succeed if the client is in the
 324  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 325  
      * .  Returns a POP3MessageInfo instance
 326  
      * containing the number of the listed message and the
 327  
      * size of the message in bytes.  Returns null if the list
 328  
      * attempt fails (e.g., if the specified message number does
 329  
      * not exist).
 330  
      * <p>
 331  
      * @param messageId  The number of the message list.
 332  
      * @return A POP3MessageInfo instance containing the number of the
 333  
      *         listed message and the size of the message in bytes.  Returns
 334  
      *         null if the list attempt fails.
 335  
      * @exception IOException If a network I/O error occurs in the process of
 336  
      *         sending the list command.
 337  
      ***/
 338  
     public POP3MessageInfo listMessage(int messageId) throws IOException
 339  
     {
 340  0
         if (getState() != TRANSACTION_STATE)
 341  0
             return null;
 342  0
         if (sendCommand(POP3Command.LIST, Integer.toString(messageId))
 343  
                 != POP3Reply.OK)
 344  0
             return null;
 345  0
         return __parseStatus(_lastReplyLine.substring(3));
 346  
     }
 347  
 
 348  
 
 349  
     /***
 350  
      * List all messages.  A list attempt can only
 351  
      * succeed if the client is in the
 352  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 353  
      * .  Returns an array of POP3MessageInfo instances,
 354  
      * each containing the number of a message and its size in bytes.
 355  
      * If there are no messages, this method returns a zero length array.
 356  
      * If the list attempt fails, it returns null.
 357  
      * <p>
 358  
      * @return An array of POP3MessageInfo instances representing all messages
 359  
      * in the order they appear in the mailbox,
 360  
      * each containing the number of a message and its size in bytes.
 361  
      * If there are no messages, this method returns a zero length array.
 362  
      * If the list attempt fails, it returns null.
 363  
      * @exception IOException If a network I/O error occurs in the process of
 364  
      *     sending the list command.
 365  
      ***/
 366  
     public POP3MessageInfo[] listMessages() throws IOException
 367  
     {
 368  
         POP3MessageInfo[] messages;
 369  
         Enumeration en;
 370  
         int line;
 371  
 
 372  0
         if (getState() != TRANSACTION_STATE)
 373  0
             return null;
 374  0
         if (sendCommand(POP3Command.LIST) != POP3Reply.OK)
 375  0
             return null;
 376  0
         getAdditionalReply();
 377  
 
 378  
         // This could be a zero length array if no messages present
 379  0
         messages = new POP3MessageInfo[_replyLines.size() - 2];
 380  0
         en = _replyLines.elements();
 381  
 
 382  
         // Skip first line
 383  0
         en.nextElement();
 384  
 
 385  
         // Fetch lines.
 386  0
         for (line = 0; line < messages.length; line++)
 387  0
             messages[line] = __parseStatus((String)en.nextElement());
 388  
 
 389  0
         return messages;
 390  
     }
 391  
 
 392  
     /***
 393  
      * List the unique identifier for a message.  A list attempt can only
 394  
      * succeed if the client is in the
 395  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 396  
      * .  Returns a POP3MessageInfo instance
 397  
      * containing the number of the listed message and the
 398  
      * unique identifier for that message.  Returns null if the list
 399  
      * attempt fails  (e.g., if the specified message number does
 400  
      * not exist).
 401  
      * <p>
 402  
      * @param messageId  The number of the message list.
 403  
      * @return A POP3MessageInfo instance containing the number of the
 404  
      *         listed message and the unique identifier for that message.
 405  
      *         Returns null if the list attempt fails.
 406  
      * @exception IOException If a network I/O error occurs in the process of
 407  
      *        sending the list unique identifier command.
 408  
      ***/
 409  
     public POP3MessageInfo listUniqueIdentifier(int messageId)
 410  
     throws IOException
 411  
     {
 412  0
         if (getState() != TRANSACTION_STATE)
 413  0
             return null;
 414  0
         if (sendCommand(POP3Command.UIDL, Integer.toString(messageId))
 415  
                 != POP3Reply.OK)
 416  0
             return null;
 417  0
         return __parseUID(_lastReplyLine.substring(3));
 418  
     }
 419  
 
 420  
 
 421  
     /***
 422  
      * List the unique identifiers for all messages.  A list attempt can only
 423  
      * succeed if the client is in the
 424  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 425  
      * .  Returns an array of POP3MessageInfo instances,
 426  
      * each containing the number of a message and its unique identifier.
 427  
      * If there are no messages, this method returns a zero length array.
 428  
      * If the list attempt fails, it returns null.
 429  
      * <p>
 430  
      * @return An array of POP3MessageInfo instances representing all messages
 431  
      * in the order they appear in the mailbox,
 432  
      * each containing the number of a message and its unique identifier
 433  
      * If there are no messages, this method returns a zero length array.
 434  
      * If the list attempt fails, it returns null.
 435  
      * @exception IOException If a network I/O error occurs in the process of
 436  
      *     sending the list unique identifier command.
 437  
      ***/
 438  
     public POP3MessageInfo[] listUniqueIdentifiers() throws IOException
 439  
     {
 440  
         POP3MessageInfo[] messages;
 441  
         Enumeration en;
 442  
         int line;
 443  
 
 444  0
         if (getState() != TRANSACTION_STATE)
 445  0
             return null;
 446  0
         if (sendCommand(POP3Command.UIDL) != POP3Reply.OK)
 447  0
             return null;
 448  0
         getAdditionalReply();
 449  
 
 450  
         // This could be a zero length array if no messages present
 451  0
         messages = new POP3MessageInfo[_replyLines.size() - 2];
 452  0
         en = _replyLines.elements();
 453  
 
 454  
         // Skip first line
 455  0
         en.nextElement();
 456  
 
 457  
         // Fetch lines.
 458  0
         for (line = 0; line < messages.length; line++)
 459  0
             messages[line] = __parseUID((String)en.nextElement());
 460  
 
 461  0
         return messages;
 462  
     }
 463  
 
 464  
 
 465  
     /***
 466  
      * Retrieve a message from the POP3 server.  A retrieve message attempt
 467  
      * can only succeed if the client is in the
 468  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 469  
      * .  Returns a DotTerminatedMessageReader instance
 470  
      * from which the entire message can be read.
 471  
      * Returns null if the retrieval attempt fails  (e.g., if the specified
 472  
      * message number does not exist).
 473  
      * <p>
 474  
      * You must not issue any commands to the POP3 server (i.e., call any
 475  
      * other methods) until you finish reading the message from the
 476  
      * returned Reader instance.
 477  
      * The POP3 protocol uses the same stream for issuing commands as it does
 478  
      * for returning results.  Therefore the returned Reader actually reads
 479  
      * directly from the POP3 connection.  After the end of message has been
 480  
      * reached, new commands can be executed and their replies read.  If
 481  
      * you do not follow these requirements, your program will not work
 482  
      * properly.
 483  
      * <p>
 484  
      * @param messageId  The number of the message to fetch.
 485  
      * @return A DotTerminatedMessageReader instance
 486  
      * from which the entire message can be read.
 487  
      * Returns null if the retrieval attempt fails  (e.g., if the specified
 488  
      * message number does not exist).
 489  
      * @exception IOException If a network I/O error occurs in the process of
 490  
      *        sending the retrieve message command.
 491  
      ***/
 492  
     public Reader retrieveMessage(int messageId) throws IOException
 493  
     {
 494  0
         if (getState() != TRANSACTION_STATE)
 495  0
             return null;
 496  0
         if (sendCommand(POP3Command.RETR, Integer.toString(messageId))
 497  
                 != POP3Reply.OK)
 498  0
             return null;
 499  
 
 500  0
         return new DotTerminatedMessageReader(_reader);
 501  
     }
 502  
 
 503  
 
 504  
     /***
 505  
      * Retrieve only the specified top number of lines of a message from the
 506  
      * POP3 server.  A retrieve top lines attempt
 507  
      * can only succeed if the client is in the
 508  
      * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
 509  
      * .  Returns a DotTerminatedMessageReader instance
 510  
      * from which the specified top number of lines of the message can be
 511  
      * read.
 512  
      * Returns null if the retrieval attempt fails  (e.g., if the specified
 513  
      * message number does not exist).
 514  
      * <p>
 515  
      * You must not issue any commands to the POP3 server (i.e., call any
 516  
      * other methods) until you finish reading the message from the returned
 517  
      * Reader instance.
 518  
      * The POP3 protocol uses the same stream for issuing commands as it does
 519  
      * for returning results.  Therefore the returned Reader actually reads
 520  
      * directly from the POP3 connection.  After the end of message has been
 521  
      * reached, new commands can be executed and their replies read.  If
 522  
      * you do not follow these requirements, your program will not work
 523  
      * properly.
 524  
      * <p>
 525  
      * @param messageId  The number of the message to fetch.
 526  
      * @param numLines  The top number of lines to fetch. This must be >= 0.
 527  
      * @return  A DotTerminatedMessageReader instance
 528  
      * from which the specified top number of lines of the message can be
 529  
      * read.
 530  
      * Returns null if the retrieval attempt fails  (e.g., if the specified
 531  
      * message number does not exist).
 532  
      * @exception IOException If a network I/O error occurs in the process of
 533  
      *       sending the top command.
 534  
      ***/
 535  
     public Reader retrieveMessageTop(int messageId, class="keyword">int numLines)
 536  
     throws IOException
 537  
     {
 538  0
         if (numLines < 0 || getState() != TRANSACTION_STATE)
 539  0
             return null;
 540  0
         if (sendCommand(POP3Command.TOP, Integer.toString(messageId) + " " +
 541  
                         Integer.toString(numLines)) != POP3Reply.OK)
 542  0
             return null;
 543  
 
 544  0
         return new DotTerminatedMessageReader(_reader);
 545  
     }
 546  
 
 547  
 
 548  
 }
 549  
 

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.