public void fetch(Query q, int spec, String[] headers, int start, int end, boolean uid);
public void lsub(String start, String ref);
public void list(String start, String ref);
- public static interface Authenticator { public abstract Mailbox authenticate(String user, String pass); }
public static class Exn extends MailException { public Exn(String s) { super(s); } }
public static class Bad extends Exn { public Bad(String s) { super(s); } }
public static class No extends Exn { public No(String s) { super(s); } }
Mailbox selected = null;
Mailbox root = null;
Mailbox selected() { if (selected == null) throw new Bad("no mailbox selected"); return selected; }
- final Server.Authenticator auth;
+ final Login auth;
final Client client;
- public MailboxWrapper(Server.Authenticator auth, Client c) { this.auth=auth; this.client=c;}
+ public MailboxWrapper(Login auth, Client c) { this.auth=auth; this.client=c;}
- private Mailbox mailbox(String name, boolean create) {
+ private Mailbox mailbox(String name, boolean create) { return mailbox(name, create, true); }
+ private Mailbox mailbox(String name, boolean create, boolean throwexn) {
if (name.equalsIgnoreCase("inbox")) return inbox;
Mailbox m = root;
for(StringTokenizer st = new StringTokenizer(name, sep + ""); st.hasMoreTokens();)
- if ((m = m.slash(st.nextToken(), create)) == null) throw new Server.No("no such mailbox " + name);
+ if ((m = m.slash(st.nextToken(), create)) == null) {
+ if (throwexn) throw new Server.No("no such mailbox " + name);
+ return null;
+ }
return m;
}
String[] children = (start.length() == 0 ? root : mailbox(start, false)).children();
for(int i=0; i<children.length; i++) {
String s = children[i], pre = ref, kid = start + (start.length() > 0 ? sep+"" : "") + s;
+ if (mailbox(kid, false) == null) continue;
boolean phantom = mailbox(kid, false).phantom();
while(true) {
if (pre.length() == 0) {
for(Mailbox.Iterator it=selected().iterator(q);it.next();) to.add(it.cur(), it.flags() | Mailbox.Flag.RECENT); }
public void login(String u, String p) {
- if ((root = auth.authenticate(u,p)) == null) throw new No("Login failed.");
- inbox = mailbox("INBOX", false); // FEATURE: ??
+ Account account = null;
+ if ((account = auth.login(u,p)) == null) throw new No("Login failed.");
+ root = account.getMailbox(IMAP.class);
+ inbox = root.slash("INBOX", false);
+ if (inbox == null) inbox = root;
}
public void unselect() { selected = null; }
public void delete(String m0) { delete(mailbox(m0,false)); }
public void delete(Mailbox m) { if (!m.equals(inbox)) m.destroy(false); else throw new Bad("can't delete inbox"); }
- public void create(String m) { mailbox(m, true); }
+ public void create(String m) { mailbox(m, true, false); }
public void append(String m,int f,Date a,String b) { try {
mailbox(m,false).add(new Message(new Stream(b), new Message.Envelope(null,null,a)),f|Mailbox.Flag.RECENT);
} catch (Message.Malformed e) { throw new No(e.getMessage()); } }
String selectedName = null;
Mailbox inbox = null, root = null;
Server api;
+ Login auth = null;
Parser parser = null;
Connection conn = null;
- public Listener() { }
+ public Listener(Login auth) { this.auth = auth; }
Parser.Token token() { return parser.token(); }
void println(String s) { conn.println(s); }
void newline() { parser.newline(); }
public void handleRequest(Connection conn) {
this.conn = conn;
parser = new Parser(conn);
- api = new IMAP.MailboxWrapper(new BogusAuthenticator(), this);
+ api = new IMAP.MailboxWrapper(auth, this);
conn.setTimeout(30 * 60 * 1000);
println("* OK " + conn.vhost + " " + IMAP.class.getName() + " IMAP4rev1 [RFC3501] v" + version + " server ready");
for(String tag = null;; newline()) try {
case CAPABILITY: println("* CAPABILITY " + Printer.join(" ", api.capability())); break;
case AUTHENTICATE: throw new Server.No("AUTHENTICATE not supported");
case LOGOUT: api.logout(); println("* BYE"); conn.close(); return;
- case LIST: api.list(token().q(), token().q()); break;
+ case LIST: api.list(token().q(), token().astring()); break; /*astring is a hack for EUDORA*/
case LSUB: api.lsub(token().q(), token().q()); break;
case SUBSCRIBE: api.subscribe(token().astring()); break;
case UNSUBSCRIBE: api.unsubscribe(token().astring()); break;
s = list.length == 0 ? "" : list[0].s.toUpperCase();
r.append(s);
if (list.length == 0) { spec |= RFC822TEXT; if(e) payload = m.headers.raw+"\r\n"+m.body; }
- else if (s.equals("")) { spec |= RFC822TEXT; if(e) payload = m.headers.raw+"\r\n"+m.body; }
+ else if (s.equals("") || s.equals("1")) { spec |= RFC822TEXT; if(e) payload = m.headers.raw+"\r\n"+m.body; }
else if (s.equals("TEXT")) { spec |= RFC822TEXT; if(e) payload = m.body; }
else if (s.equals("HEADER")) { spec |= HEADER; if(e) payload = m.headers.raw+"\r\n"; }
else if (s.equals("HEADER.FIELDS")) { spec |= FIELDS; payload=headers(r,t[i].l()[1].sl(),false,m,e); }
public static String addressList(Object a) {
if (a == null) return "NIL";
if (a instanceof Address) return "("+address((Address)a)+")";
+ if (a instanceof String) return "("+address(Address.parse((String)a))+")";
Address[] aa = (Address[])a;
StringBuffer ret = new StringBuffer();
ret.append("(");
return "(\"TEXT\" \"PLAIN\" (\"CHARSET\" \"ISO-8859-1\") NIL NIL \"7BIT\" "+m.size()+" "+m.lines+")";
}
static String message(Message m) { return m.toString(); }
- static String date(Date d) { return d.toString(); }
+ static String date(Date d) { return "\""+d.toString()+"\""; }
static String envelope(Message m) {
return
"(" + quotify(m.envelope.arrival.toString()) +
// Main //////////////////////////////////////////////////////////////////////////////
- /** simple listener for testing purposes */
- public static void main(String[] args) throws Exception {
- ServerSocket ss = new ServerSocket(143);
- for(;;) {
- final Socket s = ss.accept();
- new Thread() { public void run() { try {
- final Mailbox root = FileBasedMailbox.getFileBasedMailbox(Mailbox.STORAGE_ROOT+File.separatorChar+"imap", true);
- new Listener();
- } catch (Exception e) { e.printStackTrace(); } } }.start();
- }
- }
-
public static final int
PEEK=0x1, BODYSTRUCTURE=0x2, ENVELOPE=0x4, FLAGS=0x8, INTERNALDATE=0x10, FIELDS=0x800, FIELDSNOT=0x1000,
RFC822=0x20, RFC822TEXT=0x40, RFC822SIZE=0x80, HEADERNOT=0x100, UID=0x200, HEADER=0x400;
-
- public static class BogusAuthenticator implements IMAP.Server.Authenticator {
- final Mailbox root = FileBasedMailbox.getFileBasedMailbox(Mailbox.STORAGE_ROOT, true).slash("user", true);
- public Mailbox authenticate(String user, String pass) {
- return EtcPasswd.verify(user, pass) ? root.slash(user, false) : null; }
- }
}