/* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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$ */ #include "imapdriver.h" #include "mail.h" #include "imapdriver_tools.h" #include "mailmessage.h" #include "imapdriver_message.h" #include "imapdriver_types.h" #include "maildriver.h" #include "maildriver_tools.h" #include "generic_cache.h" #include #include static int imapdriver_initialize(mailsession * session); static void imapdriver_uninitialize(mailsession * session); static int imapdriver_connect_stream(mailsession * session, mailstream * s); static int imapdriver_starttls(mailsession * session); static int imapdriver_login(mailsession * session, char * userid, char * password); static int imapdriver_logout(mailsession * session); static int imapdriver_noop(mailsession * session); static int imapdriver_build_folder_name(mailsession * session, char * mb, char * name, char ** result); static int imapdriver_create_folder(mailsession * session, char * mb); static int imapdriver_delete_folder(mailsession * session, char * mb); static int imapdriver_rename_folder(mailsession * session, char * mb, char * new_name); static int imapdriver_check_folder(mailsession * session); static int imapdriver_examine_folder(mailsession * session, char * mb); static int imapdriver_select_folder(mailsession * session, char * mb); static int imapdriver_expunge_folder(mailsession * session); static int imapdriver_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int imapdriver_messages_number(mailsession * session, char * mb, uint32_t * result); static int imapdriver_recent_number(mailsession * session, char * mb, uint32_t * result); static int imapdriver_unseen_number(mailsession * session, char * mb, uint32_t * result); static int imapdriver_list_folders(mailsession * session, char * mb, struct mail_list ** result); static int imapdriver_lsub_folders(mailsession * session, char * mb, struct mail_list ** result); static int imapdriver_subscribe_folder(mailsession * session, char * mb); static int imapdriver_unsubscribe_folder(mailsession * session, char * mb); static int imapdriver_append_message(mailsession * session, char * message, size_t size); static int imapdriver_append_message_flags(mailsession * session, char * message, size_t size, struct mail_flags * flags); static int imapdriver_copy_message(mailsession * session, uint32_t num, char * mb); static int imapdriver_get_messages_list(mailsession * session, struct mailmessage_list ** result); static int imapdriver_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list); #if 0 static int imapdriver_search_messages(mailsession * session, char * charset, struct mail_search_key * key, struct mail_search_result ** result); #endif static int imapdriver_get_message(mailsession * session, uint32_t num, mailmessage ** result); static int imapdriver_get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result); static mailsession_driver local_imap_session_driver = { .sess_name = "imap", .sess_initialize = imapdriver_initialize, .sess_uninitialize = imapdriver_uninitialize, .sess_parameters = NULL, .sess_connect_stream = imapdriver_connect_stream, .sess_connect_path = NULL, .sess_starttls = imapdriver_starttls, .sess_login = imapdriver_login, .sess_logout = imapdriver_logout, .sess_noop = imapdriver_noop, .sess_build_folder_name = imapdriver_build_folder_name, .sess_create_folder = imapdriver_create_folder, .sess_delete_folder = imapdriver_delete_folder, .sess_rename_folder = imapdriver_rename_folder, .sess_check_folder = imapdriver_check_folder, .sess_examine_folder = imapdriver_examine_folder, .sess_select_folder = imapdriver_select_folder, .sess_expunge_folder = imapdriver_expunge_folder, .sess_status_folder = imapdriver_status_folder, .sess_messages_number = imapdriver_messages_number, .sess_recent_number = imapdriver_recent_number, .sess_unseen_number = imapdriver_unseen_number, .sess_list_folders = imapdriver_list_folders, .sess_lsub_folders = imapdriver_lsub_folders, .sess_subscribe_folder = imapdriver_subscribe_folder, .sess_unsubscribe_folder = imapdriver_unsubscribe_folder, .sess_append_message = imapdriver_append_message, .sess_append_message_flags = imapdriver_append_message_flags, .sess_copy_message = imapdriver_copy_message, .sess_move_message = NULL, .sess_get_messages_list = imapdriver_get_messages_list, .sess_get_envelopes_list = imapdriver_get_envelopes_list, .sess_remove_message = NULL, #if 0 .sess_search_messages = imapdriver_search_messages, #endif .sess_get_message = imapdriver_get_message, .sess_get_message_by_uid = imapdriver_get_message_by_uid, }; mailsession_driver * imap_session_driver = &local_imap_session_driver; static inline struct imap_session_state_data * get_data(mailsession * session) { return session->sess_data; } static mailimap * get_imap_session(mailsession * session) { return get_data(session)->imap_session; } static int imapdriver_initialize(mailsession * session) { struct imap_session_state_data * data; mailimap * imap; struct mail_flags_store * flags_store; imap = mailimap_new(0, NULL); if (imap == NULL) goto err; flags_store = mail_flags_store_new(); if (flags_store == NULL) goto free_session; data = malloc(sizeof(* data)); if (data == NULL) goto free_flags_store; data->imap_mailbox = NULL; data->imap_session = imap; data->imap_flags_store = flags_store; session->sess_data = data; return MAIL_NO_ERROR; free_flags_store: mail_flags_store_free(flags_store); free_session: mailimap_free(imap); err: return MAIL_ERROR_MEMORY; } static void imap_flags_store_process(mailimap * imap, struct mail_flags_store * flags_store) { unsigned int i; int r; mailmessage * first; mailmessage * last; mail_flags_store_sort(flags_store); if (carray_count(flags_store->fls_tab) == 0) return; first = carray_get(flags_store->fls_tab, 0); last = first; for(i = 1 ; i < carray_count(flags_store->fls_tab) ; i ++) { mailmessage * msg; msg = carray_get(flags_store->fls_tab, i); if (last->msg_index + 1 == msg->msg_index) { r = mail_flags_compare(first->msg_flags, msg->msg_flags); if (r == 0) { last = msg; continue; } } r = imap_store_flags(imap, first->msg_index, last->msg_index, first->msg_flags); first = msg; last = msg; } r = imap_store_flags(imap, first->msg_index, last->msg_index, first->msg_flags); mail_flags_store_clear(flags_store); } static void imapdriver_uninitialize(mailsession * session) { struct imap_session_state_data * data; data = get_data(session); imap_flags_store_process(data->imap_session, data->imap_flags_store); mail_flags_store_free(data->imap_flags_store); mailimap_free(data->imap_session); if (data->imap_mailbox != NULL) free(data->imap_mailbox); free(data); session->sess_data = NULL; } static int imapdriver_connect_stream(mailsession * session, mailstream * s) { int r; r = mailimap_connect(get_imap_session(session), s); return imap_error_to_mail_error(r); } static int imapdriver_login(mailsession * session, char * userid, char * password) { int r; r = mailimap_login(get_imap_session(session), userid, password); return imap_error_to_mail_error(r); } static int imapdriver_logout(mailsession * session) { int r; imap_flags_store_process(get_imap_session(session), get_data(session)->imap_flags_store); r = mailimap_logout(get_imap_session(session)); return imap_error_to_mail_error(r); } static int imapdriver_noop(mailsession * session) { int r; r = mailimap_noop(get_imap_session(session)); return imap_error_to_mail_error(r); } static int imapdriver_build_folder_name(mailsession * session, char * mb, char * name, char ** result) { char delimiter[2] = "X"; char * folder_name; mailimap * imap; struct mailimap_mailbox_list * mb_list; int r; clist * imap_list; imap = get_imap_session(session); r = mailimap_list(imap, mb, "", &imap_list); if (r != MAILIMAP_NO_ERROR) return r; if (clist_begin(imap_list) == NULL) return MAIL_ERROR_LIST; mb_list = clist_begin(imap_list)->data; delimiter[0] = mb_list->mb_delimiter; folder_name = malloc(strlen(mb) + strlen(delimiter) + strlen(name) + 1); if (folder_name == NULL) return MAIL_ERROR_MEMORY; strcpy(folder_name, mb); strcat(folder_name, delimiter); strcat(folder_name, name); * result = folder_name; return MAIL_NO_ERROR; } /* folders operations */ static int imapdriver_create_folder(mailsession * session, char * mb) { int r; r = mailimap_create(get_imap_session(session), mb); return imap_error_to_mail_error(r); } static int imapdriver_delete_folder(mailsession * session, char * mb) { int r; r = mailimap_delete(get_imap_session(session), mb); return imap_error_to_mail_error(r); } static int imapdriver_rename_folder(mailsession * session, char * mb, char * new_name) { int r; r = mailimap_rename(get_imap_session(session), mb, new_name); return imap_error_to_mail_error(r); } static int imapdriver_check_folder(mailsession * session) { int r; imap_flags_store_process(get_imap_session(session), get_data(session)->imap_flags_store); r = mailimap_check(get_imap_session(session)); return imap_error_to_mail_error(r); } static int imapdriver_examine_folder(mailsession * session, char * mb) { int r; r = mailimap_examine(get_imap_session(session), mb); return imap_error_to_mail_error(r); } static int imapdriver_select_folder(mailsession * session, char * mb) { int r; char * new_mb; char * old_mb; old_mb = get_data(session)->imap_mailbox; if (old_mb != NULL) if (strcmp(mb, old_mb) == 0) return MAIL_NO_ERROR; imap_flags_store_process(get_imap_session(session), get_data(session)->imap_flags_store); r = mailimap_select(get_imap_session(session), mb); switch (r) { case MAILIMAP_NO_ERROR: new_mb = strdup(mb); if (new_mb == NULL) { if (old_mb != NULL) free(old_mb); get_data(session)->imap_mailbox = NULL; return MAIL_ERROR_MEMORY; } get_data(session)->imap_mailbox = new_mb; return MAIL_NO_ERROR; default: return imap_error_to_mail_error(r); } } static int imapdriver_expunge_folder(mailsession * session) { int r; imap_flags_store_process(get_imap_session(session), get_data(session)->imap_flags_store); r = mailimap_expunge(get_imap_session(session)); return imap_error_to_mail_error(r); } static int status_selected_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen) { int r; int res; mailimap * imap; uint32_t exists; uint32_t unseen; uint32_t recent; struct mailimap_search_key * search_key; clist * search_result; imap = get_imap_session(session); exists = imap->imap_selection_info->sel_exists; recent = imap->imap_selection_info->sel_recent; search_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL); if (search_key == NULL) { res = MAIL_ERROR_MEMORY; goto err; } /* default : use the RECENT count if search fails */ unseen = recent; r = mailimap_search(imap, NULL, search_key, &search_result); mailimap_search_key_free(search_key); if (r == MAILIMAP_NO_ERROR) { /* if this succeed, we use the real count */ unseen = clist_count(search_result); mailimap_mailbox_data_search_free(search_result); } * result_messages = exists; * result_unseen = unseen; * result_recent = recent; return MAIL_NO_ERROR; err: return res; } static int status_unselected_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen) { struct mailimap_status_att_list * att_list; struct mailimap_mailbox_data_status * status; int r; int res; clistiter * cur; mailimap * imap; imap = get_imap_session(session); att_list = mailimap_status_att_list_new_empty(); if (att_list == NULL) { res = MAIL_ERROR_MEMORY; goto err; } r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_MESSAGES); switch (r) { case MAILIMAP_NO_ERROR: break; default: res = MAIL_ERROR_MEMORY; goto free; } r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_RECENT); switch (r) { case MAILIMAP_NO_ERROR: break; default: res = MAIL_ERROR_MEMORY; goto free; } r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_UNSEEN); switch (r) { case MAILIMAP_NO_ERROR: break; default: res = MAIL_ERROR_MEMORY; goto free; } r = mailimap_status(imap, mb, att_list, &status); switch (r) { case MAILIMAP_NO_ERROR: break; default: res = imap_error_to_mail_error(r); goto free; } * result_messages = 0; * result_recent = 0; * result_unseen = 0; for (cur = clist_begin(status->st_info_list); cur != NULL ; cur = clist_next(cur)) { struct mailimap_status_info * status_info; status_info = clist_content(cur); switch (status_info->st_att) { case MAILIMAP_STATUS_ATT_MESSAGES: * result_messages = status_info->st_value; break; case MAILIMAP_STATUS_ATT_RECENT: * result_recent = status_info->st_value; break; case MAILIMAP_STATUS_ATT_UNSEEN: * result_unseen = status_info->st_value; break; } } mailimap_mailbox_data_status_free(status); mailimap_status_att_list_free(att_list); return MAIL_NO_ERROR; free: mailimap_status_att_list_free(att_list); err: return res; } static int imapdriver_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen) { int res; int current_folder; char * current_mb; if (mb == NULL) { mb = get_data(session)->imap_mailbox; if (mb == NULL) { res = MAIL_ERROR_BAD_STATE; goto err; } } current_mb = get_data(session)->imap_mailbox; if (strcmp(mb, current_mb) == 0) current_folder = 1; else current_folder = 0; if (current_folder) return status_selected_folder(session, mb, result_messages, result_recent, result_unseen); else return status_unselected_folder(session, mb, result_messages, result_recent, result_unseen); err: return res; } /* TODO : more efficient functions */ static int imapdriver_messages_number(mailsession * session, char * mb, uint32_t * result) { uint32_t messages; uint32_t recent; uint32_t unseen; int r; r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); if (r != MAIL_NO_ERROR) return r; * result = messages; return MAIL_NO_ERROR; } static int imapdriver_recent_number(mailsession * session, char * mb, uint32_t * result) { uint32_t messages; uint32_t recent; uint32_t unseen; int r; r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); if (r != MAIL_NO_ERROR) return r; * result = recent; return MAIL_NO_ERROR; } static int imapdriver_unseen_number(mailsession * session, char * mb, uint32_t * result) { uint32_t messages; uint32_t recent; uint32_t unseen; int r; r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); if (r != MAIL_NO_ERROR) return r; * result = unseen; return MAIL_NO_ERROR; } enum { IMAP_LIST, IMAP_LSUB }; static int imapdriver_list_lsub_folders(mailsession * session, int type, char * mb, struct mail_list ** result) { clist * imap_list; struct mail_list * resp; int r; int res; switch (type) { case IMAP_LIST: r = mailimap_list(get_imap_session(session), mb, "*", &imap_list); break; case IMAP_LSUB: r = mailimap_lsub(get_imap_session(session), mb, "*", &imap_list); break; default: res = MAIL_ERROR_LIST; goto err; } switch (r) { case MAILIMAP_NO_ERROR: break; default: res = imap_error_to_mail_error(r); goto err; } r = imap_list_to_list(imap_list, &resp); if (r != MAIL_NO_ERROR) { mailimap_list_result_free(imap_list); res = r; goto err; } mailimap_list_result_free(imap_list); * result = resp; return MAIL_NO_ERROR; err: return res; } static int imapdriver_list_folders(mailsession * session, char * mb, struct mail_list ** result) { return imapdriver_list_lsub_folders(session, IMAP_LIST, mb, result); } static int imapdriver_lsub_folders(mailsession * session, char * mb, struct mail_list ** result) { return imapdriver_list_lsub_folders(session, IMAP_LSUB, mb, result); } static int imapdriver_subscribe_folder(mailsession * session, char * mb) { int r; r = mailimap_subscribe(get_imap_session(session), mb); return imap_error_to_mail_error(r); } static int imapdriver_unsubscribe_folder(mailsession * session, char * mb) { int r; r = mailimap_unsubscribe(get_imap_session(session), mb); return imap_error_to_mail_error(r); } /* messages operations */ static int imapdriver_append_message(mailsession * session, char * message, size_t size) { int r; r = mailimap_append_simple(get_imap_session(session), get_data(session)->imap_mailbox, message, size); return imap_error_to_mail_error(r); } static int imapdriver_append_message_flags(mailsession * session, char * message, size_t size, struct mail_flags * flags) { struct mailimap_flag_list * flag_list; int r; if (flags != NULL) { r = imap_flags_to_imap_flags(flags, &flag_list); if (r != MAIL_NO_ERROR) return r; } else { flag_list = NULL; } r = mailimap_append(get_imap_session(session), get_data(session)->imap_mailbox, flag_list, NULL, message, size); if (flag_list != NULL) mailimap_flag_list_free(flag_list); return imap_error_to_mail_error(r); } static int imapdriver_copy_message(mailsession * session, uint32_t num, char * mb) { int r; struct mailimap_set * set; int res; set = mailimap_set_new_single(num); if (set == NULL) { res = MAIL_ERROR_MEMORY; goto err; } r = mailimap_uid_copy(get_imap_session(session), set, mb); mailimap_set_free(set); return imap_error_to_mail_error(r); err: return res; } static int imapdriver_get_messages_list(mailsession * session, struct mailmessage_list ** result) { return imap_get_messages_list(get_imap_session(session), session, imap_message_driver, 1, result); } static int imapdriver_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list) { struct mailimap_set * set; struct mailimap_fetch_att * fetch_att; struct mailimap_fetch_type * fetch_type; int res; clist * fetch_result; int r; uint32_t exists; clist * msg_list; if (get_imap_session(session)->imap_selection_info == NULL) { res = MAIL_ERROR_BAD_STATE; goto err; } imap_flags_store_process(get_imap_session(session), get_data(session)->imap_flags_store); exists = get_imap_session(session)->imap_selection_info->sel_exists; if (exists == 0) return MAIL_NO_ERROR; fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); if (fetch_type == NULL) { res = MAIL_ERROR_MEMORY; goto err; } fetch_att = mailimap_fetch_att_new_uid(); if (fetch_att == NULL) { res = MAIL_ERROR_MEMORY; goto free_fetch_type; } r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); if (r != MAILIMAP_NO_ERROR) { mailimap_fetch_att_free(fetch_att); res = MAIL_ERROR_MEMORY; goto free_fetch_type; } fetch_att = mailimap_fetch_att_new_flags(); if (fetch_att == NULL) { res = MAIL_ERROR_MEMORY; goto free_fetch_type; } r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); if (r != MAILIMAP_NO_ERROR) { mailimap_fetch_att_free(fetch_att); res = MAIL_ERROR_MEMORY; goto free_fetch_type; } r = imap_add_envelope_fetch_att(fetch_type); if (r != MAIL_NO_ERROR) { res = r; goto free_fetch_type; } r = maildriver_env_list_to_msg_list(env_list, &msg_list); if (r != MAIL_NO_ERROR) { res = MAIL_ERROR_MEMORY; goto free_fetch_type; } if (clist_begin(msg_list) == NULL) { /* no need to fetch envelopes */ mailimap_fetch_type_free(fetch_type); clist_free(msg_list); return MAIL_NO_ERROR; } r = msg_list_to_imap_set(msg_list, &set); if (r != MAIL_NO_ERROR) { clist_foreach(msg_list, (clist_func) free, NULL); clist_free(msg_list); res = MAIL_ERROR_MEMORY; goto free_fetch_type; } clist_foreach(msg_list, (clist_func) free, NULL); clist_free(msg_list); r = mailimap_uid_fetch(get_imap_session(session), set, fetch_type, &fetch_result); mailimap_fetch_type_free(fetch_type); mailimap_set_free(set); switch (r) { case MAILIMAP_NO_ERROR: break; default: return imap_error_to_mail_error(r); } if (clist_begin(fetch_result) == NULL) { res = MAIL_ERROR_FETCH; goto err; } r = imap_fetch_result_to_envelop_list(fetch_result, env_list); mailimap_fetch_list_free(fetch_result); if (r != MAIL_NO_ERROR) { res = MAIL_ERROR_MEMORY; goto err; } return MAIL_NO_ERROR; free_fetch_type: mailimap_fetch_type_free(fetch_type); err: return res; } #if 0 static int imapdriver_search_messages(mailsession * session, char * charset, struct mail_search_key * key, struct mail_search_result ** result) { struct mailimap_search_key * imap_key; int r; clist * imap_result; clist * result_list; struct mail_search_result * search_result; clistiter * cur; r = mail_search_to_imap_search(key, &imap_key); if (r != MAIL_NO_ERROR) return MAIL_ERROR_MEMORY; r = mailimap_uid_search(get_imap_session(session), charset, imap_key, &imap_result); mailimap_search_key_free(imap_key); switch (r) { case MAILIMAP_NO_ERROR: break; default: return imap_error_to_mail_error(r); } result_list = clist_new(); if (result_list == NULL) return MAIL_ERROR_MEMORY; for(cur = clist_begin(imap_result) ; cur != NULL ; cur = clist_next(cur)) { uint32_t val = * (uint32_t *) clist_content(cur); uint32_t * new; new = malloc(sizeof(* new)); if (new == NULL) { goto free_imap_result; } * new = val; r = clist_append(result_list, new); if (r != 0) { free(new); goto free_imap_result; } } search_result = mail_search_result_new(result_list); if (search_result == NULL) goto free_imap_result; mailimap_search_result_free(imap_result); * result = search_result; return MAIL_NO_ERROR; free_imap_result: mailimap_search_result_free(imap_result); return MAIL_ERROR_MEMORY; } #endif static int imapdriver_starttls(mailsession * session) { mailimap * imap; int r; struct mailimap_capability_data * cap_data; clistiter * cur; int starttls; int fd; mailstream_low * low; mailstream_low * new_low; int capability_available; imap = get_imap_session(session); capability_available = FALSE; if (imap->imap_connection_info != NULL) if (imap->imap_connection_info->imap_capability != NULL) { capability_available = TRUE; cap_data = imap->imap_connection_info->imap_capability; } if (!capability_available) { r = mailimap_capability(imap, &cap_data); switch (r) { case MAILIMAP_NO_ERROR: break; default: return imap_error_to_mail_error(r); } } starttls = FALSE; for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ; cur = clist_next(cur)) { struct mailimap_capability * cap; cap = clist_content(cur); if (cap->cap_type == MAILIMAP_CAPABILITY_NAME) if (strcasecmp(cap->cap_data.cap_name, "STARTTLS") == 0) { starttls = TRUE; break; } } if (!capability_available) mailimap_capability_data_free(cap_data); if (!starttls) return MAIL_ERROR_NO_TLS; r = mailimap_starttls(imap); switch (r) { case MAILIMAP_NO_ERROR: break; default: return imap_error_to_mail_error(r); } low = mailstream_get_low(imap->imap_stream); fd = mailstream_low_get_fd(low); if (fd == -1) return MAIL_ERROR_STREAM; new_low = mailstream_low_ssl_open(fd); if (new_low == NULL) return MAIL_ERROR_STREAM; mailstream_low_free(low); mailstream_set_low(imap->imap_stream, new_low); return MAIL_NO_ERROR; } static int imapdriver_get_message(mailsession * session, uint32_t num, mailmessage ** result) { mailmessage * msg_info; int r; msg_info = mailmessage_new(); if (msg_info == NULL) return MAIL_ERROR_MEMORY; r = mailmessage_init(msg_info, session, imap_message_driver, num, 0); if (r != MAIL_NO_ERROR) { mailmessage_free(msg_info); return r; } * result = msg_info; return MAIL_NO_ERROR; } /* Retrieve a message by UID libEtPan! uid format for IMAP is "UIDVALIDITY-UID" where UIDVALIDITY and UID are decimal representation of respectively uidvalidity and uid numbers. Return value: MAIL_ERROR_INVAL if uid is NULL or has an incorrect format. MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found MAIL_NO_ERROR if message was found. Result is in result */ static int imapdriver_get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result) { uint32_t uidvalidity; uint32_t num; char * p1, * p2; mailimap * imap; if (uid == NULL) return MAIL_ERROR_INVAL; uidvalidity = strtoul(uid, &p1, 10); if (p1 == uid || * p1 != '-') return MAIL_ERROR_INVAL; p1++; num = strtoul(p1, &p2, 10); if (p2 == p1 || * p2 != '\0') return MAIL_ERROR_INVAL; imap = get_imap_session(session); if (imap->imap_selection_info->sel_uidvalidity != uidvalidity) return MAIL_ERROR_MSG_NOT_FOUND; return imapdriver_get_message(session, num, result); }