static CURLcode imap_fetch(struct connectdata *conn) { CURLcode result = CURLE_OK; const char *str; str = getcmdid(conn); /* TODO: make this select the correct mail * Use "1 body[text]" to get the full mail body of mail 1 */ result = imapsendf(conn, str, "%s FETCH 1 BODY[TEXT]", str); if(result) return result; /* * When issued, the server will respond with a single line similar to * '* 1 FETCH (BODY[TEXT] {2021}' * * Identifying the fetch and how many bytes of contents we can expect. We * must extract that number before continuing to "download as usual". */ state(conn, IMAP_FETCH); return result; }
/* For the initial server greeting */ static CURLcode imap_state_servergreet_resp(struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; (void)instate; /* no use for this yet */ if(imapcode != 'O') { failf(data, "Got unexpected imap-server response"); return CURLE_FTP_WEIRD_SERVER_REPLY; } if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { /* We don't have a SSL/TLS connection yet, but SSL is requested. Switch to TLS connection now */ const char *str = getcmdid(conn); result = imap_sendf(conn, str, "%s STARTTLS", str); state(conn, IMAP_STARTTLS); } else result = imap_state_login(conn); return result; }
static CURLcode imap_state_capability(struct connectdata *conn) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; const char *str; imapc->authmechs = 0; /* No known authentication mechanisms yet */ imapc->authused = 0; /* Clear the authentication mechanism used */ /* Check we have a username and password to authenticate with and end the connect phase if we don't */ if(!conn->bits.user_passwd) { state(conn, IMAP_STOP); return result; } str = getcmdid(conn); /* Send the CAPABILITY command */ result = imap_sendf(conn, str, "%s CAPABILITY", str); if(result) return result; state(conn, IMAP_CAPABILITY); return CURLE_OK; }
static CURLcode imap_authenticate(struct connectdata *conn) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; const char *mech = NULL; imapstate authstate = IMAP_STOP; /* Check supported authentication mechanisms by decreasing order of security */ #ifndef CURL_DISABLE_CRYPTO_AUTH if(imapc->authmechs & SASL_MECH_DIGEST_MD5) { mech = "DIGEST-MD5"; authstate = IMAP_AUTHENTICATE_DIGESTMD5; imapc->authused = SASL_MECH_DIGEST_MD5; } else if(imapc->authmechs & SASL_MECH_CRAM_MD5) { mech = "CRAM-MD5"; authstate = IMAP_AUTHENTICATE_CRAMMD5; imapc->authused = SASL_MECH_CRAM_MD5; } else #endif #ifdef USE_NTLM if(imapc->authmechs & SASL_MECH_NTLM) { mech = "NTLM"; authstate = IMAP_AUTHENTICATE_NTLM; imapc->authused = SASL_MECH_NTLM; } else #endif if(imapc->authmechs & SASL_MECH_LOGIN) { mech = "LOGIN"; authstate = IMAP_AUTHENTICATE_LOGIN; imapc->authused = SASL_MECH_LOGIN; } else if(imapc->authmechs & SASL_MECH_PLAIN) { mech = "PLAIN"; authstate = IMAP_AUTHENTICATE_PLAIN; imapc->authused = SASL_MECH_PLAIN; } else { infof(conn->data, "No known authentication mechanisms supported!\n"); result = CURLE_LOGIN_DENIED; /* Other mechanisms not supported */ } if(!result) { const char *str = getcmdid(conn); result = imap_sendf(conn, str, "%s AUTHENTICATE %s", str, mech); if(!result) state(conn, authstate); } return result; }
/*********************************************************************** * * imap_logout() * * This should be called before calling sclose(). We should then wait for the * response from the server before returning. The calling code should then try * to close the connection. * */ static CURLcode imap_logout(struct connectdata *conn) { CURLcode result = CURLE_OK; const char *str = getcmdid(conn); result = imap_sendf(conn, str, "%s LOGOUT", str, NULL); if(result) return result; state(conn, IMAP_LOGOUT); result = imap_easy_statemach(conn); return result; }
/* Start the DO phase */ static CURLcode imap_select(struct connectdata *conn) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; const char *str = getcmdid(conn); result = imap_sendf(conn, str, "%s SELECT %s", str, imapc->mailbox?imapc->mailbox:""); if(result) return result; state(conn, IMAP_SELECT); return result; }
static CURLcode imap_state_login(struct connectdata *conn) { CURLcode result; struct FTP *imap = conn->data->state.proto.imap; const char *str; str = getcmdid(conn); /* send USER and password */ result = imapsendf(conn, str, "%s LOGIN %s %s", str, imap->user?imap->user:"", imap->passwd?imap->passwd:""); if(result) return result; state(conn, IMAP_LOGIN); return CURLE_OK; }
static CURLcode imap_state_login(struct connectdata *conn) { CURLcode result; struct FTP *imap = conn->data->state.proto.imap; const char *str = getcmdid(conn); char *user = imap_atom(imap->user); char *passwd = imap_atom(imap->passwd); /* send USER and password */ result = imap_sendf(conn, str, "%s LOGIN %s %s", str, user ? user : "", passwd ? passwd : ""); Curl_safefree(user); Curl_safefree(passwd); if(result) return result; state(conn, IMAP_LOGIN); return CURLE_OK; }
static CURLcode imap_statemach_act(struct connectdata *conn) { CURLcode result; curl_socket_t sock = conn->sock[FIRSTSOCKET]; struct SessionHandle *data=conn->data; int imapcode; struct imap_conn *imapc = &conn->proto.imapc; struct pingpong *pp = &imapc->pp; size_t nread = 0; if(pp->sendleft) return Curl_pp_flushsend(pp); /* we read a piece of response */ result = Curl_pp_readresp(sock, pp, &imapcode, &nread); if(result) return result; if(imapcode) /* we have now received a full IMAP server response */ switch(imapc->state) { case IMAP_SERVERGREET: if(imapcode != 'O') { failf(data, "Got unexpected imap-server response"); return CURLE_FTP_WEIRD_SERVER_REPLY; } if(data->set.ftp_ssl && !conn->ssl[FIRSTSOCKET].use) { /* We don't have a SSL/TLS connection yet, but SSL is requested. Switch to TLS connection now */ const char *str; str = getcmdid(conn); result = imapsendf(conn, str, "%s STARTTLS", str); state(conn, IMAP_STARTTLS); } else result = imap_state_login(conn); if(result) return result; break; case IMAP_LOGIN: result = imap_state_login_resp(conn, imapcode, imapc->state); break; case IMAP_STARTTLS: result = imap_state_starttls_resp(conn, imapcode, imapc->state); break; case IMAP_FETCH: result = imap_state_fetch_resp(conn, imapcode, imapc->state); break; case IMAP_SELECT: result = imap_state_select_resp(conn, imapcode, imapc->state); break; case IMAP_LOGOUT: /* fallthrough, just stop! */ default: /* internal error */ state(conn, IMAP_STOP); break; } return result; }