📄 imapconnection.java
字号:
/* * IMAPConnection.java * Copyright (C) 2003,2004,2005 The Free Software Foundation * * This file is part of GNU inetlib, a library. * * GNU inetlib is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * GNU inetlib is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Linking this library statically or dynamically with other modules is * making a combined work based on this library. Thus, the terms and * conditions of the GNU General Public License cover the whole * combination. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obliged to do so. If you do not wish to do so, delete this * exception statement from your version. */package gnu.inet.imap;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.EOFException;import java.io.InputStream;import java.io.IOException;import java.io.OutputStream;import java.net.InetSocketAddress;import java.net.ProtocolException;import java.net.Socket;import java.net.UnknownHostException;import java.security.GeneralSecurityException;import java.security.KeyStore;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.TreeMap;import java.util.logging.Level;import java.util.logging.Logger;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSocket;import javax.net.ssl.SSLSocketFactory;import javax.net.ssl.TrustManager;import javax.security.auth.callback.CallbackHandler;import javax.security.sasl.Sasl;import javax.security.sasl.SaslClient;import javax.security.sasl.SaslException;import gnu.inet.util.BASE64;import gnu.inet.util.CRLFOutputStream;import gnu.inet.util.EmptyX509TrustManager;import gnu.inet.util.SaslCallbackHandler;import gnu.inet.util.SaslCramMD5;import gnu.inet.util.SaslInputStream;import gnu.inet.util.SaslLogin;import gnu.inet.util.SaslOutputStream;import gnu.inet.util.SaslPlain;import gnu.inet.util.TraceLevel;/** * The protocol class implementing IMAP4rev1. * * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> */public class IMAPConnection implements IMAPConstants{ /** * The logger used for IMAP protocol traces. */ public static final Logger logger = Logger.getLogger("gnu.inet.imap"); /** * The network trace level. */ public static final Level IMAP_TRACE = new TraceLevel("imap"); /** * Prefix for tags. */ protected static final String TAG_PREFIX = "A"; /** * The encoding used to create strings for IMAP commands. */ protected static final String US_ASCII = "US-ASCII"; /** * The default IMAP port. */ protected static final int DEFAULT_PORT = 143; /** * The default IMAP-SSL port. */ protected static final int DEFAULT_SSL_PORT = 993; /** * The socket used for communication with the server. */ protected Socket socket; /** * The tokenizer used to read IMAP responses from. */ protected IMAPResponseTokenizer in; /** * The output stream. */ protected CRLFOutputStream out; /** * List of responses received asynchronously. */ protected List asyncResponses; /** * List of alert strings. */ private List alerts; /* * Used to generate new tags for tagged commands. */ private int tagIndex = 0; /* * Print debugging output using ANSI colour escape sequences. */ private boolean ansiDebug = false; /** * Creates a new connection to the default IMAP port. * @param host the name of the host to connect to */ public IMAPConnection(String host) throws UnknownHostException, IOException { this(host, -1, 0, 0, false, null); } /** * Creates a new connection. * @param host the name of the host to connect to * @param port the port to connect to, or -1 for the default */ public IMAPConnection(String host, int port) throws UnknownHostException, IOException { this(host, port, 0, 0, false, null); } /** * Creates a new connection. * @param host the name of the host to connect to * @param port the port to connect to, or -1 for the default * @param connectionTimeout the socket connection timeout * @param timeout the socket timeout */ public IMAPConnection(String host, int port, int connectionTimeout, int timeout) throws UnknownHostException, IOException { this(host, port, connectionTimeout, timeout, false, null); } /** * Creates a new secure connection using the specified trust manager. * @param host the name of the host to connect to * @param port the port to connect to, or -1 for the default * @param tm a trust manager used to check SSL certificates, or null to * use the default */ public IMAPConnection(String host, int port, TrustManager tm) throws UnknownHostException, IOException { this(host, port, 0, 0, true, tm); } /** * Creates a new connection. * @param host the name of the host to connect to * @param port the port to connect to, or -1 for the default * @param connectionTimeout the socket connection timeout * @param timeout the socket timeout * @param secure if an IMAP-SSL connection should be made * @param tm a trust manager used to check SSL certificates, or null to * use the default */ public IMAPConnection(String host, int port, int connectionTimeout, int timeout, boolean secure, TrustManager tm) throws UnknownHostException, IOException { if (port < 0) { port = secure ? DEFAULT_SSL_PORT : DEFAULT_PORT; } // Set up socket try { socket = new Socket(); InetSocketAddress address = new InetSocketAddress(host, port); if (connectionTimeout > 0) { socket.connect(address, connectionTimeout); } else { socket.connect(address); } if (timeout > 0) { socket.setSoTimeout(timeout); } if (secure) { SSLSocketFactory factory = getSSLSocketFactory(tm); SSLSocket ss = (SSLSocket) factory.createSocket(socket, host, port, true); String[] protocols = { "TLSv1", "SSLv3" }; ss.setEnabledProtocols(protocols); ss.setUseClientMode(true); ss.startHandshake(); socket = ss; } } catch (GeneralSecurityException e) { IOException e2 = new IOException(); e2.initCause(e); throw e2; } InputStream in = socket.getInputStream(); in = new BufferedInputStream(in); this.in = new IMAPResponseTokenizer(in); OutputStream out = socket.getOutputStream(); out = new BufferedOutputStream(out); this.out = new CRLFOutputStream(out); asyncResponses = new ArrayList(); alerts = new ArrayList(); } /** * Sets whether debugging output should use ANSI colour escape sequences. */ public void setAnsiDebug(boolean flag) { ansiDebug = flag; } /** * Returns a new tag for a command. */ protected String newTag() { return TAG_PREFIX + (++tagIndex); } /** * Sends the specified IMAP tagged command to the server. */ protected void sendCommand(String tag, String command) throws IOException { logger.log(IMAP_TRACE, "> " + tag + " " + command); out.write(tag + ' ' + command); out.writeln(); out.flush(); } /** * Sends the specified IMAP command. * @param command the command * @return true if OK was received, or false if NO was received * @exception IOException if BAD was received or an I/O error occurred */ protected boolean invokeSimpleCommand(String command) throws IOException { String tag = newTag(); sendCommand(tag, command); while (true) { IMAPResponse response = readResponse(); String id = response.getID(); if (tag.equals(response.getTag())) { processAlerts(response); if (id == OK) { return true; } else if (id == NO) { return false; } else { throw new IMAPException(id, response.getText()); } } else if (response.isUntagged()) { asyncResponses.add(response); } else { throw new IMAPException(id, response.getText()); } } } /** * Reads an IMAP response from the server. * The response will consist of <i>either</i>: * <ul> * <li>A tagged response corresponding to a pending command</li> * <li>An untagged error response</li> * <li>A continuation response</li> */ protected IMAPResponse readResponse() throws IOException { IMAPResponse response = in.next(); if (response == null) { logger.log(IMAP_TRACE, "<EOF"); throw new EOFException(); } else if (ansiDebug) { logger.log(IMAP_TRACE, "< " + response.toANSIString()); } else { logger.log(IMAP_TRACE, "< " + response.toString()); } return response; } // -- Alert notifications -- private void processAlerts(IMAPResponse response) { List code = response.getResponseCode(); if (code != null && code.contains(ALERT)) { alerts.add(response.getText()); } } /** * Indicates if there are alerts pending for the user-agent. */ public boolean alertsPending() { return (alerts.size() > 0); } /** * Returns the pending alerts for the user-agent as an array. */ public String[] getAlerts() { String[] a = new String[alerts.size()]; alerts.toArray(a); alerts.clear(); // flush return a; } // -- IMAP commands -- /** * Returns a list of the capabilities of the IMAP server. */ public List capability() throws IOException { String tag = newTag(); sendCommand(tag, CAPABILITY); List capabilities = new ArrayList(); while (true) { IMAPResponse response = readResponse(); String id = response.getID(); if (tag.equals(response.getTag())) { processAlerts(response); if (id == OK) { if (capabilities.size() == 0) { // The capability list may be contained in the // response text. addTokens(capabilities, response.getText()); } return capabilities; } else { throw new IMAPException(id, response.getText()); } } else if (response.isUntagged()) { if (id == CAPABILITY) { // The capability list may be contained in the // response text. addTokens(capabilities, response.getText());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -