OP_COMPOSE_EDIT_REPLY_TO "edit the Reply-To field"
OP_COMPOSE_EDIT_SUBJECT "edit the subject of this message"
OP_COMPOSE_EDIT_TO "edit the TO list"
+OP_CREATE_MAILBOX "create a new mailbox (IMAP only)"
OP_EDIT_TYPE "edit attachment content type"
OP_COMPOSE_GET_ATTACHMENT "get a temporary copy of an attachment"
OP_COMPOSE_ISPELL "run ispell on the message"
OP_MAIN_UNDELETE_PATTERN "undelete messages matching a pattern"
OP_MAIN_UNTAG_PATTERN "untag messages matching a pattern"
OP_MIDDLE_PAGE "move to the middle of the page"
-OP_NEW_MAILBOX "create a new mailbox (IMAP only)"
OP_NEXT_ENTRY "move to the next entry"
OP_NEXT_LINE "scroll down one line"
OP_NEXT_PAGE "move to the next page"
snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
snprintf (dest, destlen, tmp, permission);
}
- else
- {
#ifdef USE_IMAP
- if (folder->ff->imap)
- {
- /* mark folders with subfolders AND mail */
- sprintf (permission, "IMAP %c",
- (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');
- snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
- snprintf (dest, destlen, tmp, permission);
- }
+ else if (folder->ff->imap)
+ {
+ /* mark folders with subfolders AND mail */
+ sprintf (permission, "IMAP %c",
+ (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');
+ snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
+ snprintf (dest, destlen, tmp, permission);
+ }
#endif
+ else
+ {
+ snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
+ snprintf (dest, destlen, tmp, "");
}
break;
break;
case 'N':
+#ifdef USE_IMAP
+ if (mx_is_imap (folder->ff->desc))
+ {
+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
+ snprintf (dest, destlen, tmp, folder->ff->new);
+ break;
+ }
+#endif
snprintf (tmp, sizeof (tmp), "%%%sc", fmt);
- snprintf (dest, destlen, tmp, folder->ff->is_new ? 'N' : ' ');
+ snprintf (dest, destlen, tmp, folder->ff->new ? 'N' : ' ');
break;
case 's':
memcpy ((state->entry)[state->entrylen].st, s, sizeof (struct stat));
}
- (state->entry)[state->entrylen].is_new = new;
+ (state->entry)[state->entrylen].new = new;
(state->entry)[state->entrylen].name = safe_strdup (name);
(state->entry)[state->entrylen].desc = safe_strdup (name);
#ifdef USE_IMAP
mutt_ungetch (0, OP_CHECK_NEW);
break;
- case OP_NEW_MAILBOX:
- mutt_error (_("Creating mailboxes is not yet supported."));
+ case OP_CREATE_MAILBOX:
+ if (!state.imap_browse)
+ mutt_error (_("Create is only supported for IMAP mailboxes"));
+ else
+ {
+ imap_mailbox_create (LastDir);
+ /* TODO: find a way to detect if the new folder would appear in
+ * this window, and insert it without starting over. */
+ destroy_state (&state);
+ init_state (&state, NULL);
+ state.imap_browse = 1;
+ imap_browse (LastDir, &state);
+ menu->data = state.entry;
+ menu->current = 0;
+ menu->top = 0;
+ init_menu (&state, menu, title, sizeof (title), buffy);
+ MAYBE_REDRAW (menu->redraw);
+ }
break;
case OP_DELETE_MAILBOX:
mutt_error (_("Delete is only supported for IMAP mailboxes"));
else
{
- char msg[LONG_STRING];
+ char msg[SHORT_STRING];
IMAP_MBOX mx;
int nentry = menu->current;
}
else
mutt_message _("Mailbox not deleted.");
+ FREE (&mx.mbox);
}
break;
#endif
char *name;
char *desc;
+
+ unsigned short new;
#ifdef USE_IMAP
char delim;
unsigned inferiors : 1;
#endif
unsigned tagged : 1;
- unsigned is_new : 1;
};
struct browser_state
char path[_POSIX_PATH_MAX];
struct stat contex_sb;
time_t t;
-#ifdef USE_IMAP
- static time_t last_imap_check = 0;
- int do_imap_check = 1;
-
- if (ImapCheckTimeout)
- {
- time_t now = time (NULL);
- if (now - last_imap_check < ImapCheckTimeout)
- do_imap_check = 0;
- else
- last_imap_check = now;
- }
+#ifdef USE_IMAP
/* update postponed count as well, on force */
if (force)
mutt_update_num_postponed ();
-
#endif
/* fastest return if there are no mailboxes */
for (tmp = Incoming; tmp; tmp = tmp->next)
{
+ tmp->new = 0;
+
#ifdef USE_IMAP
if ((tmp->magic == M_IMAP) || mx_is_imap (tmp->path))
tmp->magic = M_IMAP;
else
#endif
+ if (stat (tmp->path, &sb) != 0 || sb.st_size == 0 ||
+ (!tmp->magic && (tmp->magic = mx_get_magic (tmp->path)) <= 0))
{
- tmp->new = 0;
-
- if (stat (tmp->path, &sb) != 0 || sb.st_size == 0 ||
- (!tmp->magic && (tmp->magic = mx_get_magic (tmp->path)) <= 0))
- {
- /* if the mailbox still doesn't exist, set the newly created flag to
- * be ready for when it does.
- */
- tmp->newly_created = 1;
- tmp->magic = 0;
+ /* if the mailbox still doesn't exist, set the newly created flag to
+ * be ready for when it does. */
+ tmp->newly_created = 1;
+ tmp->magic = 0;
#ifdef BUFFY_SIZE
- tmp->size = 0;
+ tmp->size = 0;
#endif
- continue;
- }
+ continue;
}
/* check to see if the folder is the currently selected folder
* before polling */
if (!Context || !Context->path ||
#ifdef USE_IMAP
- /* unless folder is an IMAP folder */
- tmp->magic == M_IMAP ||
+ (tmp->magic == M_IMAP && mutt_strcmp (tmp->path, Context->path)) ||
+ (tmp->magic != M_IMAP && (
#endif
sb.st_dev != contex_sb.st_dev || sb.st_ino != contex_sb.st_ino)
+#ifdef USE_IMAP
+ ))
+#endif
{
switch (tmp->magic)
{
#ifdef USE_IMAP
case M_IMAP:
- /* poll on do_imap_check, else return cached value.
- * If the check is forced (eg on mailbox open), check only current
- * folder */
- if (do_imap_check || (force && Context && Context->path &&
- !mutt_strcmp (Context->path, tmp->path)))
- {
- tmp->new = 0;
- if (imap_mailbox_check (tmp->path, 1) > 0)
- {
- BuffyCount++;
- tmp->new = 1;
- }
- }
- else
- if (tmp->new)
- BuffyCount++;
+ if ((tmp->new = imap_mailbox_check (tmp->path, 1)) > 0)
+ BuffyCount++;
+ else
+ tmp->new = 0;
break;
#endif
<em/toggle-subscribed/ command. See also the
<ref id="imap_list_subscribed" name="$imap_list_subscribed"> variable.
-Polling for new mail is more expensive over IMAP than locally. For this reason
-the frequency at which Mutt will check for mail remotely can be controlled by
-the
-<ref id="imap_checkinterval" name="$imap_checkinterval">
-variable, which defaults to every 60 seconds.
+Polling for new mail on an IMAP server can cause noticeable delays. So, you'll
+want to carefully tune the
+<ref id="mail_check" name="$mail_check">
+and
+<ref id="timeout" name="$timeout">
+variables. Personally I use
+<tscreen><verb>
+set mail_check=90
+set timeout=15
+</verb></tscreen>
+with relatively good results over my slow modem line.
Note that if you are using mbox as the mail store on UW servers prior to
v12.250, the server has been reported to disconnect a client if another client
{ "toggle-mailboxes", OP_TOGGLE_MAILBOXES, "\t" },
{ "view-file", OP_BROWSER_VIEW_FILE, " " },
#ifdef USE_IMAP
- { "new-mailbox", OP_NEW_MAILBOX, "n" },
+ { "create-mailbox", OP_CREATE_MAILBOX, "C" },
{ "delete-mailbox", OP_DELETE_MAILBOX, "d" },
{ "subscribe", OP_BROWSER_SUBSCRIBE, "s" },
{ "unsubscribe", OP_BROWSER_UNSUBSCRIBE, "u" },
#ifdef USE_IMAP
WHERE char *ImapUser INITVAL (NULL);
WHERE char *ImapPass INITVAL (NULL);
-WHERE short ImapCheckTimeout;
WHERE char *ImapHomeNamespace INITVAL (NULL);
#endif
WHERE char *InReplyTo;
strfcpy (list_cmd, option (OPTIMAPLSUB) ? "LSUB" : "LIST", sizeof (list_cmd));
if (!(idata = imap_conn_find (&(mx.account), 0)))
- return -1;
+ goto fail;
- if (mx.mbox[0] == '\0')
+ if (!mx.mbox)
{
home_namespace = 1;
mbox[0] = '\0'; /* Do not replace "" with "INBOX" here */
- mx.mbox = ImapHomeNamespace;
+ mx.mbox = safe_strdup(ImapHomeNamespace);
nns = 0;
if (mutt_bit_isset(idata->capabilities,NAMESPACE))
{
mutt_message _("Getting namespaces...");
if (browse_get_namespace (idata, nsbuf, sizeof (nsbuf),
nsi, sizeof (nsi), &nns) != 0)
- return -1;
+ goto fail;
if (browse_verify_namespace (idata, nsi, nns) != 0)
- return -1;
+ goto fail;
}
}
{
if (imap_parse_list_response (idata, &cur_folder, &noselect,
&noinferiors, &idata->delim) != 0)
- return -1;
+ goto fail;
if (cur_folder)
{
* server to see if it has descendants. */
dprint (4, (debugfile, "imap_init_browse: adding INBOX\n"));
if (browse_add_list_result (idata, "LIST \"\" \"INBOX\"", state, 0))
- return -1;
+ goto fail;
}
nsup = state->entrylen;
snprintf (buf, sizeof (buf), "%s \"\" \"%s%%\"", list_cmd, mbox);
if (browse_add_list_result (idata, buf, state, 0))
- return -1;
+ goto fail;
qsort(&(state->entry[nsup]),state->entrylen-nsup,sizeof(state->entry[0]),
(int (*)(const void*,const void*)) compare_names);
}
mutt_clear_error ();
+ FREE (&mx.mbox);
+ return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
+}
+
+/* imap_mailbox_create: Prompt for a new mailbox name, and try to create it */
+int imap_mailbox_create (const char* folder)
+{
+ IMAP_DATA* idata;
+ IMAP_MBOX mx;
+ char buf[LONG_STRING];
+ short n;
+
+ if (imap_parse_path (folder, &mx) < 0)
+ {
+ dprint (1, (debugfile, "imap_mailbox_create: Bad starting path %s\n",
+ folder));
+ return -1;
+ }
+
+ if (!(idata = imap_conn_find (&mx.account, M_IMAP_CONN_NONEW)))
+ {
+ dprint (1, (debugfile, "imap_mailbox_create: Couldn't find open connection to %s", mx.account.host));
+ goto fail;
+ }
+
+ strfcpy (buf, NONULL (mx.mbox), sizeof (buf));
+
+ /* append a delimiter if necessary */
+ n = mutt_strlen (buf);
+ if (n && (n < sizeof (buf) - 1) && (buf[n-1] != idata->delim))
+ {
+ buf[n++] = idata->delim;
+ buf[n] = '\0';
+ }
+
+ if (mutt_get_field (_("Create mailbox: "), buf, sizeof (buf), M_FILE) < 0)
+ goto fail;
+
+ if (imap_create_mailbox (idata, buf) < 0)
+ goto fail;
+
+ mutt_message _("Mailbox created.");
+ sleep (1);
+
+ FREE (&mx.mbox);
return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
static int browse_add_list_result (IMAP_DATA* idata, const char* cmd,
{
if (imap_parse_list_response(idata, &name, &noselect, &noinferiors,
&idata->delim) != 0)
+ {
+ FREE (&mx.mbox);
return -1;
+ }
if (name)
{
}
while ((mutt_strncmp (idata->buf, idata->seq, SEQLEN) != 0));
+ FREE (&mx.mbox);
return 0;
}
* than at scan, since it's so expensive to scan. But that's big changes
* to browser.c */
if (!((regexec (Mask.rx, relpath, 0, NULL, 0) == 0) ^ Mask.not))
+ {
+ FREE (&mx.mbox);
return;
+ }
imap_qualify_path (tmp, sizeof (tmp), &mx, folder, NULL);
(state->entry)[state->entrylen].name = safe_strdup (tmp);
(state->entry)[state->entrylen].selectable = !noselect;
(state->entry)[state->entrylen].inferiors = !noinferiors;
(state->entrylen)++;
+
+ FREE (&mx.mbox);
}
static int compare_names(struct folder_file *a, struct folder_file *b)
{
/* read new mail messages */
dprint (2, (debugfile, "cmd_finish: Fetching new mail\n"));
- count = imap_read_headers (idata, idata->ctx->msgcount, count-1)+1;
/* check_status: curs_main uses imap_check_mailbox to detect
* whether the index needs updating */
idata->check_status = IMAP_NEWMAIL_PENDING;
idata->reopen &= ~IMAP_NEWMAIL_PENDING;
+ count = imap_read_headers (idata, idata->ctx->msgcount, count-1)+1;
}
else
{
static void imap_set_flag (IMAP_DATA* idata, int aclbit, int flag,
const char* str, char* flags);
-int imap_create_mailbox (CONTEXT* ctx, char* mailbox)
+int imap_create_mailbox (IMAP_DATA* idata, char* mailbox)
{
char buf[LONG_STRING], mbox[LONG_STRING];
imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);
snprintf (buf, sizeof (buf), "CREATE %s", mbox);
- if (imap_exec ((IMAP_DATA*) ctx->data, buf, 0) != 0)
- {
- imap_error ("imap_create_mailbox", CTX_DATA->buf);
+ if (imap_exec (idata, buf, 0) != 0)
return -1;
- }
return 0;
}
{
char buf[LONG_STRING], mbox[LONG_STRING];
- imap_quote_string (mbox, sizeof (mbox), mailbox);
+ imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);
snprintf (buf, sizeof (buf), "DELETE %s", mbox);
if (imap_exec ((IMAP_DATA*) ctx->data, buf, 0) != 0)
- {
- imap_error ("imap_delete_mailbox", CTX_DATA->buf);
return -1;
- }
return 0;
}
/* we require a connection which isn't currently in IMAP_SELECTED state */
if (!(idata = imap_conn_find (&(mx.account), M_IMAP_CONN_NOSELECT)))
- return -1;
+ goto fail;
conn = idata->conn;
/* once again the context is new */
ctx->data = idata;
if (idata->status == IMAP_FATAL)
- return -1;
+ goto fail;
/* Clean up path and replace the one in the ctx */
imap_fix_path (idata, mx.mbox, buf, sizeof (buf));
{
dprint (2, (debugfile, "Getting mailbox FLAGS\n"));
if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL)
- return -1;
+ goto fail;
}
}
/* PERMANENTFLAGS are massaged to look like FLAGS, then override FLAGS */
/* skip "OK [PERMANENT" so syntax is the same as FLAGS */
pc += 13;
if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL)
- return -1;
+ goto fail;
}
}
while (rc == IMAP_CMD_CONTINUE);
if (rc != IMAP_CMD_DONE)
- return -1;
+ goto fail;
/* check for READ-ONLY notification */
if (!strncmp (imap_get_qualifier (idata->buf), "[READ-ONLY]", 11))
mutt_error ("%s", s);
idata->state = IMAP_AUTHENTICATED;
sleep (1);
- return -1;
+ goto fail;
}
if (mutt_bit_isset (idata->capabilities, ACL))
{
if (imap_check_acl (idata))
- return -1;
+ goto fail;
}
/* assume we have all rights if ACL is unavailable */
else
count = imap_read_headers (idata, 0, count - 1) + 1;
dprint (1, (debugfile, "imap_open_mailbox(): msgcount is %d\n", ctx->msgcount));
+ FREE (&mx.mbox);
return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
int imap_open_mailbox_append (CONTEXT *ctx)
* ctx is brand new and mostly empty */
if (!(idata = imap_conn_find (&(mx.account), 0)))
- return -1;
+ goto fail;
conn = idata->conn;
ctx->magic = M_IMAP;
/* STATUS not supported */
mutt_message _("Unable to append to IMAP mailboxes at this server");
- return -1;
+ goto fail;
}
r = imap_exec (idata, buf, IMAP_CMD_FAIL_OK);
/* command failed cause folder doesn't exist */
snprintf (buf, sizeof (buf), _("Create %s?"), mailbox);
if (option (OPTCONFIRMCREATE) && mutt_yesorno (buf, 1) < 1)
- return -1;
+ goto fail;
- if (imap_create_mailbox (ctx, mailbox) < 0)
- return -1;
+ if (imap_create_mailbox (idata, mailbox) < 0)
+ goto fail;
}
else if (r == -1)
/* Hmm, some other failure */
- return -1;
+ goto fail;
+ FREE (&mx.mbox);
return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
/* imap_logout: Gracefully log out of server. */
mutt_remove_trailing_ws (flags);
- snprintf (buf, sizeof (buf), "STORE %d -FLAGS.SILENT (%s)",
- ctx->hdrs[n]->index + 1, flags);
+ snprintf (buf, sizeof (buf), "UID STORE %d -FLAGS.SILENT (%s)",
+ HEADER_DATA (ctx->hdrs[n])->uid, flags);
}
else
- snprintf (buf, sizeof (buf), "STORE %d FLAGS.SILENT (%s)",
- ctx->hdrs[n]->index + 1, flags);
+ snprintf (buf, sizeof (buf), "UID STORE %d FLAGS.SILENT (%s)",
+ HEADER_DATA (ctx->hdrs[n])->uid, flags);
/* after all this it's still possible to have no flags, if you
* have no ACL rights */
if (!idata)
return;
- idata->reopen &= IMAP_REOPEN_ALLOW;
-
if ((idata->status != IMAP_FATAL) &&
(idata->state == IMAP_SELECTED) &&
(ctx == idata->ctx))
{
if (!(idata->noclose) && imap_exec (idata, "CLOSE", 0))
imap_error ("CLOSE failed", idata->buf);
-
+
+ idata->reopen &= IMAP_REOPEN_ALLOW;
idata->state = IMAP_AUTHENTICATED;
FREE (&(idata->mailbox));
}
*/
int imap_check_mailbox (CONTEXT *ctx, int *index_hint)
{
- static time_t checktime=0;
+ /* overload keyboard timeout to avoid many mailbox checks in a row.
+ * Most users don't like having to wait exactly when they press a key. */
+ static time_t LastCheck = 0;
IMAP_DATA* idata;
- time_t t = 0;
+ time_t now;
idata = (IMAP_DATA*) ctx->data;
- /*
- * gcc thinks it has to warn about uninitialized use
- * of t. This is wrong.
- */
-
- if (ImapCheckTimeout)
- {
- t = time(NULL);
- t -= checktime;
- }
-
- /* TODO: wtf?! */
- if ((ImapCheckTimeout && t >= ImapCheckTimeout)
- || ((idata->reopen & IMAP_REOPEN_ALLOW) && (idata->reopen & ~IMAP_REOPEN_ALLOW)))
- {
- if (ImapCheckTimeout) checktime += t;
+ now = time(NULL);
+ if (now > LastCheck + Timeout) {
+ LastCheck = now;
if (imap_exec (idata, "NOOP", 0) != 0)
{
imap_error ("imap_check_mailbox", idata->buf);
return -1;
}
+ }
- if (idata->check_status & IMAP_NEWMAIL_PENDING)
- {
- idata->check_status &= ~IMAP_NEWMAIL_PENDING;
- return M_NEW_MAIL;
- }
-
- /* TODO: we should be able to detect external changes and return
- * M_REOPENED here. */
+ if (idata->check_status & IMAP_NEWMAIL_PENDING)
+ {
+ idata->check_status &= ~IMAP_NEWMAIL_PENDING;
+ return M_NEW_MAIL;
}
+ /* TODO: we should be able to detect external changes and return
+ * M_REOPENED here. */
return 0;
}
connflags = M_IMAP_CONN_NONEW;
if (!(idata = imap_conn_find (&(mx.account), connflags)))
- return -1;
+ goto fail;
conn = idata->conn;
imap_fix_path (idata, mx.mbox, buf, sizeof (buf));
new ? "RECENT" : "MESSAGES");
}
else
- {
/* Server does not support STATUS, and this is not the current mailbox.
* There is no lightweight way to check recent arrivals */
- return -1;
- }
+ goto fail;
imap_cmd_start (idata, buf);
{
if (*s != '0')
{
- dprint (1, (debugfile, "Mail in %s\n", path));
msgcount = atoi(s);
+ dprint (2, (debugfile, "%d new messages in %s\n", msgcount, path));
}
}
}
}
while (rc == IMAP_CMD_CONTINUE);
+ FREE (&mx.mbox);
return msgcount;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
/* all this listing/browsing is a mess. I don't like that name is a pointer
return -1;
if (!(idata = imap_conn_find (&(mx.account), 0)))
- return -1;
+ goto fail;
conn = idata->conn;
"UNSUBSCRIBE", mbox);
if (imap_exec (idata, buf, 0) < 0)
- return -1;
+ goto fail;
+ FREE (&mx.mbox);
return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
/* imap_complete: given a partial IMAP folder path, return a string which
/* don't open a new socket just for completion */
if (!(idata = imap_conn_find (&(mx.account), M_IMAP_CONN_NONEW)))
- return -1;
+ goto fail;
conn = idata->conn;
/* reformat path for IMAP list, and append wildcard */
imap_qualify_path (dest, dlen, &mx, completion, NULL);
mutt_pretty_mailbox (dest);
+ FREE (&mx.mbox);
return 0;
}
+ fail:
+ FREE (&mx.mbox);
return -1;
}
/* imap.c */
int imap_check_mailbox (CONTEXT *ctx, int *index_hint);
-int imap_create_mailbox (CONTEXT* idata, char* mailbox);
int imap_close_connection (CONTEXT *ctx);
int imap_delete_mailbox (CONTEXT* idata, char* mailbox);
int imap_open_mailbox (CONTEXT *ctx);
/* browse.c */
int imap_browse (char* path, struct browser_state* state);
+int imap_mailbox_create (const char* folder);
/* message.c */
int imap_append_message (CONTEXT* ctx, MESSAGE* msg);
#define SEQLEN 5
#define IMAP_REOPEN_ALLOW (1<<0)
-#define IMAP_EXPUNGE_PENDING (1<<1)
+#define IMAP_EXPUNGE_PENDING (1<<1)
#define IMAP_NEWMAIL_PENDING (1<<2)
/* imap_exec flags (see imap_exec) */
/* -- private IMAP functions -- */
/* imap.c */
+int imap_create_mailbox (IMAP_DATA* idata, char* mailbox);
int imap_make_msg_set (IMAP_DATA* idata, char* buf, size_t buflen, int flag,
int changed);
int imap_open_connection (IMAP_DATA* idata);
int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
{
IMAP_DATA* idata;
+ HEADER* h;
char buf[LONG_STRING];
char path[_POSIX_PATH_MAX];
char *pc;
!ctx->hdrs[msgno]->changed)
{
IMAP_HEADER newh;
- HEADER* h = ctx->hdrs[msgno];
unsigned char readonly;
+ h = ctx->hdrs[msgno];
+
memset (&newh, 0, sizeof (newh));
newh.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA));
/* Update the header information. Previously, we only downloaded a
* portion of the headers, those required for the main display.
*/
+ h = ctx->hdrs[msgno];
rewind (msg->fp);
- mutt_free_envelope (&ctx->hdrs[msgno]->env);
- ctx->hdrs[msgno]->env = mutt_read_rfc822_header (msg->fp, ctx->hdrs[msgno],0, 0);
- ctx->hdrs[msgno]->lines = 0;
+ /* I hate do this here, since it's so low-level, but I'm not sure where
+ * I can abstract it. Problem: the id and subj hashes lose their keys when
+ * mutt_free_envelope gets called, but keep their spots in the hash. This
+ * confuses threading. Alternatively we could try to merge the new
+ * envelope into the old one. Also messy and lowlevel. */
+ if (h->env->message_id)
+ hash_delete (ctx->id_hash, h->env->message_id, h, NULL);
+ if (h->env->real_subj)
+ hash_delete (ctx->subj_hash, h->env->real_subj, h, NULL);
+ mutt_free_envelope (&h->env);
+ h->env = mutt_read_rfc822_header (msg->fp, h, 0, 0);
+ if (h->env->message_id)
+ hash_insert (ctx->id_hash, h->env->message_id, h, 0);
+ if (h->env->real_subj)
+ hash_insert (ctx->subj_hash, h->env->real_subj, h, 1);
+
+ h->lines = 0;
fgets (buf, sizeof (buf), msg->fp);
while (!feof (msg->fp))
{
- ctx->hdrs[msgno]->lines++;
+ h->lines++;
fgets (buf, sizeof (buf), msg->fp);
}
- ctx->hdrs[msgno]->content->length = ftell (msg->fp) -
- ctx->hdrs[msgno]->content->offset;
+ h->content->length = ftell (msg->fp) - h->content->offset;
/* This needs to be done in case this is a multipart message */
#ifdef HAVE_PGP
- ctx->hdrs[msgno]->pgp = pgp_query (ctx->hdrs[msgno]->content);
+ h->pgp = pgp_query (h->content);
#endif /* HAVE_PGP */
mutt_clear_error();
if ((fp = fopen (msg->path, "r")) == NULL)
{
mutt_perror (msg->path);
- return (-1);
+ goto fail;
}
for (last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c)
mutt_error ("%s", pc);
sleep (1);
fclose (fp);
- return (-1);
+ goto fail;
}
mutt_message _("Uploading message ...");
pc = imap_next_word (pc);
mutt_error ("%s", pc);
sleep (1);
- return (-1);
+ goto fail;
}
+ FREE (&mx.mbox);
return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
/* imap_copy_messages: use server COPY command to copy messages to another
{
dprint (3, (debugfile, "imap_copy_message: %s not same server as %s\n",
dest, ctx->path));
- return 1;
+ goto fail;
}
imap_fix_path (idata, mx.mbox, cmd, sizeof (cmd));
if (!rc)
{
dprint (1, (debugfile, "imap_copy_messages: No messages tagged\n"));
- return -1;
+ goto fail;
}
mutt_message (_("Copying %d messages to %s..."), rc, cmd);
}
if (strncmp (imap_get_qualifier (idata->buf), "[TRYCREATE]", 11))
{
imap_error ("imap_copy_messages", idata->buf);
- return -1;
+ goto fail;
}
dprint (2, (debugfile, "imap_copy_messages: server suggests TRYCREATE\n"));
snprintf (buf, sizeof (buf), _("Create %s?"), mbox);
if (option (OPTCONFIRMCREATE) && mutt_yesorno (buf, 1) < 1)
{
mutt_clear_error ();
- return -1;
+ goto fail;
}
- if (imap_create_mailbox (ctx, mbox) < 0)
- return -1;
+ if (imap_create_mailbox (idata, mbox) < 0)
+ goto fail;
/* try again */
rc = imap_exec (idata, cmd, 0);
if (rc != 0)
{
imap_error ("imap_copy_messages", idata->buf);
- return -1;
+ goto fail;
}
/* cleanup */
}
}
+ FREE (&mx.mbox);
return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
/* imap_add_keywords: concatenate custom IMAP tags to list, if they
}
/* imap_parse_path: given an IMAP mailbox name, return host, port
- * and a path IMAP servers will recognise. */
+ * and a path IMAP servers will recognise.
+ * mx.mbox is malloc'd, caller must free it */
int imap_parse_path (const char* path, IMAP_MBOX* mx)
{
char tmp[128];
return -1;
else
/* walk past closing '}' */
- mx->mbox = strdup (c+1);
+ mx->mbox = safe_strdup (c+1);
/* Defaults */
mx->account.flags = 0;
if ((n = sscanf (tmp, "%128[^:/]%128s", mx->account.host, tmp)) < 1)
{
dprint (1, (debugfile, "imap_parse_path: NULL host in %s\n", path));
+ FREE (&mx->mbox);
return -1;
}
#endif
{
dprint (1, (debugfile, "imap_parse_path: Unknown connection type in %s\n", path));
+ FREE (&mx->mbox);
return -1;
}
}
sigaction (SIGALRM, &act, &oldalrm);
- alarm (ImapCheckTimeout > 0 ? ImapCheckTimeout : 60);
+ /* RFC 2060 specifies a minimum of 30 minutes before disconnect when in
+ * the AUTHENTICATED state. We'll poll at half that. */
+ alarm (900);
while (waitpid (pid, &rc, 0) < 0 && errno == EINTR)
{
alarm (0); /* cancel a possibly pending alarm */
imap_keepalive ();
- alarm (ImapCheckTimeout > 0 ? ImapCheckTimeout : 60);
+ alarm (900);
}
alarm (0); /* cancel a possibly pending alarm */
** list.
*/
#ifdef USE_IMAP
- { "imap_checkinterval", DT_NUM, R_NONE, UL &ImapCheckTimeout, 60 },
- /*
- ** .pp
- ** This variable configures how often (in seconds) IMAP should look for
- ** new mail.
- */
# ifdef USE_SSL
{ "imap_force_ssl", DT_BOOL, R_NONE, OPTIMAPFORCESSL, 0 },
/*