diff --git a/lib/pop3.c b/lib/pop3.c index 65169cff5..e48c9b4f8 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -436,6 +436,24 @@ static CURLcode pop3_state_list_resp(struct connectdata *conn, return result; } +/* for LIST response with a given message */ +static CURLcode pop3_state_list_single_resp(struct connectdata *conn, + int pop3code, + pop3state instate) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + (void)instate; /* no use for this yet */ + + if(pop3code != 'O') { + failf(data, "Invalid message. %c", pop3code); + result = CURLE_REMOTE_FILE_NOT_FOUND; + } + + state(conn, POP3_STOP); + return result; +} + /* start the DO phase for RETR */ static CURLcode pop3_retr(struct connectdata *conn) { @@ -460,7 +478,10 @@ static CURLcode pop3_list(struct connectdata *conn) if(result) return result; - state(conn, POP3_LIST); + if (strlen(pop3c->mailbox)) + state(conn, POP3_LIST_SINGLE); + else + state(conn, POP3_LIST); return result; } @@ -523,6 +544,10 @@ static CURLcode pop3_statemach_act(struct connectdata *conn) result = pop3_state_list_resp(conn, pop3code, pop3c->state); break; + case POP3_LIST_SINGLE: + result = pop3_state_list_single_resp(conn, pop3code, pop3c->state); + break; + case POP3_QUIT: /* fallthrough, just stop! */ default: @@ -747,7 +772,7 @@ CURLcode pop3_perform(struct connectdata *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)) + if (strlen(pop3c->mailbox) && !conn->data->set.ftp_list_only) result = pop3_retr(conn); else result = pop3_list(conn); diff --git a/lib/pop3.h b/lib/pop3.h index 337421cac..15256738e 100644 --- a/lib/pop3.h +++ b/lib/pop3.h @@ -33,6 +33,7 @@ typedef enum { POP3_PASS, POP3_STARTTLS, POP3_LIST, + POP3_LIST_SINGLE, POP3_RETR, POP3_QUIT, POP3_LAST /* never used */ diff --git a/tests/data/DISABLED b/tests/data/DISABLED index b6071cbd9..9ac123b18 100644 --- a/tests/data/DISABLED +++ b/tests/data/DISABLED @@ -3,3 +3,4 @@ # per line. # Lines starting with '#' letters are treated as comments. 564 +811 diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index c3c68cae3..502abecc5 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -70,7 +70,8 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \ test313 test1115 test578 test579 test1116 test1200 test1201 test1202 \ test1203 test1117 test1118 test1119 test1120 test1300 test1301 test1302 \ test1303 test320 test321 test322 test323 test324 test1121 test581 test580 \ - test1304 test1305 test1306 test1307 test582 test583 + test1304 test1305 test1306 test1307 test582 test583 test808 test809 \ + test810 test811 filecheck: @mkdir test-place; \ diff --git a/tests/data/test808 b/tests/data/test808 new file mode 100644 index 000000000..756801c6b --- /dev/null +++ b/tests/data/test808 @@ -0,0 +1,41 @@ + + + +POP3 +LIST + + + +# +# Server-side + + +REPLY LIST +OK 808 100 + + + +# +# Client-side + + +pop3 + + +POP3 LIST one message + + +pop3://%HOSTIP:%POP3PORT/808 -l -u user:secret + + + +# +# Verify data after the test has been "shot" + + +USER user +PASS secret +LIST 808 +QUIT + + + diff --git a/tests/data/test809 b/tests/data/test809 new file mode 100644 index 000000000..29358e00c --- /dev/null +++ b/tests/data/test809 @@ -0,0 +1,45 @@ + + + +POP3 +LIST +FAILURE + + + +# +# Server-side + + +REPLY LIST -ERR no such message + + + +# +# Client-side + + +pop3 + + +POP3 LIST invalid message + + +pop3://%HOSTIP:%POP3PORT/809 -l -u user:secret + + + +# +# Verify data after the test has been "shot" + + +78 + + +USER user +PASS secret +LIST 809 +QUIT + + + diff --git a/tests/data/test810 b/tests/data/test810 new file mode 100644 index 000000000..d4f75972a --- /dev/null +++ b/tests/data/test810 @@ -0,0 +1,45 @@ + + + +POP3 +LIST + + + +# +# Server-side + +# When doing LIST, we get the default list output hard-coded in the test +# POP3 server + +1 100 +2 4294967400 +4 200 + + + +# +# Client-side + + +pop3 + + +POP3 LIST messages + + +pop3://%HOSTIP:%POP3PORT/ -u user:secret + + + +# +# Verify data after the test has been "shot" + + +USER user +PASS secret +LIST +QUIT + + + diff --git a/tests/data/test811 b/tests/data/test811 new file mode 100644 index 000000000..850e5e27d --- /dev/null +++ b/tests/data/test811 @@ -0,0 +1,43 @@ + + + +POP3 +LIST + + + +# +# Server-side + + +REPLY LIST +OK but no messages\r\n. + + + + + +# +# Client-side + + +pop3 + + +POP3 LIST no messages available + + +pop3://%HOSTIP:%POP3PORT/ -u user:secret + + + +# +# Verify data after the test has been "shot" + + +USER user +PASS secret +LIST +QUIT + + + diff --git a/tests/ftpserver.pl b/tests/ftpserver.pl index bbbf7be29..182511f13 100755 --- a/tests/ftpserver.pl +++ b/tests/ftpserver.pl @@ -392,6 +392,7 @@ sub protocolsetup { elsif($proto eq 'pop3') { %commandfunc = ( 'RETR' => \&RETR_pop3, + 'LIST' => \&LIST_pop3, ); %displaytext = ( 'USER' => '+OK We are happy you popped in!', @@ -683,6 +684,29 @@ sub RETR_pop3 { return 0; } +sub LIST_pop3 { + +# this is a built-in fake-message list +my @pop3list=( +"1 100\r\n", +"2 4294967400\r\n", # > 4 GB +"4 200\r\n", # Note that message 3 is a simulated "deleted" message +); + + logmsg "retrieve a message list\n"; + + sendcontrol "+OK Listing starts\r\n"; + + for my $d (@pop3list) { + sendcontrol $d; + } + + # end with the magic 5-byte end of listing marker + sendcontrol "\r\n.\r\n"; + + return 0; +} + ################ ################ FTP commands ################