gboolean authenticated;
- gchar **capability;
+ GSList *capability;
gboolean uidplus;
gchar *mbox;
/* low-level IMAP4rev1 commands */
static gint imap_cmd_login (IMAPSession *session,
const gchar *user,
- const gchar *pass);
+ const gchar *pass,
+ const gchar *type);
static gint imap_cmd_logout (IMAPSession *session);
static gint imap_cmd_noop (IMAPSession *session);
#if USE_OPENSSL
g_node_traverse(folder->node, G_IN_ORDER, G_TRAVERSE_ALL, -1, imap_reset_uid_lists_func, NULL);
}
+void imap_get_capabilities(IMAPSession *session)
+{
+ struct mailimap_capability_data *capabilities = NULL;
+ clistiter *cur;
+
+ if (session->capability != NULL)
+ return;
+
+ capabilities = imap_threaded_capability(session->folder);
+ for(cur = clist_begin(capabilities->cap_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct mailimap_capability * cap =
+ clist_content(cur);
+ if (cap->cap_data.cap_name == NULL)
+ continue;
+ session->capability = g_slist_append
+ (session->capability,
+ g_strdup(cap->cap_data.cap_name));
+ debug_print("got capa %s\n", cap->cap_data.cap_name);
+ }
+ mailimap_capability_data_free(capabilities);
+}
+
+gboolean imap_has_capability(IMAPSession *session, const gchar *cap)
+{
+ GSList *cur;
+ for (cur = session->capability; cur; cur = cur->next) {
+ if (!g_ascii_strcasecmp(cur->data, cap))
+ return TRUE;
+ }
+ return FALSE;
+}
+
static gint imap_auth(IMAPSession *session, const gchar *user, const gchar *pass,
IMAPAuthType type)
{
- gint ok;
-
- ok = imap_cmd_login(session, user, pass);
+ gint ok = IMAP_ERROR;
+ static time_t last_login_err = 0;
+ imap_get_capabilities(session);
+
+ switch(type) {
+ case IMAP_AUTH_CRAM_MD5:
+ ok = imap_cmd_login(session, user, pass, "CRAM-MD5");
+ break;
+ case IMAP_AUTH_LOGIN:
+ ok = imap_cmd_login(session, user, pass, "LOGIN");
+ break;
+ default:
+ debug_print("capabilities:\n"
+ "\t CRAM-MD5 %d\n"
+ "\t LOGIN %d\n",
+ imap_has_capability(session, "CRAM-MD5"),
+ imap_has_capability(session, "LOGIN"));
+ if (imap_has_capability(session, "CRAM-MD5"))
+ ok = imap_cmd_login(session, user, pass, "CRAM-MD5");
+ if (ok == IMAP_ERROR) /* we always try LOGIN before giving up */
+ ok = imap_cmd_login(session, user, pass, "LOGIN");
+ }
if (ok == IMAP_SUCCESS)
session->authenticated = TRUE;
-
+ else {
+ gchar *ext_info = NULL;
+
+ if (type == IMAP_AUTH_CRAM_MD5) {
+ ext_info = _("\n\nCRAM-MD5 logins only work if libetpan has been "
+ "compiled with SASL support and the "
+ "CRAM-MD5 SASL plugin is installed.");
+ } else {
+ ext_info = "";
+ }
+
+ if (time(NULL) - last_login_err > 10) {
+ alertpanel_error(_("Connection to %s failed: login refused.%s"),
+ SESSION(session)->server, ext_info);
+ }
+ last_login_err = time(NULL);
+ }
return ok;
}
+static IMAPSession *imap_reconnect_if_possible(Folder *folder, IMAPSession *session)
+{
+ RemoteFolder *rfolder = REMOTE_FOLDER(folder);
+ /* Check if this is the first try to establish a
+ connection, if yes we don't try to reconnect */
+ debug_print("reconnecting\n");
+ if (rfolder->session == NULL) {
+ log_warning(_("Connecting to %s failed"),
+ folder->account->recv_server);
+ session_destroy(SESSION(session));
+ session = NULL;
+ } else {
+ log_warning(_("IMAP4 connection to %s has been"
+ " disconnected. Reconnecting...\n"),
+ folder->account->recv_server);
+ statusbar_print_all(_("IMAP4 connection to %s has been"
+ " disconnected. Reconnecting...\n"),
+ folder->account->recv_server);
+ SESSION(session)->state = SESSION_DISCONNECTED;
+ session_destroy(SESSION(session));
+ /* Clear folders session to make imap_session_get create
+ a new session, because of rfolder->session == NULL
+ it will not try to reconnect again and so avoid an
+ endless loop */
+ rfolder->session = NULL;
+ session = imap_session_get(folder);
+ rfolder->session = SESSION(session);
+ statusbar_pop_all();
+ }
+ return session;
+}
+
static IMAPSession *imap_session_get(Folder *folder)
{
RemoteFolder *rfolder = REMOTE_FOLDER(folder);
if (time(NULL) - SESSION(session)->last_access_time > SESSION_TIMEOUT_INTERVAL) {
/* verify that the session is still alive */
if (imap_cmd_noop(session) != IMAP_SUCCESS) {
- /* Check if this is the first try to establish a
- connection, if yes we don't try to reconnect */
- if (rfolder->session == NULL) {
- log_warning(_("Connecting to %s failed"),
- folder->account->recv_server);
- session_destroy(SESSION(session));
- session = NULL;
- } else {
- log_warning(_("IMAP4 connection to %s has been"
- " disconnected. Reconnecting...\n"),
- folder->account->recv_server);
- statusbar_print_all(_("IMAP4 connection to %s has been"
- " disconnected. Reconnecting...\n"),
- folder->account->recv_server);
- session_destroy(SESSION(session));
- /* Clear folders session to make imap_session_get create
- a new session, because of rfolder->session == NULL
- it will not try to reconnect again and so avoid an
- endless loop */
- rfolder->session = NULL;
- session = imap_session_get(folder);
- statusbar_pop_all();
- }
+ debug_print("disconnected!\n");
+ session = imap_reconnect_if_possible(folder, session);
}
}
if(!prefs_common.no_recv_err_panel) {
alertpanel_error(_("Can't connect to IMAP4 server: %s:%d"),
account->recv_server, port);
- }
+ } else {
+ log_error(_("Can't connect to IMAP4 server: %s:%d"),
+ account->recv_server, port);
+ }
return NULL;
}
gchar *tmp_pass;
tmp_pass = input_dialog_query_password(account->recv_server, account->userid);
if (!tmp_pass)
- return;
+ tmp_pass = g_strdup(""); /* allow empty password */
Xstrdup_a(pass, tmp_pass, {g_free(tmp_pass); return;});
g_free(tmp_pass);
}
static void imap_session_destroy(Session *session)
{
- imap_threaded_disconnect(IMAP_SESSION(session)->folder);
+ if (session->state != SESSION_DISCONNECTED)
+ imap_threaded_disconnect(IMAP_SESSION(session)->folder);
imap_free_capabilities(IMAP_SESSION(session));
g_free(IMAP_SESSION(session)->mbox);
return imap_fetch_msg_full(folder, item, uid, TRUE, TRUE);
}
-static guint get_size_with_lfs(MsgInfo *info)
+static guint get_size_with_crs(MsgInfo *info)
{
FILE *fp = NULL;
guint cnt = 0;
* we have to update the local file (UNIX \n only) size */
MsgInfo *msginfo = imap_parse_msg(filename, item);
MsgInfo *cached = msgcache_get_msg(item->cache,uid);
- guint have_size = get_size_with_lfs(msginfo);
- debug_print("message %d has been already %scached (%d/%d).\n", uid,
+ guint have_size = get_size_with_crs(msginfo);
+
+ if (cached)
+ debug_print("message %d has been already %scached (%d/%d).\n", uid,
have_size == cached->size ? "fully ":"",
- have_size, cached? (int)cached->size : -1);
+ have_size, (int)cached->size);
if (cached && (cached->size == have_size || !body)) {
procmsg_msginfo_free(cached);
procmsg_msginfo_free(msginfo);
+ file_strip_crs(filename);
return filename;
} else {
procmsg_msginfo_free(cached);
return NULL;
}
+ file_strip_crs(filename);
return filename;
}
iflags |= IMAP_FLAG_SEEN;
}
- if (dest->stype == F_OUTBOX ||
- dest->stype == F_QUEUE ||
- dest->stype == F_DRAFT ||
- dest->stype == F_TRASH)
+ if (folder_has_parent_of_type(dest, F_QUEUE) ||
+ folder_has_parent_of_type(dest, F_OUTBOX) ||
+ folder_has_parent_of_type(dest, F_DRAFT) ||
+ folder_has_parent_of_type(dest, F_TRASH))
iflags |= IMAP_FLAG_SEEN;
ok = imap_cmd_append(session, destdir, fileinfo->file, iflags,
{
GSList *list = folder_item_get_msg_list(item);
gint res = imap_remove_msgs(folder, item, list, NULL);
- g_slist_free(list);
+ procmsg_msg_list_free(list);
return res;
}
if (!folder->trash)
folder->trash = imap_create_special_folder
(folder, F_TRASH, "Trash");
+ if (!folder->queue)
+ folder->queue = imap_create_special_folder
+ (folder, F_QUEUE, "Queue");
+ if (!folder->outbox)
+ folder->outbox = imap_create_special_folder
+ (folder, F_OUTBOX, "Sent");
+ if (!folder->draft)
+ folder->draft = imap_create_special_folder
+ (folder, F_DRAFT, "Drafts");
}
static FolderItem *imap_create_special_folder(Folder *folder,
static void imap_free_capabilities(IMAPSession *session)
{
- g_strfreev(session->capability);
+ slist_free_strings(session->capability);
+ g_slist_free(session->capability);
session->capability = NULL;
}
#endif
static gint imap_cmd_login(IMAPSession *session,
- const gchar *user, const gchar *pass)
+ const gchar *user, const gchar *pass,
+ const gchar *type)
{
int r;
gint ok;
- static time_t last_login_err = 0;
- log_print("IMAP4> Logging in to %s\n", SESSION(session)->server);
- r = imap_threaded_login(session->folder, user, pass);
+ log_print("IMAP4> Logging %s to %s using %s\n",
+ user,
+ SESSION(session)->server,
+ type);
+ r = imap_threaded_login(session->folder, user, pass, type);
if (r != MAILIMAP_NO_ERROR) {
- if (time(NULL) - last_login_err > 10) {
- alertpanel_error(_("Connection to %s failed: login refused."),
- SESSION(session)->server);
- }
- last_login_err = time(NULL);
log_error("IMAP4< Error logging in to %s\n",
SESSION(session)->server);
ok = IMAP_ERROR;
g_free(data);
return -1;
}
-
+ statusbar_print_all(_("Fetching message..."));
result = GPOINTER_TO_INT(imap_cmd_fetch_thread(data));
+ statusbar_pop_all();
g_free(data);
return result;
}
g_return_val_if_fail(file != NULL, IMAP_ERROR);
flag_list = imap_flag_to_lep(flags);
+ statusbar_print_all(_("Adding messages..."));
r = imap_threaded_append(session->folder, destfolder,
file, flag_list);
-
+ statusbar_pop_all();
if (new_uid != NULL)
*new_uid = 0;
g_return_val_if_fail(set != NULL, IMAP_ERROR);
g_return_val_if_fail(destfolder != NULL, IMAP_ERROR);
+ statusbar_print_all(_("Copying messages..."));
r = imap_threaded_copy(session->folder, set, destfolder);
+ statusbar_pop_all();
if (r != MAILIMAP_NO_ERROR) {
return IMAP_ERROR;
struct mailimap_set * set;
clist * lep_uidlist;
int r;
-
+
session = imap_session_get(folder);
if (session == NULL) {
stuff->done = TRUE;
gboolean selected_folder;
debug_print("get_num_list\n");
+ statusbar_print_all("Scanning %s...\n", FOLDER_ITEM(item)->path
+ ? FOLDER_ITEM(item)->path:"");
g_return_val_if_fail(folder != NULL, -1);
g_return_val_if_fail(item != NULL, -1);
if (selected_folder) {
ok = imap_cmd_noop(session);
if (ok != IMAP_SUCCESS) {
-
- return -1;
+ debug_print("disconnected!\n");
+ session = imap_reconnect_if_possible(folder, session);
+ if (session == NULL) {
+ statusbar_pop_all();
+ return -1;
+ }
}
exists = session->exists;
ok = imap_status(session, IMAP_FOLDER(folder), item->item.path,
&exists, &recent, &uid_next, &uid_val, &unseen, FALSE);
if (ok != IMAP_SUCCESS) {
-
+ statusbar_pop_all();
return -1;
}
if(item->item.mtime == uid_val)
out which numbers have been removed */
if (exists == nummsgs) {
*msgnum_list = g_slist_copy(item->uid_list);
+ statusbar_pop_all();
return nummsgs;
} else if (exists < nummsgs) {
debug_print("Freeing imap uid cache");
if (exists == 0) {
*msgnum_list = NULL;
+ statusbar_pop_all();
return 0;
}
nummsgs = get_list_of_uids(folder, item, &uidlist);
if (nummsgs < 0) {
-
+ statusbar_pop_all();
return -1;
}
g_free(dir);
debug_print("get_num_list - ok - %i\n", nummsgs);
-
+ statusbar_pop_all();
return nummsgs;
}
g_return_val_if_fail(item != NULL, NULL);
g_return_val_if_fail(file != NULL, NULL);
- if (item->stype == F_QUEUE) {
+ if (folder_has_parent_of_type(item, F_QUEUE)) {
MSG_SET_TMP_FLAGS(flags, MSG_QUEUED);
- } else if (item->stype == F_DRAFT) {
+ } else if (folder_has_parent_of_type(item, F_DRAFT)) {
MSG_SET_TMP_FLAGS(flags, MSG_DRAFT);
}
if (ok != IMAP_SUCCESS)
return NULL;
- if (!(item->stype == F_QUEUE || item->stype == F_DRAFT)) {
+ if (!(folder_has_parent_of_type(item, F_DRAFT) ||
+ folder_has_parent_of_type(item, F_QUEUE))) {
ret = g_slist_concat(ret,
imap_get_uncached_messages(session, item,
msgnum_list));
(!strcmp(session->mbox, item->item.path));
if (selected_folder) {
ok = imap_cmd_noop(session);
- if (ok != IMAP_SUCCESS)
- return FALSE;
+ if (ok != IMAP_SUCCESS) {
+ debug_print("disconnected!\n");
+ session = imap_reconnect_if_possible(folder, session);
+ if (session == NULL)
+ return FALSE;
+ }
if (session->folder_content_changed
|| session->exists != item->item.total_msgs)
free(dup_name);
continue;
}
+
+ if (dup_name[strlen(dup_name)-1] == '/') {
+ g_free(base);
+ free(dup_name);
+ continue;
+ }
loc_name = imap_modified_utf7_to_utf8(base);
loc_path = imap_modified_utf7_to_utf8(dup_name);
MsgFlags flags = {0, 0};
MSG_SET_TMP_FLAGS(flags, MSG_IMAP);
- if (item->stype == F_QUEUE) {
+ if (folder_has_parent_of_type(item, F_QUEUE)) {
MSG_SET_TMP_FLAGS(flags, MSG_QUEUED);
- } else if (item->stype == F_DRAFT) {
+ } else if (folder_has_parent_of_type(item, F_DRAFT)) {
MSG_SET_TMP_FLAGS(flags, MSG_DRAFT);
}
flags.perm_flags = info->flags;