⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imap.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 4 页
字号:
  char uid[11];  hdr->changed = 0;  if (!compare_flags (hdr))  {    idata->ctx->changed--;    return 0;  }  snprintf (uid, sizeof (uid), "%u", HEADER_DATA(hdr)->uid);  cmd->dptr = cmd->data;  mutt_buffer_addstr (cmd, "UID STORE ");  mutt_buffer_addstr (cmd, uid);  flags[0] = '\0';        imap_set_flag (idata, IMAP_ACL_SEEN, hdr->read, "\\Seen ",		 flags, sizeof (flags));  imap_set_flag (idata, IMAP_ACL_WRITE, hdr->old,                 "Old ", flags, sizeof (flags));  imap_set_flag (idata, IMAP_ACL_WRITE, hdr->flagged,		 "\\Flagged ", flags, sizeof (flags));  imap_set_flag (idata, IMAP_ACL_WRITE, hdr->replied,		 "\\Answered ", flags, sizeof (flags));  imap_set_flag (idata, IMAP_ACL_DELETE, hdr->deleted,		 "\\Deleted ", flags, sizeof (flags));  /* now make sure we don't lose custom tags */  if (mutt_bit_isset (idata->rights, IMAP_ACL_WRITE))    imap_add_keywords (flags, hdr, idata->flags, sizeof (flags));  mutt_remove_trailing_ws (flags);  /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to   * explicitly revoke all system flags (if we have permission) */  if (!*flags)  {    imap_set_flag (idata, IMAP_ACL_SEEN, 1, "\\Seen ", flags, sizeof (flags));    imap_set_flag (idata, IMAP_ACL_WRITE, 1, "Old ", flags, sizeof (flags));    imap_set_flag (idata, IMAP_ACL_WRITE, 1, "\\Flagged ", flags, sizeof (flags));    imap_set_flag (idata, IMAP_ACL_WRITE, 1, "\\Answered ", flags, sizeof (flags));    imap_set_flag (idata, IMAP_ACL_DELETE, 1, "\\Deleted ", flags, sizeof (flags));    mutt_remove_trailing_ws (flags);    mutt_buffer_addstr (cmd, " -FLAGS.SILENT (");  } else    mutt_buffer_addstr (cmd, " FLAGS.SILENT (");  mutt_buffer_addstr (cmd, flags);  mutt_buffer_addstr (cmd, ")");  /* dumb hack for bad UW-IMAP 4.7 servers spurious FLAGS updates */  hdr->active = 0;  /* after all this it's still possible to have no flags, if you   * have no ACL rights */  if (*flags && (imap_exec (idata, cmd->data, 0) != 0) &&      err_continue && (*err_continue != M_YES))  {    *err_continue = imap_continue ("imap_sync_message: STORE failed",				   idata->buf);    if (*err_continue != M_YES)      return -1;  }  hdr->active = 1;  idata->ctx->changed--;  return 0;}static int sync_helper (IMAP_DATA* idata, BUFFER* buf, int right, int flag,                        const char* name){  int rc = 0;  if (!mutt_bit_isset (idata->rights, right))    return 0;    if (right == IMAP_ACL_WRITE && !imap_has_flag (idata->flags, name))    return 0;  buf->dptr = buf->data;  mutt_buffer_addstr (buf, "UID STORE ");  if (imap_make_msg_set (idata, buf, flag, 1, 0))  {    rc++;    mutt_buffer_printf (buf, " +FLAGS.SILENT (%s)", name);    imap_cmd_queue (idata, buf->data);  }  buf->dptr = buf->data;  mutt_buffer_addstr (buf, "UID STORE ");  if (imap_make_msg_set (idata, buf, flag, 1, 1))  {    rc++;    mutt_buffer_printf (buf, " -FLAGS.SILENT (%s)", name);    imap_cmd_queue (idata, buf->data);  }    return rc;}/* update the IMAP server to reflect message changes done within mutt. * Arguments *   ctx: the current context *   expunge: 0 or 1 - do expunge?  */int imap_sync_mailbox (CONTEXT* ctx, int expunge, int* index_hint){  IMAP_DATA* idata;  CONTEXT* appendctx = NULL;  BUFFER cmd;  HEADER* h;  HEADER** hdrs = NULL;  int oldsort;  int deleted;  int n;  int rc;#if USE_HCACHE  void* hc = NULL;  char uidbuf[32];#endif    idata = (IMAP_DATA*) ctx->data;  if (idata->state < IMAP_SELECTED)  {    dprint (2, (debugfile, "imap_sync_mailbox: no mailbox selected\n"));    return -1;  }  /* This function is only called when the calling code	expects the context   * to be changed. */  imap_allow_reopen (ctx);  if ((rc = imap_check_mailbox (ctx, index_hint, 0)) != 0)    return rc;  memset (&cmd, 0, sizeof (cmd));  /* if we are expunging anyway, we can do deleted messages very quickly... */  if (expunge && mutt_bit_isset (idata->rights, IMAP_ACL_DELETE))  {    mutt_buffer_addstr (&cmd, "UID STORE ");    deleted = imap_make_msg_set (idata, &cmd, M_DELETED, 1, 0);    /* if we have a message set, then let's delete */    if (deleted)    {      mutt_message (_("Marking %d messages deleted..."), deleted);      mutt_buffer_addstr (&cmd, " +FLAGS.SILENT (\\Deleted)");      /* mark these messages as unchanged so second pass ignores them. Done       * here so BOGUS UW-IMAP 4.7 SILENT FLAGS updates are ignored. */      for (n = 0; n < ctx->msgcount; n++)	if (ctx->hdrs[n]->deleted && ctx->hdrs[n]->changed)	  ctx->hdrs[n]->active = 0;      if (imap_exec (idata, cmd.data, 0) != 0)      {	mutt_error (_("Expunge failed"));	mutt_sleep (1);	rc = -1;	goto out;      }    }  }#if USE_HCACHE  if (expunge && ctx->closing)    hc = mutt_hcache_open (HeaderCache, idata->ctx->path);#endif  /* save messages with real (non-flag) changes */  for (n = 0; n < ctx->msgcount; n++)  {    h = ctx->hdrs[n];    if (h->deleted)      imap_cache_del (idata, h);#if USE_HCACHE    if (hc && h->deleted)    {      sprintf (uidbuf, "/%u", HEADER_DATA(h)->uid);      mutt_hcache_delete (hc, uidbuf, imap_hcache_keylen);    }#endif    if (h->active && h->changed)    {      /* if the message has been rethreaded or attachments have been deleted       * we delete the message and reupload it.       * This works better if we're expunging, of course. */      if ((h->env && (h->env->refs_changed || h->env->irt_changed)) ||	  h->attach_del)      {        mutt_message (_("Saving changed messages... [%d/%d]"), n+1,                      ctx->msgcount);	if (!appendctx)	  appendctx = mx_open_mailbox (ctx->path, M_APPEND | M_QUIET, NULL);	if (!appendctx)	{	  dprint (1, (debugfile, "imap_sync_mailbox: Error opening mailbox in append mode\n"));	}	else	  _mutt_save_message (h, appendctx, 1, 0, 0);      }    }  }  /* sync +/- flags for the five flags mutt cares about */  rc = 0;  /* presort here to avoid doing 10 resorts in imap_make_msg_set */  oldsort = Sort;  if (Sort != SORT_ORDER)  {    hdrs = ctx->hdrs;    ctx->hdrs = safe_malloc (ctx->msgcount * sizeof (HEADER*));    memcpy (ctx->hdrs, hdrs, ctx->msgcount * sizeof (HEADER*));    oldsort = Sort;    Sort = SORT_ORDER;    qsort (ctx->hdrs, ctx->msgcount, sizeof (HEADER*),           mutt_get_sort_func (SORT_ORDER));  }  rc += sync_helper (idata, &cmd, IMAP_ACL_DELETE, M_DELETED, "\\Deleted");  rc += sync_helper (idata, &cmd, IMAP_ACL_WRITE, M_FLAG, "\\Flagged");  rc += sync_helper (idata, &cmd, IMAP_ACL_WRITE, M_OLD, "Old");  rc += sync_helper (idata, &cmd, IMAP_ACL_SEEN, M_READ, "\\Seen");  rc += sync_helper (idata, &cmd, IMAP_ACL_WRITE, M_REPLIED, "\\Answered");  if (oldsort != Sort)  {    Sort = oldsort;    FREE (&ctx->hdrs);    ctx->hdrs = hdrs;  }  if (rc)  {    if ((rc = imap_exec (idata, NULL, 0)) != IMAP_CMD_OK)    {      if (ctx->closing)      {        if (mutt_yesorno (_("Error saving flags. Close anyway?"), 0) == M_YES)        {          rc = 0;          idata->state = IMAP_AUTHENTICATED;          goto out;        }      }      else        mutt_error _("Error saving flags");      goto out;    }  }  for (n = 0; n < ctx->msgcount; n++)    ctx->hdrs[n]->changed = 0;  ctx->changed = 0;  /* We must send an EXPUNGE command if we're not closing. */  if (expunge && !(ctx->closing) &&      mutt_bit_isset(idata->rights, IMAP_ACL_DELETE))  {    mutt_message _("Expunging messages from server...");    /* Set expunge bit so we don't get spurious reopened messages */    idata->reopen |= IMAP_EXPUNGE_EXPECTED;    if (imap_exec (idata, "EXPUNGE", 0) != 0)    {      imap_error (_("imap_sync_mailbox: EXPUNGE failed"), idata->buf);      rc = -1;      goto out;    }  }  if (expunge && ctx->closing)  {    imap_cmd_queue (idata, "CLOSE");    idata->state = IMAP_AUTHENTICATED;  }  rc = 0; out:#if USE_HCACHE  mutt_hcache_close (hc);#endif  if (cmd.data)    FREE (&cmd.data);  if (appendctx)  {    mx_fastclose_mailbox (appendctx);    FREE (&appendctx);  }  return rc;}/* imap_close_mailbox: clean up IMAP data in CONTEXT */void imap_close_mailbox (CONTEXT* ctx){  IMAP_DATA* idata;  int i;  idata = (IMAP_DATA*) ctx->data;  /* Check to see if the mailbox is actually open */  if (!idata)    return;  if (ctx == idata->ctx)  {    if (idata->status != IMAP_FATAL && idata->state >= IMAP_SELECTED)    {      /* mx_close_mailbox won't sync if there are no deleted messages       * and the mailbox is unchanged, so we may have to close here */      if (!ctx->deleted)        imap_cmd_queue (idata, "CLOSE");      if (idata->state == IMAP_IDLE)      {        mutt_buffer_addstr (idata->cmdbuf, "DONE\r\n");        idata->state = IMAP_SELECTED;      }            idata->state = IMAP_AUTHENTICATED;    }    idata->reopen &= IMAP_REOPEN_ALLOW;    FREE (&(idata->mailbox));    mutt_free_list (&idata->flags);    idata->ctx = NULL;  }  /* free IMAP part of headers */  for (i = 0; i < ctx->msgcount; i++)    imap_free_header_data (&(ctx->hdrs[i]->data));  for (i = 0; i < IMAP_CACHE_LEN; i++)  {    if (idata->cache[i].path)    {      unlink (idata->cache[i].path);      FREE (&idata->cache[i].path);    }  }  mutt_bcache_close (&idata->bcache);}/* use the NOOP or IDLE command to poll for new mail * * return values: *	M_REOPENED	mailbox has been externally modified *	M_NEW_MAIL	new mail has arrived! *	0		no change *	-1		error */int imap_check_mailbox (CONTEXT *ctx, int *index_hint, int force){  /* 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. */  IMAP_DATA* idata;  int result = 0;  idata = (IMAP_DATA*) ctx->data;  /* try IDLE first, unless force is set */  if (!force && option (OPTIMAPIDLE) && mutt_bit_isset (idata->capabilities, IDLE)      && (idata->state != IMAP_IDLE || time(NULL) >= idata->lastread + ImapKeepalive))  {    imap_cmd_start (idata, "IDLE");    idata->state = IMAP_IDLE;    do      result = imap_cmd_step (idata);    while (result == IMAP_CMD_CONTINUE);    /* it's possible that we were notified and fetched mail before     * getting to the +, in which case we've automatically unidled. */    if (result != IMAP_CMD_RESPOND && result != IMAP_CMD_OK)    {      dprint (1, (debugfile, "Error starting IDLE\n"));      idata->state = IMAP_SELECTED;      return -1;    }  }  if (idata->state == IMAP_IDLE)  {    while ((result = mutt_socket_poll (idata->conn)) > 0)    {      if (imap_cmd_step (idata) != IMAP_CMD_CONTINUE)      {        dprint (1, (debugfile, "Error reading IDLE response\n"));        return -1;      }    }    if (result < 0)    {      dprint (1, (debugfile, "Poll failed, disabling IDLE\n"));      mutt_bit_unset (idata->capabilities, IDLE);    }  }  if ((force ||        (idata->state != IMAP_IDLE && time(NULL) >= idata->lastread + Timeout))      && imap_exec (idata, "NOOP", 0) != 0)    return -1;  /* We call this even when we haven't run NOOP in case we have pending   * changes to process, since we can reopen here. */  imap_cmd_finish (idata);  if (idata->check_status & IMAP_EXPUNGE_PENDING)    result = M_REOPENED;  else if (idata->check_status & IMAP_NEWMAIL_PENDING)    result = M_NEW_MAIL;  else if (idata->check_status & IMAP_FLAGS_PENDING)    result = M_FLAGS;  idata->check_status = 0;  return result;}/* split path into (idata,mailbox name) */static int imap_get_mailbox (const char* path, IMAP_DATA** hidata, char* buf, size_t blen){  IMAP_MBOX mx;  if (imap_parse_path (path, &mx))  {    dprint (1, (debugfile, "imap_get_mailbox: Error parsing %s\n", path));    return -1;  }  if (!(*hidata = imap_conn_find (&(mx.account), option (OPTIMAPPASSIVE) ? M_IMAP_CONN_NONEW : 0))      || (*hidata)->state < IMAP_AUTHENTICATED)  {    FREE (&mx.mbox);    return -1;  }    imap_fix_path (*hidata, mx.mbox, buf, blen);  FREE (&mx.mbox);  return 0;}/* check for new mail in any subscribed mailboxes. Given a list of mailboxes * rather than called once for each so that it can batch the commands and * save on round trips. Returns number of mailboxes with new mail. */int imap_buffy_check (int force){  IMAP_DATA* idata;  IMAP_DATA* lastdata = NULL;  BUFFY* mailbox;  char name[LONG_STRING];  char command[LONG_STRING];  char munged[LONG_STRING];  int buffies = 0;  for (mailbox = Incoming; mailbox; mailbox = mailbox->next)  {    /* Init newly-added mailboxes */    if (! mailbox->magic)    {      if (mx_is_imap (mailbox->path))        mailbox->magic = M_IMAP;    }        if (mailbox->magic != M_IMAP)      continue;    mailbox->new = 0;    if (imap_get_mailbox (mailbox->path, &idata, name, sizeof (name)) < 0)      continue;    /* Don't issue STATUS on the selected mailbox, it will be NOOPed or     * IDLEd elsewhere */    if (!imap_mxcmp (name, idata->mailbox))      continue;          if (!lastdata)      lastdata = idata;    if (idata != lastdata)    {      /* Send commands to previous server. Sorting the buffy list       * may prevent some infelicitous interleavings */      if (imap_exec (lastdata, NULL, 0) != IMAP_CMD_OK)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -