return result;
}
+/* Detect IMAP listings vs. downloading a single email */
+static bool is_custom_fetch_listing_match(const char *params)
+{
+ /* match " 1:* (FLAGS ..." or " 1,2,3 (FLAGS ..." */
+ if(*params++ != ' ')
+ return FALSE;
+
+ while(ISDIGIT(*params)) {
+ params++;
+ if(*params == 0)
+ return FALSE;
+ }
+ if(*params == ':')
+ return true;
+ if(*params == ',')
+ return true;
+ return FALSE;
+}
+
+static bool is_custom_fetch_listing(struct IMAP *imap)
+{
+ /* filter out "UID FETCH 1:* (FLAGS ..." queries to list emails */
+ if(!imap->custom)
+ return FALSE;
+ else if(curl_strequal(imap->custom, "FETCH") && imap->custom_params) {
+ const char *p = imap->custom_params;
+ return is_custom_fetch_listing_match(p);
+ }
+ else if(curl_strequal(imap->custom, "UID") && imap->custom_params) {
+ if(curl_strnequal(imap->custom_params, " FETCH ", 7)) {
+ const char *p = imap->custom_params + 6;
+ return is_custom_fetch_listing_match(p);
+ }
+ }
+ return FALSE;
+}
+
/* For LIST and SEARCH responses */
static CURLcode imap_state_listsearch_resp(struct Curl_easy *data,
struct imap_conn *imapc,
CURLcode result = CURLE_OK;
char *line = curlx_dyn_ptr(&imapc->pp.recvbuf);
size_t len = imapc->pp.nfinal;
+ struct IMAP *imap = Curl_meta_get(data, CURL_META_IMAP_EASY);
(void)instate;
- if(imapcode == '*') {
+ if(imapcode == '*' && is_custom_fetch_listing(imap)) {
+ /* custom FETCH or UID FETCH for listing is not handled here */
+ }
+ else if(imapcode == '*') {
/* Check if this response contains a literal (e.g. FETCH responses with
body data). Literal syntax is {size}\r\n */
const char *cr = memchr(line, '\r', len);
test1700 test1701 test1702 test1703 test1704 test1705 test1706 test1707 \
test1708 test1709 test1710 test1711 \
\
-test1800 test1801 test1802 \
+test1800 test1801 test1802 test1847 test1848 \
\
test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 \
test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \
--- /dev/null
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+IMAP
+Clear Text
+FETCH
+CUSTOMREQUEST
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data crlf="yes">
+From: me@somewhere
+To: fake@nowhere
+
+body
+
+--
+ yours sincerely
+</data>
+<datacheck crlf="yes">
+* FETCH FETCH (1 BODY[] {71}
+From: me@somewhere
+To: fake@nowhere
+
+body
+
+--
+ yours sincerely
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+imap
+</server>
+<name>
+IMAP FETCH message with custom request
+</name>
+<command>
+'imap://%HOSTIP:%IMAPPORT/%TESTNUMBER' --request 'UID FETCH 1 BODY[]' -u '"user:sec"ret{'
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+A001 CAPABILITY
+A002 LOGIN "\"user" "sec\"ret{"
+A003 SELECT %TESTNUMBER
+A004 UID FETCH 1 BODY[]
+A005 LOGOUT
+</protocol>
+</verify>
+</testcase>
--- /dev/null
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+IMAP
+Clear Text
+FETCH
+CUSTOMREQUEST
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data crlf="yes">
+From: me@somewhere
+To: fake@nowhere
+
+body
+
+--
+ yours sincerely
+</data>
+# listing goes to debug output, so data output is empty
+<datacheck crlf="yes">
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+imap
+</server>
+<name>
+IMAP FETCH message with custom request to get list of email.
+</name>
+<command>
+'imap://%HOSTIP:%IMAPPORT/%TESTNUMBER' --request 'UID FETCH 1:* (FLAGS INTERNALDATE RFC822.SIZE BODY.PEEK[HEADER.FIELDS (Message-Id DATE FROM SUBJECT TO SENDER REPLY-TO CC BCC)])' -u '"user:sec"ret{'
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+A001 CAPABILITY
+A002 LOGIN "\"user" "sec\"ret{"
+A003 SELECT %TESTNUMBER
+A004 UID FETCH 1:* (FLAGS INTERNALDATE RFC822.SIZE BODY.PEEK[HEADER.FIELDS (Message-Id DATE FROM SUBJECT TO SENDER REPLY-TO CC BCC)])
+A005 LOGOUT
+</protocol>
+</verify>
+</testcase>