forked from pEp.foundation/libetpan
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2608 lines
67 KiB
2608 lines
67 KiB
/*
|
|
* libEtPan! -- a mail stuff library
|
|
*
|
|
* Copyright (C) 2001, 2005 - DINH Viet Hoa
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the libEtPan! project nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
/*
|
|
* $Id: mailimap.c,v 1.51 2011/07/10 23:10:12 hoa Exp $
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include "mailimap.h"
|
|
#include "mailimap_parser.h"
|
|
#include "mailimap_sender.h"
|
|
#include "mailimap_extension.h"
|
|
#include "mail.h"
|
|
#include "condstore.h"
|
|
#include "condstore_private.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifdef USE_SASL
|
|
#include <sasl/sasl.h>
|
|
#include <sasl/saslutil.h>
|
|
#endif
|
|
|
|
#include "mailsasl.h"
|
|
|
|
#ifdef DEBUG
|
|
#include "mailimap_print.h"
|
|
#endif
|
|
|
|
/*
|
|
RFC 2060 : IMAP4rev1
|
|
draft-crispin-imapv-15
|
|
RFC 2222 : Simple Authentication and Security Layer
|
|
|
|
2061 IMAP4 Compatibility with IMAP2bis. M. Crispin. December 1996.
|
|
(Format: TXT=5867 bytes) (Obsoletes RFC1730) (Status: INFORMATIONAL)
|
|
|
|
2062 Internet Message Access Protocol - Obsolete Syntax. M. Crispin.
|
|
December 1996. (Format: TXT=14222 bytes) (Status: INFORMATIONAL)
|
|
|
|
2086 IMAP4 ACL extension. J. Myers. January 1997. (Format: TXT=13925
|
|
bytes) (Status: PROPOSED STANDARD)
|
|
|
|
2087 IMAP4 QUOTA extension. J. Myers. January 1997. (Format: TXT=8542
|
|
bytes) (Status: PROPOSED STANDARD)
|
|
|
|
2088 IMAP4 non-synchronizing literals. J. Myers. January 1997.
|
|
(Format: TXT=4052 bytes) (Status: PROPOSED STANDARD)
|
|
|
|
2177 IMAP4 IDLE command. B. Leiba. June 1997. (Format: TXT=6770 bytes)
|
|
(Status: PROPOSED STANDARD)
|
|
|
|
2180 IMAP4 Multi-Accessed Mailbox Practice. M. Gahrns. July 1997.
|
|
(Format: TXT=24750 bytes) (Status: INFORMATIONAL)
|
|
|
|
2192 IMAP URL Scheme. C. Newman. September 1997. (Format: TXT=31426
|
|
bytes) (Status: PROPOSED STANDARD)
|
|
|
|
2193 IMAP4 Mailbox Referrals. M. Gahrns. September 1997. (Format:
|
|
TXT=16248 bytes) (Status: PROPOSED STANDARD)
|
|
|
|
2195 IMAP/POP AUTHorize Extension for Simple Challenge/Response. J.
|
|
Klensin, R. Catoe, P. Krumviede. September 1997. (Format: TXT=10468
|
|
bytes) (Obsoletes RFC2095) (Status: PROPOSED STANDARD)
|
|
|
|
2221 IMAP4 Login Referrals. M. Gahrns. October 1997. (Format: TXT=9251
|
|
bytes) (Status: PROPOSED STANDARD)
|
|
|
|
2342 IMAP4 Namespace. M. Gahrns, C. Newman. May 1998. (Format:
|
|
TXT=19489 bytes) (Status: PROPOSED STANDARD)
|
|
|
|
2359 IMAP4 UIDPLUS extension. J. Myers. June 1998. (Format: TXT=10862
|
|
bytes) (Status: PROPOSED STANDARD)
|
|
|
|
2595 Using TLS with IMAP, POP3 and ACAP. C. Newman. June 1999.
|
|
(Format: TXT=32440 bytes) (Status: PROPOSED STANDARD)
|
|
|
|
2683 IMAP4 Implementation Recommendations. B. Leiba. September 1999.
|
|
(Format: TXT=56300 bytes) (Status: INFORMATIONAL)
|
|
|
|
2971 IMAP4 ID extension. T. Showalter. October 2000. (Format:
|
|
TXT=14670 bytes) (Status: PROPOSED STANDARD)
|
|
|
|
http://www.ietf.org/ids.by.wg/imapext.html
|
|
*/
|
|
|
|
static inline void imap_logger(mailstream * s, int log_type,
|
|
const char * str, size_t size, void * context);
|
|
|
|
static int parse_greeting(mailimap * session,
|
|
struct mailimap_greeting ** result);
|
|
|
|
|
|
/* struct mailimap_response_info * */
|
|
|
|
static void resp_text_store(mailimap * session,
|
|
struct mailimap_resp_text *
|
|
resp_text)
|
|
{
|
|
struct mailimap_resp_text_code * resp_text_code;
|
|
|
|
resp_text_code = resp_text->rsp_code;
|
|
|
|
if (resp_text_code != NULL) {
|
|
switch (resp_text_code->rc_type) {
|
|
case MAILIMAP_RESP_TEXT_CODE_ALERT:
|
|
if (session->imap_response_info) {
|
|
if (session->imap_response_info->rsp_alert != NULL)
|
|
free(session->imap_response_info->rsp_alert);
|
|
session->imap_response_info->rsp_alert = strdup(resp_text->rsp_text);
|
|
}
|
|
break;
|
|
|
|
case MAILIMAP_RESP_TEXT_CODE_BADCHARSET:
|
|
if (session->imap_response_info) {
|
|
if (session->imap_response_info->rsp_badcharset != NULL) {
|
|
clist_foreach(resp_text_code->rc_data.rc_badcharset,
|
|
(clist_func) mailimap_astring_free, NULL);
|
|
clist_free(resp_text_code->rc_data.rc_badcharset);
|
|
}
|
|
session->imap_response_info->rsp_badcharset =
|
|
resp_text_code->rc_data.rc_badcharset;
|
|
resp_text_code->rc_data.rc_badcharset = NULL;
|
|
}
|
|
break;
|
|
|
|
case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA:
|
|
if (session->imap_connection_info) {
|
|
if (session->imap_connection_info->imap_capability != NULL)
|
|
mailimap_capability_data_free(session->imap_connection_info->imap_capability);
|
|
session->imap_connection_info->imap_capability =
|
|
resp_text_code->rc_data.rc_cap_data;
|
|
/* detach before free */
|
|
resp_text_code->rc_data.rc_cap_data = NULL;
|
|
}
|
|
break;
|
|
|
|
case MAILIMAP_RESP_TEXT_CODE_PARSE:
|
|
if (session->imap_response_info) {
|
|
if (session->imap_response_info->rsp_parse != NULL)
|
|
free(session->imap_response_info->rsp_parse);
|
|
session->imap_response_info->rsp_parse = strdup(resp_text->rsp_text);
|
|
}
|
|
break;
|
|
|
|
case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS:
|
|
if (session->imap_selection_info) {
|
|
if (session->imap_selection_info->sel_perm_flags != NULL) {
|
|
clist_foreach(session->imap_selection_info->sel_perm_flags,
|
|
(clist_func) mailimap_flag_perm_free, NULL);
|
|
clist_free(session->imap_selection_info->sel_perm_flags);
|
|
}
|
|
session->imap_selection_info->sel_perm_flags =
|
|
resp_text_code->rc_data.rc_perm_flags;
|
|
/* detach before free */
|
|
resp_text_code->rc_data.rc_perm_flags = NULL;
|
|
}
|
|
break;
|
|
|
|
case MAILIMAP_RESP_TEXT_CODE_READ_ONLY:
|
|
if (session->imap_selection_info)
|
|
session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READONLY;
|
|
break;
|
|
|
|
case MAILIMAP_RESP_TEXT_CODE_READ_WRITE:
|
|
if (session->imap_selection_info)
|
|
session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READWRITE;
|
|
break;
|
|
|
|
case MAILIMAP_RESP_TEXT_CODE_TRY_CREATE:
|
|
if (session->imap_response_info)
|
|
session->imap_response_info->rsp_trycreate = TRUE;
|
|
break;
|
|
|
|
case MAILIMAP_RESP_TEXT_CODE_UIDNEXT:
|
|
if (session->imap_selection_info)
|
|
session->imap_selection_info->sel_uidnext =
|
|
resp_text_code->rc_data.rc_uidnext;
|
|
break;
|
|
|
|
case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY:
|
|
if (session->imap_selection_info)
|
|
session->imap_selection_info->sel_uidvalidity =
|
|
resp_text_code->rc_data.rc_uidvalidity;
|
|
break;
|
|
|
|
case MAILIMAP_RESP_TEXT_CODE_UNSEEN:
|
|
if (session->imap_selection_info)
|
|
session->imap_selection_info->sel_first_unseen =
|
|
resp_text_code->rc_data.rc_first_unseen;
|
|
break;
|
|
|
|
case MAILIMAP_RESP_TEXT_CODE_OTHER:
|
|
if (session->imap_response_info) {
|
|
if (session->imap_response_info->rsp_atom != NULL)
|
|
free(session->imap_response_info->rsp_atom);
|
|
if (session->imap_response_info->rsp_value != NULL)
|
|
free(session->imap_response_info->rsp_value);
|
|
session->imap_response_info->rsp_atom =
|
|
resp_text_code->rc_data.rc_atom.atom_name;
|
|
resp_text_code->rc_data.rc_atom.atom_name = NULL;
|
|
session->imap_response_info->rsp_value =
|
|
resp_text_code->rc_data.rc_atom.atom_value;
|
|
resp_text_code->rc_data.rc_atom.atom_value = NULL;
|
|
}
|
|
break;
|
|
case MAILIMAP_RESP_TEXT_CODE_EXTENSION:
|
|
mailimap_extension_data_store(session, &(resp_text_code->rc_data.rc_ext_data));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void resp_cond_state_store(mailimap * session,
|
|
struct mailimap_resp_cond_state * resp_cond_state)
|
|
{
|
|
resp_text_store(session, resp_cond_state->rsp_text);
|
|
}
|
|
|
|
static void mailbox_data_store(mailimap * session,
|
|
struct mailimap_mailbox_data * mb_data)
|
|
{
|
|
int r;
|
|
|
|
switch (mb_data->mbd_type) {
|
|
case MAILIMAP_MAILBOX_DATA_FLAGS:
|
|
if (session->imap_selection_info) {
|
|
if (session->imap_selection_info->sel_flags != NULL)
|
|
mailimap_flag_list_free(session->imap_selection_info->sel_flags);
|
|
session->imap_selection_info->sel_flags = mb_data->mbd_data.mbd_flags;
|
|
mb_data->mbd_data.mbd_flags = NULL;
|
|
}
|
|
break;
|
|
|
|
case MAILIMAP_MAILBOX_DATA_LIST:
|
|
if (session->imap_response_info) {
|
|
r = clist_append(session->imap_response_info->rsp_mailbox_list,
|
|
mb_data->mbd_data.mbd_list);
|
|
if (r == 0)
|
|
mb_data->mbd_data.mbd_list = NULL;
|
|
else {
|
|
/* TODO must handle error case */
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MAILIMAP_MAILBOX_DATA_LSUB:
|
|
if (session->imap_response_info) {
|
|
r = clist_append(session->imap_response_info->rsp_mailbox_lsub,
|
|
mb_data->mbd_data.mbd_lsub);
|
|
if (r == 0)
|
|
mb_data->mbd_data.mbd_lsub = NULL;
|
|
else {
|
|
/* TODO must handle error case */
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MAILIMAP_MAILBOX_DATA_SEARCH:
|
|
if (session->imap_response_info) {
|
|
if (session->imap_response_info->rsp_search_result != NULL) {
|
|
if (mb_data->mbd_data.mbd_search != NULL) {
|
|
clist_concat(session->imap_response_info->rsp_search_result,
|
|
mb_data->mbd_data.mbd_search);
|
|
clist_free(mb_data->mbd_data.mbd_search);
|
|
mb_data->mbd_data.mbd_search = NULL;
|
|
}
|
|
}
|
|
else {
|
|
if (mb_data->mbd_data.mbd_search != NULL) {
|
|
session->imap_response_info->rsp_search_result =
|
|
mb_data->mbd_data.mbd_search;
|
|
mb_data->mbd_data.mbd_search = NULL;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MAILIMAP_MAILBOX_DATA_STATUS:
|
|
if (session->imap_response_info) {
|
|
if (session->imap_response_info->rsp_status != NULL)
|
|
mailimap_mailbox_data_status_free(session->imap_response_info->rsp_status);
|
|
session->imap_response_info->rsp_status = mb_data->mbd_data.mbd_status;
|
|
#if 0
|
|
if (session->imap_selection_info != NULL) {
|
|
clistiter * cur;
|
|
|
|
for(cur = clist_begin(mb_data->status->status_info_list)
|
|
; cur != NULL ; cur = clist_next(cur)) {
|
|
struct mailimap_status_info * info;
|
|
|
|
info = clist_content(cur);
|
|
switch (info->att) {
|
|
case MAILIMAP_STATUS_ATT_MESSAGES:
|
|
session->imap_selection_info->exists = info->value;
|
|
break;
|
|
case MAILIMAP_STATUS_ATT_RECENT:
|
|
session->imap_selection_info->recent = info->value;
|
|
break;
|
|
case MAILIMAP_STATUS_ATT_UIDNEXT:
|
|
session->imap_selection_info->uidnext = info->value;
|
|
break;
|
|
case MAILIMAP_STATUS_ATT_UIDVALIDITY:
|
|
session->imap_selection_info->uidvalidity = info->value;
|
|
break;
|
|
case MAILIMAP_STATUS_ATT_UNSEEN:
|
|
session->imap_selection_info->unseen = info->value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#if 0
|
|
mailimap_mailbox_data_status_free(mb_data->status);
|
|
#endif
|
|
mb_data->mbd_data.mbd_status = NULL;
|
|
}
|
|
break;
|
|
|
|
case MAILIMAP_MAILBOX_DATA_EXISTS:
|
|
if (session->imap_selection_info) {
|
|
session->imap_selection_info->sel_exists = mb_data->mbd_data.mbd_exists;
|
|
session->imap_selection_info->sel_has_exists = 1;
|
|
}
|
|
break;
|
|
|
|
case MAILIMAP_MAILBOX_DATA_RECENT:
|
|
if (session->imap_selection_info) {
|
|
session->imap_selection_info->sel_recent = mb_data->mbd_data.mbd_recent;
|
|
session->imap_selection_info->sel_has_recent = 1;
|
|
}
|
|
break;
|
|
case MAILIMAP_MAILBOX_DATA_EXTENSION_DATA:
|
|
mailimap_extension_data_store(session, &mb_data->mbd_data.mbd_extension);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
message_data_store(mailimap * session,
|
|
struct mailimap_message_data * msg_data)
|
|
{
|
|
uint32_t * expunged;
|
|
int r;
|
|
|
|
switch (msg_data->mdt_type) {
|
|
case MAILIMAP_MESSAGE_DATA_EXPUNGE:
|
|
if (session->imap_response_info) {
|
|
expunged = mailimap_number_alloc_new(msg_data->mdt_number);
|
|
if (expunged != NULL) {
|
|
r = clist_append(session->imap_response_info->rsp_expunged, expunged);
|
|
if (r == 0) {
|
|
/* do nothing */
|
|
}
|
|
else {
|
|
/* TODO : must handle error case */
|
|
mailimap_number_alloc_free(expunged);
|
|
}
|
|
if (session->imap_selection_info != NULL)
|
|
session->imap_selection_info->sel_exists --;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MAILIMAP_MESSAGE_DATA_FETCH:
|
|
r = clist_append(session->imap_response_info->rsp_fetch_list,
|
|
msg_data->mdt_msg_att);
|
|
if (r == 0) {
|
|
msg_data->mdt_msg_att->att_number = msg_data->mdt_number;
|
|
msg_data->mdt_msg_att = NULL;
|
|
}
|
|
else {
|
|
/* TODO : must handle error case */
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
cont_req_or_resp_data_store(mailimap * session,
|
|
struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data)
|
|
{
|
|
if (cont_req_or_resp_data->rsp_type == MAILIMAP_RESP_RESP_DATA) {
|
|
struct mailimap_response_data * resp_data;
|
|
|
|
resp_data = cont_req_or_resp_data->rsp_data.rsp_resp_data;
|
|
|
|
switch (resp_data->rsp_type) {
|
|
case MAILIMAP_RESP_DATA_TYPE_COND_STATE:
|
|
resp_cond_state_store(session, resp_data->rsp_data.rsp_cond_state);
|
|
break;
|
|
case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA:
|
|
mailbox_data_store(session, resp_data->rsp_data.rsp_mailbox_data);
|
|
break;
|
|
case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA:
|
|
message_data_store(session, resp_data->rsp_data.rsp_message_data);
|
|
break;
|
|
case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA:
|
|
if (session->imap_connection_info) {
|
|
if (session->imap_connection_info->imap_capability != NULL)
|
|
mailimap_capability_data_free(session->imap_connection_info->imap_capability);
|
|
session->imap_connection_info->imap_capability = resp_data->rsp_data.rsp_capability_data;
|
|
resp_data->rsp_data.rsp_capability_data = NULL;
|
|
}
|
|
break;
|
|
case MAILIMAP_RESP_DATA_TYPE_EXTENSION_DATA:
|
|
mailimap_extension_data_store(session, &(resp_data->rsp_data.rsp_extension_data));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void response_tagged_store(mailimap * session,
|
|
struct mailimap_response_tagged * tagged)
|
|
{
|
|
resp_cond_state_store(session, tagged->rsp_cond_state);
|
|
}
|
|
|
|
static void resp_cond_bye_store(mailimap * session,
|
|
struct mailimap_resp_cond_bye * resp_cond_bye)
|
|
{
|
|
resp_text_store(session, resp_cond_bye->rsp_text);
|
|
}
|
|
|
|
static void response_fatal_store(mailimap * session,
|
|
struct mailimap_response_fatal * fatal)
|
|
{
|
|
resp_cond_bye_store(session, fatal->rsp_bye);
|
|
}
|
|
|
|
static void response_done_store(mailimap * session,
|
|
struct mailimap_response_done * resp_done)
|
|
{
|
|
switch(resp_done->rsp_type) {
|
|
case MAILIMAP_RESP_DONE_TYPE_TAGGED:
|
|
response_tagged_store(session, resp_done->rsp_data.rsp_tagged);
|
|
break;
|
|
case MAILIMAP_RESP_DONE_TYPE_FATAL:
|
|
response_fatal_store(session, resp_done->rsp_data.rsp_fatal);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
response_store(mailimap * session,
|
|
struct mailimap_response * response)
|
|
{
|
|
clistiter * cur;
|
|
|
|
if (session->imap_response_info) {
|
|
mailimap_response_info_free(session->imap_response_info);
|
|
session->imap_response_info = NULL;
|
|
}
|
|
|
|
session->imap_response_info = mailimap_response_info_new();
|
|
if (session->imap_response_info == NULL) {
|
|
/* ignored error */
|
|
return;
|
|
}
|
|
|
|
if (response->rsp_cont_req_or_resp_data_list != NULL) {
|
|
for(cur = clist_begin(response->rsp_cont_req_or_resp_data_list) ;
|
|
cur != NULL ; cur = clist_next(cur)) {
|
|
struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data;
|
|
|
|
cont_req_or_resp_data = clist_content(cur);
|
|
|
|
cont_req_or_resp_data_store(session, cont_req_or_resp_data);
|
|
}
|
|
}
|
|
|
|
response_done_store(session, response->rsp_resp_done);
|
|
}
|
|
|
|
static void resp_cond_auth_store(mailimap * session,
|
|
struct mailimap_resp_cond_auth * cond_auth)
|
|
{
|
|
resp_text_store(session, cond_auth->rsp_text);
|
|
}
|
|
|
|
static void greeting_store(mailimap * session,
|
|
struct mailimap_greeting * greeting)
|
|
{
|
|
switch (greeting->gr_type) {
|
|
case MAILIMAP_GREETING_RESP_COND_AUTH:
|
|
resp_cond_auth_store(session, greeting->gr_data.gr_auth);
|
|
break;
|
|
|
|
case MAILIMAP_GREETING_RESP_COND_BYE:
|
|
resp_cond_bye_store(session, greeting->gr_data.gr_bye);
|
|
break;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_connect(mailimap * session, mailstream * s)
|
|
{
|
|
struct mailimap_greeting * greeting;
|
|
int r;
|
|
int auth_type;
|
|
struct mailimap_connection_info * connection_info;
|
|
|
|
if (session->imap_state != MAILIMAP_STATE_DISCONNECTED)
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
session->imap_stream = s;
|
|
mailstream_set_logger(s, imap_logger, session);
|
|
|
|
if (session->imap_connection_info)
|
|
mailimap_connection_info_free(session->imap_connection_info);
|
|
connection_info = mailimap_connection_info_new();
|
|
if (connection_info != NULL)
|
|
session->imap_connection_info = connection_info;
|
|
|
|
if (mailimap_read_line(session) == NULL) {
|
|
return MAILIMAP_ERROR_STREAM;
|
|
}
|
|
|
|
r = parse_greeting(session, &greeting);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
return r;
|
|
}
|
|
|
|
auth_type = greeting->gr_data.gr_auth->rsp_type;
|
|
|
|
mailimap_greeting_free(greeting);
|
|
|
|
switch (auth_type) {
|
|
case MAILIMAP_RESP_COND_AUTH_PREAUTH:
|
|
session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
|
|
return MAILIMAP_NO_ERROR_AUTHENTICATED;
|
|
default:
|
|
session->imap_state = MAILIMAP_STATE_NON_AUTHENTICATED;
|
|
return MAILIMAP_NO_ERROR_NON_AUTHENTICATED;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ********************************************************************** */
|
|
|
|
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_append(mailimap * session, const char * mailbox,
|
|
struct mailimap_flag_list * flag_list,
|
|
struct mailimap_date_time * date_time,
|
|
const char * literal, size_t literal_size)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
struct mailimap_continue_req * cont_req;
|
|
size_t indx;
|
|
size_t fixed_literal_size;
|
|
|
|
if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
|
|
(session->imap_state != MAILIMAP_STATE_SELECTED))
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
fixed_literal_size = mailstream_get_data_crlf_size(literal, literal_size);
|
|
|
|
r = mailimap_append_send(session->imap_stream, mailbox, flag_list, date_time,
|
|
fixed_literal_size);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
indx = 0;
|
|
|
|
r = mailimap_continue_req_parse(session->imap_stream,
|
|
session->imap_stream_buffer,
|
|
&indx, &cont_req,
|
|
session->imap_progr_rate, session->imap_progr_fun);
|
|
if (r == MAILIMAP_NO_ERROR)
|
|
mailimap_continue_req_free(cont_req);
|
|
|
|
if (r == MAILIMAP_ERROR_PARSE) {
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
mailimap_response_free(response);
|
|
|
|
return MAILIMAP_ERROR_APPEND;
|
|
}
|
|
|
|
if (session->imap_body_progress_fun != NULL) {
|
|
r = mailimap_literal_data_send_with_context(session->imap_stream, literal, literal_size,
|
|
session->imap_body_progress_fun,
|
|
session->imap_progress_context);
|
|
}
|
|
else {
|
|
r = mailimap_literal_data_send(session->imap_stream, literal, literal_size,
|
|
session->imap_progr_rate, session->imap_progr_fun);
|
|
}
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_APPEND;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_noop(mailimap * session)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_noop_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_NOOP;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_logout(mailimap * session)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
int res;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
res = r;
|
|
goto close;
|
|
}
|
|
|
|
r = mailimap_logout_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
res = r;
|
|
goto close;
|
|
}
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
res = r;
|
|
goto close;
|
|
}
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1) {
|
|
res = MAILIMAP_ERROR_STREAM;
|
|
goto close;
|
|
}
|
|
|
|
if (mailimap_read_line(session) == NULL) {
|
|
res = MAILIMAP_ERROR_STREAM;
|
|
goto close;
|
|
}
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
res = r;
|
|
goto close;
|
|
}
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
if (session->imap_connection_info) {
|
|
mailimap_connection_info_free(session->imap_connection_info);
|
|
session->imap_connection_info = NULL;
|
|
}
|
|
res = MAILIMAP_NO_ERROR;
|
|
goto close;
|
|
|
|
default:
|
|
res = MAILIMAP_ERROR_LOGOUT;
|
|
goto close;
|
|
}
|
|
|
|
close:
|
|
mailstream_close(session->imap_stream);
|
|
session->imap_stream = NULL;
|
|
session->imap_state = MAILIMAP_STATE_DISCONNECTED;
|
|
return res;
|
|
}
|
|
|
|
/* send the results back to the caller */
|
|
/* duplicate the result */
|
|
|
|
static struct mailimap_capability *
|
|
mailimap_capability_dup(struct mailimap_capability * orig_cap)
|
|
{
|
|
struct mailimap_capability * cap;
|
|
char * auth_type;
|
|
char * name;
|
|
|
|
name = NULL;
|
|
auth_type = NULL;
|
|
switch (orig_cap->cap_type) {
|
|
case MAILIMAP_CAPABILITY_NAME:
|
|
name = strdup(orig_cap->cap_data.cap_name);
|
|
if (name == NULL)
|
|
goto err;
|
|
break;
|
|
case MAILIMAP_CAPABILITY_AUTH_TYPE:
|
|
auth_type = strdup(orig_cap->cap_data.cap_auth_type);
|
|
if (auth_type == NULL)
|
|
goto err;
|
|
break;
|
|
}
|
|
|
|
cap = mailimap_capability_new(orig_cap->cap_type, auth_type, name);
|
|
if (cap == NULL)
|
|
goto free;
|
|
|
|
return cap;
|
|
|
|
free:
|
|
if (name != NULL)
|
|
free(name);
|
|
if (auth_type != NULL)
|
|
free(auth_type);
|
|
err:
|
|
return NULL;
|
|
}
|
|
|
|
static struct mailimap_capability_data *
|
|
mailimap_capability_data_dup(struct mailimap_capability_data * orig_cap_data)
|
|
{
|
|
struct mailimap_capability_data * cap_data;
|
|
struct mailimap_capability * cap_dup;
|
|
clist * list;
|
|
clistiter * cur;
|
|
int r;
|
|
|
|
list = clist_new();
|
|
if (list == NULL)
|
|
goto err;
|
|
|
|
for(cur = clist_begin(orig_cap_data->cap_list) ;
|
|
cur != NULL ; cur = clist_next(cur)) {
|
|
struct mailimap_capability * cap;
|
|
|
|
cap = clist_content(cur);
|
|
|
|
cap_dup = mailimap_capability_dup(cap);
|
|
if (cap_dup == NULL)
|
|
goto list;
|
|
|
|
r = clist_append(list, cap_dup);
|
|
if (r < 0) {
|
|
mailimap_capability_free(cap_dup);
|
|
goto list;
|
|
}
|
|
}
|
|
|
|
cap_data = mailimap_capability_data_new(list);
|
|
if (cap_data == NULL)
|
|
goto list;
|
|
|
|
return cap_data;
|
|
|
|
list:
|
|
clist_foreach(list, (clist_func) mailimap_capability_free, NULL);
|
|
clist_free(list);
|
|
err:
|
|
return NULL;
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_capability(mailimap * session,
|
|
struct mailimap_capability_data ** result)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
struct mailimap_capability_data * cap_data;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_capability_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
cap_data =
|
|
mailimap_capability_data_dup(session->imap_connection_info->imap_capability);
|
|
if (cap_data == NULL)
|
|
return MAILIMAP_ERROR_MEMORY;
|
|
|
|
* result = cap_data;
|
|
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_CAPABILITY;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_check(mailimap * session)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if (session->imap_state != MAILIMAP_STATE_SELECTED)
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_check_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_CHECK;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_close(mailimap * session)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if (session->imap_state != MAILIMAP_STATE_SELECTED)
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_close_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
/* leave selected state */
|
|
mailimap_selection_info_free(session->imap_selection_info);
|
|
session->imap_selection_info = NULL;
|
|
|
|
session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_CLOSE;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_expunge(mailimap * session)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if (session->imap_state != MAILIMAP_STATE_SELECTED)
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_expunge_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_EXPUNGE;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_copy(mailimap * session, struct mailimap_set * set,
|
|
const char * mb)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if (session->imap_state != MAILIMAP_STATE_SELECTED)
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_copy_send(session->imap_stream, set, mb);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_COPY;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_uid_copy(mailimap * session, struct mailimap_set * set,
|
|
const char * mb)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if (session->imap_state != MAILIMAP_STATE_SELECTED)
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_uid_copy_send(session->imap_stream, set, mb);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_UID_COPY;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_create(mailimap * session, const char * mb)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
|
|
(session->imap_state != MAILIMAP_STATE_SELECTED))
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_create_send(session->imap_stream, mb);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_CREATE;
|
|
}
|
|
}
|
|
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_delete(mailimap * session, const char * mb)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
|
|
(session->imap_state != MAILIMAP_STATE_SELECTED))
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_delete_send(session->imap_stream, mb);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_DELETE;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
LIBETPAN_EXPORT
|
|
int mailimap_examine(mailimap * session, const char * mb)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
|
|
(session->imap_state != MAILIMAP_STATE_SELECTED))
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_examine_send(session->imap_stream, mb);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (session->imap_selection_info != NULL)
|
|
mailimap_selection_info_free(session->imap_selection_info);
|
|
session->imap_selection_info = mailimap_selection_info_new();
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
session->imap_state = MAILIMAP_STATE_SELECTED;
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
mailimap_selection_info_free(session->imap_selection_info);
|
|
session->imap_selection_info = NULL;
|
|
session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
|
|
return MAILIMAP_ERROR_EXAMINE;
|
|
}
|
|
}
|
|
#else
|
|
LIBETPAN_EXPORT
|
|
int mailimap_examine(mailimap * session, const char * mb)
|
|
{
|
|
uint64_t dummy;
|
|
return mailimap_examine_condstore_optional(session, mb, 0, &dummy);
|
|
}
|
|
#endif
|
|
|
|
LIBETPAN_EXPORT
|
|
int
|
|
mailimap_fetch(mailimap * session, struct mailimap_set * set,
|
|
struct mailimap_fetch_type * fetch_type, clist ** result)
|
|
{
|
|
#if 0
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if (session->imap_state != MAILIMAP_STATE_SELECTED)
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_fetch_send(session->imap_stream, set, fetch_type);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
* result = session->imap_response_info->rsp_fetch_list;
|
|
session->imap_response_info->rsp_fetch_list = NULL;
|
|
|
|
if (clist_count(* result) == 0) {
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
}
|
|
else {
|
|
error_code = MAILIMAP_RESP_COND_STATE_OK;
|
|
}
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
mailimap_fetch_list_free(* result);
|
|
return MAILIMAP_ERROR_FETCH;
|
|
}
|
|
#else
|
|
return mailimap_fetch_changedsince(session, set, fetch_type, 0, result);
|
|
#endif
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
void mailimap_fetch_list_free(clist * fetch_list)
|
|
{
|
|
clist_foreach(fetch_list, (clist_func) mailimap_msg_att_free, NULL);
|
|
clist_free(fetch_list);
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int
|
|
mailimap_uid_fetch(mailimap * session,
|
|
struct mailimap_set * set,
|
|
struct mailimap_fetch_type * fetch_type, clist ** result)
|
|
{
|
|
#if 0
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if (session->imap_state != MAILIMAP_STATE_SELECTED)
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_uid_fetch_send(session->imap_stream, set, fetch_type);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
return r;
|
|
}
|
|
|
|
* result = session->imap_response_info->rsp_fetch_list;
|
|
session->imap_response_info->rsp_fetch_list = NULL;
|
|
|
|
if (clist_count(* result) == 0) {
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
}
|
|
else {
|
|
error_code = MAILIMAP_RESP_COND_STATE_OK;
|
|
}
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
mailimap_fetch_list_free(* result);
|
|
* result = NULL;
|
|
return MAILIMAP_ERROR_UID_FETCH;
|
|
}
|
|
#else
|
|
return mailimap_uid_fetch_changedsince(session, set, fetch_type, 0, result);
|
|
#endif
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_list(mailimap * session, const char * mb,
|
|
const char * list_mb, clist ** result)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
|
|
(session->imap_state != MAILIMAP_STATE_SELECTED))
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_list_send(session->imap_stream, mb, list_mb);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
* result = session->imap_response_info->rsp_mailbox_list;
|
|
session->imap_response_info->rsp_mailbox_list = NULL;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_LIST;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_login(mailimap * session,
|
|
const char * userid, const char * password)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED)
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
mailstream_set_privacy(session->imap_stream, 0);
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
mailstream_set_privacy(session->imap_stream, 1);
|
|
return r;
|
|
}
|
|
|
|
r = mailimap_login_send(session->imap_stream, userid, password);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
mailstream_set_privacy(session->imap_stream, 1);
|
|
return r;
|
|
}
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
mailstream_set_privacy(session->imap_stream, 1);
|
|
return r;
|
|
}
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1) {
|
|
mailstream_set_privacy(session->imap_stream, 1);
|
|
return MAILIMAP_ERROR_STREAM;
|
|
}
|
|
mailstream_set_privacy(session->imap_stream, 1);
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_LOGIN;
|
|
}
|
|
}
|
|
|
|
#ifdef USE_SASL
|
|
static int sasl_getsimple(void * context, int id,
|
|
const char ** result, unsigned * len)
|
|
{
|
|
mailimap * session;
|
|
|
|
session = context;
|
|
|
|
switch (id) {
|
|
case SASL_CB_USER:
|
|
if (result != NULL)
|
|
* result = session->imap_sasl.sasl_login;
|
|
if (len != NULL)
|
|
* len = (unsigned) strlen(session->imap_sasl.sasl_login);
|
|
return SASL_OK;
|
|
|
|
case SASL_CB_AUTHNAME:
|
|
if (result != NULL)
|
|
* result = session->imap_sasl.sasl_auth_name;
|
|
if (len != NULL)
|
|
* len = (unsigned) strlen(session->imap_sasl.sasl_auth_name);
|
|
return SASL_OK;
|
|
}
|
|
|
|
return SASL_FAIL;
|
|
}
|
|
|
|
static int sasl_getsecret(sasl_conn_t * conn, void * context, int id,
|
|
sasl_secret_t ** psecret)
|
|
{
|
|
mailimap * session;
|
|
|
|
session = context;
|
|
|
|
switch (id) {
|
|
case SASL_CB_PASS:
|
|
if (psecret != NULL)
|
|
* psecret = session->imap_sasl.sasl_secret;
|
|
return SASL_OK;
|
|
}
|
|
|
|
return SASL_FAIL;
|
|
}
|
|
|
|
static int sasl_getrealm(void * context, int id,
|
|
const char ** availrealms,
|
|
const char ** result)
|
|
{
|
|
mailimap * session;
|
|
|
|
session = context;
|
|
|
|
switch (id) {
|
|
case SASL_CB_GETREALM:
|
|
if (result != NULL)
|
|
* result = session->imap_sasl.sasl_realm;
|
|
return SASL_OK;
|
|
}
|
|
|
|
return SASL_FAIL;
|
|
}
|
|
#endif
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_authenticate(mailimap * session, const char * auth_type,
|
|
const char * server_fqdn,
|
|
const char * local_ip_port,
|
|
const char * remote_ip_port,
|
|
const char * login, const char * auth_name,
|
|
const char * password, const char * realm)
|
|
{
|
|
#ifdef USE_SASL
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
size_t indx;
|
|
sasl_callback_t sasl_callback[5];
|
|
const char * sasl_out;
|
|
unsigned sasl_out_len;
|
|
const char * mechusing;
|
|
sasl_secret_t * secret;
|
|
int res;
|
|
size_t len;
|
|
|
|
if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED) {
|
|
res = MAILIMAP_ERROR_BAD_STATE;
|
|
goto err;
|
|
}
|
|
|
|
sasl_callback[0].id = SASL_CB_GETREALM;
|
|
sasl_callback[0].proc = (int(*)(void)) sasl_getrealm;
|
|
sasl_callback[0].context = session;
|
|
sasl_callback[1].id = SASL_CB_USER;
|
|
sasl_callback[1].proc = (int(*)(void)) sasl_getsimple;
|
|
sasl_callback[1].context = session;
|
|
sasl_callback[2].id = SASL_CB_AUTHNAME;
|
|
sasl_callback[2].proc = (int(*)(void)) sasl_getsimple;
|
|
sasl_callback[2].context = session;
|
|
sasl_callback[3].id = SASL_CB_PASS;
|
|
sasl_callback[3].proc = (int(*)(void)) sasl_getsecret;
|
|
sasl_callback[3].context = session;
|
|
sasl_callback[4].id = SASL_CB_LIST_END;
|
|
sasl_callback[4].proc = NULL;
|
|
sasl_callback[4].context = NULL;
|
|
|
|
len = strlen(password);
|
|
secret = malloc(sizeof(* secret) + len);
|
|
if (secret == NULL) {
|
|
res = MAILIMAP_ERROR_MEMORY;
|
|
goto err;
|
|
}
|
|
secret->len = len;
|
|
memcpy(secret->data, password, len + 1);
|
|
|
|
session->imap_sasl.sasl_server_fqdn = server_fqdn;
|
|
session->imap_sasl.sasl_login = login;
|
|
session->imap_sasl.sasl_auth_name = auth_name;
|
|
session->imap_sasl.sasl_password = password;
|
|
session->imap_sasl.sasl_realm = realm;
|
|
session->imap_sasl.sasl_secret = secret;
|
|
|
|
/* init SASL */
|
|
if (session->imap_sasl.sasl_conn != NULL) {
|
|
sasl_dispose((sasl_conn_t **) &session->imap_sasl.sasl_conn);
|
|
session->imap_sasl.sasl_conn = NULL;
|
|
}
|
|
else {
|
|
mailsasl_ref();
|
|
}
|
|
|
|
r = sasl_client_new("imap", server_fqdn,
|
|
local_ip_port, remote_ip_port, sasl_callback, 0,
|
|
(sasl_conn_t **) &session->imap_sasl.sasl_conn);
|
|
if (r != SASL_OK) {
|
|
res = MAILIMAP_ERROR_LOGIN;
|
|
goto free_secret;
|
|
}
|
|
|
|
r = sasl_client_start(session->imap_sasl.sasl_conn,
|
|
auth_type, NULL, &sasl_out, &sasl_out_len, &mechusing);
|
|
if ((r != SASL_CONTINUE) && (r != SASL_OK)) {
|
|
res = MAILIMAP_ERROR_LOGIN;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
mailstream_set_privacy(session->imap_stream, 0);
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
res = r;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
r = mailimap_authenticate_send(session->imap_stream, auth_type);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
res = r;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
res = r;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1) {
|
|
res = MAILIMAP_ERROR_STREAM;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
while (1) {
|
|
struct mailimap_continue_req * cont_req;
|
|
char * response_base64;
|
|
int got_response;
|
|
char * encoded;
|
|
unsigned int encoded_len;
|
|
unsigned int max_encoded;
|
|
|
|
if (mailimap_read_line(session) == NULL) {
|
|
res = MAILIMAP_ERROR_STREAM;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
indx = 0;
|
|
|
|
r = mailimap_continue_req_parse(session->imap_stream,
|
|
session->imap_stream_buffer,
|
|
&indx, &cont_req,
|
|
session->imap_progr_rate, session->imap_progr_fun);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
break;
|
|
|
|
got_response = 1;
|
|
if (cont_req->cr_type == MAILIMAP_CONTINUE_REQ_BASE64) {
|
|
response_base64 = cont_req->cr_data.cr_base64;
|
|
if (* response_base64 == '\0')
|
|
got_response = 0;
|
|
}
|
|
else {
|
|
response_base64 = "";
|
|
got_response = 0;
|
|
}
|
|
|
|
if (got_response) {
|
|
unsigned int response_len;
|
|
char * decoded;
|
|
unsigned int decoded_len;
|
|
unsigned int max_decoded;
|
|
|
|
response_len = (unsigned int) strlen(response_base64);
|
|
max_decoded = response_len * 3 / 4;
|
|
decoded = malloc(max_decoded + 1);
|
|
if (decoded == NULL) {
|
|
mailimap_continue_req_free(cont_req);
|
|
res = MAILIMAP_ERROR_MEMORY;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
r = sasl_decode64(response_base64, response_len,
|
|
decoded, max_decoded + 1, &decoded_len);
|
|
|
|
mailimap_continue_req_free(cont_req);
|
|
|
|
if (r != SASL_OK) {
|
|
free(decoded);
|
|
res = MAILIMAP_ERROR_MEMORY;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
r = sasl_client_step(session->imap_sasl.sasl_conn,
|
|
decoded, decoded_len, NULL, &sasl_out, &sasl_out_len);
|
|
|
|
free(decoded);
|
|
|
|
if ((r != SASL_CONTINUE) && (r != SASL_OK)) {
|
|
res = MAILIMAP_ERROR_LOGIN;
|
|
goto free_sasl_conn;
|
|
}
|
|
}
|
|
else {
|
|
mailimap_continue_req_free(cont_req);
|
|
}
|
|
|
|
max_encoded = ((sasl_out_len + 2) / 3) * 4;
|
|
encoded = malloc(max_encoded + 1);
|
|
if (encoded == NULL) {
|
|
res = MAILIMAP_ERROR_MEMORY;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
r = sasl_encode64(sasl_out, sasl_out_len,
|
|
encoded, max_encoded + 1, &encoded_len);
|
|
if (r != SASL_OK) {
|
|
free(encoded);
|
|
res = MAILIMAP_ERROR_MEMORY;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
r = mailimap_token_send(session->imap_stream, encoded);
|
|
|
|
free(encoded);
|
|
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
res = r;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
res = r;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1) {
|
|
res = MAILIMAP_ERROR_STREAM;
|
|
goto free_sasl_conn;
|
|
}
|
|
}
|
|
|
|
free(session->imap_sasl.sasl_secret);
|
|
session->imap_sasl.sasl_secret = NULL;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR) {
|
|
res = r;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
|
|
res = MAILIMAP_NO_ERROR;
|
|
goto free_sasl_conn;
|
|
|
|
default:
|
|
res = MAILIMAP_ERROR_LOGIN;
|
|
goto free_sasl_conn;
|
|
}
|
|
|
|
free_sasl_conn:
|
|
mailstream_set_privacy(session->imap_stream, 1);
|
|
sasl_dispose((sasl_conn_t **) &session->imap_sasl.sasl_conn);
|
|
session->imap_sasl.sasl_conn = NULL;
|
|
mailsasl_unref();
|
|
free_secret:
|
|
free(session->imap_sasl.sasl_secret);
|
|
session->imap_sasl.sasl_secret = NULL;
|
|
err:
|
|
return res;
|
|
#else
|
|
return MAILIMAP_ERROR_LOGIN;
|
|
#endif
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_lsub(mailimap * session, const char * mb,
|
|
const char * list_mb, clist ** result)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
|
|
(session->imap_state != MAILIMAP_STATE_SELECTED))
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_lsub_send(session->imap_stream, mb, list_mb);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
* result = session->imap_response_info->rsp_mailbox_lsub;
|
|
session->imap_response_info->rsp_mailbox_lsub = NULL;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_LSUB;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
void mailimap_list_result_free(clist * list)
|
|
{
|
|
clist_foreach(list, (clist_func) mailimap_mailbox_list_free, NULL);
|
|
clist_free(list);
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_rename(mailimap * session,
|
|
const char * mb, const char * new_name)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
|
|
(session->imap_state != MAILIMAP_STATE_SELECTED))
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_rename_send(session->imap_stream, mb, new_name);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (!mailimap_crlf_send(session->imap_stream))
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_RENAME;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int
|
|
mailimap_search(mailimap * session, const char * charset,
|
|
struct mailimap_search_key * key, clist ** result)
|
|
{
|
|
return mailimap_search_modseq(session, charset, key, result, NULL);
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int
|
|
mailimap_uid_search(mailimap * session, const char * charset,
|
|
struct mailimap_search_key * key, clist ** result)
|
|
{
|
|
return mailimap_uid_search_modseq(session, charset, key, result, NULL);
|
|
}
|
|
|
|
LIBETPAN_EXPORT int mailimap_search_literalplus(mailimap * session, const char * charset,
|
|
struct mailimap_search_key * key, clist ** result)
|
|
{
|
|
return mailimap_search_literalplus_modseq(session, charset, key, result, NULL);
|
|
}
|
|
|
|
LIBETPAN_EXPORT int mailimap_uid_search_literalplus(mailimap * session, const char * charset,
|
|
struct mailimap_search_key * key, clist ** result)
|
|
{
|
|
return mailimap_uid_search_literalplus_modseq(session, charset, key, result, NULL);
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
void mailimap_search_result_free(clist * search_result)
|
|
{
|
|
clist_foreach(search_result, (clist_func) free, NULL);
|
|
clist_free(search_result);
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int
|
|
mailimap_select(mailimap * session, const char * mb)
|
|
{
|
|
uint64_t dummy;
|
|
return mailimap_select_condstore_optional(session, mb, 0, &dummy);
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int
|
|
mailimap_status(mailimap * session, const char * mb,
|
|
struct mailimap_status_att_list * status_att_list,
|
|
struct mailimap_mailbox_data_status ** result)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
|
|
(session->imap_state != MAILIMAP_STATE_SELECTED))
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_status_send(session->imap_stream, mb, status_att_list);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
* result = session->imap_response_info->rsp_status;
|
|
session->imap_response_info->rsp_status = NULL;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_STATUS;
|
|
}
|
|
}
|
|
|
|
|
|
LIBETPAN_EXPORT
|
|
int
|
|
mailimap_store(mailimap * session,
|
|
struct mailimap_set * set,
|
|
struct mailimap_store_att_flags * store_att_flags)
|
|
{
|
|
#if 0
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if (session->imap_state != MAILIMAP_STATE_SELECTED)
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_store_send(session->imap_stream, set, store_att_flags);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_STORE;
|
|
}
|
|
#else
|
|
return mailimap_store_unchangedsince_optional(session,
|
|
set, 0, 0, store_att_flags);
|
|
#endif
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int
|
|
mailimap_uid_store(mailimap * session,
|
|
struct mailimap_set * set,
|
|
struct mailimap_store_att_flags * store_att_flags)
|
|
{
|
|
#if 0
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if (session->imap_state != MAILIMAP_STATE_SELECTED)
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_uid_store_send(session->imap_stream, set, store_att_flags);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_UID_STORE;
|
|
}
|
|
#else
|
|
return mailimap_uid_store_unchangedsince_optional(session,
|
|
set, 0, 0, store_att_flags);
|
|
#endif
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_subscribe(mailimap * session, const char * mb)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
|
|
(session->imap_state != MAILIMAP_STATE_SELECTED))
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_subscribe_send(session->imap_stream, mb);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_SUBSCRIBE;
|
|
}
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_unsubscribe(mailimap * session, const char * mb)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
|
|
(session->imap_state != MAILIMAP_STATE_SELECTED))
|
|
return MAILIMAP_ERROR_BAD_STATE;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_unsubscribe_send(session->imap_stream, mb);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_UNSUBSCRIBE;
|
|
}
|
|
}
|
|
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_starttls(mailimap * session)
|
|
{
|
|
struct mailimap_response * response;
|
|
int r;
|
|
int error_code;
|
|
|
|
r = mailimap_send_current_tag(session);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_starttls_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_crlf_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
if (mailstream_flush(session->imap_stream) == -1)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
if (mailimap_read_line(session) == NULL)
|
|
return MAILIMAP_ERROR_STREAM;
|
|
|
|
r = mailimap_parse_response(session, &response);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
|
|
|
|
mailimap_response_free(response);
|
|
|
|
switch (error_code) {
|
|
case MAILIMAP_RESP_COND_STATE_OK:
|
|
return MAILIMAP_NO_ERROR;
|
|
|
|
default:
|
|
return MAILIMAP_ERROR_STARTTLS;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
char * mailimap_read_line(mailimap * session)
|
|
{
|
|
return mailstream_read_line(session->imap_stream, session->imap_stream_buffer);
|
|
}
|
|
|
|
int mailimap_send_current_tag(mailimap * session)
|
|
{
|
|
char tag_str[15];
|
|
int r;
|
|
|
|
session->imap_tag ++;
|
|
|
|
if(mailimap_is_163_workaround_enabled(session))
|
|
snprintf(tag_str, 15, "C%i", session->imap_tag);
|
|
else
|
|
snprintf(tag_str, 15, "%i", session->imap_tag);
|
|
|
|
|
|
r = mailimap_tag_send(session->imap_stream, tag_str);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
r = mailimap_space_send(session->imap_stream);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
return MAILIMAP_NO_ERROR;
|
|
}
|
|
|
|
int mailimap_parse_response(mailimap * session,
|
|
struct mailimap_response ** result)
|
|
{
|
|
size_t indx;
|
|
struct mailimap_response * response;
|
|
char tag_str[15];
|
|
int r;
|
|
|
|
indx = 0;
|
|
|
|
session->imap_response = NULL;
|
|
|
|
if (session->imap_stream_buffer->allocated_len > 128 * 1024) {
|
|
MMAPString * buffer;
|
|
|
|
buffer = mmap_string_new_len(session->imap_stream_buffer->str, session->imap_stream_buffer->len);
|
|
mmap_string_free(session->imap_stream_buffer);
|
|
session->imap_stream_buffer = buffer;
|
|
}
|
|
|
|
if ((session->imap_body_progress_fun != NULL) ||
|
|
(session->imap_items_progress_fun != NULL)) {
|
|
r = mailimap_response_parse_with_context(session->imap_stream,
|
|
session->imap_stream_buffer,
|
|
&indx, &response,
|
|
session->imap_body_progress_fun,
|
|
session->imap_items_progress_fun,
|
|
session->imap_progress_context,
|
|
session->imap_msg_att_handler,
|
|
session->imap_msg_att_handler_context);
|
|
}
|
|
else {
|
|
r = mailimap_response_parse(session->imap_stream,
|
|
session->imap_stream_buffer,
|
|
&indx, &response,
|
|
session->imap_progr_rate, session->imap_progr_fun);
|
|
}
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
#if 0
|
|
mailimap_response_print(response);
|
|
#endif
|
|
|
|
response_store(session, response);
|
|
|
|
if (response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_text->rsp_text != NULL) {
|
|
if (mmap_string_assign(session->imap_response_buffer,
|
|
response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_text->rsp_text)
|
|
== NULL) {
|
|
mailimap_response_free(response);
|
|
return MAILIMAP_ERROR_MEMORY;
|
|
}
|
|
}
|
|
|
|
session->imap_response = session->imap_response_buffer->str;
|
|
|
|
if (response->rsp_resp_done->rsp_type == MAILIMAP_RESP_DONE_TYPE_FATAL) {
|
|
mailimap_response_free(response);
|
|
return MAILIMAP_ERROR_FATAL;
|
|
}
|
|
|
|
snprintf(tag_str, 15, "%i", session->imap_tag);
|
|
if (strcmp(response->rsp_resp_done->rsp_data.rsp_tagged->rsp_tag, tag_str) != 0) {
|
|
mailimap_response_free(response);
|
|
return MAILIMAP_ERROR_PROTOCOL;
|
|
}
|
|
|
|
if (response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type ==
|
|
MAILIMAP_RESP_COND_STATE_BAD) {
|
|
mailimap_response_free(response);
|
|
return MAILIMAP_ERROR_PROTOCOL;
|
|
}
|
|
|
|
* result = response;
|
|
|
|
return MAILIMAP_NO_ERROR;
|
|
}
|
|
|
|
|
|
static int parse_greeting(mailimap * session,
|
|
struct mailimap_greeting ** result)
|
|
{
|
|
size_t indx;
|
|
struct mailimap_greeting * greeting;
|
|
int r;
|
|
|
|
indx = 0;
|
|
|
|
session->imap_response = NULL;
|
|
|
|
r = mailimap_greeting_parse(session->imap_stream,
|
|
session->imap_stream_buffer,
|
|
&indx, &greeting, session->imap_progr_rate,
|
|
session->imap_progr_fun);
|
|
if (r != MAILIMAP_NO_ERROR)
|
|
return r;
|
|
|
|
#if 0
|
|
mailimap_greeting_print(greeting);
|
|
#endif
|
|
|
|
greeting_store(session, greeting);
|
|
|
|
if (greeting->gr_type == MAILIMAP_GREETING_RESP_COND_BYE) {
|
|
if (greeting->gr_data.gr_bye->rsp_text->rsp_text != NULL) {
|
|
if (mmap_string_assign(session->imap_response_buffer,
|
|
greeting->gr_data.gr_bye->rsp_text->rsp_text) == NULL)
|
|
return MAILIMAP_ERROR_MEMORY;
|
|
}
|
|
|
|
session->imap_response = session->imap_response_buffer->str;
|
|
|
|
return MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION;
|
|
}
|
|
|
|
if (greeting->gr_data.gr_auth->rsp_text->rsp_text != NULL) {
|
|
if (mmap_string_assign(session->imap_response_buffer,
|
|
greeting->gr_data.gr_auth->rsp_text->rsp_text) == NULL)
|
|
return MAILIMAP_ERROR_MEMORY;
|
|
}
|
|
|
|
session->imap_response = session->imap_response_buffer->str;
|
|
|
|
* result = greeting;
|
|
|
|
return MAILIMAP_NO_ERROR;
|
|
}
|
|
|
|
|
|
LIBETPAN_EXPORT
|
|
mailimap * mailimap_new(size_t imap_progr_rate,
|
|
progress_function * imap_progr_fun)
|
|
{
|
|
mailimap * f;
|
|
|
|
f = malloc(sizeof(* f));
|
|
if (f == NULL)
|
|
goto err;
|
|
|
|
f->imap_response = NULL;
|
|
|
|
f->imap_stream = NULL;
|
|
|
|
f->imap_progr_rate = imap_progr_rate;
|
|
f->imap_progr_fun = imap_progr_fun;
|
|
|
|
f->imap_stream_buffer = mmap_string_new("");
|
|
if (f->imap_stream_buffer == NULL)
|
|
goto free_f;
|
|
|
|
f->imap_response_buffer = mmap_string_new("");
|
|
if (f->imap_response_buffer == NULL)
|
|
goto free_stream_buffer;
|
|
|
|
f->imap_state = MAILIMAP_STATE_DISCONNECTED;
|
|
f->imap_tag = 0;
|
|
|
|
f->imap_selection_info = NULL;
|
|
f->imap_response_info = NULL;
|
|
f->imap_connection_info = NULL;
|
|
|
|
#ifdef USE_SASL
|
|
f->imap_sasl.sasl_conn = NULL;
|
|
#endif
|
|
|
|
f->imap_idle_timestamp = 0;
|
|
f->imap_idle_maxdelay = 29 * 60; /* IMAP IDLE spec */
|
|
|
|
f->imap_body_progress_fun = NULL;
|
|
f->imap_items_progress_fun = NULL;
|
|
f->imap_progress_context = NULL;
|
|
|
|
f->imap_msg_att_handler = NULL;
|
|
f->imap_msg_att_handler_context = NULL;
|
|
|
|
f->imap_timeout = 0;
|
|
|
|
f->imap_logger = NULL;
|
|
f->imap_logger_context = NULL;
|
|
f->is_163_workaround_enabled = 0;
|
|
return f;
|
|
|
|
free_stream_buffer:
|
|
mmap_string_free(f->imap_stream_buffer);
|
|
free_f:
|
|
free(f);
|
|
err:
|
|
return NULL;
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
void mailimap_free(mailimap * session)
|
|
{
|
|
#ifdef USE_SASL
|
|
if (session->imap_sasl.sasl_conn != NULL) {
|
|
sasl_dispose((sasl_conn_t **) &session->imap_sasl.sasl_conn);
|
|
mailsasl_unref();
|
|
}
|
|
#endif
|
|
|
|
if (session->imap_stream)
|
|
mailimap_logout(session);
|
|
|
|
mmap_string_free(session->imap_response_buffer);
|
|
mmap_string_free(session->imap_stream_buffer);
|
|
|
|
if (session->imap_response_info)
|
|
mailimap_response_info_free(session->imap_response_info);
|
|
if (session->imap_selection_info)
|
|
mailimap_selection_info_free(session->imap_selection_info);
|
|
if (session->imap_connection_info)
|
|
mailimap_connection_info_free(session->imap_connection_info);
|
|
|
|
free(session);
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
void mailimap_set_timeout(mailimap * session, time_t timeout)
|
|
{
|
|
session->imap_timeout = timeout;
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
time_t mailimap_get_timeout(mailimap * session)
|
|
{
|
|
return session->imap_timeout;
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
void mailimap_set_progress_callback(mailimap * session,
|
|
mailprogress_function * body_progr_fun,
|
|
mailprogress_function * items_progr_fun,
|
|
void * context)
|
|
{
|
|
session->imap_body_progress_fun = body_progr_fun;
|
|
session->imap_items_progress_fun = items_progr_fun;
|
|
session->imap_progress_context = context;
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
void mailimap_set_msg_att_handler(mailimap * session,
|
|
mailimap_msg_att_handler * handler,
|
|
void * context)
|
|
{
|
|
session->imap_msg_att_handler = handler;
|
|
session->imap_msg_att_handler_context = context;
|
|
}
|
|
|
|
static inline void imap_logger(mailstream * s, int log_type,
|
|
const char * str, size_t size, void * context)
|
|
{
|
|
mailimap * session;
|
|
|
|
session = context;
|
|
if (session->imap_logger == NULL)
|
|
return;
|
|
|
|
session->imap_logger(session, log_type, str, size, session->imap_logger_context);
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
void mailimap_set_logger(mailimap * session, void (* logger)(mailimap * session, int log_type,
|
|
const char * str, size_t size, void * context), void * logger_context)
|
|
{
|
|
session->imap_logger = logger;
|
|
session->imap_logger_context = logger_context;
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
void mailimap_set_163_workaround_enabled(mailimap * session, int enabled) {
|
|
imap->is_163_workaround_enabled = enabled;
|
|
}
|
|
|
|
LIBETPAN_EXPORT
|
|
int mailimap_is_163_workaround_enabled(mailimap * session) {
|
|
return imap->is_163_workaround_enabled;
|
|
}
|