📄 mail.c
字号:
* Returns: stream to use on success, NIL on failure */MAILSTREAM *mail_open (MAILSTREAM *stream,char *name,long options){ int i; char c,*s,tmp[MAILTMPLEN]; NETMBX mb; DRIVER *d; switch (name[0]) { /* see if special handling */ case '#': /* possible special hacks */ if (((name[1] == 'M') || (name[1] == 'm')) && ((name[2] == 'O') || (name[2] == 'o')) && ((name[3] == 'V') || (name[3] == 'v')) && ((name[4] == 'E') || (name[4] == 'e')) && (c = name[5]) && (s = strchr (name+6,c)) && (i = s - (name + 6)) && (i < MAILTMPLEN)) { if (stream = mail_open (stream,s+1,options)) { strncpy (tmp,name+6,i); /* copy snarf mailbox name */ tmp[i] = '\0'; /* tie off name */ mail_parameters (stream,SET_SNARFMAILBOXNAME,(void *) tmp); stream->snarf.options = options; mail_ping (stream); /* do initial snarf */ /* punt if can't do initial snarf */ if (!stream->snarf.time) stream = mail_close (stream); } return stream; } /* special POP hack */ else if (((name[1] == 'P') || (name[1] == 'p')) && ((name[2] == 'O') || (name[2] == 'o')) && ((name[3] == 'P') || (name[3] == 'p')) && mail_valid_net_parse_work (name+4,&mb,"pop3") && !strcmp (mb.service,"pop3") && !mb.anoflag && !mb.readonlyflag) { if (stream = mail_open (stream,mb.mailbox,options)) { sprintf (tmp,"{%.255s",mb.host); if (mb.port) sprintf (tmp + strlen (tmp),":%lu",mb.port); if (mb.user[0]) sprintf (tmp + strlen (tmp),"/user=%.64s",mb.user); if (mb.dbgflag) strcat (tmp,"/debug"); if (mb.secflag) strcat (tmp,"/secure"); if (mb.tlsflag) strcat (tmp,"/tls"); if (mb.notlsflag) strcat (tmp,"/notls"); if (mb.sslflag) strcat (tmp,"/ssl"); if (mb.trysslflag) strcat (tmp,"/tryssl"); if (mb.novalidate) strcat (tmp,"/novalidate-cert"); strcat (tmp,"/pop3/loser}"); mail_parameters (stream,SET_SNARFMAILBOXNAME,(void *) tmp); mail_ping (stream); /* do initial snarf */ } return stream; /* return local mailbox stream */ } else if ((options & OP_PROTOTYPE) && ((name[1] == 'D') || (name[1] == 'd')) && ((name[2] == 'R') || (name[2] == 'r')) && ((name[3] == 'I') || (name[3] == 'i')) && ((name[4] == 'V') || (name[4] == 'v')) && ((name[5] == 'E') || (name[5] == 'e')) && ((name[6] == 'R') || (name[6] == 'r')) && (name[7] == '.')) { sprintf (tmp,"%.80s",name+8); /* tie off name at likely delimiter */ if (s = strpbrk (tmp,"/\\:")) *s++ = '\0'; else { sprintf (tmp,"Can't resolve mailbox %.80s: bad driver syntax",name); MM_LOG (tmp,ERROR); return mail_close (stream); } for (d = maildrivers; d && compare_cstring (d->name,tmp); d = d->next); if (d) return (*d->open) (NIL); sprintf (tmp,"Can't resolve mailbox %.80s: unknown driver",name); MM_LOG (tmp,ERROR); return mail_close (stream); } /* fall through to default case */ default: /* not special hack (but could be # name */ d = mail_valid (NIL,name,(options & OP_SILENT) ? (char *) NIL : "open mailbox"); } return d ? mail_open_work (d,stream,name,options) : stream;}/* Mail open worker routine * Accepts: factory * candidate stream for recycling * mailbox name * open options * Returns: stream to use on success, NIL on failure */MAILSTREAM *mail_open_work (DRIVER *d,MAILSTREAM *stream,char *name, long options){ int i; char tmp[MAILTMPLEN]; NETMBX mb; if (options & OP_PROTOTYPE) return (*d->open) (NIL); /* name is copied here in case the caller does a re-open using * stream->mailbox or stream->original_mailbox as the argument. */ name = cpystr (name); /* make copy of name */ if (stream) { /* recycling requested? */ if ((stream->dtb == d) && (d->flags & DR_RECYCLE) && ((d->flags & DR_HALFOPEN) || !(options & OP_HALFOPEN)) && mail_usable_network_stream (stream,name)) { /* yes, checkpoint if needed */ if (d->flags & DR_XPOINT) mail_check (stream); mail_free_cache (stream); /* clean up stream */ if (stream->mailbox) fs_give ((void **) &stream->mailbox); if (stream->original_mailbox) fs_give ((void **) &stream->original_mailbox); /* flush user flags */ for (i = 0; i < NUSERFLAGS; i++) if (stream->user_flags[i]) fs_give ((void **) &stream->user_flags[i]); } else { /* stream not recycleable, babble if net */ if (!stream->silent && stream->dtb && !(stream->dtb->flags&DR_LOCAL) && mail_valid_net_parse (stream->mailbox,&mb)) { sprintf (tmp,"Closing connection to %.80s",mb.host); MM_LOG (tmp,(long) NIL); } /* flush the old stream */ stream = mail_close (stream); } } /* check if driver does not support halfopen */ else if ((options & OP_HALFOPEN) && !(d->flags & DR_HALFOPEN)) { fs_give ((void **) &name); return NIL; } /* instantiate new stream if not recycling */ if (!stream) (*mailcache) (stream = (MAILSTREAM *) memset (fs_get (sizeof (MAILSTREAM)),0, sizeof (MAILSTREAM)),(long) 0,CH_INIT); stream->dtb = d; /* set dispatch */ /* set mailbox name */ stream->mailbox = cpystr (stream->original_mailbox = name); /* initialize stream flags */ stream->inbox = stream->lock = NIL; stream->debug = (options & OP_DEBUG) ? T : NIL; stream->rdonly = (options & OP_READONLY) ? T : NIL; stream->anonymous = (options & OP_ANONYMOUS) ? T : NIL; stream->scache = (options & OP_SHORTCACHE) ? T : NIL; stream->silent = (options & OP_SILENT) ? T : NIL; stream->halfopen = (options & OP_HALFOPEN) ? T : NIL; stream->secure = (options & OP_SECURE) ? T : NIL; stream->tryssl = (options & OP_TRYSSL) ? T : NIL; stream->mulnewsrc = (options & OP_MULNEWSRC) ? T : NIL; stream->nokod = (options & OP_NOKOD) ? T : NIL; stream->sniff = (options & OP_SNIFF) ? T : NIL; stream->perm_seen = stream->perm_deleted = stream->perm_flagged = stream->perm_answered = stream->perm_draft = stream->kwd_create = NIL; stream->uid_nosticky = (d->flags & DR_NOSTICKY) ? T : NIL; stream->uid_last = 0; /* default UID validity */ stream->uid_validity = (unsigned long) time (0); /* have driver open, flush if failed */ return ((*d->open) (stream)) ? stream : mail_close (stream);}/* Mail close * Accepts: mail stream * close options * Returns: NIL, always */MAILSTREAM *mail_close_full (MAILSTREAM *stream,long options){ int i; if (stream) { /* make sure argument given */ /* do the driver's close action */ if (stream->dtb) (*stream->dtb->close) (stream,options); stream->dtb = NIL; /* resign driver */ if (stream->mailbox) fs_give ((void **) &stream->mailbox); if (stream->original_mailbox) fs_give ((void **) &stream->original_mailbox); if (stream->snarf.name) fs_give ((void **) &stream->snarf.name); stream->sequence++; /* invalidate sequence */ /* flush user flags */ for (i = 0; i < NUSERFLAGS; i++) if (stream->user_flags[i]) fs_give ((void **) &stream->user_flags[i]); mail_free_cache (stream); /* finally free the stream's storage */ if (mailfreestreamsparep && stream->sparep) (*mailfreestreamsparep) (&stream->sparep); if (!stream->use) fs_give ((void **) &stream); } return NIL;}/* Mail make handle * Accepts: mail stream * Returns: handle * * Handles provide a way to have multiple pointers to a stream yet allow the * stream's owner to nuke it or recycle it. */MAILHANDLE *mail_makehandle (MAILSTREAM *stream){ MAILHANDLE *handle = (MAILHANDLE *) fs_get (sizeof (MAILHANDLE)); handle->stream = stream; /* copy stream */ /* and its sequence */ handle->sequence = stream->sequence; stream->use++; /* let stream know another handle exists */ return handle;}/* Mail release handle * Accepts: Mail handle */void mail_free_handle (MAILHANDLE **handle){ MAILSTREAM *s; if (*handle) { /* only free if exists */ /* resign stream, flush unreferenced zombies */ if ((!--(s = (*handle)->stream)->use) && !s->dtb) fs_give ((void **) &s); fs_give ((void **) handle); /* now flush the handle */ }}/* Mail get stream handle * Accepts: Mail handle * Returns: mail stream or NIL if stream gone */MAILSTREAM *mail_stream (MAILHANDLE *handle){ MAILSTREAM *s = handle->stream; return (s->dtb && (handle->sequence == s->sequence)) ? s : NIL;}/* Mail fetch cache element * Accepts: mail stream * message # to fetch * Returns: cache element of this message * Can also be used to create cache elements for new messages. */MESSAGECACHE *mail_elt (MAILSTREAM *stream,unsigned long msgno){ if (msgno < 1 || msgno > stream->nmsgs) { char tmp[MAILTMPLEN]; sprintf (tmp,"Bad msgno %lu in mail_elt, nmsgs = %lu, mbx=%.80s", msgno,stream->nmsgs,stream->mailbox ? stream->mailbox : "???"); fatal (tmp); } return (MESSAGECACHE *) (*mailcache) (stream,msgno,CH_MAKEELT);}/* Mail fetch fast information * Accepts: mail stream * sequence * option flags * * Generally, mail_fetch_structure is preferred */void mail_fetch_fast (MAILSTREAM *stream,char *sequence,long flags){ /* do the driver's action */ if (stream->dtb && stream->dtb->fast) (*stream->dtb->fast) (stream,sequence,flags);}/* Mail fetch flags * Accepts: mail stream * sequence * option flags */void mail_fetch_flags (MAILSTREAM *stream,char *sequence,long flags){ /* do the driver's action */ if (stream->dtb && stream->dtb->msgflags) (*stream->dtb->msgflags) (stream,sequence,flags);}/* Mail fetch message overview * Accepts: mail stream * UID sequence to fetch * pointer to overview return function */void mail_fetch_overview (MAILSTREAM *stream,char *sequence,overview_t ofn){ if (stream->dtb && mail_uid_sequence (stream,sequence) && !(stream->dtb->overview && (*stream->dtb->overview) (stream,ofn)) && mail_ping (stream)) mail_fetch_overview_default (stream,ofn);}/* Mail fetch message overview using sequence numbers instead of UIDs * Accepts: mail stream * sequence to fetch * pointer to overview return function */void mail_fetch_overview_sequence (MAILSTREAM *stream,char *sequence, overview_t ofn){ if (stream->dtb && mail_sequence (stream,sequence) && !(stream->dtb->overview && (*stream->dtb->overview) (stream,ofn)) && mail_ping (stream)) mail_fetch_overview_default (stream,ofn);}/* Mail fetch message overview default handler * Accepts: mail stream with sequence bits lit * pointer to overview return function */void mail_fetch_overview_default (MAILSTREAM *stream,overview_t ofn){ MESSAGECACHE *elt; ENVELOPE *env; OVERVIEW ov; unsigned long i; ov.optional.lines = 0; ov.optional.xref = NIL; 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,i); }}/* Mail fetch message 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 *mail_fetch_structure (MAILSTREAM *stream,unsigned long msgno, BODY **body,long flags){ ENVELOPE **env; BODY **b; MESSAGECACHE *elt; char c,*s,*hdr; unsigned long hdrsize; STRING bs; /* do the driver's action if specified */ if (stream->dtb && stream->dtb->structure) return (*stream->dtb->structure) (stream,msgno,body,flags); if (flags & FT_UID) { /* UID form of call */ if (msgno = mail_msgno (stream,msgno)) flags &= ~FT_UID; else return NIL; /* must get UID/msgno map first */ } elt = mail_elt (stream,msgno);/* get elt for real message number */ if (stream->scache) { /* short caching */ if (msgno != stream->msgno){/* garbage collect if not same message */ mail_gc (stream,GC_ENV | GC_TEXTS); stream->msgno = msgno; /* this is the current message now */ } env = &stream->env; /* get pointers to envelope and body */ b = &stream->body; } else { /* get pointers to elt envelope and body */ env = &elt->private.msg.env; b = &elt->private.msg.body; } if (stream->dtb && ((body && !*b) || !*env || (*env)->incomplete)) { mail_free_envelope (env); /* flush old envelope and body */ mail_free_body (b); /* see if need to fetch the whole thing */ if (body || !elt->rfc822_size) { s = (*stream->dtb->header) (stream,msgno,&hdrsize,flags & ~FT_INTERNAL); /* make copy in case body fetch smashes it */ hdr = (char *) memcpy (fs_get ((size_t) hdrsize+1),s,(size_t) hdrsize); hdr[hdrsize] = '\0'; /* tie off header */ (*stream->dtb->text) (stream,msgno,&bs,(flags & ~FT_INTERNAL) | FT_PEEK); if (!elt->rfc822_size) elt->rfc822_size = hdrsize + SIZE (&bs); if (body) /* only parse body if requested */ rfc822_parse_msg (env,b,hdr,hdrsize,&bs,BADHOST,stream->dtb->flags); else rfc822_parse_msg (env,NIL,hdr,hdrsize,NIL,BADHOST,stream->dtb->flags); fs_give ((void **) &hdr); /* flush header */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -