📄 imapprotocol.java
字号:
handleResult(response);
return null;
}
}
/**
* Partial FETCH of given BODY section, without setting SEEN flag.
*/
public BODY peekBody(int msgno, String section, int start, int size)
throws ProtocolException {
return fetchBody(msgno, section, start, size, true, null);
}
/**
* Partial FETCH of given BODY section.
*/
public BODY fetchBody(int msgno, String section, int start, int size)
throws ProtocolException {
return fetchBody(msgno, section, start, size, false, null);
}
/**
* Partial FETCH of given BODY section, without setting SEEN flag.
*/
public BODY peekBody(int msgno, String section, int start, int size,
ByteArray ba) throws ProtocolException {
return fetchBody(msgno, section, start, size, true, ba);
}
/**
* Partial FETCH of given BODY section.
*/
public BODY fetchBody(int msgno, String section, int start, int size,
ByteArray ba) throws ProtocolException {
return fetchBody(msgno, section, start, size, false, ba);
}
protected BODY fetchBody(int msgno, String section, int start, int size,
boolean peek, ByteArray ba) throws ProtocolException {
this.ba = ba; // save for later use by getResponseBuffer
Response[] r = fetch(
msgno, (peek ? "BODY.PEEK[" : "BODY[" ) +
(section == null ? "]<" : (section +"]<")) +
String.valueOf(start) + "." +
String.valueOf(size) + ">"
);
notifyResponseHandlers(r);
Response response = r[r.length-1];
if (response.isOK())
return (BODY)FetchResponse.getItem(r, msgno, BODY.class);
else if (response.isNO())
return null;
else {
handleResult(response);
return null;
}
}
/**
* Return a buffer to read a response into.
* The buffer is provided by fetchBody and is
* used only once.
*/
protected ByteArray getResponseBuffer() {
ByteArray ret = ba;
ba = null;
return ret;
}
/**
* Fetch the specified RFC822 Data item. 'what' names
* the item to be fetched. 'what' can be <code>null</code>
* to fetch the whole message.
*/
public RFC822DATA fetchRFC822(int msgno, String what)
throws ProtocolException {
Response[] r = fetch(msgno,
what == null ? "RFC822" : "RFC822." + what
);
// dispatch untagged responses
notifyResponseHandlers(r);
Response response = r[r.length-1];
if (response.isOK())
return (RFC822DATA)FetchResponse.getItem(r, msgno,
RFC822DATA.class);
else if (response.isNO())
return null;
else {
handleResult(response);
return null;
}
}
/**
* Fetch the FLAGS for the given message.
*/
public Flags fetchFlags(int msgno) throws ProtocolException {
Flags flags = null;
Response[] r = fetch(msgno, "FLAGS");
// Search for our FLAGS response
for (int i = 0, len = r.length; i < len; i++) {
if (r[i] == null ||
!(r[i] instanceof FetchResponse) ||
((FetchResponse)r[i]).getNumber() != msgno)
continue;
FetchResponse fr = (FetchResponse)r[i];
if ((flags = (Flags)fr.getItem(Flags.class)) != null) {
r[i] = null; // remove this response
break;
}
}
// dispatch untagged responses
notifyResponseHandlers(r);
handleResult(r[r.length-1]);
return flags;
}
/**
* Fetch the IMAP UID for the given message.
*/
public UID fetchUID(int msgno) throws ProtocolException {
Response[] r = fetch(msgno, "UID");
// dispatch untagged responses
notifyResponseHandlers(r);
Response response = r[r.length-1];
if (response.isOK())
return (UID)FetchResponse.getItem(r, msgno, UID.class);
else if (response.isNO()) // XXX: Issue NOOP ?
return null;
else {
handleResult(response);
return null; // NOTREACHED
}
}
/**
* Get the sequence number for the given UID. A UID object
* containing the sequence number is returned. If the given UID
* is invalid, <code>null</code> is returned.
*/
public UID fetchSequenceNumber(long uid) throws ProtocolException {
UID u = null;
Response[] r = fetch(String.valueOf(uid), "UID", true);
for (int i = 0, len = r.length; i < len; i++) {
if (r[i] == null || !(r[i] instanceof FetchResponse))
continue;
FetchResponse fr = (FetchResponse)r[i];
if ((u = (UID)fr.getItem(UID.class)) != null) {
if (u.uid == uid) // this is the one we want
break;
else
u = null;
}
}
notifyResponseHandlers(r);
handleResult(r[r.length-1]);
return u;
}
/**
* Get the sequence numbers for UIDs ranging from start till end.
* UID objects that contain the sequence numbers are returned.
* If no UIDs in the given range are found, an empty array is returned.
*/
public UID[] fetchSequenceNumbers(long start, long end)
throws ProtocolException {
Response[] r = fetch(String.valueOf(start) + ":" +
(end == UIDFolder.LASTUID ? "*" :
String.valueOf(end)),
"UID", true);
UID u;
Vector v = new Vector();
for (int i = 0, len = r.length; i < len; i++) {
if (r[i] == null || !(r[i] instanceof FetchResponse))
continue;
FetchResponse fr = (FetchResponse)r[i];
if ((u = (UID)fr.getItem(UID.class)) != null)
v.addElement(u);
}
notifyResponseHandlers(r);
handleResult(r[r.length-1]);
UID[] ua = new UID[v.size()];
v.copyInto(ua);
return ua;
}
/**
* Get the sequence numbers for UIDs ranging from start till end.
* UID objects that contain the sequence numbers are returned.
* If no UIDs in the given range are found, an empty array is returned.
*/
public UID[] fetchSequenceNumbers(long[] uids) throws ProtocolException {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < uids.length; i++) {
if (i > 0)
sb.append(",");
sb.append(String.valueOf(uids[i]));
}
Response[] r = fetch(sb.toString(), "UID", true);
UID u;
Vector v = new Vector();
for (int i = 0, len = r.length; i < len; i++) {
if (r[i] == null || !(r[i] instanceof FetchResponse))
continue;
FetchResponse fr = (FetchResponse)r[i];
if ((u = (UID)fr.getItem(UID.class)) != null)
v.addElement(u);
}
notifyResponseHandlers(r);
handleResult(r[r.length-1]);
UID[] ua = new UID[v.size()];
v.copyInto(ua);
return ua;
}
public Response[] fetch(MessageSet[] msgsets, String what)
throws ProtocolException {
return fetch(MessageSet.toString(msgsets), what, false);
}
public Response[] fetch(int start, int end, String what)
throws ProtocolException {
return fetch(String.valueOf(start) + ":" + String.valueOf(end),
what, false);
}
public Response[] fetch(int msg, String what)
throws ProtocolException {
return fetch(String.valueOf(msg), what, false);
}
private Response[] fetch(String msgSequence, String what, boolean uid)
throws ProtocolException {
if (uid)
return command("UID FETCH " + msgSequence +" (" + what + ")",null);
else
return command("FETCH " + msgSequence + " (" + what + ")", null);
}
/**
* COPY command.
*/
public void copy(MessageSet[] msgsets, String mbox)
throws ProtocolException {
copy(MessageSet.toString(msgsets), mbox);
}
public void copy(int start, int end, String mbox)
throws ProtocolException {
copy(String.valueOf(start) + ":" + String.valueOf(end),
mbox);
}
private void copy(String msgSequence, String mbox)
throws ProtocolException {
// encode the mbox as per RFC2060
mbox = BASE64MailboxEncoder.encode(mbox);
Argument args = new Argument();
args.writeAtom(msgSequence);
args.writeString(mbox);
simpleCommand("COPY", args);
}
public void storeFlags(MessageSet[] msgsets, Flags flags, boolean set)
throws ProtocolException {
storeFlags(MessageSet.toString(msgsets), flags, set);
}
public void storeFlags(int start, int end, Flags flags, boolean set)
throws ProtocolException {
storeFlags(String.valueOf(start) + ":" + String.valueOf(end),
flags, set);
}
/**
* Set the specified flags on this message. <p>
*/
public void storeFlags(int msg, Flags flags, boolean set)
throws ProtocolException {
storeFlags(String.valueOf(msg), flags, set);
}
private void storeFlags(String msgset, Flags flags, boolean set)
throws ProtocolException {
Response[] r;
if (set)
r = command("STORE " + msgset + " +FLAGS " +
createFlagList(flags), null);
else
r = command("STORE " + msgset + " -FLAGS " +
createFlagList(flags), null);
// Dispatch untagged responses
notifyResponseHandlers(r);
handleResult(r[r.length-1]);
}
/**
* Creates an IMAP flag_list from the given Flags object.
*/
private String createFlagList(Flags flags) {
StringBuffer sb = new StringBuffer();
sb.append("("); // start of flag_list
Flags.Flag[] sf = flags.getSystemFlags(); // get the system flags
boolean first = true;
for (int i = 0; i < sf.length; i++) {
String s;
Flags.Flag f = sf[i];
if (f == Flags.Flag.ANSWERED)
s = "\\Answered";
else if (f == Flags.Flag.DELETED)
s = "\\Deleted";
else if (f == Flags.Flag.DRAFT)
s = "\\Draft";
else if (f == Flags.Flag.FLAGGED)
s = "\\Flagged";
else if (f == Flags.Flag.RECENT)
s = "\\Recent";
else if (f == Flags.Flag.SEEN)
s = "\\Seen";
else
continue; // skip it
if (first)
first = false;
else
sb.append(' ');
sb.append(s);
}
String[] uf = flags.getUserFlags(); // get the user flag strings
for (int i = 0; i < uf.length; i++) {
if (first)
first = false;
else
sb.append(' ');
sb.append(uf[i]);
}
sb.append(")"); // terminate flag_list
return sb.toString();
}
/**
* Issue the given search criterion on the specified message sets.
* Returns array of matching sequence numbers. An empty array
* is returned if no matches are found.
*
* @param msgsets array of MessageSets
* @param term SearchTerm
* @return array of matching sequence numbers.
*/
public int[] search(MessageSet[] msgsets, SearchTerm term)
throws ProtocolException, SearchException {
return search(MessageSet.toString(msgsets), term);
}
/**
* Issue the given search criterion on all messages in this folder.
* Returns array of matching sequence numbers. An empty array
* is returned if no matches are found.
*
* @param term SearchTerm
* @return array of matching sequence numbers.
*/
public int[] search(SearchTerm term)
throws ProtocolException, SearchException {
return search("ALL", term);
}
/* Apply the given SearchTerm on the specified sequence.
* Returns array of matching sequence numbers. Note that an empty
* array is returned for no matches.
*/
private int[] search(String msgSequence, SearchTerm term)
throws ProtocolException, SearchException {
// Check if the search "text" terms contain only ASCII chars
if (SearchSequence.isAscii(term)) {
try {
return issueSearch(msgSequence, term, null);
} catch (IOException ioex) { /* will not happen */ }
}
/* The search "text" terms do contain non-ASCII chars. We need to
* use SEARCH CHARSET <charset> ...
* The charsets we try to use are UTF-8 and the locale's
* default charset. If the server supports UTF-8, great,
* always use it. Else we try to use the default charset.
*/
// Cycle thru the list of charsets
for (int i = 0; i < searchCharsets.length; i++) {
if (searchCharsets[i] == null)
continue;
try {
return issueSearch(msgSequence, term, searchCharsets[i]);
} catch (CommandFailedException cfx) {
/* Server returned NO. For now, I'll just assume that
* this indicates that this charset is unsupported.
* We can check the BADCHARSET response code once
* that's spec'd into the IMAP RFC ..
*/
searchCharsets[i] = null;
continue;
} catch (IOException ioex) {
/* Charset conversion failed. Try the next one */
continue;
} catch (ProtocolException pex) {
throw pex;
} catch (SearchException sex) {
throw sex;
}
}
// No luck.
throw new SearchException("Search failed");
}
/* Apply the given SearchTerm on the specified sequence, using the
* given charset. <p>
* Returns array of matching sequence numbers. Note that an empty
* array is returned for no matches.
*/
private int[] issueSearch(String msgSequence, SearchTerm term,
String charset)
throws ProtocolException, SearchException, IOException {
// Generate a search-sequence with the given charset
Argument args = SearchSequence.generateSequence(term,
charset == null ? null :
MimeUtility.javaCharset(charset)
);
args.writeAtom(msgSequence);
Response[] r;
if (charset == null) // text is all US-ASCII
r = command("SEARCH", args);
else
r = command("SEARCH CHARSET " + charset, args);
Response response = r[r.length-1];
int[] matches = null;
// Grab all SEARCH responses
if (response.isOK()) { // command succesful
Vector v = new Vector();
int num;
for (int i = 0, len = r.length; i < len; i++) {
if (!(r[i] instanceof IMAPResponse))
continue;
IMAPResponse ir = (IMAPResponse)r[i];
// There *will* be one SEARCH response.
if (ir.keyEquals("SEARCH")) {
while ((num = ir.readNumber()) != -1)
v.addElement(new Integer(num));
r[i] = null;
}
}
// Copy the vector into 'matches'
int vsize = v.size();
matches = new int[vsize];
for (int i = 0; i < vsize; i++)
matches[i] = ((Integer)v.elementAt(i)).intValue();
}
// dispatch remaining untagged responses
notifyResponseHandlers(r);
handleResult(response);
return matches;
}
/**
* NAMESPACE Command.
*
* @see "RFC2342"
*/
public Namespaces namespace() throws ProtocolException {
if (!hasCapability("NAMESPACE"))
throw new BadCommandException("NAMESPACE not supported");
Response[] r = command("NAMESPACE", null);
Namespaces namespace = null;
Response response = r[r.length-1];
// Grab NAMESPACE response
if (response.isOK()) { // command succesful
for (int i = 0, len = r.length; i < len; i++) {
if (!(r[i] instanceof IMAPResponse))
continue;
IMAPResponse ir = (IMAPResponse)r[i];
if (ir.keyEquals("NAMESPACE")) {
if (namespace == null)
namespace = new Namespaces(ir);
r[i] = null;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -