📄 mail.c
字号:
else { /* can save memory doing it this way */ hdr = (*stream->dtb->header) (stream,msgno,&hdrsize,flags | FT_INTERNAL); if (hdrsize) { /* in case null header */ c = hdr[hdrsize]; /* preserve what's there */ hdr[hdrsize] = '\0'; /* tie off header */ rfc822_parse_msg (env,NIL,hdr,hdrsize,NIL,BADHOST,stream->dtb->flags); hdr[hdrsize] = c; /* restore in case cached data */ } else *env = mail_newenvelope (); } } /* if need date, have date in envelope? */ if (!elt->day && *env && (*env)->date) mail_parse_date (elt,(*env)->date); /* sigh, fill in bogus default */ if (!elt->day) elt->day = elt->month = 1; if (body) *body = *b; /* return the body */ return *env; /* return the envelope */}/* Mail mark single message (internal use only) * Accepts: mail stream * elt to mark * fetch flags */static void markseen (MAILSTREAM *stream,MESSAGECACHE *elt,long flags){ unsigned long i; char sequence[20]; MESSAGECACHE *e; /* non-peeking and needs to set \Seen? */ if (!(flags & FT_PEEK) && !elt->seen) { if (stream->dtb->flagmsg){ /* driver wants per-message call? */ elt->valid = NIL; /* do pre-alteration driver call */ (*stream->dtb->flagmsg) (stream,elt); /* set seen, do post-alteration driver call */ elt->seen = elt->valid = T; (*stream->dtb->flagmsg) (stream,elt); } if (stream->dtb->flag) { /* driver wants one-time call? */ /* better safe than sorry, save seq bits */ for (i = 1; i <= stream->nmsgs; i++) { e = mail_elt (stream,i); e->private.sequence = e->sequence; } /* call driver to set the message */ sprintf (sequence,"%lu",elt->msgno); (*stream->dtb->flag) (stream,sequence,"\\Seen",ST_SET); /* restore sequence bits */ for (i = 1; i <= stream->nmsgs; i++) { e = mail_elt (stream,i); e->sequence = e->private.sequence; } } /* notify mail program of flag change */ MM_FLAGS (stream,elt->msgno); }}/* Mail fetch message * Accepts: mail stream * message # to fetch * pointer to returned length * flags * Returns: message text */char *mail_fetch_message (MAILSTREAM *stream,unsigned long msgno, unsigned long *len,long flags){ GETS_DATA md; SIZEDTEXT *t; STRING bs; MESSAGECACHE *elt; char *s,*u; unsigned long i,j; if (len) *len = 0; /* default return size */ if (flags & FT_UID) { /* UID form of call */ if (msgno = mail_msgno (stream,msgno)) flags &= ~FT_UID; else return ""; /* must get UID/msgno map first */ } /* initialize message data identifier */ INIT_GETS (md,stream,msgno,"",0,0); /* is data already cached? */ if ((t = &(elt = mail_elt (stream,msgno))->private.msg.full.text)->data) { markseen (stream,elt,flags);/* mark message seen */ return mail_fetch_text_return (&md,t,len); } if (!stream->dtb) return ""; /* not in cache, must have live driver */ if (stream->dtb->msgdata) return ((*stream->dtb->msgdata) (stream,msgno,"",0,0,NIL,flags) && t->data) ? mail_fetch_text_return (&md,t,len) : ""; /* ugh, have to do this the crufty way */ u = mail_fetch_header (stream,msgno,NIL,NIL,&i,flags); /* copy in case text method stomps on it */ s = (char *) memcpy (fs_get ((size_t) i),u,(size_t) i); if ((*stream->dtb->text) (stream,msgno,&bs,flags)) { t = &stream->text; /* build combined copy */ if (t->data) fs_give ((void **) &t->data); t->data = (unsigned char *) fs_get ((t->size = i + SIZE (&bs)) + 1); if (!elt->rfc822_size) elt->rfc822_size = t->size; else if (elt->rfc822_size != t->size) { char tmp[MAILTMPLEN]; sprintf (tmp,"Calculated RFC822.SIZE (%lu) != reported size (%lu)", t->size,elt->rfc822_size); mm_log (tmp,WARN); /* bug trap */ } memcpy (t->data,s,(size_t) i); for (u = (char *) t->data + i, j = SIZE (&bs); j;) { memcpy (u,bs.curpos,bs.cursize); u += bs.cursize; /* update text */ j -= bs.cursize; bs.curpos += (bs.cursize -1); bs.cursize = 0; (*bs.dtb->next) (&bs); /* advance to next buffer's worth */ } *u = '\0'; /* tie off data */ u = mail_fetch_text_return (&md,t,len); } else u = ""; fs_give ((void **) &s); /* finished with copy of header */ return u;}/* Mail fetch message header * Accepts: mail stream * message # to fetch * MIME section specifier (#.#.#...#) * list of lines to fetch * pointer to returned length * flags * Returns: message header in RFC822 format * * Note: never calls a mailgets routine */char *mail_fetch_header (MAILSTREAM *stream,unsigned long msgno,char *section, STRINGLIST *lines,unsigned long *len,long flags){ STRING bs; BODY *b = NIL; SIZEDTEXT *t = NIL,rt; MESSAGE *m = NIL; MESSAGECACHE *elt; char tmp[MAILTMPLEN]; if (len) *len = 0; /* default return size */ if (section && (strlen (section) > (MAILTMPLEN - 20))) return ""; if (flags & FT_UID) { /* UID form of call */ if (msgno = mail_msgno (stream,msgno)) flags &= ~FT_UID; else return ""; /* must get UID/msgno map first */ } elt = mail_elt (stream,msgno);/* get cache data */ if (section && *section) { /* nested body header wanted? */ if (!((b = mail_body (stream,msgno,section)) && (b->type == TYPEMESSAGE) && !strcmp (b->subtype,"RFC822"))) return ""; /* lose if no body or not MESSAGE/RFC822 */ m = b->nested.msg; /* point to nested message */ } /* else top-level message header wanted */ else m = &elt->private.msg; if (m->header.text.data && mail_match_lines (lines,m->lines,flags)) { if (lines) textcpy (t = &stream->text,&m->header.text); else t = &m->header.text; /* in cache, and cache is valid */ markseen (stream,elt,flags);/* mark message seen */ } else if (stream->dtb) { /* not in cache, has live driver? */ if (stream->dtb->msgdata) { /* has driver section fetch? */ /* build driver section specifier */ if (section && *section) sprintf (tmp,"%s.HEADER",section); else strcpy (tmp,"HEADER"); if ((*stream->dtb->msgdata) (stream,msgno,tmp,0,0,lines,flags)) { t = &m->header.text; /* fetch data */ /* don't need to postprocess lines */ if (m->lines) lines = NIL; else if (lines) textcpy (t = &stream->text,&m->header.text); } } else if (b) { /* nested body wanted? */ if (stream->private.search.text) { rt.data = (unsigned char *) stream->private.search.text + b->nested.msg->header.offset; rt.size = b->nested.msg->header.text.size; t = &rt; } else if ((*stream->dtb->text) (stream,msgno,&bs,flags & ~FT_INTERNAL)) { if ((bs.dtb->next == mail_string_next) && !lines) { rt.data = (unsigned char *) bs.curpos + b->nested.msg->header.offset; rt.size = b->nested.msg->header.text.size; if (stream->private.search.string) stream->private.search.text = bs.curpos; t = &rt; /* special hack to avoid extra copy */ } else textcpyoffstring (t = &stream->text,&bs, b->nested.msg->header.offset, b->nested.msg->header.text.size); } } else { /* top-level header fetch */ /* mark message seen */ markseen (stream,elt,flags); if (rt.data = (unsigned char *) (*stream->dtb->header) (stream,msgno,&rt.size,flags)) { /* make a safe copy if need to filter */ if (lines) textcpy (t = &stream->text,&rt); else t = &rt; /* top level header */ } } } if (!t || !t->data) return "";/* error if no string */ /* filter headers if requested */ if (lines) t->size = mail_filter ((char *) t->data,t->size,lines,flags); if (len) *len = t->size; /* return size if requested */ return (char *) t->data; /* and text */}/* Mail fetch message text * Accepts: mail stream * message # to fetch * MIME section specifier (#.#.#...#) * pointer to returned length * flags * Returns: message text */char *mail_fetch_text (MAILSTREAM *stream,unsigned long msgno,char *section, unsigned long *len,long flags){ GETS_DATA md; PARTTEXT *p; STRING bs; MESSAGECACHE *elt; BODY *b = NIL; char tmp[MAILTMPLEN]; unsigned long i; if (len) *len = 0; /* default return size */ memset (&stream->private.string,NIL,sizeof (STRING)); if (section && (strlen (section) > (MAILTMPLEN - 20))) return ""; if (flags & FT_UID) { /* UID form of call */ if (msgno = mail_msgno (stream,msgno)) flags &= ~FT_UID; else return ""; /* must get UID/msgno map first */ } elt = mail_elt (stream,msgno);/* get cache data */ if (section && *section) { /* nested body text wanted? */ if (!((b = mail_body (stream,msgno,section)) && (b->type == TYPEMESSAGE) && !strcmp (b->subtype,"RFC822"))) return ""; /* lose if no body or not MESSAGE/RFC822 */ p = &b->nested.msg->text; /* point at nested message */ /* build IMAP-format section specifier */ sprintf (tmp,"%s.TEXT",section); flags &= ~FT_INTERNAL; /* can't win with this set */ } else { /* top-level message text wanted */ p = &elt->private.msg.text; strcpy (tmp,"TEXT"); } /* initialize message data identifier */ INIT_GETS (md,stream,msgno,section,0,0); if (p->text.data) { /* is data already cached? */ markseen (stream,elt,flags);/* mark message seen */ return mail_fetch_text_return (&md,&p->text,len); } if (!stream->dtb) return ""; /* not in cache, must have live driver */ if (stream->dtb->msgdata) return ((*stream->dtb->msgdata) (stream,msgno,tmp,0,0,NIL,flags) && p->text.data)? mail_fetch_text_return (&md,&p->text,len) : ""; if (!(*stream->dtb->text) (stream,msgno,&bs,flags)) return ""; if (section && *section) { /* nested is more complex */ SETPOS (&bs,p->offset); i = p->text.size; /* just want this much */ } else i = SIZE (&bs); /* want entire text */ return mail_fetch_string_return (&md,&bs,i,len,flags);}/* Mail fetch message body part MIME headers * Accepts: mail stream * message # to fetch * MIME section specifier (#.#.#...#) * pointer to returned length * flags * Returns: message text */char *mail_fetch_mime (MAILSTREAM *stream,unsigned long msgno,char *section, unsigned long *len,long flags){ PARTTEXT *p; STRING bs; BODY *b; char tmp[MAILTMPLEN]; if (len) *len = 0; /* default return size */ if (section && (strlen (section) > (MAILTMPLEN - 20))) return ""; if (flags & FT_UID) { /* UID form of call */ if (msgno = mail_msgno (stream,msgno)) flags &= ~FT_UID; else return ""; /* must get UID/msgno map first */ } flags &= ~FT_INTERNAL; /* can't win with this set */ if (!(section && *section && (b = mail_body (stream,msgno,section)))) return ""; /* not valid section */ /* in cache? */ if ((p = &b->mime)->text.data) { /* mark message seen */ markseen (stream,mail_elt (stream,msgno),flags); if (len) *len = p->text.size; return (char *) p->text.data; } if (!stream->dtb) return ""; /* not in cache, must have live driver */ if (stream->dtb->msgdata) { /* has driver fetch? */ /* build driver section specifier */ sprintf (tmp,"%s.MIME",section); if ((*stream->dtb->msgdata) (stream,msgno,tmp,0,0,NIL,flags) && p->text.data) { if (len) *len = p->text.size; return (char *) p->text.data; } else return ""; } if (len) *len = b->mime.text.size; if (!b->mime.text.size) { /* empty MIME header -- mark seen anyway */ markseen (stream,mail_elt (stream,msgno),flags); return ""; } /* have to get it from offset */ if (stream->private.search.text) return stream->private.search.text + b->mime.offset; if (!(*stream->dtb->text) (stream,msgno,&bs,flags)) { if (len) *len = 0; return ""; } if (bs.dtb->next == mail_string_next) { if (stream->private.search.string) stream->private.search.text = bs.curpos; return bs.curpos + b->mime.offset; } return textcpyoffstring (&stream->text,&bs,b->mime.offset,b->mime.text.size);}/* Mail fetch message body part * Accepts: mail stream * message # to fetch * MIME section specifier (#.#.#...#) * pointer to returned length * flags * Returns: message body */char *mail_fetch_body (MAILSTREAM *stream,unsigned long msgno,char *section, unsigned long *len,long flags){ GETS_DATA md; PARTTEXT *p; STRING bs; BODY *b; SIZEDTEXT *t; char *s,tmp[MAILTMPLEN]; memset (&stream->private.string,NIL,sizeof (STRING)); if (!(section && *section)) /* top-level text wanted? */ return mail_fetch_message (stream,msgno,len,flags); else if (strlen (section) > (MAILTMPLEN - 20)) return ""; flags &= ~FT_INTERNAL; /* can't win with this set */ /* initialize message data identifier */ INIT_GETS (md,stream,msgno,section,0,0); /* kludge for old section 0 header */ if (!strcmp (s = strcpy (tmp,section),"0") || ((s = strstr (tmp,".0")) && !s[2])) { SIZEDTEXT ht; *s = '\0'; /* tie off section */ /* this silly way so it does mailgets */ ht.data = (unsigned char *) mail_fetch_header (stream,msgno, tmp[0] ? tmp : NIL,NIL, &ht.size,flags); /* may have UIDs here */ md.flags = (flags & FT_UID) ? MG_UID : NIL; return mail_fetch_text_return (&md,&ht,len); } if (len) *len = 0; /* default return size */ if (flags & FT_UID) { /* UID form of call */ if (msgno = mail_msgno (stream,msgno)) flags &= ~FT_UID; else return ""; /* must get UID/msgno map first */ } /* must have body */ if (!(b = mail_body (stream,msgno,section))) return ""; /* have cached text? */ if ((t = &(p = &b->contents)->text)->data) { /* mark message seen */ markseen (stream,mail_elt (stream,msgno),flags); return mail_fetch_text_return (&md,t,len); } if (!stream->dtb) return ""; /* not in cache, must have live driver */ if (stream->dtb->msgdata) return ((*stream->dtb->msgdata)(stream,msgno,section,0,0,NIL,flag
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -