📄 imap4r1.c
字号:
} imap_send (stream,"FETCH",args); fs_give ((void **) &s); } ov.optional.lines = 0; /* now overview each message */ ov.optional.xref = NIL; if (ofn) for (i = 1; i <= stream->nmsgs; i++) if (((elt = mail_elt (stream,i))->sequence) && (env = mail_fetch_structure (stream,i,NIL,NIL)) && ofn) { ov.subject = env->subject; ov.from = env->from; ov.date = env->date; ov.message_id = env->message_id; ov.references = env->references; ov.optional.octets = elt->rfc822_size; (*ofn) (stream,mail_uid (stream,i),&ov); } return LONGT;}/* IMAP fetch structure * Accepts: MAIL stream * message # to fetch * pointer to return body * option flags * Returns: envelope of this message, body returned in body value * * Fetches the "fast" information as well */ENVELOPE *imap_structure (MAILSTREAM *stream,unsigned long msgno,BODY **body, long flags){ unsigned long i,j,k; char *s,seq[128],tmp[MAILTMPLEN]; MESSAGECACHE *elt; ENVELOPE **env; BODY **b; IMAPPARSEDREPLY *reply = NIL; IMAPARG *args[3],aseq,aatt; args[0] = &aseq; args[1] = &aatt; args[2] = NIL; aseq.type = SEQUENCE; aseq.text = (void *) seq; aatt.type = ATOM; aatt.text = NIL; if (flags & FT_UID) /* see if can find msgno from UID */ for (i = 1; i <= stream->nmsgs; i++) if ((elt = mail_elt (stream,i))->private.uid == msgno) { msgno = i; /* found msgno, use it from now on */ flags &= ~FT_UID; /* no longer a UID fetch */ } sprintf (seq,"%lu",msgno); /* initial sequence */ /* IMAP UID fetching is a special case */ if (LEVELIMAP4 (stream) && (flags & FT_UID)) { strcpy (tmp,allheader); if (LEVELIMAP4rev1(stream)){/* get extra headers if IMAP4rev1 */ if (imap_extrahdrs) sprintf (tmp + strlen (tmp)," %s %s %s", hdrheader,imap_extrahdrs,hdrtrailer); else sprintf (tmp + strlen (tmp)," %s %s",hdrheader,hdrtrailer); } if (body) strcat (tmp," BODYSTRUCTURE"); sprintf (tmp + strlen (tmp)," %s",fasttrailer); aatt.text = (void *) tmp; /* do the built command */ if (!imap_OK (stream,reply = imap_send (stream,"UID FETCH",args))) { mm_log (reply->text,ERROR); } /* now hunt for this UID */ for (i = 1; i <= stream->nmsgs; i++) if ((elt = mail_elt (stream,i))->private.uid == msgno) { if (body) *body = elt->private.msg.body; return elt->private.msg.env; } if (body) *body = NIL; /* can't find the UID */ return NIL; } elt = mail_elt (stream,msgno);/* get cache pointer */ if (stream->scache) { /* short caching? */ env = &stream->env; /* use temporaries on the stream */ b = &stream->body; if (msgno != stream->msgno){/* flush old poop if a different message */ mail_free_envelope (env); mail_free_body (b); stream->msgno = msgno; /* this is now the current short cache msg */ } } else { /* normal cache */ env = &elt->private.msg.env;/* get envelope and body pointers */ b = &elt->private.msg.body; /* prefetch if don't have envelope */ if ((k = imap_lookahead) && (!*env || (*env)->incomplete)) /* build message number list */ for (i = msgno + 1, s = seq; k && (i <= stream->nmsgs); i++) if (!mail_elt (stream,i)->private.msg.env) { s += strlen (s); /* find string end, see if nearing end */ if ((s - seq) > (MAILTMPLEN - 20)) break; sprintf (s,",%lu",i); /* append message */ for (j = i + 1, k--; /* hunt for last message without an envelope */ k && (j <= stream->nmsgs) && !mail_elt (stream,j)->private.msg.env; j++, k--); /* if different, make a range */ if (i != --j) sprintf (s + strlen (s),":%lu",i = j); } } if (LEVELIMAP4 (stream)) { /* has extensible body structure and UIDs */ tmp[0] = '\0'; /* initialize command */ /* need envelope? */ if (!*env || (*env)->incomplete) { strcat (tmp," ENVELOPE"); /* yes, get it and possible extra poop */ 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); } } /* need anything else? */ if (body && !*b) strcat (tmp," BODYSTRUCTURE"); if (!elt->private.uid) strcat (tmp," UID"); if (!elt->day) strcat (tmp," INTERNALDATE"); if (!elt->rfc822_size) strcat (tmp," RFC822.SIZE"); if (tmp[0]) { /* anything to do? */ strcat (tmp," FLAGS)"); /* always get current flags */ tmp[0] = '('; /* make into a list */ aatt.text = (void *) tmp; /* do the built command */ } } /* has non-extensive body */ else if (LEVELIMAP2bis (stream)) { if (!*env || (*env)->incomplete) aatt.text = (body && !*b) ? (void *) "FULL" : (void *) "ALL"; else if (body && !*b) aatt.text = (void *) "BODY"; else if (!(elt->rfc822_size && elt->day)) aatt.text = (void *) "FAST"; } else if (!*env || (*env)->incomplete) aatt.text = (void *) "ALL"; else if (!(elt->rfc822_size && elt->day)) aatt.text = (void *) "FAST"; if (aatt.text) { /* need to fetch anything? */ if (!imap_OK (stream,reply = imap_send (stream,"FETCH",args))) { /* failed, probably RFC-1176 server */ if (!LEVELIMAP4 (stream) && LEVELIMAP2bis (stream) && body && !*b){ aatt.text = (void *) "ALL"; if (imap_OK (stream,reply = imap_send (stream,"FETCH",args))) LOCAL->imap2bis = NIL;/* doesn't have body capabilities */ else mm_log (reply->text,ERROR); } else mm_log (reply->text,ERROR); } } if (body) *body = *b; /* return the body */ return *env; /* return the envelope */}/* IMAP fetch message data * Accepts: MAIL stream * message number * section specifier * offset of first designated byte or 0 to start at beginning * maximum number of bytes or 0 for all bytes * lines to fetch if header * flags * Returns: T on success, NIL on failure */long imap_msgdata (MAILSTREAM *stream,unsigned long msgno,char *section, unsigned long first,unsigned long last,STRINGLIST *lines, long flags){ char *t,tmp[MAILTMPLEN],part[40]; char *cmd = (LEVELIMAP4 (stream) && (flags & FT_UID)) ? "UID FETCH":"FETCH"; IMAPPARSEDREPLY *reply; IMAPARG *args[5],aseq,aatt,alns,acls; aseq.type = NUMBER; aseq.text = (void *) msgno; aatt.type = ATOM; /* assume atomic attribute */ alns.type = LIST; alns.text = (void *) lines; acls.type = BODYCLOSE; acls.text = (void *) part; args[0] = &aseq; args[1] = &aatt; args[2] = args[3] = args[4] = NIL; part[0] = '\0'; /* initially no partial specifier */ if (!(flags & FT_PREFETCHTEXT) && LEVELIMAP4rev1 (stream)) {/* easy if IMAP4rev1 server and no prefetch */ aatt.type = (flags & FT_PEEK) ? BODYPEEK : BODYTEXT; if (lines) { /* want specific header lines? */ sprintf (tmp,"%s.FIELDS%s",section,(flags & FT_NOT) ? ".NOT" : ""); aatt.text = (void *) tmp; args[2] = &alns; args[3] = &acls; } else { aatt.text = (void *) section; args[2] = &acls; } if (first || last) sprintf (part,"<%lu.%lu>",first,last ? last:-1); }#if 0 /* I don't think that this is a good idea. If partial fetch isn't available, * the application is going to have to do a full fetch anyway if it wants to * get the data. The mailgets call will indicate what happened. */ else if (first || last) { /* partial fetching is only on IMAP4rev1 */ mm_notify (stream,"[NOTIMAP4REV1] Can't do partial fetch",WARN); return NIL; }#endif /* BODY.PEEK[HEADER] becomes RFC822.HEADER */ else if (!strcmp (section,"HEADER")) { if (flags & FT_PEEK) aatt.text = (void *) ((flags & FT_PREFETCHTEXT) ? "(RFC822.HEADER RFC822.TEXT)" : "RFC822.HEADER"); else { mm_notify (stream,"[NOTIMAP4] Can't do non-peeking header fetch",WARN); return NIL; } } /* other peeking was introduced in RFC-1730 */ else if ((flags & FT_PEEK) && !LEVEL1730 (stream)) { mm_notify (stream,"[NOTIMAP4] Can't do peeking fetch",WARN); return NIL; } /* BODY[TEXT] becomes RFC822.TEXT */ else if (!strcmp (section,"TEXT")) aatt.text = (void *) ((flags & FT_PEEK) ? "RFC822.TEXT.PEEK" : "RFC822.TEXT"); /* BODY[] becomes RFC822 */ else if (!section[0]) aatt.text = (void *) ((flags & FT_PEEK) ? "RFC822.PEEK" : "RFC822"); /* nested header */ else if (t = strstr (section,".HEADER")) { if (!LEVEL1730 (stream)) { /* this was introduced in RFC-1730 */ mm_notify (stream,"[NOTIMAP4] Can't do nested header fetch",WARN); return NIL; } aatt.type = (flags & FT_PEEK) ? BODYPEEK : BODYTEXT; args[2] = &acls; /* will need to close section */ aatt.text = (void *) tmp; /* convert .HEADER to .0 for RFC-1730 server */ strncpy (tmp,section,t-section); strcpy (tmp+(t-section),".0"); } /* extended nested text */ else if (strstr (section,".MIME") || strstr (section,".TEXT")) { mm_notify (stream,"[NOTIMAP4REV1] Can't do extended body part fetch",WARN); return NIL; } /* nested message */ else if (LEVELIMAP2bis (stream)) { aatt.type = (flags & FT_PEEK) ? BODYPEEK : BODYTEXT; args[2] = &acls; /* will need to close section */ aatt.text = (void *) section; } else { /* ancient server */ mm_notify (stream,"[NOTIMAP2BIS] Can't do body part fetch",WARN); return NIL; } /* send the fetch command */ if (!imap_OK (stream,reply = imap_send (stream,cmd,args))) { mm_log (reply->text,ERROR); return NIL; /* failure */ } return T;}/* IMAP fetch UID * Accepts: MAIL stream * message number * Returns: UID */unsigned long imap_uid (MAILSTREAM *stream,unsigned long msgno){ MESSAGECACHE *elt; IMAPPARSEDREPLY *reply; IMAPARG *args[3],aseq,aatt; char *s,seq[MAILTMPLEN]; unsigned long i,j,k; /* IMAP2 didn't have UIDs */ if (!LEVELIMAP4 (stream)) return msgno; /* do we know its UID yet? */ if (!(elt = mail_elt (stream,msgno))->private.uid) { aseq.type = SEQUENCE; aseq.text = (void *) seq; aatt.type = ATOM; aatt.text = (void *) "UID"; args[0] = &aseq; args[1] = &aatt; args[2] = NIL; sprintf (seq,"%lu",msgno); if (k = imap_uidlookahead) {/* build UID list */ for (i = msgno + 1, s = seq; k && (i <= stream->nmsgs); i++) if (!mail_elt (stream,i)->private.uid) { s += strlen (s); /* find string end, see if nearing end */ if ((s - seq) > (MAILTMPLEN - 20)) break; sprintf (s,",%lu",i); /* append message */ for (j = i + 1, k--; /* hunt for last message without a UID */ k && (j <= stream->nmsgs) && !mail_elt (stream,j)->private.uid; j++, k--); /* if different, make a range */ if (i != --j) sprintf (s + strlen (s),":%lu",i = j); } } /* send "FETCH msgno UID" */ if (!imap_OK (stream,reply = imap_send (stream,"FETCH",args))) mm_log (reply->text,ERROR); } return elt->private.uid; /* return our UID now */}/* IMAP fetch message number from UID * Accepts: MAIL stream * UID * Returns: message number */unsigned long imap_msgno (MAILSTREAM *stream,unsigned long uid){ IMAPPARSEDREPLY *reply; IMAPARG *args[3],aseq,aatt; char seq[MAILTMPLEN]; unsigned long msgno; /* IMAP2 didn't have UIDs */ if (!LEVELIMAP4 (stream)) return uid; /* have server hunt for UID */ aseq.type = SEQUENCE; aseq.text = (void *) seq; aatt.type = ATOM; aatt.text = (void *) "UID"; args[0] = &aseq; args[1] = &aatt; args[2] = NIL; sprintf (seq,"%lu",uid); /* send "UID FETCH uid UID" */ if (!imap_OK (stream,reply = imap_send (stream,"UID FETCH",args))) mm_log (reply->text,ERROR); for (msgno = 1; msgno <= stream->nmsgs; msgno++) if (mail_elt (stream,msgno)->private.uid == uid) return msgno; return 0; /* didn't find the UID anywhere */}/* IMAP modify flags * Accepts: MAIL stream * sequence * flag(s) * option flags */void imap_flag (MAILSTREAM *stream,char *sequence,char *flag,long flags){ char *cmd = (LEVELIMAP4 (stream) && (flags & ST_UID)) ? "UID STORE":"STORE"; IMAPPARSEDREPLY *reply; IMAPARG *args[4],aseq,ascm,aflg; aseq.type = SEQUENCE; aseq.text = (void *) sequence; ascm.type = ATOM; ascm.text = (void *) ((flags & ST_SET) ? ((LEVELIMAP4 (stream) && (flags & ST_SILENT)) ? "+Flags.silent" : "+Flags") : ((LEVELIMAP4 (stream) && (flags & ST_SILENT)) ? "-Flags.silent" : "-Flags")); aflg.type = FLAGS; aflg.text = (void *) flag; args[0] = &aseq; args[1] = &ascm; args[2] = &aflg; args[3] = NIL; /* send "STORE sequence +Flags flag" */ if (!imap_OK (stream,reply = imap_send (stream,cmd,args))) mm_log (reply->text,ERROR);}/* IMAP search for messages * Accepts: MAIL stream * character set * search program * option flags */void imap_search (MAILSTREAM *stream,char *charset,SEARCHPGM *pgm,long flags){ char *cmd = (LEVELIMAP4 (stream) && (flags & SE_UID)) ?"UID SEARCH":"SEARCH"; unsigned long i,j,k; char *s,tmp[MAILTMPLEN]; IMAPPARSEDREPLY *reply; MESSAGECACHE *elt; IMAPARG *args[4],apgm,aseq,aatt,achs; args[1] = args[2] = args[3] = NIL; apgm.type = SEARCHPROGRAM; apgm.text = (void *) pgm; aseq.type = SEQUENCE; aatt.type = ATOM; achs.type = ASTRING; if (charset) { /* optional charset argument requested */ args[0] = &aatt; args[1] = &achs; args[2] = &apgm; aatt.text = (void *) "CHARSET"; achs.text = (void *) charset; } else args[0] = &apgm; /* be sure that receiver understands */ LOCAL->uidsearch = (flags & SE_UID) ? T : NIL; if (!LEVELIMAP4 (stream) && /* if old server but new functions... */ (charset || LOCAL->uidsearch || pgm->msgno || pgm->uid || pgm->search_or || pgm->search_not || pgm->header || pgm->larger || pgm->smaller || pgm->sentbefore || pgm->senton || pgm->sentsince || pgm->draft || pgm->undraft || pgm->return_path || pgm->sender || pgm->reply_to || pgm->message_id || pgm->in_reply_to || pgm->newsgroups ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -