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