⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imapprotocol.java

📁 java Email you can use it to send email to others
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License").  You * may not use this file except in compliance with the License. You can obtain * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. * Sun designates this particular file as subject to the "Classpath" exception * as provided by Sun in the GPL Version 2 section of the License file that * accompanied this code.  If applicable, add the following below the License * Header, with the fields enclosed by brackets [] replaced by your own * identifying information: "Portions Copyrighted [year] * [name of copyright owner]" * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license."  If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above.  However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. *//* * @(#)IMAPProtocol.java	1.64 07/05/04 */package com.sun.mail.imap.protocol;import java.io.*;import java.util.*;import java.text.*;import java.lang.reflect.*;import javax.mail.*;import javax.mail.internet.*;import javax.mail.search.*;import com.sun.mail.util.*;import com.sun.mail.iap.*;import com.sun.mail.imap.ACL;import com.sun.mail.imap.Rights;import com.sun.mail.imap.AppendUID;/** * This class extends the iap.Protocol object and implements IMAP * semantics. In general, there is a method corresponding to each * IMAP protocol command. The typical implementation issues the * appropriate protocol command, collects all responses, processes * those responses that are specific to this command and then * dispatches the rest (the unsolicited ones) to the dispatcher * using the <code>notifyResponseHandlers(r)</code>. * * @version 1.64, 07/05/04 * @author  John Mani * @author  Bill Shannon */public class IMAPProtocol extends Protocol {        private boolean connected = false;		// did constructor succeed?    private boolean rev1 = false;		// REV1 server ?    private boolean authenticated;		// authenticated?    // WARNING: authenticated may be set to true in superclass    //		constructor, don't initialize it here.    private Map capabilities = null;    private List authmechs = null;    private String[] searchCharsets; 	// array of search charsets    private String name;    private SaslAuthenticator saslAuthenticator;	// if SASL is being used    private ByteArray ba;		// a buffer for fetchBody    private static final byte[] CRLF = { (byte)'\r', (byte)'\n'};    /**     * Constructor.     * Opens a connection to the given host at given port.     *     * @param host	host to connect to     * @param port	portnumber to connect to     * @param debug     debug mode     * @param props     Properties object used by this protocol     */    public IMAPProtocol(String name, String host, int port, 			boolean debug, PrintStream out, Properties props,			boolean isSSL) throws IOException, ProtocolException {	super(host, port, debug, out, props, "mail." + name, isSSL);	try {	    this.name = name;	    if (capabilities == null)		capability();	    if (hasCapability("IMAP4rev1"))		rev1 = true;	    searchCharsets = new String[2]; // 2, for now.	    searchCharsets[0] = "UTF-8";	    searchCharsets[1] = MimeUtility.mimeCharset(				    MimeUtility.getDefaultJavaCharset()				);	    connected = true;	// must be last statement in constructor	} finally {	    /*	     * If we get here because an exception was thrown, we need	     * to disconnect to avoid leaving a connected socket that	     * no one will be able to use because this object was never	     * completely constructed.	     */	    if (!connected)		disconnect();	}    }    /**     * CAPABILITY command.     *     * @see "RFC2060, section 6.1.1"     */    public void capability() throws ProtocolException {	// Check CAPABILITY	Response[] r = command("CAPABILITY", null);	if (!r[r.length-1].isOK())	    throw new ProtocolException(r[r.length-1].toString());	capabilities = new HashMap(10);	authmechs = new ArrayList(5);	for (int i = 0, len = r.length; i < len; i++) {	    if (!(r[i] instanceof IMAPResponse))		continue;	    IMAPResponse ir = (IMAPResponse)r[i];	    // Handle *all* untagged CAPABILITY responses.	    //   Though the spec seemingly states that only	    // one CAPABILITY response string is allowed (6.1.1),	    // some server vendors claim otherwise.	    if (ir.keyEquals("CAPABILITY"))		parseCapabilities(ir);	}    }    /**     * If the response contains a CAPABILITY response code, extract     * it and save the capabilities.     */    protected void setCapabilities(Response r) {	byte b;	while ((b = r.readByte()) > 0 && b != (byte)'[')	    ;	if (b == 0)	    return;	String s;	s = r.readAtom();	if (!s.equalsIgnoreCase("CAPABILITY"))	    return;	capabilities = new HashMap(10);	authmechs = new ArrayList(5);	parseCapabilities(r);    }    /**     * Parse the capabilities from a CAPABILITY response or from     * a CAPABILITY response code attached to (e.g.) an OK response.     */    protected void parseCapabilities(Response r) {	String s;	while ((s = r.readAtom(']')) != null) {	    if (s.length() == 0) {		if (r.peekByte() == (byte)']')		    break;		/*		 * Probably found something here that's not an atom.		 * Rather than loop forever or fail completely, we'll		 * try to skip this bogus capability.  This is known		 * to happen with:		 *   Netscape Messaging Server 4.03 (built Apr 27 1999)		 * that returns:		 *   * CAPABILITY * CAPABILITY IMAP4 IMAP4rev1 ...		 * The "*" in the middle of the capability list causes		 * us to loop forever here.		 */		r.skipToken();	    } else {		capabilities.put(s.toUpperCase(Locale.ENGLISH), s);		if (s.regionMatches(true, 0, "AUTH=", 0, 5)) {		    authmechs.add(s.substring(5));		    if (debug)			out.println("IMAP DEBUG: AUTH: " + s.substring(5));		}	    }	}    }    /**     * Check the greeting when first connecting; look for PREAUTH response.     */    protected void processGreeting(Response r) throws ProtocolException {	super.processGreeting(r);	// check if it's BAD	if (r.isOK()) {			// check if it's OK	    setCapabilities(r);	    return;	}	// only other choice is PREAUTH	IMAPResponse ir = (IMAPResponse)r;	if (ir.keyEquals("PREAUTH")) {	    authenticated = true;	    setCapabilities(r);	} else	    throw new ConnectionException(this, r);    }    /**     * Returns <code>true</code> if the connection has been authenticated,     * either due to a successful login, or due to a PREAUTH greeting response.     */    public boolean isAuthenticated() {	return authenticated;    }    /**     * Returns <code>true</code> if this is a IMAP4rev1 server     */    public boolean isREV1() {	return rev1;    }    /**     * Returns whether this Protocol supports non-synchronizing literals.     */    protected boolean supportsNonSyncLiterals() {	return hasCapability("LITERAL+");    }    /**     * Read a response from the server.     */    public Response readResponse() throws IOException, ProtocolException {	// assert Thread.holdsLock(this);	// can't assert because it's called from constructor	return IMAPResponse.readResponse(this);    }    /**     * Check whether the given capability is supported by     * this server. Returns <code>true</code> if so, otherwise     * returns false.     */    public boolean hasCapability(String c) {	return capabilities.containsKey(c.toUpperCase(Locale.ENGLISH));    }    /**     * Return the map of capabilities returned by the server.     *      * @since	JavaMail 1.4.1     */    public Map getCapabilities() {	return capabilities;    }    /**     * Close socket connection.     *     * This method just makes the Protocol.disconnect() method     * public.     */    public void disconnect() {	super.disconnect();	authenticated = false;	// just in case    }    /**     * The NOOP command.     *     * @see "RFC2060, section 6.1.2"     */    public void noop() throws ProtocolException {	if (debug)	    out.println("IMAP DEBUG: IMAPProtocol noop");	simpleCommand("NOOP", null);    }    /**     * LOGOUT Command.     *     * @see "RFC2060, section 6.1.3"     */    public void logout() throws ProtocolException {	// XXX - what happens if exception is thrown?	Response[] r = command("LOGOUT", null);	authenticated = false;	// dispatch any unsolicited responses.	//  NOTE that the BYE response is dispatched here as well	notifyResponseHandlers(r);	disconnect();    }    /**     * LOGIN Command.     *      * @see "RFC2060, section 6.2.2"     */    public void login(String u, String p) throws ProtocolException {	Argument args = new Argument();	args.writeString(u);	args.writeString(p);	Response[] r = command("LOGIN", args);	// dispatch untagged responses	notifyResponseHandlers(r);	// Handle result of this command	handleResult(r[r.length-1]);	// If the response includes a CAPABILITY response code, process it	setCapabilities(r[r.length-1]);	// if we get this far without an exception, we're authenticated	authenticated = true;    }    /**     * The AUTHENTICATE command with AUTH=LOGIN authenticate scheme     *     * @see "RFC2060, section 6.2.1"     */    public synchronized void authlogin(String u, String p)				throws ProtocolException {	Vector v = new Vector();	String tag = null;	Response r = null;	boolean done = false;	try {	    tag = writeCommand("AUTHENTICATE LOGIN", null);	} catch (Exception ex) {	    // Convert this into a BYE response	    r = Response.byeResponse(ex);	    done = true;	}	OutputStream os = getOutputStream(); // stream to IMAP server	/* Wrap a BASE64Encoder around a ByteArrayOutputstream	 * to craft b64 encoded username and password strings	 *	 * Note that the encoded bytes should be sent "as-is" to the	 * server, *not* as literals or quoted-strings.	 *	 * Also note that unlike the B64 definition in MIME, CRLFs 	 * should *not* be inserted during the encoding process. So, I	 * use Integer.MAX_VALUE (0x7fffffff (> 1G)) as the bytesPerLine,	 * which should be sufficiently large !	 *	 * Finally, format the line in a buffer so it can be sent as	 * a single packet, to avoid triggering a bug in SUN's SIMS 2.0	 * server caused by patch 105346.	 */	ByteArrayOutputStream bos = new ByteArrayOutputStream();	OutputStream b64os = new BASE64EncoderStream(bos, Integer.MAX_VALUE);	boolean first = true;	while (!done) { // loop till we are done	    try {		r = readResponse();	    	if (r.isContinuation()) {		    // Server challenge ..		    String s;		    if (first) { // Send encoded username			s = u;			first = false;		    } else 	// Send encoded password			s = p;		    		    // obtain b64 encoded bytes		    b64os.write(ASCIIUtility.getBytes(s));		    b64os.flush(); 	// complete the encoding		    bos.write(CRLF); 	// CRLF termination		    os.write(bos.toByteArray()); // write out line		    os.flush(); 	// flush the stream		    bos.reset(); 	// reset buffer		} else if (r.isTagged() && r.getTag().equals(tag))		    // Ah, our tagged response		    done = true;		else if (r.isBYE()) // outta here		    done = true;		else // hmm .. unsolicited response here ?!		    v.addElement(r);	    } catch (Exception ioex) {		// convert this into a BYE response		r = Response.byeResponse(ioex);		done = true;	    }	}	/* Dispatch untagged responses.	 * NOTE: in our current upper level IMAP classes, we add the	 * responseHandler to the Protocol object only *after* the 	 * connection has been authenticated. So, for now, the below	 * code really ends up being just a no-op.	 */	Response[] responses = new Response[v.size()];	v.copyInto(responses);	notifyResponseHandlers(responses);	// Handle the final OK, NO, BAD or BYE response	handleResult(r);	// If the response includes a CAPABILITY response code, process it	setCapabilities(r);	// if we get this far without an exception, we're authenticated	authenticated = true;    }    /**     * The AUTHENTICATE command with AUTH=PLAIN authentication scheme.     * This is based heavly on the {@link #authlogin} method.     *     * @param  authzid		the authorization id     * @param  u		the username     * @param  p		the password     * @throws ProtocolException as thrown by {@link Protocol#handleResult}.     * @see "RFC3501, section 6.2.2"     * @see "RFC2595, section 6"     * @since  JavaMail 1.3.2     */    public synchronized void authplain(String authzid, String u, String p)				throws ProtocolException {	Vector v = new Vector();	String tag = null;	Response r = null;	boolean done = false;	try {	    tag = writeCommand("AUTHENTICATE PLAIN", null);	} catch (Exception ex) {	    // Convert this into a BYE response	    r = Response.byeResponse(ex);	    done = true;	}	OutputStream os = getOutputStream(); // stream to IMAP server	/* Wrap a BASE64Encoder around a ByteArrayOutputstream	 * to craft b64 encoded username and password strings	 *	 * Note that the encoded bytes should be sent "as-is" to the	 * server, *not* as literals or quoted-strings.	 *	 * Also note that unlike the B64 definition in MIME, CRLFs	 * should *not* be inserted during the encoding process. So, I	 * use Integer.MAX_VALUE (0x7fffffff (> 1G)) as the bytesPerLine,	 * which should be sufficiently large !	 *	 * Finally, format the line in a buffer so it can be sent as	 * a single packet, to avoid triggering a bug in SUN's SIMS 2.0	 * server caused by patch 105346.	 */	ByteArrayOutputStream bos = new ByteArrayOutputStream();	OutputStream b64os = new BASE64EncoderStream(bos, Integer.MAX_VALUE);	while (!done) { // loop till we are done	    try {		r = readResponse();		if (r.isContinuation()) {		    // Server challenge ..		    final String nullByte = "\0";		    String s = authzid + nullByte + u + nullByte + p;		    // obtain b64 encoded bytes		    b64os.write(ASCIIUtility.getBytes(s));		    b64os.flush(); 	// complete the encoding		    bos.write(CRLF); 	// CRLF termination		    os.write(bos.toByteArray()); // write out line		    os.flush(); 	// flush the stream		    bos.reset(); 	// reset buffer		} else if (r.isTagged() && r.getTag().equals(tag))		    // Ah, our tagged response		    done = true;		else if (r.isBYE()) // outta here		    done = true;		else // hmm .. unsolicited response here ?!		    v.addElement(r);	    } catch (Exception ioex) {		// convert this into a BYE response		r = Response.byeResponse(ioex);		done = true;	    }	}	/* Dispatch untagged responses.	 * NOTE: in our current upper level IMAP classes, we add the	 * responseHandler to the Protocol object only *after* the	 * connection has been authenticated. So, for now, the below	 * code really ends up being just a no-op.	 */	Response[] responses = new Response[v.size()];	v.copyInto(responses);	notifyResponseHandlers(responses);	// Handle the final OK, NO, BAD or BYE response	handleResult(r);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -