/* * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * http://www.mozilla.org/NPL/. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the License. * * The Original Code is the Netscape Messaging Access SDK Version 3.5 code, * released on or about June 15, 1998. * * The Initial Developer of the Original Code is Netscape Communications * Corporation. Portions created by Netscape are Copyright (C) 1998 Netscape * Communications Corporation. All Rights Reserved. * * Contributor(s): ______________________________________. */ /* * Copyright (c) 1997 and 1998 Netscape Communications Corporation * (http://home.netscape.com/misc/trademarks.html) */ package netscape.messaging.imap4; import java.io.*; import java.net.*; import java.util.*; import java.lang.reflect.*; import netscape.messaging.IO; /** *The IMAP4Client exposes the IMAP4 client level API. *The client uses this class for communicating with a *server using the IMAP4 protocol. *
The IMAP4Client class contains API calls that map *directly to the client commands defined in RFC 2060, *as well as other API calls that are necessary to establish *and maintain an IMAP4 session. *
For a list of the IMAP4 RFCs referenced in the *Messaging Access SDK and their URLs, *see "Where to Find More Information" in "About This Book." */ public class IMAP4Client { /** * Creates an IMAP4_Client object. * Default constructor for an IMAP4_Client object; * takes an IMAP4 response sink as a parameter. *@param in_sink Response sink that implements the IIMAP4Sink interface. * @see IIMAP4Sink#taggedLine * @see IIMAP4Sink#error */ public IMAP4Client(IIMAP4Sink in_sink) { //Internal objects m_IOHandler = new IO(); m_systemPreferences = new SystemPreferences(); m_systemPreferences.setIO(m_IOHandler); m_pendingCommands = new Vector(); m_commandVector = new Vector(); m_firstResponse = true; m_tagID = 0; m_processBlock = new Integer(1); //Parsing variables m_sink = in_sink; m_dispatcher = null; m_serverResponse = new StringBuffer(); m_tokens = new StringBuffer[3]; m_parserArgs = new StringBuffer[1]; for(int i = 0; i < m_tokens.length; i++) { m_tokens[i] = new StringBuffer(); } //Note: The hashtables are static so there is only one set of hashtables //for n connections and are defined under data members } /////////////////////////////////////////////// //General Commands /** * Connects to the IMAP server in_IMAPHost using the default port (143). *
To specify the connection port, use the *form of connect that takes a port number. * @param in_IMAPHost Name of the host server to connect to. * @return Boolean true if successfully connected, false otherwise. * @exception IOException If an I/O error occurs. * @see #connect * @see #disconnect * @see IIMAP4Sink#taggedLine * @see IIMAP4Sink#error * @see IIMAP4Sink#ok */ public synchronized boolean connect(String in_IMAPHost) throws IOException { return connect(in_IMAPHost, m_systemPreferences.getPort()); } /** * Connects to the IMAP server in_IMAPHost through the specified port. *
To use the default connection port, use the *form of connect that takes only the server name. * @param in_IMAPHost Name of the host server to connect to. * @param in_portNumber Number of the port to connect to. * @return Boolean value: true if successfully connected, false otherwise. * @exception IOException If an I/O error occurs. * @see #disconnect * @see IIMAP4Sink#taggedLine * @see IIMAP4Sink#error * @see IIMAP4Sink#ok */ public synchronized boolean connect(String in_IMAPHost, int in_portNumber) throws IOException { //Check parameters if(in_IMAPHost == null) { throw new IllegalArgumentException(); } //Establish the IMAP connection m_IOHandler.connect(in_IMAPHost, in_portNumber); m_IOHandler.setTimeout(m_systemPreferences.getTimeout()); m_dispatcher = new Dispatcher(m_IOHandler, m_sink, m_pendingCommands, m_systemPreferences); m_pendingCommands.addElement(IGlobals.connect); m_firstResponse = true; m_tagID = 0; return true; } /** * Closes the socket connection with the server. * Can be used to perform a high level "Cancel" while retrieving a message. *
NOTE: Do not call processResponses() after this method. * @exception IOException If an I/O error occurs. * @see #connect * @see IIMAP4Sink#bye * @see IIMAP4Sink#taggedLine * @see IIMAP4Sink#error */ public synchronized void disconnect() throws IOException { m_IOHandler.disconnect(); m_pendingCommands.removeAllElements(); m_tagID = 0; } /** * Processes the server responses for all API commands executed prior to * the invocation of this command. * Calls the appropriate functions on the response * sink to relay the results back to the user. * Checks for responses that are buffered at the socket. * It then reads, parses, and pushes the data through the IIMAP4Sink. * NOTE: Synchronized internally. * @exception IOException If an I/O error occurs. * @see IIMAP4Sink#taggedLine * @see IIMAP4Sink#error */ public void processResponses() throws IOException { synchronized (m_processBlock) { String l_responseType = null; Method l_responseParser = null; char l_tokenChar; //Parse server response and route data through the appropriate //methods in the response sink while(!m_pendingCommands.isEmpty()) { m_IOHandler.readLine(m_serverResponse); //Special case for connect if(m_firstResponse) { m_pendingCommands.removeElement(IGlobals.connect); } //Initialize the tokens array for(int i = 0; i < m_tokens.length; i++) { m_tokens[i].setLength(0); } //Tokenize the server response for(int i = 0, j = 0; i < m_serverResponse.length(); i++) { l_tokenChar = m_serverResponse.charAt(i); if(l_tokenChar == ' ') { j++; if(j >= m_tokens.length) { break; } else { continue; } } m_tokens[j].append(l_tokenChar); } //Parse the server response and dispatch to appropriate method on sink try { l_responseType = resolveType(m_tokens); if(l_responseType.equals(IGlobals.BYE)) { m_pendingCommands.removeAllElements(); m_tagID = 0; } m_parserArgs[0] = m_serverResponse; l_responseParser = (Method)m_responseMapper.get(l_responseType); l_responseParser.invoke(m_dispatcher, m_parserArgs); } catch(InvocationTargetException e) { Throwable l_exception = e.getTargetException(); if(l_exception instanceof IMAP4ServerException) { throw (IMAP4ServerException)l_exception; } else if(l_exception instanceof IMAP4Exception) { throw (IMAP4Exception)l_exception; } l_exception.printStackTrace(); throw (new IOException(IGlobals.DispatcherError + " " + l_exception.getMessage())); } catch(IllegalAccessException e) { throw (new IOException(IGlobals.DispatcherError + " " + e.getMessage())); } } } } /** * Sends the specified command to the IMAP4 server. * Allows the developer to extend the default commands supplied * through the SDK. Equivalent to writing the value of * the in_command parameter directly to the socket. * Do not prepend a tag to the command; this is added * internally. The server response is pushed back through * IIMAP4Sink.rawResponse(). *
Success does not indicate successful completion of the * command, just that it has been invoked on the IMAP4 Server. * Finding out if the command executed successfully requires * using IMAP4Sink.rawResponse() to examine the returned data. * @param in_command The command to send to the IMAP server. * @return String The tag associated with the command; * FALSE otherwise. * @exception IOException If an I/O error occurs. * @see IIMAP4Sink#rawResponse * @see IIMAP4Sink#rawResponse * @see IIMAP4Sink#taggedLine * @see IIMAP4Sink#error */ public synchronized String sendCommand(String in_command) throws IOException { //Check parameters if(in_command == null) { throw new IllegalArgumentException(); } m_commandVector.addElement(in_command); return sendCommand(m_commandVector); } /** * Sends in_command to the IMAP server. * Allows the developer to extend the default commands supplied * through the SDK. Equivalent to writing the value of * the in_command parameter directly to the socket. * Do not prepend a tag to the command; this is added * internally. The server response is pushed back through * IIMAP4Sink.rawResponse(). *
Success does not indicate successful completion of the * command, just that it has been invoked on the IMAP4 Server. * Finding out if the command executed successfully requires * using IMAP4Sink.rawResponse() to examine the returned data. * @param in_command The command to send to the IMAP server * @return String The tag associated with the command; * FALSE otherwise. * @exception IOException If an I/O error occurs. * @see IIMAP4Sink#rawResponse * @see IIMAP4Sink#taggedLine * @see IIMAP4Sink#error */ protected synchronized String sendCommand(Vector in_command) throws IOException { String l_tag = null; //Prepend a tag id and send the command m_tagID++; l_tag = String.valueOf(m_tagID); in_command.insertElementAt(IGlobals.Space, 0); in_command.insertElementAt(l_tag, 0); in_command.addElement(IGlobals.CarriageNewLine); try { m_IOHandler.write(in_command); m_IOHandler.flush(); m_pendingCommands.addElement(l_tag); in_command.removeAllElements(); } catch(IOException e) { in_command.removeAllElements(); throw e; } return l_tag; } /** * Retrieves the system preferences. * @return SystemPreferences Object representing the system preferences. * @see IIMAP4Sink#taggedLine * @see IIMAP4Sink#error */ public synchronized SystemPreferences getSystemPreferences() { return m_systemPreferences; } /** * Sets a new response sink to route the server responses to. * @param in_sink New IMAP4 response sink to use. * @exception IOException If an I/O error occurs. * @see #getResponseSink * @see IIMAP4Sink#taggedLine * @see IIMAP4Sink#error */ public synchronized void setResponseSink(IIMAP4Sink in_sink) throws IOException { synchronized (m_processBlock) { //Check parameters if(in_sink == null) { throw new IllegalArgumentException(); } m_sink = in_sink; m_dispatcher.setResponseSink(m_sink); } } /** * Retrieves the response sink. * @return IIMAP4Sink Response sink to which to route server responses. * @see #setResponseSink * @see IIMAP4Sink#taggedLine * @see IIMAP4Sink#error */ public synchronized IIMAP4Sink getResponseSink() { return m_sink; } //////////////////////////////////////////////////// //The non-authenticated state /** * Logs in to server with user name and password. * Identifies the client to the server and carries the plain text password * authenticating this user. Logs in the user after establishing a connection * to the IMAP4 server, which passes the user * password over the network in the clear. * @param in_user The user name. * @param in_password The password of this user. * @return String The tag associated with this command. * @exception IOException If an I/O error occurs. * @see #logout * @see IIMAP4Sink#taggedLine * @see IIMAP4Sink#error * @see IIMAP4Sink#bye */ public synchronized String login(String in_user, String in_password) throws IOException { //Check parameters if((in_user == null) || (in_password == null)) { throw new IllegalArgumentException(); } m_commandVector.addElement(IGlobals.LOGIN); m_commandVector.addElement(in_user); m_commandVector.addElement(IGlobals.Space); m_commandVector.addElement(in_password); return sendCommand(m_commandVector); } /** * Informs the server that the client is done with the connection. * Closes the connection and logs the user out. * @return String The tag associated with this command. * @exception IOException If an I/O error occurs. * @see #logout * @see IIMAP4Sink#taggedLine * @see IIMAP4Sink#error * @see IIMAP4Sink#bye */ public synchronized String logout() throws IOException { //Ending session.. close connection m_commandVector.addElement(IGlobals.LOGOUT); return sendCommand(m_commandVector); } /** * Gets positive server response; does not affect IMAP4 session. *
The server responds to commands with a "still here" response. * Sending the noop method does nothing except force this server response. * Can be used to maintain server connection, perhaps being issued * at timed intervals to make sure that the server is still active. *
Can be used to poll for mail or get new mail. Most servers look for * new mail whenever they receive a command. This method does nothing * in itself, so it is ideal for triggering this server action. *
Resets the autologout timer inside the server; may change the
* number of messages in a mailbox (due to new mail).
* May change or update the status of messages in mailboxes.
* Not needed by applications that do something and disconnect at once.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#noop
* @see IIMAP4Sink#exists
* @see IIMAP4Sink#expunge
* @see IIMAP4Sink#recent
* @see IIMAP4Sink#fetchStart
* @see IIMAP4Sink#fetchFlags
* @see IIMAP4Sink#fetchEnd
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String noop() throws IOException
{
m_commandVector.addElement(IGlobals.NOOP);
return sendCommand(m_commandVector);
}
/**
* Requests a listing of capabilities that the server supports.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see #connect
* @see IIMAP4Sink#capability
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String capability() throws IOException
{
m_commandVector.addElement(IGlobals.CAPABILITY);
return sendCommand(m_commandVector);
}
////////////////////////////////////////////////////
//The authenticated state
/**
* Appends the literal argument as a new message to the end of the
* specified destination mailbox.
* @param in_mailbox Mailbox name.
* @param in_optFlags Parenthesized list of optional flags.
* @param in_optDateTime Optional date/time string.
* @param in_inputLiteralStream The message literal.
* @return String The command object and the (available) server response.
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String append(String in_mailbox, String in_optFlags,
String in_optDateTime, InputStream in_inputLiteralStream)
throws IOException
{
//Check parameters
if((in_mailbox == null) || (in_inputLiteralStream == null))
{
throw new IllegalArgumentException();
}
if(m_dispatcher == null)
{
throw new IOException(errNotConnected);
}
//Note: This is a command continuation request. The subsequent response
//to the server's request for the message data is handled in Dispatcher.plus
String l_flags = in_optFlags;
String l_dateTime = in_optDateTime;
int l_totalSize = in_inputLiteralStream.available();
//Format the optional parameters
if(l_flags != null)
{
formatOptionalParam(l_flags);
}
else
{
l_flags = IGlobals.EmptyString;
}
if(l_dateTime != null)
{
formatOptionalParam(l_dateTime);
}
else
{
l_dateTime = IGlobals.EmptyString;
}
//Pass the input stream to the dispatcher
m_dispatcher.setAppendStream(in_inputLiteralStream);
//Issue the command
m_commandVector.addElement(IGlobals.APPEND);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_mailbox);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(l_flags);
m_commandVector.addElement(l_dateTime);
m_commandVector.addElement(IGlobals.LCurly);
m_commandVector.addElement(String.valueOf(l_totalSize));
m_commandVector.addElement(IGlobals.RCurly);
try
{
return sendCommand(m_commandVector);
}
catch(IOException e)
{
m_commandVector.removeAllElements();
throw e;
}
}
/**
* Creates a new mailbox with the given name.
* Be careful to use the correct separator character if you want to create
* a directory on the server side.
* You cannot and should not CREATE an INBOX.
* It is always there.
* @param in_mailbox Name of the mailbox to create.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String create(String in_mailbox) throws IOException
{
//Check parameters
if(in_mailbox == null)
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.CREATE);
m_commandVector.addElement(in_mailbox);
return sendCommand(m_commandVector);
}
/**
* PERMANENTLY removes the mailbox with the given name.
* You can not and should not DELETE the INBOX. The system needs it.
* @param in_mailbox Name of the mailbox to delete.
* @return String The tag associated with this command
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String delete(String in_mailbox) throws IOException
{
//Check parameters
if(in_mailbox == null)
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.DELETE);
m_commandVector.addElement(in_mailbox);
return sendCommand(m_commandVector);
}
/**
* Selects a server mailbox for read-only access.
* @param in_mailbox Name of the mailbox to examine.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#flags
* @see IIMAP4Sink#exists
* @see IIMAP4Sink#recent
* @see IIMAP4Sink#ok
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String examine(String in_mailbox) throws IOException
{
//Check parameters
if(in_mailbox == null)
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.EXAMINE);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_mailbox);
return sendCommand(m_commandVector);
}
/**
* Lists a subset of all names available
* to the client.
* @param in_refName String with reference name (prefix).
* @param in_mailbox String with mailbox name (suffix).
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#list
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String list(String in_refName, String in_mailbox)
throws IOException
{
//Check parameters
if((in_refName == null) || (in_mailbox == null))
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.LIST);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_refName);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_mailbox);
return sendCommand(m_commandVector);
}
/**
* Return a subset of all names that the user has
* declared as being "active" or "subscribed".
* @param in_refName Reference name.
* @param in_mailbox Mailbox name with possible wildcards.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#lsub
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String lsub(String in_refName, String in_mailbox)
throws IOException
{
//Check parameters
if((in_refName == null) || (in_mailbox == null))
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.LSUB);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_refName);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_mailbox);
return sendCommand(m_commandVector);
}
/**
* Renames a mailbox.
* @param in_currentMB String with the mailbox's current name.
* @param in_newMB String with the mailbox's new name.
* @return String The tag associated with this command
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String rename(String in_currentMB,String in_newMB)
throws IOException
{
//Check parameters
if((in_currentMB == null) || (in_newMB == null))
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.RENAME);
m_commandVector.addElement(in_currentMB);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_newMB);
return sendCommand(m_commandVector);
}
/**
* Selects a mailbox on the server.
* @param in_mailbox Name of the mailbox.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see #examine
* @see IIMAP4Sink#flags
* @see IIMAP4Sink#exists
* @see IIMAP4Sink#recent
* @see IIMAP4Sink#ok
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String select(String in_mailbox) throws IOException
{
//Check parameters
if(in_mailbox == null)
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.SELECT);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_mailbox);
return sendCommand(m_commandVector);
}
/**
* Requests the status of the specified mailbox.
* Requests one or more types of status, as specified by the data items parameter.
* @param in_mailbox Name of the mailbox.
* @param in_statusData Status data items.
* @return String The tag associated with this command
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#statusMessages
* @see IIMAP4Sink#statusRecent
* @see IIMAP4Sink#statusUidnext
* @see IIMAP4Sink#statusUidvalidity
* @see IIMAP4Sink#statusUnseen
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String status(String in_mailbox, String in_statusData)
throws IOException
{
//Check parameters
if((in_mailbox == null) || (in_statusData == null))
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.STATUS);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_mailbox);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_statusData);
return sendCommand(m_commandVector);
}
/**
* Adds the specified mailbox name to the server's set of "active" or
* "subscribed" mailboxes.
* This list is accessed through the lsub method.
* @param in_mailbox Name of the mailbox to add.
* @return String The tag associated with this command
* @exception IOException If an I/O error occurs.
* @see #unsubscribe
* @see #lsub
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String subscribe(String in_mailbox)
throws IOException
{
//Check parameters
if(in_mailbox == null)
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.SUBSCRIBE);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_mailbox);
return sendCommand(m_commandVector);
}
/**
* Removes the specified mailbox name from the server's set of "active" or
* "subscribed" mailboxes.
* @param in_mailbox Name of the mailbox to remove.
* @return String The tag associated with this command
* @exception IOException If an I/O error occurs.
* @see #unsubscribe
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String unsubscribe(String in_mailbox)
throws IOException
{
//Check parameters
if(in_mailbox == null)
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.UNSUBSCRIBE);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_mailbox);
return sendCommand(m_commandVector);
}
////////////////////////////////////////////////////
//The selected state
/**
* Requests a checkpoint of the currently selected mailbox.
* Also flushes existing mailbox states to disk.
* Actual method behavior depends on server implementation.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String check() throws IOException
{
m_commandVector.addElement(IGlobals.CHECK);
return sendCommand(m_commandVector);
}
/**
* Closes the mailbox.
* Also removes any messages marked with the \Deleted flag.
* The session moves to the mailbox that contained the closed mailbox.
* The expunge() method removes messages without closing.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see #expunge
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String close() throws IOException
{
m_commandVector.addElement(IGlobals.CLOSE);
return sendCommand(m_commandVector);
}
/**
* Copies the specified message(s) from the currently selected mailbox
* to the end of the specified destination mailbox.
* @param in_msgSet Message numbers to copy (for example, "1:2").
* @param in_mailbox Name of target mailbox.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see #uidCopy
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String copy(String in_msgSet, String in_mailbox)
throws IOException
{
//Check parameters
if((in_msgSet == null) || (in_mailbox == null))
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.COPY);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_msgSet);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_mailbox);
return sendCommand(m_commandVector);
}
/**
* Removes all messages flagged for deletion.
* Deletes all the messages in the
* mailbox with the \Deleted flag set. As described in RFC 1730, if there is
* an EXPUNGEd message, all messages with higher numbers are automatically
* decremented by one. This happens BEFORE this call returns,
* so, immediately following this call, you should think about
* what the state of the message cache might be.
* @return String The tag associated with this command
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#expunge
* @see #delete
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String expunge() throws IOException
{
m_commandVector.addElement(IGlobals.EXPUNGE);
return sendCommand(m_commandVector);
}
/**
* Retrieves data specified by the fetch criteria for the given message
* set and returns the corresponding message sequence numbers.
* @param in_msgSet Message set.
* @param in_fetchCriteria Message data item names.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see #uidFetch
* @see IIMAP4Sink#fetchStart
* @see IIMAP4Sink#fetchEnd
* @see IIMAP4Sink#fetchSize
* @see IIMAP4Sink#fetchData
* @see IIMAP4Sink#fetchFlags
* @see IIMAP4Sink#fetchBodyStructure
* @see IIMAP4Sink#fetchEnvelope
* @see IIMAP4Sink#fetchInternalDate
* @see IIMAP4Sink#fetchHeader
* @see IIMAP4Sink#fetchUid
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String fetch(String in_msgSet, String in_fetchCriteria)
throws IOException
{
//Check parameters
if((in_msgSet == null) || (in_fetchCriteria == null))
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.FETCH);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_msgSet);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_fetchCriteria);
return sendCommand(m_commandVector);
}
/**
* Searches the mailbox for messages that match the given search
* criteria.
* @param in_criteria Search criteria consisting of one or more search keys.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#search
* @see #uidSearch
* @see IIMAP4Sink#searchStart
* @see IIMAP4Sink#search
* @see IIMAP4Sink#searchEnd
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String search(String in_criteria)
throws IOException
{
//Check parameters
if(in_criteria == null)
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.SEARCH);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_criteria);
return sendCommand(m_commandVector);
}
/**
* Alters data associated with a message in the mailbox.
* @param in_msgSet Message set.
* @param in_dataItem Message data item name.
* @param in_value Value for the message data item.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see #uidStore
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String store(String in_msgSet, String in_dataItem, String in_value)
throws IOException
{
//Check parameters
if((in_msgSet == null) || (in_dataItem == null) || (in_value == null))
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.STORE);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_msgSet);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_dataItem);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_value);
return sendCommand(m_commandVector);
}
/**
* Copies messages specified with a unique identifier.
* Performs a UID COPY.
* @param in_msgSet Message numbers to copy (for example, "1:2").
* @param in_mailbox Name of target mailbox.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see #copy
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String uidCopy(String in_msgSet, String in_mailbox)
throws IOException
{
//Check parameters
if((in_msgSet == null) || (in_mailbox == null))
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.UID);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(IGlobals.COPY);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_msgSet);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_mailbox);
return sendCommand(m_commandVector);
}
/**
* Fetches messages specified with a unique identifier
* and retrieve the corresponding unique identifiers.
* Performs a UID FETCH.
* @param in_msgSet The message set
* @param in_fetchCriteria The message data item names
* @return String The tag associated with this command
* @exception IOException If an I/O error occurs.
* @see #fetch
* @see IIMAP4Sink#fetchStart
* @see IIMAP4Sink#fetchEnd
* @see IIMAP4Sink#fetchSize
* @see IIMAP4Sink#fetchData
* @see IIMAP4Sink#fetchFlags
* @see IIMAP4Sink#fetchBodyStructure
* @see IIMAP4Sink#fetchEnvelope
* @see IIMAP4Sink#fetchInternalDate
* @see IIMAP4Sink#fetchHeader
* @see IIMAP4Sink#fetchUid
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String uidFetch(String in_msgSet, String in_fetchCriteria)
throws IOException
{
//Check parameters
if((in_msgSet == null) || (in_fetchCriteria == null))
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.UID);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(IGlobals.FETCH);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_msgSet);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_fetchCriteria);
return sendCommand(m_commandVector);
}
/**
*
* Stores a message specified by a unique identifier.
* Performs a UID STORE.
* @param in_set Message set.
* @param in_dataItem Message data item name.
* @param in_value Value for the message data item.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see #store
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String uidStore(String in_msgSet, String in_dataItem, String in_value)
throws IOException
{
//Check parameters
if((in_msgSet == null) || (in_dataItem == null) || (in_value == null))
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.UID);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(IGlobals.STORE);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_msgSet);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_dataItem);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_value);
return sendCommand(m_commandVector);
}
/**
* Searches the mailbox for messages that match the search criteria
* and retrieves the corresponding unique identifiers.
* Performs a UID SEARCH.
* @param in_criteria Search criteria consisting of one or more search keys.
* @return String The tag associated with this command
* @exception IOException If an I/O error occurs.
* @see #search
* @see IIMAP4Sink#searchStart
* @see IIMAP4Sink#search
* @see IIMAP4Sink#searchEnd
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String uidSearch(String in_criteria)
throws IOException
{
//Check parameters
if(in_criteria == null)
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.UID);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(IGlobals.SEARCH);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_criteria);
return sendCommand(m_commandVector);
}
////////////////////////////////////////////////////////////////////
// Extended Commands
////////////////////////////////////////////////////////////////////
/**
* Retrieves the prefixes of namespaces used by a server for
* personal mailboxes, other user's mailboxes, and shared mailboxes.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see IIMAP4Sink#nameSpaceStart
* @see IIMAP4Sink#nameSpacePersonal
* @see IIMAP4Sink#nameSpaceOtherUsers
* @see IIMAP4Sink#nameSpaceShared
* @see IIMAP4Sink#nameSpaceEnd
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String nameSpace() throws IOException
{
m_commandVector.addElement(IGlobals.NAMESPACE);
return sendCommand(m_commandVector);
}
/**
* Changes the access control list on the specified mailbox.
* The specified identifier is granted permissions specified in the
* third argument
* @param in_mailbox Name of the mailbox.
* @param in_authId Authentication identifier.
* @param in_accessRight Access rights modification.
* @return String The tag associated with this command.
* @exception IOException If an I/O error occurs.
* @see deleteACL
* @see #getACL
* @see IIMAP4Sink#taggedLine
* @see IIMAP4Sink#error
*/
public synchronized String setACL(String in_mailbox, String in_authId, String in_accessRight)
throws IOException
{
//Check parameters
if((in_mailbox == null) || (in_authId == null) || (in_accessRight == null))
{
throw new IllegalArgumentException();
}
m_commandVector.addElement(IGlobals.SETACL);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_mailbox);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_authId);
m_commandVector.addElement(IGlobals.Space);
m_commandVector.addElement(in_accessRight);
return sendCommand(m_commandVector);
}
/**
* Removes an