imapmessage.java

来自「此源码是在sun站点上提供的javamail基础上改进。用来解决中文邮件或很多国」· Java 代码 · 共 1,442 行 · 第 1/3 页

JAVA
1,442
字号
		    return true; // no flags
		if (needBodyStructure && m._getBodyStructure() == null)
		    return true; // no BODYSTRUCTURE
		if (needUID && m.getUID() == -1)	// no UID
		    return true;
		if (needHeaders && !m.areHeadersLoaded()) // no headers
		    return true;
		if (needSize && m.size == -1)		// no size
		    return true;

		// Is the desired header present ?
		for (int i = 0; i < hdrs.length; i++) {
		    if (!m.isHeaderLoaded(hdrs[i]))
			return true; // Nope, return
		}

		return false;
	    }
	}

	StringBuffer command = new StringBuffer();
	boolean first = true;
	boolean allHeaders = false;

	if (fp.contains(FetchProfile.Item.ENVELOPE)) {
	    command.append(EnvelopeCmd);
	    first = false;
	}
	if (fp.contains(FetchProfile.Item.FLAGS)) {
	    command.append(first ? "FLAGS" : " FLAGS");
	    first = false;
	}
	if (fp.contains(FetchProfile.Item.CONTENT_INFO)) {
	    command.append(first ? "BODYSTRUCTURE" : " BODYSTRUCTURE");
	    first = false;
	}
	if (fp.contains(UIDFolder.FetchProfileItem.UID)) {
	    command.append(first ? "UID" : " UID");
	    first = false;
	}
	if (fp.contains(IMAPFolder.FetchProfileItem.HEADERS)) {
	    allHeaders = true;
	    if (folder.protocol.isREV1())
		command.append(first ?
			    "BODY.PEEK[HEADER]" : " BODY.PEEK[HEADER]");
	    else
		command.append(first ? "RFC822.HEADER" : " RFC822.HEADER");
	    first = false;
	}
	if (fp.contains(IMAPFolder.FetchProfileItem.SIZE)) {
	    command.append(first ? "RFC822.SIZE" : " RFC822.SIZE");
	    first = false;
	}

	// if we're not fetching all headers, fetch individual headers
	String[] hdrs = null;
	if (!allHeaders) {
	    hdrs = fp.getHeaderNames();
	    if (hdrs.length > 0) {
		if (!first)
		    command.append(" ");
		command.append(craftHeaderCmd(folder.protocol, hdrs));
	    }
	}

	Utility.Condition condition = new FetchProfileCondition(fp);

        // Acquire the Folder's MessageCacheLock.
        synchronized(folder.messageCacheLock) {

	    // Apply the test, and get the sequence-number set for
	    // the messages that need to be prefetched.
	    MessageSet[] msgsets = Utility.toMessageSet(msgs, condition);

	    if (msgsets == null)
		// We already have what we need.
		return;

	    Response[] r = null;
	    Vector v = new Vector(); // to collect non-FETCH responses &
	    			     // unsolicited FETCH FLAG responses 
	    try {
		r = folder.protocol.fetch(msgsets, command.toString());
	    } catch (ConnectionException cex) {
		throw new FolderClosedException(folder, cex.getMessage());
	    } catch (CommandFailedException cfx) {
		// Ignore these, as per RFC 2180
	    } catch (ProtocolException pex) { 
		throw new MessagingException(pex.getMessage(), pex);
	    }

	    if (r == null)
		return;
	   
	    for (int i = 0; i < r.length; i++) {
		if (r[i] == null)
		    continue;
		if (!(r[i] instanceof FetchResponse)) {
		    v.addElement(r[i]); // Unsolicited Non-FETCH response
		    continue;
		}

		// Got a FetchResponse.
		FetchResponse f = (FetchResponse)r[i];
		// Get the corresponding message.
		IMAPMessage msg = folder.getMessageBySeqNumber(f.getNumber());

		int count = f.getItemCount();
		boolean unsolicitedFlags = false;

		for (int j = 0; j < count; j++) {
		    Item item = f.getItem(j);

		    // Check for the FLAGS item
		    if (item instanceof Flags) {
			if (!fp.contains(FetchProfile.Item.FLAGS) ||
			    msg == null)
			    // Ok, Unsolicited FLAGS update.
			    unsolicitedFlags = true;
			else
			    msg.flags = (Flags)item;
		    }

		    // Check for ENVELOPE items
		    else if (item instanceof ENVELOPE)
			msg.envelope = (ENVELOPE)item;
		    else if (item instanceof INTERNALDATE)
			msg.receivedDate = ((INTERNALDATE)item).getDate();
		    else if (item instanceof RFC822SIZE)
			msg.size = ((RFC822SIZE)item).size;

		    // Check for the BODYSTRUCTURE item
		    else if (item instanceof BODYSTRUCTURE)
			msg.bs = (BODYSTRUCTURE)item;
		    // Check for the UID item
		    else if (item instanceof UID) {
			UID u = (UID)item;
			msg.uid = u.uid; // set uid
			// add entry into uid table
			if (folder.uidTable == null)
			    folder.uidTable = new Hashtable();
			folder.uidTable.put(new Long(u.uid), msg);
		    }

		    // Check for header items
		    else if (item instanceof RFC822DATA ||
			     item instanceof BODY) {
			InputStream headerStream;
			if (item instanceof RFC822DATA) // IMAP4
			    headerStream = 
				((RFC822DATA)item).getByteArrayInputStream();
			else	// IMAP4rev1
			    headerStream = 
				((BODY)item).getByteArrayInputStream();
			
			// Load the obtained headers.
			InternetHeaders h = new InternetHeaders();
			h.load(headerStream);
			if (msg.headers == null || allHeaders)
			    msg.headers = h;
			else {
			    /*
			     * This is really painful.  A second fetch
			     * of the same headers (which might occur because
			     * a new header was added to the set requested)
			     * will return headers we already know about.
			     * In this case, only load the headers we haven't
			     * seen before to avoid adding duplicates of
			     * headers we already have.
			     */
			    Enumeration e = h.getAllHeaders();
			    while (e.hasMoreElements()) {
				Header he = (Header)e.nextElement();
				if (!msg.isHeaderLoaded(he.getName()))
				    msg.headers.addHeader(
						he.getName(), he.getValue());
			    }
			}

			// if we asked for all headers, assume we got them
			if (allHeaders)
			    msg.setHeadersLoaded(true);
			else {
			    // Mark all headers we asked for as 'loaded'
			    for (int k = 0; k < hdrs.length; k++)
				msg.setHeaderLoaded(hdrs[k]);
			}
		    }
		}

		// If this response contains any unsolicited FLAGS
		// add it to the unsolicited response vector
		if (unsolicitedFlags)
		    v.addElement(f);
	    }

	    // Dispatch any unsolicited responses
	    int size = v.size();
	    if (size != 0) {
		Response[] responses = new Response[size];
		v.copyInto(responses);
		folder.handleResponses(responses);
	    }

	} // Release messageCacheLock
    }

    /*
     * Load the Envelope for this message.
     */
    private synchronized void loadEnvelope() throws MessagingException {
	if (envelope != null) // already loaded
	    return;

	Response[] r = null;

	// Acquire MessageCacheLock, to freeze seqnum.
	synchronized(getMessageCacheLock()) {
	    try {
		IMAPProtocol p = getProtocol();

		checkExpunged(); // Insure that this message is not expunged

		int seqnum = getSequenceNumber();
		r = p.fetch(seqnum, EnvelopeCmd);

		for (int i = 0; i < r.length; i++) {
		    // If this response is NOT a FetchResponse or if it does
		    // not match our seqnum, skip.
		    if (r[i] == null ||
			!(r[i] instanceof FetchResponse) ||
			((FetchResponse)r[i]).getNumber() != seqnum)
			continue;

		    FetchResponse f = (FetchResponse)r[i];
		    
		    // Look for the Envelope items.
		    int count = f.getItemCount();
		    for (int j = 0; j < count; j++) {
			Item item = f.getItem(j);
			
			if (item instanceof ENVELOPE)
			    envelope = (ENVELOPE)item;
			else if (item instanceof INTERNALDATE)
			    receivedDate = ((INTERNALDATE)item).getDate();
			else if (item instanceof RFC822SIZE)
			    size = ((RFC822SIZE)item).size;
		    }
		}

		// ((IMAPFolder)folder).handleResponses(r);
		p.notifyResponseHandlers(r);
		p.handleResult(r[r.length - 1]);
	    } catch (ConnectionException cex) {
		throw new FolderClosedException(folder, cex.getMessage());
	    } catch (ProtocolException pex) {
		forceCheckExpunged();
		throw new MessagingException(pex.getMessage(), pex);
	    }

	} // Release MessageCacheLock

	if (envelope == null)
	    throw new MessagingException("Failed to load IMAP envelope");
    }

    private static String craftHeaderCmd(IMAPProtocol p, String[] hdrs) {
	StringBuffer sb;

	if (p.isREV1())
	    sb = new StringBuffer("BODY.PEEK[HEADER.FIELDS (");
	else
	    sb = new StringBuffer("RFC822.HEADER.LINES (");

	for (int i = 0; i < hdrs.length; i++) {
	    if (i > 0)
		sb.append(" ");
	    sb.append(hdrs[i]);
	}

	if (p.isREV1())
	    sb.append(")]");
	else
	    sb.append(")");
	
	return sb.toString();
    }

    /*
     * Load the BODYSTRUCTURE
     */
    private synchronized void loadBODYSTRUCTURE() 
		throws MessagingException {
	if (bs != null) // already loaded
	    return;

	// Acquire MessageCacheLock, to freeze seqnum.
	synchronized(getMessageCacheLock()) {
	    try {
		IMAPProtocol p = getProtocol();

		// This message could be expunged when we were waiting 
		// to acquire the lock ...
		checkExpunged();

		bs = p.fetchBodyStructure(getSequenceNumber());
	    } catch (ConnectionException cex) {
		throw new FolderClosedException(folder, cex.getMessage());
	    } catch (ProtocolException pex) {
		forceCheckExpunged();
		throw new MessagingException(pex.getMessage(), pex);
	    }
	    if (bs == null) {
		// if the FETCH is successful, we should always get a
		// BODYSTRUCTURE, but some servers fail to return it
		// if the message has been expunged
		forceCheckExpunged();
		throw new MessagingException("Unable to load BODYSTRUCTURE");
	    }
	}
    }

    /*
     * Load all headers.
     */
    private synchronized void loadHeaders() throws MessagingException {
	if (headersLoaded)
	    return;

	InputStream is = null;

	// Acquire MessageCacheLock, to freeze seqnum.
	synchronized (getMessageCacheLock()) {
	    try {
		IMAPProtocol p = getProtocol();

		// This message could be expunged when we were waiting 
		// to acquire the lock ...
		checkExpunged();

		if (p.isREV1()) {
		    BODY b = p.peekBody(getSequenceNumber(), 
					 toSection("HEADER"));
		    if (b != null)
			is = b.getByteArrayInputStream();
		} else {
		    RFC822DATA rd = p.fetchRFC822(getSequenceNumber(), 
						  "HEADER");
		    if (rd != null)
			is = rd.getByteArrayInputStream();
		}
	    } catch (ConnectionException cex) {
		throw new FolderClosedException(folder, cex.getMessage());
	    } catch (ProtocolException pex) {
		forceCheckExpunged();
		throw new MessagingException(pex.getMessage(), pex);
	    }
	} // Release MessageCacheLock

	if (is == null)
	    throw new MessagingException("Cannot load header");
	headers = new InternetHeaders(is);
	headersLoaded = true;
    }

    /*
     * Load this message's Flags
     */
    private synchronized void loadFlags() throws MessagingException {
	if (flags != null)
	    return;
	
	// Acquire MessageCacheLock, to freeze seqnum.
	synchronized(getMessageCacheLock()) {
	    try {
		IMAPProtocol p = getProtocol();

		// This message could be expunged when we were waiting 
		// to acquire the lock ...
		checkExpunged();

		flags = p.fetchFlags(getSequenceNumber());
	    } catch (ConnectionException cex) {
		throw new FolderClosedException(folder, cex.getMessage());
	    } catch (ProtocolException pex) {
		forceCheckExpunged();
		throw new MessagingException(pex.getMessage(), pex);
	    }
	} // Release MessageCacheLock
    }

    /*
     * Are all headers loaded?
     */
    private synchronized boolean areHeadersLoaded() {
	return headersLoaded;
    }

    /*
     * Set whether all headers are loaded.
     */
    private synchronized void setHeadersLoaded(boolean loaded) {
	headersLoaded = loaded;
    }

    /* 
     * Check if the given header was ever loaded from the server
     */
    private synchronized boolean isHeaderLoaded(String name) {
	if (headersLoaded) // All headers for this message have been loaded
	    return true;
	
	return (loadedHeaders != null) ? 
		loadedHeaders.containsKey(name.toUpperCase(Locale.ENGLISH)) :
		false;
    }

    /*
     * Mark that the given headers have been loaded from the server.
     */
    private synchronized void setHeaderLoaded(String name) {
	if (loadedHeaders == null)
	    loadedHeaders = new Hashtable(1);
	loadedHeaders.put(name.toUpperCase(Locale.ENGLISH), name);
    }

    /*
     * Convert the given FETCH item identifier to the approriate 
     * section-string for this message.
     */
    private String toSection(String what) {
	if (sectionId == null)
	    return what;
	else
	    return sectionId + "." + what;
    }

    /*
     * Clone an array of InternetAddresses.
     */
    private InternetAddress[] aaclone(InternetAddress[] aa) {
	if (aa == null)
	    return null;
	else
	    return (InternetAddress[])aa.clone();
    }

    private Flags _getFlags() {
	return flags;
    }

    private ENVELOPE _getEnvelope() {
	return envelope;
    }

    private BODYSTRUCTURE _getBodyStructure() {
	return bs;
    }

    /***********************************************************
     * accessor routines to make available certain private/protected
     * fields to other classes in this package.
     ***********************************************************/

    /*
     * Called by IMAPFolder.
     * Must not be synchronized.
     */
    void _setFlags(Flags flags) {
	this.flags = flags;
    }

    /*
     * Called by IMAPNestedMessage.
     */
    Session _getSession() {
	return session;
    }
}

⌨️ 快捷键说明

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