📄 imap4r1.c
字号:
pgm->followup_to || pgm->references)) mail_search_default (stream,charset,pgm,flags); /* do the SEARCH */ else if (!imap_OK (stream,reply = imap_send (stream,cmd,args))) mm_log (reply->text,ERROR); /* can never pre-fetch with a short cache */ else if ((k = imap_prefetch) && !(flags & (SE_NOPREFETCH|SE_UID)) && !stream->scache) { /* only if prefetching permitted */ s = LOCAL->tmp; /* build sequence in temporary buffer */ *s = '\0'; /* initially nothing */ /* search through mailbox */ for (i = 1; k && (i <= stream->nmsgs); ++i) /* for searched messages with no envelope */ if ((elt = mail_elt (stream,i)) && elt->searched && !mail_elt (stream,i)->private.msg.env) { /* prepend with comma if not first time */ if (LOCAL->tmp[0]) *s++ = ','; sprintf (s,"%lu",j = i);/* output message number */ s += strlen (s); /* point at end of string */ k--; /* count one up */ /* search for possible end of range */ while (k && (i < stream->nmsgs) && (elt = mail_elt (stream,i+1))->searched && !elt->private.msg.env) i++,k--; if (i != j) { /* if a range */ sprintf (s,":%lu",i); /* output delimiter and end of range */ s += strlen (s); /* point at end of string */ } } if (LOCAL->tmp[0]) { /* anything to pre-fetch? */ args[0] = &aseq; args[1] = &aatt; args[2] = NIL; aseq.text = (void *) cpystr (LOCAL->tmp); if (LEVELIMAP4 (stream)) {/* IMAP4 fetching does more */ strcpy (tmp,allheader); if (LEVELIMAP4rev1 (stream)) { if (imap_extrahdrs) sprintf (tmp + strlen (tmp)," %s %s %s", hdrheader,imap_extrahdrs,hdrtrailer); else sprintf (tmp + strlen (tmp)," %s %s",hdrheader,hdrtrailer); } sprintf (tmp + strlen (tmp)," %s",fasttrailer); aatt.text = (void *) tmp; } else aatt.text = (void *) "ALL"; if (!imap_OK (stream,reply = imap_send (stream,"FETCH",args))) mm_log (reply->text,ERROR); /* flush copy of sequence */ fs_give ((void **) &aseq.text); } }}/* IMAP sort messages * Accepts: mail stream * character set * search program * sort program * option flags * Returns: vector of sorted message sequences or NIL if error */unsigned long *imap_sort (MAILSTREAM *stream,char *charset,SEARCHPGM *spg, SORTPGM *pgm,long flags){ unsigned long i,j,start,last; unsigned long *ret = NIL; pgm->nmsgs = 0; /* start off with no messages */ /* can use server-based sort? */ if (LEVELSORT (stream) && !(flags & SO_NOSERVER)) { char *cmd = (flags & SE_UID) ? "UID SORT" : "SORT"; IMAPARG *args[4],apgm,achs,aspg; IMAPPARSEDREPLY *reply; SEARCHSET *ss = NIL; apgm.type = SORTPROGRAM; apgm.text = (void *) pgm; achs.type = ASTRING; achs.text = (void *) (charset ? charset : "US-ASCII"); aspg.type = SEARCHPROGRAM; /* did he provide a searchpgm? */ if (!(aspg.text = (void *) spg)) { for (i = 1,start = last = 0; i <= stream->nmsgs; ++i) if (mail_elt (stream,i)->searched) { if (ss) { /* continuing a sequence */ if (i == last + 1) last = i; else { /* end of range */ if (last != start) ss->last = last; (ss = ss->next = mail_newsearchset ())->first = i; start = last = i; /* begin a new range */ } } else { /* first time, start new searchpgm */ (spg = mail_newsearchpgm ())->msgno = ss = mail_newsearchset (); ss->first = start = last = i; } } /* nothing to sort if no messages */ if (!(aspg.text = (void *) spg)) return NIL; /* else install last sequence */ if (last != start) ss->last = last; } args[0] = &apgm; args[1] = &achs; args[2] = &aspg; args[3] = NIL; if (imap_OK (stream,reply = imap_send (stream,cmd,args))) { pgm->nmsgs = LOCAL->sortsize; ret = LOCAL->sortdata; LOCAL->sortdata = NIL; /* mail program is responsible for flushing */ } else mm_log (reply->text,ERROR); /* free any temporary searchpgm */ if (ss) mail_free_searchpgm (&spg); } /* not much can do if short caching */ else if (stream->scache) ret = mail_sort_msgs (stream,charset,spg,pgm,flags); else { /* try to be a bit more clever */ char *s,*t; unsigned long len; MESSAGECACHE *elt; SORTCACHE **sc; SORTPGM *sp; int needenvs = 0; /* see if need envelopes */ for (sp = pgm; sp && !needenvs; sp = sp->next) switch (sp->function) { case SORTDATE: case SORTFROM: case SORTSUBJECT: case SORTTO: case SORTCC: needenvs = T; } if (spg) { /* only if a search needs to be done */ int silent = stream->silent; stream->silent = T; /* don't pass up mm_searched() events */ /* search for messages */ mail_search_full (stream,charset,spg,NIL); stream->silent = silent; /* restore silence state */ } /* initialize progress counters */ pgm->nmsgs = pgm->progress.cached = 0; /* pass 1: count messages to sort */ for (i = 1,len = start = last = 0,s = t = NIL; i <= stream->nmsgs; ++i) if ((elt = mail_elt (stream,i))->searched) { pgm->nmsgs++; if (needenvs ? !elt->private.msg.env : !elt->day) { if (s) { /* continuing a sequence */ if (i == last + 1) last = i; else { /* end of range */ if (last != start) sprintf (t,":%lu,%lu",last,i); else sprintf (t,",%lu",i); start = last = i; /* begin a new range */ if ((j = ((t += strlen (t)) - s)) > (MAILTMPLEN - 20)) { fs_resize ((void **) s,len += MAILTMPLEN); t = s + j; /* relocate current pointer */ } } } else { /* first time, start new buffer */ s = (char *) fs_get (len = MAILTMPLEN); sprintf (s,"%lu",start = last = i); t = s + strlen (s); /* end of buffer */ } } } /* last sequence */ if (last != start) sprintf (t,":%lu",last); if (s) { /* prefetch needed data */ IMAPARG *args[7],aseq,aatt[5]; args[0] = &aseq; args[1] = &aatt[0]; aseq.type = SEQUENCE; aseq.text = (void *) s; /* send the hairier form if IMAP4rev1 */ if (needenvs && LEVELIMAP4rev1 (stream)) { aatt[0].type = aatt[1].type = aatt[2].type = aatt[3].type = aatt[4].type = ATOM; aatt[0].text = (void *) allheader; aatt[1].text = (void *) hdrheader; aatt[3].text = (void *) hdrtrailer; aatt[4].text = (void *) fasttrailer; args[i = 2] = &aatt[1]; if (aatt[2].text = (void *) imap_extrahdrs) args[++i] = &aatt[2]; args[++i] = &aatt[3]; args[++i] = &aatt[4]; args[++i] = NIL; } else { /* just do FETCH ALL */ aatt[0].type = ATOM; aatt[0].text = (void *) (needenvs ? "ALL" : "FAST"); args[2] = NIL; } imap_send (stream,"FETCH",args); fs_give ((void **) &s); } if (pgm->nmsgs) { /* pass 2: sort cache */ sortresults_t sr = (sortresults_t) mail_parameters (NIL,GET_SORTRESULTS,NIL); sc = mail_sort_loadcache (stream,pgm); /* pass 3: sort messages */ if (!pgm->abort) ret = mail_sort_cache (stream,pgm,sc,flags); fs_give ((void **) &sc); /* don't need sort vector any more */ /* also return via callback if requested */ if (sr) (*sr) (stream,ret,pgm->nmsgs); } } return ret;}/* IMAP thread messages * Accepts: mail stream * thread type * character set * search program * option flags * Returns: thread node tree */THREADNODE *imap_thread (MAILSTREAM *stream,char *type,char *charset, SEARCHPGM *spg,long flags){ THREADNODE *ret = NIL; THREADER *thr; /* does server have this threader type? */ for (thr = LOCAL->threader; thr && mail_compare_cstring (thr->name,type); thr = thr->next); if (thr) { /* found threader? */ unsigned long i,start,last; char *cmd = (flags & SE_UID) ? "UID THREAD" : "THREAD"; IMAPARG *args[4],apgm,achs,aspg; IMAPPARSEDREPLY *reply; SEARCHSET *ss = NIL; apgm.type = ATOM; apgm.text = (void *) type; achs.type = ASTRING; achs.text = (void *) (charset ? charset : "US-ASCII"); aspg.type = SEARCHPROGRAM; /* did he provide a searchpgm? */ if (!(aspg.text = (void *) spg)) { for (i = 1,start = last = 0; i <= stream->nmsgs; ++i) if (mail_elt (stream,i)->searched) { if (ss) { /* continuing a sequence */ if (i == last + 1) last = i; else { /* end of range */ if (last != start) ss->last = last; (ss = ss->next = mail_newsearchset ())->first = i; start = last = i; /* begin a new range */ } } else { /* first time, start new searchpgm */ (spg = mail_newsearchpgm ())->msgno = ss = mail_newsearchset (); ss->first = start = last = i; } } /* nothing to sort if no messages */ if (!(aspg.text = (void *) spg)) return NIL; /* else install last sequence */ if (last != start) ss->last = last; } args[0] = &apgm; args[1] = &achs; args[2] = &aspg; args[3] = NIL; if (imap_OK (stream,reply = imap_send (stream,cmd,args))) { ret = LOCAL->threaddata; LOCAL->threaddata = NIL; /* mail program is responsible for flushing */ } else mm_log (reply->text,ERROR); /* free any temporary searchpgm */ if (ss) mail_free_searchpgm (&spg); } else ret = mail_thread_msgs (stream,type,charset,spg,flags | SO_NOSERVER, imap_sort); return ret;}/* IMAP ping mailbox * Accepts: MAIL stream * Returns: T if stream still alive, else NIL */long imap_ping (MAILSTREAM *stream){ return (LOCAL->netstream && /* send "NOOP" */ imap_OK (stream,imap_send (stream,"NOOP",NIL))) ? T : NIL;}/* IMAP check mailbox * Accepts: MAIL stream */void imap_check (MAILSTREAM *stream){ /* send "CHECK" */ IMAPPARSEDREPLY *reply = imap_send (stream,"CHECK",NIL); mm_log (reply->text,imap_OK (stream,reply) ? (long) NIL : ERROR);}/* IMAP expunge mailbox * Accepts: MAIL stream */void imap_expunge (MAILSTREAM *stream){ /* send "EXPUNGE" */ IMAPPARSEDREPLY *reply = imap_send (stream,"EXPUNGE",NIL); mm_log (reply->text,imap_OK (stream,reply) ? (long) NIL : ERROR);}/* IMAP copy message(s) * Accepts: MAIL stream * sequence * destination mailbox * option flags * Returns: T if successful else NIL */long imap_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long flags){ char *cmd = (LEVELIMAP4 (stream) && (flags & CP_UID)) ? "UID COPY" : "COPY"; char *s; IMAPPARSEDREPLY *reply; IMAPARG *args[3],aseq,ambx; imapreferral_t ir = (imapreferral_t) mail_parameters (stream,GET_IMAPREFERRAL,NIL); mailproxycopy_t pc = (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL); aseq.type = SEQUENCE; aseq.text = (void *) sequence; ambx.type = ASTRING; ambx.text = (void *) mailbox; args[0] = &aseq; args[1] = &ambx; args[2] = NIL; /* send "COPY sequence mailbox" */ if (!imap_OK (stream,reply = imap_send (stream,cmd,args))) { if (ir && pc && LOCAL->referral && mail_sequence (stream,sequence) && (s = (*ir) (stream,LOCAL->referral,REFCOPY))) return (*pc) (stream,sequence,s,flags); mm_log (reply->text,ERROR); return NIL; } /* delete the messages if the user said to */ if (flags & CP_MOVE) imap_flag (stream,sequence,"\\Deleted", ST_SET + ((flags & CP_UID) ? ST_UID : NIL)); return T;}/* IMAP mail append message from stringstruct * Accepts: MAIL stream * destination mailbox * append callback * data for callback * Returns: T if append successful, else NIL */long imap_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){ MAILSTREAM *st = stream; IMAPARG *args[3],ambx,amap; IMAPPARSEDREPLY *reply; APPENDDATA map; STRING *message; char *flags,*date,tmp[MAILTMPLEN]; long ret = NIL; imapreferral_t ir = (imapreferral_t) mail_parameters (stream,GET_IMAPREFERRAL,NIL); /* barf if bad mailbox */ if (mail_valid_net (mailbox,&imapdriver,NIL,tmp)) { /* create a stream if given one no good */ if (!(stream && LOCAL && LOCAL->netstream) && !(stream = mail_open (NIL,mailbox,OP_HALFOPEN|OP_SILENT))) mm_log ("Can't access server for append",ERROR); /* use multi-append? */ else if (LEVELMULTIAPPEND (stream)) { ambx.type = ASTRING; ambx.text = (void *) tmp; amap.type = MULTIAPPEND; amap.text = (void *) ↦ map.af = af; map.data = data; args[0] = &ambx; args[1] = &amap; args[2] = NIL; /* success if OK */ if (imap_OK (stream,reply = imap_send (stream,"APPEND",args))) ret = LONGT; /* failed, is there a referral? */ else if (ir && LOCAL->referral && (mailbox = (*ir) (stream,LOCAL->referral,REFAPPEND))) ret = imap_append (NIL,mailbox,af,data); else mm_log (reply->text,ERROR); } /* do multiple single appends */ else while ((ret = ((*af) (stream,data,&flags,&date,&message))) && message && (ret = imap_append_single (stream,tmp,flags,date,message,ir))); /* toss out temporary stream */ if (st != stream) mail_close (stream); } return ret; /* return */}/* IMAP append single message * Accepts: mail stream * dest
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -