pop3: Get message listing if no mailbox in URL
authorBen Greear <greearb@candelatech.com>
Sun, 28 Mar 2010 21:49:00 +0000 (23:49 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Sun, 28 Mar 2010 21:49:00 +0000 (23:49 +0200)
If you pass a URL to pop3 that does not contain a message ID as
part of the URL, it will currently ask for 'INBOX' which just
causes the pop3 server to return an error.

The change makes libcurl treat en empty message ID as a request
for LIST (list of pop3 message IDs).  User's code could then
parse this and download individual messages as desired.

lib/pop3.c
lib/pop3.h

index 320f756..ff929b0 100644 (file)
@@ -232,6 +232,7 @@ static void state(struct connectdata *conn,
     "USER",
     "PASS",
     "STARTTLS",
+    "LIST",
     "RETR",
     "QUIT",
     /* LAST */
@@ -382,7 +383,49 @@ static CURLcode pop3_state_retr_resp(struct connectdata *conn,
   return result;
 }
 
-/* start the DO phase */
+
+/* for the list response */
+static CURLcode pop3_state_list_resp(struct connectdata *conn,
+                                     int pop3code,
+                                     pop3state instate)
+{
+  CURLcode result = CURLE_OK;
+  struct SessionHandle *data = conn->data;
+  struct FTP *pop3 = data->state.proto.pop3;
+  struct pop3_conn *pop3c = &conn->proto.pop3c;
+  struct pingpong *pp = &pop3c->pp;
+
+  (void)instate; /* no use for this yet */
+
+  if('O' != pop3code) {
+    state(conn, POP3_STOP);
+    return CURLE_RECV_ERROR;
+  }
+
+  /* POP3 download */
+  result=Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE,
+                             pop3->bytecountp,
+                             -1, NULL); /* no upload here */
+
+  if(pp->cache) {
+    /* cache holds the email ID listing */
+
+    /* we may get the EOB already here! */
+    result = Curl_pop3_write(conn, pp->cache, pp->cache_size);
+    if(result)
+      return result;
+
+    /* cache is drained */
+    free(pp->cache);
+    pp->cache = NULL;
+    pp->cache_size = 0;
+  }
+
+  state(conn, POP3_STOP);
+  return result;
+}
+
+/* start the DO phase for RETR */
 static CURLcode pop3_retr(struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
@@ -396,6 +439,20 @@ static CURLcode pop3_retr(struct connectdata *conn)
   return result;
 }
 
+/* start the DO phase for LIST */
+static CURLcode pop3_list(struct connectdata *conn)
+{
+  CURLcode result = CURLE_OK;
+  struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+  result = Curl_pp_sendf(&conn->proto.pop3c.pp, "LIST %s", pop3c->mailbox);
+  if(result)
+    return result;
+
+  state(conn, POP3_LIST);
+  return result;
+}
+
 static CURLcode pop3_statemach_act(struct connectdata *conn)
 {
   CURLcode result;
@@ -451,6 +508,10 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
       result = pop3_state_retr_resp(conn, pop3code, pop3c->state);
       break;
 
+    case POP3_LIST:
+      result = pop3_state_list_resp(conn, pop3code, pop3c->state);
+      break;
+
     case POP3_QUIT:
       /* fallthrough, just stop! */
     default:
@@ -655,6 +716,7 @@ CURLcode pop3_perform(struct connectdata *conn,
 {
   /* this is POP3 and no proxy */
   CURLcode result=CURLE_OK;
+  struct pop3_conn *pop3c = &conn->proto.pop3c;
 
   DEBUGF(infof(conn->data, "DO phase starts\n"));
 
@@ -667,7 +729,13 @@ CURLcode pop3_perform(struct connectdata *conn,
   *dophase_done = FALSE; /* not done yet */
 
   /* start the first command in the DO phase */
-  result = pop3_retr(conn);
+  /* If mailbox is empty, then assume user wants listing for mail IDs,
+   * otherwise, attempt to retrieve the mail-id stored in mailbox
+   */
+  if (strlen(pop3c->mailbox))
+    result = pop3_retr(conn);
+  else
+    result = pop3_list(conn);
   if(result)
     return result;
 
@@ -785,9 +853,6 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
   const char *path = data->state.path;
   int len;
 
-  if(!*path)
-    path = "INBOX";
-
   /* url decode the path and use this mailbox */
   pop3c->mailbox = curl_easy_unescape(data, path, 0, &len);
 
index 3076287..20a2269 100644 (file)
@@ -32,6 +32,7 @@ typedef enum {
   POP3_USER,
   POP3_PASS,
   POP3_STARTTLS,
+  POP3_LIST,
   POP3_RETR,
   POP3_QUIT,
   POP3_LAST  /* never used */