📄 imapprotocol.java
字号:
// 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;
}
/**
* SASL-based login.
*/
public void sasllogin(String[] allowed, String realm, String authzid,
String u, String p) throws ProtocolException {
if (saslAuthenticator == null) {
try {
Class sac = Class.forName(
"com.sun.mail.imap.protocol.IMAPSaslAuthenticator");
Constructor c = sac.getConstructor(new Class[] {
IMAPProtocol.class,
String.class,
Properties.class,
Boolean.TYPE,
PrintStream.class,
String.class
});
saslAuthenticator = (SaslAuthenticator)c.newInstance(
new Object[] {
this,
name,
props,
debug ? Boolean.TRUE : Boolean.FALSE,
out,
host
});
} catch (Exception ex) {
if (debug)
out.println("IMAP DEBUG: Can't load SASL authenticator: " +
ex);
// probably because we're running on a system without SASL
return; // not authenticated, try without SASL
}
}
// were any allowed mechanisms specified?
List v;
if (allowed != null && allowed.length > 0) {
// remove anything not supported by the server
v = new ArrayList(allowed.length);
for (int i = 0; i < allowed.length; i++)
if (authmechs.contains(allowed[i])) // XXX - case must match
v.add(allowed[i]);
} else {
// everything is allowed
v = authmechs;
}
String[] mechs = (String[])v.toArray(new String[v.size()]);
if (saslAuthenticator.authenticate(mechs, realm, authzid, u, p))
authenticated = true;
}
// XXX - for IMAPSaslAuthenticator access to protected method
OutputStream getIMAPOutputStream() {
return getOutputStream();
}
/**
* PROXYAUTH Command.
*
* @see "Netscape/iPlanet/SunONE Messaging Server extension"
*/
public void proxyauth(String u) throws ProtocolException {
Argument args = new Argument();
args.writeString(u);
simpleCommand("PROXYAUTH", args);
}
/**
* STARTTLS Command.
*
* @see "RFC3501, section 6.2.1"
*/
public void startTLS() throws ProtocolException {
try {
super.startTLS("STARTTLS");
} catch (ProtocolException pex) {
// ProtocolException just means the command wasn't recognized,
// or failed. This should never happen if we check the
// CAPABILITY first.
throw pex;
} catch (Exception ex) {
// any other exception means we have to shut down the connection
// generate an artificial BYE response and disconnect
Response[] r = { Response.byeResponse(ex) };
notifyResponseHandlers(r);
disconnect();
}
}
/**
* SELECT Command.
*
* @see "RFC2060, section 6.3.1"
*/
public MailboxInfo select(String mbox) throws ProtocolException {
// encode the mbox as per RFC2060
mbox = BASE64MailboxEncoder.encode(mbox);
Argument args = new Argument();
args.writeString(mbox);
Response[] r = command("SELECT", args);
// Note that MailboxInfo also removes those responses
// it knows about
MailboxInfo minfo = new MailboxInfo(r);
// dispatch any remaining untagged responses
notifyResponseHandlers(r);
Response response = r[r.length-1];
if (response.isOK()) { // command succesful
if (response.toString().indexOf("READ-ONLY") != -1)
minfo.mode = Folder.READ_ONLY;
else
minfo.mode = Folder.READ_WRITE;
}
handleResult(response);
return minfo;
}
/**
* EXAMINE Command.
*
* @see "RFC2060, section 6.3.2"
*/
public MailboxInfo examine(String mbox) throws ProtocolException {
// encode the mbox as per RFC2060
mbox = BASE64MailboxEncoder.encode(mbox);
Argument args = new Argument();
args.writeString(mbox);
Response[] r = command("EXAMINE", args);
// Note that MailboxInfo also removes those responses
// it knows about
MailboxInfo minfo = new MailboxInfo(r);
minfo.mode = Folder.READ_ONLY; // Obviously
// dispatch any remaining untagged responses
notifyResponseHandlers(r);
handleResult(r[r.length-1]);
return minfo;
}
/**
* STATUS Command.
*
* @see "RFC2060, section 6.3.10"
*/
public Status status(String mbox, String[] items)
throws ProtocolException {
if (!isREV1() && !hasCapability("IMAP4SUNVERSION"))
// STATUS is rev1 only, however the non-rev1 SIMS2.0
// does support this.
throw new BadCommandException("STATUS not supported");
// encode the mbox as per RFC2060
mbox = BASE64MailboxEncoder.encode(mbox);
Argument args = new Argument();
args.writeString(mbox);
Argument itemArgs = new Argument();
if (items == null)
items = Status.standardItems;
for (int i = 0, len = items.length; i < len; i++)
itemArgs.writeAtom(items[i]);
args.writeArgument(itemArgs);
Response[] r = command("STATUS", args);
Status status = null;
Response response = r[r.length-1];
// Grab all STATUS responses
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("STATUS")) {
if (status == null)
status = new Status(ir);
else // collect 'em all
Status.add(status, new Status(ir));
r[i] = null;
}
}
}
// dispatch remaining untagged responses
notifyResponseHandlers(r);
handleResult(response);
return status;
}
/**
* CREATE Command.
*
* @see "RFC2060, section 6.3.3"
*/
public void create(String mbox) throws ProtocolException {
// encode the mbox as per RFC2060
mbox = BASE64MailboxEncoder.encode(mbox);
Argument args = new Argument();
args.writeString(mbox);
simpleCommand("CREATE", args);
}
/**
* DELETE Command.
*
* @see "RFC2060, section 6.3.4"
*/
public void delete(String mbox) throws ProtocolException {
// encode the mbox as per RFC2060
mbox = BASE64MailboxEncoder.encode(mbox);
Argument args = new Argument();
args.writeString(mbox);
simpleCommand("DELETE", args);
}
/**
* RENAME Command.
*
* @see "RFC2060, section 6.3.5"
*/
public void rename(String o, String n) throws ProtocolException {
// encode the mbox as per RFC2060
o = BASE64MailboxEncoder.encode(o);
n = BASE64MailboxEncoder.encode(n);
Argument args = new Argument();
args.writeString(o);
args.writeString(n);
simpleCommand("RENAME", args);
}
/**
* SUBSCRIBE Command.
*
* @see "RFC2060, section 6.3.6"
*/
public void subscribe(String mbox) throws ProtocolException {
Argument args = new Argument();
// encode the mbox as per RFC2060
mbox = BASE64MailboxEncoder.encode(mbox);
args.writeString(mbox);
simpleCommand("SUBSCRIBE", args);
}
/**
* UNSUBSCRIBE Command.
*
* @see "RFC2060, section 6.3.7"
*/
public void unsubscribe(String mbox) throws ProtocolException {
Argument args = new Argument();
// encode the mbox as per RFC2060
mbox = BASE64MailboxEncoder.encode(mbox);
args.writeString(mbox);
simpleCommand("UNSUBSCRIBE", args);
}
/**
* LIST Command.
*
* @see "RFC2060, section 6.3.8"
*/
public ListInfo[] list(String ref, String pattern)
throws ProtocolException {
return doList("LIST", ref, pattern);
}
/**
* LSUB Command.
*
* @see "RFC2060, section 6.3.9"
*/
public ListInfo[] lsub(String ref, String pattern)
throws ProtocolException {
return doList("LSUB", ref, pattern);
}
private ListInfo[] doList(String cmd, String ref, String pat)
throws ProtocolException {
// encode the mbox as per RFC2060
ref = BASE64MailboxEncoder.encode(ref);
pat = BASE64MailboxEncoder.encode(pat);
Argument args = new Argument();
args.writeString(ref);
args.writeString(pat);
Response[] r = command(cmd, args);
ListInfo[] linfo = null;
Response response = r[r.length-1];
if (response.isOK()) { // command succesful
Vector v = new Vector(1);
for (int i = 0, len = r.length; i < len; i++) {
if (!(r[i] instanceof IMAPResponse))
continue;
IMAPResponse ir = (IMAPResponse)r[i];
if (ir.keyEquals(cmd)) {
v.addElement(new ListInfo(ir));
r[i] = null;
}
}
if (v.size() > 0) {
linfo = new ListInfo[v.size()];
v.copyInto(linfo);
}
}
// Dispatch remaining untagged responses
notifyResponseHandlers(r);
handleResult(response);
return linfo;
}
/**
* APPEND Command.
*
* @see "RFC2060, section 6.3.11"
*/
public void append(String mbox, Flags f, Date d,
Literal data) throws ProtocolException {
appenduid(mbox, f, d, data, false); // ignore return value
}
/**
* APPEND Command, return uid from APPENDUID response code.
*
* @see "RFC2060, section 6.3.11"
*/
public AppendUID appenduid(String mbox, Flags f, Date d,
Literal data) throws ProtocolException {
return appenduid(mbox, f, d, data, true);
}
public AppendUID appenduid(String mbox, Flags f, Date d,
Literal data, boolean uid) throws ProtocolException {
// encode the mbox as per RFC2060
mbox = BASE64MailboxEncoder.encode(mbox);
Argument args = new Argument();
args.writeString(mbox);
if (f != null) { // set Flags in appended message
// can't set the \Recent flag in APPEND
if (f.contains(Flags.Flag.RECENT)) {
f = new Flags(f); // copy, don't modify orig
f.remove(Flags.Flag.RECENT); // remove RECENT from copy
}
/*
* HACK ALERT: We want the flag_list to be written out
* without any checking/processing of the bytes in it. If
* I use writeString(), the flag_list will end up being
* quoted since it contains "illegal" characters. So I
* am depending on implementation knowledge that writeAtom()
* does not do any checking/processing - it just writes out
* the bytes. What we really need is a writeFoo() that just
* dumps out its argument.
*/
args.writeAtom(createFlagList(f));
}
if (d != null) // set INTERNALDATE in appended message
args.writeString(INTERNALDATE.format(d));
args.writeBytes(data);
Response[] r = command("APPEND", args);
// dispatch untagged responses
notifyResponseHandlers(r);
// Handle result of this command
handleResult(r[r.length-1]);
if (uid)
return getAppendUID(r[r.length-1]);
else
return null;
}
/**
* If the response contains an APPENDUID response code, extract
* it and return an AppendUID object with the information.
*/
private AppendUID getAppendUID(Response r) {
if (!r.isOK())
return null;
byte b;
while ((b = r.readByte()) > 0 && b != (byte)'[')
;
if (b == 0)
return null;
String s;
s = r.readAtom();
if (!s.equalsIgnoreCase("APPENDUID"))
return null;
long uidvalidity = r.readLong();
long uid = r.readLong();
return new AppendUID(uidvalidity, uid);
}
/**
* CHECK Command.
*
* @see "RFC2060, section 6.4.1"
*/
public void check() throws ProtocolException {
simpleCommand("CHECK", null);
}
/**
* CLOSE Command.
*
* @see "RFC2060, section 6.4.2"
*/
public void close() throws ProtocolException {
simpleCommand("CLOSE", null);
}
/**
* EXPUNGE Command.
*
* @see "RFC2060, section 6.4.3"
*/
public void expunge() throws ProtocolException {
simpleCommand("EXPUNGE", null);
}
/**
* UID EXPUNGE Command.
*
* @see "RFC2359, section 4.1"
*/
public void uidexpunge(UIDSet[] set) throws ProtocolException {
if (!hasCapability("UIDPLUS"))
throw new BadCommandException("UID EXPUNGE not supported");
simpleCommand("UID EXPUNGE " + UIDSet.toString(set), null);
}
/**
* Fetch the BODYSTRUCTURE of the specified message.
*/
public BODYSTRUCTURE fetchBodyStructure(int msgno)
throws ProtocolException {
Response[] r = fetch(msgno, "BODYSTRUCTURE");
notifyResponseHandlers(r);
Response response = r[r.length-1];
if (response.isOK())
return (BODYSTRUCTURE)FetchResponse.getItem(r, msgno,
BODYSTRUCTURE.class);
else if (response.isNO())
return null;
else {
handleResult(response);
return null;
}
}
/**
* Fetch given BODY section, without marking the message
* as SEEN.
*/
public BODY peekBody(int msgno, String section)
throws ProtocolException {
return fetchBody(msgno, section, true);
}
/**
* Fetch given BODY section.
*/
public BODY fetchBody(int msgno, String section)
throws ProtocolException {
return fetchBody(msgno, section, false);
}
protected BODY fetchBody(int msgno, String section, boolean peek)
throws ProtocolException {
Response[] r;
if (peek)
r = fetch(msgno,
"BODY.PEEK[" + (section == null ? "]" : section + "]"));
else
r = fetch(msgno,
"BODY[" + (section == null ? "]" : section + "]"));
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 {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -