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

📄 mail.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
 * 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 + -