KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > net > pop3 > POP3Client


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 JavaDoc;
19 import java.io.Reader JavaDoc;
20 import java.security.MessageDigest JavaDoc;
21 import java.security.NoSuchAlgorithmException JavaDoc;
22 import java.util.Enumeration JavaDoc;
23 import java.util.StringTokenizer JavaDoc;
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 public class POP3Client extends POP3
50 {
51
52     private static POP3MessageInfo __parseStatus(String JavaDoc line)
53     {
54         int num, size;
55         StringTokenizer JavaDoc tokenizer;
56
57         tokenizer = new StringTokenizer JavaDoc(line);
58
59         if (!tokenizer.hasMoreElements())
60             return null;
61
62         num = size = 0;
63
64         try
65         {
66             num = Integer.parseInt(tokenizer.nextToken());
67
68             if (!tokenizer.hasMoreElements())
69                 return null;
70
71             size = Integer.parseInt(tokenizer.nextToken());
72         }
73         catch (NumberFormatException JavaDoc e)
74         {
75             return null;
76         }
77
78         return new POP3MessageInfo(num, size);
79     }
80
81     private static POP3MessageInfo __parseUID(String JavaDoc line)
82     {
83         int num;
84         StringTokenizer JavaDoc tokenizer;
85
86         tokenizer = new StringTokenizer JavaDoc(line);
87
88         if (!tokenizer.hasMoreElements())
89             return null;
90
91         num = 0;
92
93         try
94         {
95             num = Integer.parseInt(tokenizer.nextToken());
96
97             if (!tokenizer.hasMoreElements())
98                 return null;
99
100             line = tokenizer.nextToken();
101         }
102         catch (NumberFormatException JavaDoc e)
103         {
104             return null;
105         }
106
107         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 JavaDoc username, String JavaDoc password) throws IOException JavaDoc
128     {
129         if (getState() != AUTHORIZATION_STATE)
130             return false;
131
132         if (sendCommand(POP3Command.USER, username) != POP3Reply.OK)
133             return false;
134
135         if (sendCommand(POP3Command.PASS, password) != POP3Reply.OK)
136             return false;
137
138         setState(TRANSACTION_STATE);
139
140         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 JavaDoc username, String JavaDoc timestamp, String JavaDoc secret)
178     throws IOException JavaDoc, NoSuchAlgorithmException JavaDoc
179     {
180         int i;
181         byte[] digest;
182         StringBuffer JavaDoc buffer, digestBuffer;
183         MessageDigest JavaDoc md5;
184
185         if (getState() != AUTHORIZATION_STATE)
186             return false;
187
188         md5 = MessageDigest.getInstance("MD5");
189         timestamp += secret;
190         digest = md5.digest(timestamp.getBytes());
191         digestBuffer = new StringBuffer JavaDoc(128);
192
193         for (i = 0; i < digest.length; i++)
194             digestBuffer.append(Integer.toHexString(digest[i] & 0xff));
195
196         buffer = new StringBuffer JavaDoc(256);
197         buffer.append(username);
198         buffer.append(' ');
199         buffer.append(digestBuffer.toString());
200
201         if (sendCommand(POP3Command.APOP, buffer.toString()) != POP3Reply.OK)
202             return false;
203
204         setState(TRANSACTION_STATE);
205
206         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 JavaDoc
226     {
227         if (getState() == TRANSACTION_STATE)
228             setState(UPDATE_STATE);
229         sendCommand(POP3Command.QUIT);
230         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 JavaDoc
247     {
248         if (getState() == TRANSACTION_STATE)
249             return (sendCommand(POP3Command.NOOP) == POP3Reply.OK);
250         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 JavaDoc
270     {
271         if (getState() == TRANSACTION_STATE)
272             return (sendCommand(POP3Command.DELE, Integer.toString(messageId))
273                     == POP3Reply.OK);
274         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 JavaDoc
290     {
291         if (getState() == TRANSACTION_STATE)
292             return (sendCommand(POP3Command.RSET) == POP3Reply.OK);
293         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 JavaDoc
312     {
313         if (getState() != TRANSACTION_STATE)
314             return null;
315         if (sendCommand(POP3Command.STAT) != POP3Reply.OK)
316             return null;
317         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 JavaDoc
339     {
340         if (getState() != TRANSACTION_STATE)
341             return null;
342         if (sendCommand(POP3Command.LIST, Integer.toString(messageId))
343                 != POP3Reply.OK)
344             return null;
345         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 JavaDoc
367     {
368         POP3MessageInfo[] messages;
369         Enumeration JavaDoc en;
370         int line;
371
372         if (getState() != TRANSACTION_STATE)
373             return null;
374         if (sendCommand(POP3Command.LIST) != POP3Reply.OK)
375             return null;
376         getAdditionalReply();
377
378         // This could be a zero length array if no messages present
379
messages = new POP3MessageInfo[_replyLines.size() - 2];
380         en = _replyLines.elements();
381
382         // Skip first line
383
en.nextElement();
384
385         // Fetch lines.
386
for (line = 0; line < messages.length; line++)
387             messages[line] = __parseStatus((String JavaDoc)en.nextElement());
388
389         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 JavaDoc
411     {
412         if (getState() != TRANSACTION_STATE)
413             return null;
414         if (sendCommand(POP3Command.UIDL, Integer.toString(messageId))
415                 != POP3Reply.OK)
416             return null;
417         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 JavaDoc
439     {
440         POP3MessageInfo[] messages;
441         Enumeration JavaDoc en;
442         int line;
443
444         if (getState() != TRANSACTION_STATE)
445             return null;
446         if (sendCommand(POP3Command.UIDL) != POP3Reply.OK)
447             return null;
448         getAdditionalReply();
449
450         // This could be a zero length array if no messages present
451
messages = new POP3MessageInfo[_replyLines.size() - 2];
452         en = _replyLines.elements();
453
454         // Skip first line
455
en.nextElement();
456
457         // Fetch lines.
458
for (line = 0; line < messages.length; line++)
459             messages[line] = __parseUID((String JavaDoc)en.nextElement());
460
461         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 JavaDoc retrieveMessage(int messageId) throws IOException JavaDoc
493     {
494         if (getState() != TRANSACTION_STATE)
495             return null;
496         if (sendCommand(POP3Command.RETR, Integer.toString(messageId))
497                 != POP3Reply.OK)
498             return null;
499
500         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 JavaDoc retrieveMessageTop(int messageId, int numLines)
536     throws IOException JavaDoc
537     {
538         if (numLines < 0 || getState() != TRANSACTION_STATE)
539             return null;
540         if (sendCommand(POP3Command.TOP, Integer.toString(messageId) + " " +
541                         Integer.toString(numLines)) != POP3Reply.OK)
542             return null;
543
544         return new DotTerminatedMessageReader(_reader);
545     }
546
547
548 }
549
550
Popular Tags