📄 message.c
字号:
mutt_message _("Fetching message..."); if (!(msg->fp = msg_cache_put (idata, h))) { cache->uid = HEADER_DATA(h)->uid; mutt_mktemp (path); cache->path = safe_strdup (path); if (!(msg->fp = safe_fopen (path, "w+"))) { FREE (&cache->path); return -1; } } /* mark this header as currently inactive so the command handler won't * also try to update it. HACK until all this code can be moved into the * command handler */ h->active = 0; snprintf (buf, sizeof (buf), "UID FETCH %u %s", HEADER_DATA(h)->uid, (mutt_bit_isset (idata->capabilities, IMAP4REV1) ? (option (OPTIMAPPEEK) ? "BODY.PEEK[]" : "BODY[]") : "RFC822")); imap_cmd_start (idata, buf); do { if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE) break; pc = idata->buf; pc = imap_next_word (pc); pc = imap_next_word (pc); if (!ascii_strncasecmp ("FETCH", pc, 5)) { while (*pc) { pc = imap_next_word (pc); if (pc[0] == '(') pc++; if (ascii_strncasecmp ("UID", pc, 3) == 0) { pc = imap_next_word (pc); uid = atoi (pc); if (uid != HEADER_DATA(h)->uid) mutt_error (_("The message index is incorrect. Try reopening the mailbox.")); } else if ((ascii_strncasecmp ("RFC822", pc, 6) == 0) || (ascii_strncasecmp ("BODY[]", pc, 6) == 0)) { pc = imap_next_word (pc); if (imap_get_literal_count(pc, &bytes) < 0) { imap_error ("imap_fetch_message()", buf); goto bail; } progressbar.size = bytes; progressbar.msg = _("Fetching message..."); mutt_progress_bar (&progressbar, 0); if (imap_read_literal (msg->fp, idata, bytes, &progressbar) < 0) goto bail; /* pick up trailing line */ if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE) goto bail; pc = idata->buf; fetched = 1; } /* UW-IMAP will provide a FLAGS update here if the FETCH causes a * change (eg from \Unseen to \Seen). * Uncommitted changes in mutt take precedence. If we decide to * incrementally update flags later, this won't stop us syncing */ else if ((ascii_strncasecmp ("FLAGS", pc, 5) == 0) && !h->changed) { if ((pc = imap_set_flags (idata, h, pc)) == NULL) goto bail; } } } } while (rc == IMAP_CMD_CONTINUE); /* see comment before command start. */ h->active = 1; fflush (msg->fp); if (ferror (msg->fp)) { mutt_perror (cache->path); goto bail; } if (rc != IMAP_CMD_OK) goto bail; if (!fetched || !imap_code (idata->buf)) goto bail;parsemsg: /* Update the header information. Previously, we only downloaded a * portion of the headers, those required for the main display. */ rewind (msg->fp); /* It may be that the Status header indicates a message is read, but the * IMAP server doesn't know the message has been \Seen. So we capture * the server's notion of 'read' and if it differs from the message info * picked up in mutt_read_rfc822_header, we mark the message (and context * changed). Another possiblity: ignore Status on IMAP?*/ read = h->read; newenv = mutt_read_rfc822_header (msg->fp, h, 0, 0); mutt_merge_envelopes(h->env, &newenv); /* see above. We want the new status in h->read, so we unset it manually * and let mutt_set_flag set it correctly, updating context. */ if (read != h->read) { h->read = read; mutt_set_flag (ctx, h, M_NEW, read); } h->lines = 0; fgets (buf, sizeof (buf), msg->fp); while (!feof (msg->fp)) { h->lines++; fgets (buf, sizeof (buf), msg->fp); } h->content->length = ftell (msg->fp) - h->content->offset; /* This needs to be done in case this is a multipart message */#if defined(HAVE_PGP) || defined(HAVE_SMIME) h->security = crypt_query (h->content);#endif mutt_clear_error(); rewind (msg->fp); HEADER_DATA(h)->parsed = 1; return 0;bail: safe_fclose (&msg->fp); imap_cache_del (idata, h); if (cache->path) { unlink (cache->path); FREE (&cache->path); } return -1;}int imap_append_message (CONTEXT *ctx, MESSAGE *msg){ IMAP_DATA* idata; FILE *fp; char buf[LONG_STRING]; char mbox[LONG_STRING]; char mailbox[LONG_STRING]; size_t len; progress_t progressbar; size_t sent; int c, last; IMAP_MBOX mx; int rc; idata = (IMAP_DATA*) ctx->data; if (imap_parse_path (ctx->path, &mx)) return -1; imap_fix_path (idata, mx.mbox, mailbox, sizeof (mailbox)); if ((fp = fopen (msg->path, "r")) == NULL) { mutt_perror (msg->path); goto fail; } /* currently we set the \Seen flag on all messages, but probably we * should scan the message Status header for flag info. Since we're * already rereading the whole file for length it isn't any more * expensive (it'd be nice if we had the file size passed in already * by the code that writes the file, but that's a lot of changes. * Ideally we'd have a HEADER structure with flag info here... */ for (last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c) { if(c == '\n' && last != '\r') len++; len++; } rewind (fp); progressbar.msg = _("Uploading message..."); progressbar.size = len; mutt_progress_bar (&progressbar, 0); imap_munge_mbox_name (mbox, sizeof (mbox), mailbox); snprintf (buf, sizeof (buf), "APPEND %s (%s%s%s%s%s) {%lu}", mbox, msg->flags.read ? "\\Seen" : "", msg->flags.read && (msg->flags.replied || msg->flags.flagged) ? " " : "", msg->flags.replied ? "\\Answered" : "", msg->flags.replied && msg->flags.flagged ? " " : "", msg->flags.flagged ? "\\Flagged" : "", (unsigned long) len); imap_cmd_start (idata, buf); do rc = imap_cmd_step (idata); while (rc == IMAP_CMD_CONTINUE); if (rc != IMAP_CMD_RESPOND) { char *pc; dprint (1, (debugfile, "imap_append_message(): command failed: %s\n", idata->buf)); pc = idata->buf + SEQLEN; SKIPWS (pc); pc = imap_next_word (pc); mutt_error ("%s", pc); mutt_sleep (1); fclose (fp); goto fail; } for (last = EOF, sent = len = 0; (c = fgetc(fp)) != EOF; last = c) { if (c == '\n' && last != '\r') buf[len++] = '\r'; buf[len++] = c; if (len > sizeof(buf) - 3) { sent += len; flush_buffer(buf, &len, idata->conn); mutt_progress_bar (&progressbar, sent); } } if (len) flush_buffer(buf, &len, idata->conn); mutt_socket_write (idata->conn, "\r\n"); fclose (fp); do rc = imap_cmd_step (idata); while (rc == IMAP_CMD_CONTINUE); if (!imap_code (idata->buf)) { char *pc; dprint (1, (debugfile, "imap_append_message(): command failed: %s\n", idata->buf)); pc = idata->buf + SEQLEN; SKIPWS (pc); pc = imap_next_word (pc); mutt_error ("%s", pc); mutt_sleep (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 * folder. * Return codes: * -1: error * 0: success * 1: non-fatal error - try fetch/append */int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete){ IMAP_DATA* idata; BUFFER cmd, sync_cmd; char uid[11]; char mbox[LONG_STRING]; char mmbox[LONG_STRING]; int rc; int n; IMAP_MBOX mx; int err_continue = M_NO; idata = (IMAP_DATA*) ctx->data; if (imap_parse_path (dest, &mx)) { dprint (1, (debugfile, "imap_copy_messages: bad destination %s\n", dest)); return -1; } /* check that the save-to folder is in the same account */ if (!mutt_account_match (&(CTX_DATA->conn->account), &(mx.account))) { dprint (3, (debugfile, "imap_copy_messages: %s not same server as %s\n", dest, ctx->path)); return 1; } if (h && h->attach_del) { dprint (3, (debugfile, "imap_copy_messages: Message contains attachments to be deleted\n")); return 1; } imap_fix_path (idata, mx.mbox, mbox, sizeof (mbox)); memset (&sync_cmd, 0, sizeof (sync_cmd)); memset (&cmd, 0, sizeof (cmd)); mutt_buffer_addstr (&cmd, "UID COPY "); /* Null HEADER* means copy tagged messages */ if (!h) { /* if any messages have attachments to delete, fall through to FETCH * and APPEND. TODO: Copy what we can with COPY, fall through for the * remainder. */ for (n = 0; n < ctx->msgcount; n++) { if (ctx->hdrs[n]->tagged && ctx->hdrs[n]->attach_del) { dprint (3, (debugfile, "imap_copy_messages: Message contains attachments to be deleted\n")); return 1; } if (ctx->hdrs[n]->tagged && ctx->hdrs[n]->active && ctx->hdrs[n]->changed) { rc = imap_sync_message (idata, ctx->hdrs[n], &sync_cmd, &err_continue); if (rc < 0) { dprint (1, (debugfile, "imap_copy_messages: could not sync\n")); goto fail; } } } rc = imap_make_msg_set (idata, &cmd, M_TAG, 0, 0); if (!rc) { dprint (1, (debugfile, "imap_copy_messages: No messages tagged\n")); goto fail; } mutt_message (_("Copying %d messages to %s..."), rc, mbox); } else { mutt_message (_("Copying message %d to %s..."), h->index+1, mbox); snprintf (uid, sizeof (uid), "%u", HEADER_DATA (h)->uid); mutt_buffer_addstr (&cmd, uid); if (h->active && h->changed) { rc = imap_sync_message (idata, h, &sync_cmd, &err_continue); if (rc < 0) { dprint (1, (debugfile, "imap_copy_messages: could not sync\n")); goto fail; } } } /* let's get it on */ mutt_buffer_addstr (&cmd, " "); imap_munge_mbox_name (mmbox, sizeof (mmbox), mbox); mutt_buffer_addstr (&cmd, mmbox); rc = imap_exec (idata, cmd.data, IMAP_CMD_FAIL_OK); if (rc == -2) { /* bail out if command failed for reasons other than nonexistent target */ if (ascii_strncasecmp (imap_get_qualifier (idata->buf), "[TRYCREATE]", 11)) { imap_error ("imap_copy_messages", idata->buf); goto fail; } dprint (2, (debugfile, "imap_copy_messages: server suggests TRYCREATE\n")); snprintf (mmbox, sizeof (mmbox), _("Create %s?"), mbox); if (option (OPTCONFIRMCREATE) && mutt_yesorno (mmbox, 1) < 1) { mutt_clear_error (); goto fail; } if (imap_create_mailbox (idata, mbox) < 0) goto fail; /* try again */ rc = imap_exec (idata, cmd.data, 0); } if (rc != 0) { imap_error ("imap_copy_messages", idata->buf); goto fail; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -