pop3: Get message listing if no mailbox in URL

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.
This commit is contained in:
Ben Greear 2010-03-28 23:49:00 +02:00 committed by Daniel Stenberg
parent 302507d5dc
commit 69ccc9f861
2 changed files with 71 additions and 5 deletions

View 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);

View File

@ -32,6 +32,7 @@ typedef enum {
POP3_USER,
POP3_PASS,
POP3_STARTTLS,
POP3_LIST,
POP3_RETR,
POP3_QUIT,
POP3_LAST /* never used */