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

📄 smtp.c

📁 SIP 1.5.0源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * Returns: T on success, NIL on failure */long smtp_mail (SENDSTREAM *stream,char *type,ENVELOPE *env,BODY *body){  /* Note: This assumes that the envelope will never generate a header of   * more than 8K.  If your client generates godzilla headers, you will   * need to install your own rfc822out_t routine via SET_RFC822OUTPUT   * to use in place of this.   */  char tmp[8*MAILTMPLEN];  long error = NIL;  if (!(env->to || env->cc || env->bcc)) {  				/* no recipients in request */    smtp_fake (stream,SMTPHARDERROR,"No recipients specified");    return NIL;  }  smtp_send (stream,"RSET",NIL);/* make sure stream is in good shape */  strcpy (tmp,"FROM:<");	/* compose "MAIL FROM:<return-path>" */  if (env->return_path && env->return_path->host &&      !((env->return_path->adl &&	 (strlen (env->return_path->adl) > SMTPMAXPATH)) ||	(strlen (env->return_path->mailbox) > SMTPMAXLOCALPART) ||	(strlen (env->return_path->host) > SMTPMAXDOMAIN)))    rfc822_address (tmp,env->return_path);  strcat (tmp,">");  if (ESMTP.ok) {    if (ESMTP.eightbit.ok && ESMTP.eightbit.want) strcat(tmp," BODY=8BITMIME");    if (ESMTP.dsn.ok && ESMTP.dsn.want)      strcat (tmp,ESMTP.dsn.full ? " RET=FULL" : " RET=HDRS");  }				/* send "MAIL FROM" command */  if (!(smtp_send (stream,type,tmp) == SMTPOK)) return NIL;				/* negotiate the recipients */  if (env->to) smtp_rcpt (stream,env->to,&error);  if (env->cc) smtp_rcpt (stream,env->cc,&error);  if (env->bcc) smtp_rcpt (stream,env->bcc,&error);  if (error) {			/* any recipients failed? */      				/* reset the stream */    smtp_send (stream,"RSET",NIL);    smtp_fake (stream,SMTPHARDERROR,"One or more recipients failed");    return NIL;  }				/* negotiate data command */  if (!(smtp_send (stream,"DATA",NIL) == SMTPREADY)) return NIL;				/* set up error in case failure */  smtp_fake (stream,SMTPSOFTFATAL,"SMTP connection went away!");				/* output data, return success status */  return rfc822_output (tmp,env,body,smtp_soutr,stream->netstream,			ESMTP.eightbit.ok && ESMTP.eightbit.want) &&			  (smtp_send (stream,".",NIL) == SMTPOK);}/* Internal routines *//* Simple Mail Transfer Protocol send recipient * Accepts: SMTP stream *	    address list *	    pointer to error flag */void smtp_rcpt (SENDSTREAM *stream,ADDRESS *adr,long *error){  char *s,tmp[MAILTMPLEN];  while (adr) {			/* for each address on the list */				/* clear any former error */    if (adr->error) fs_give ((void **) &adr->error);    if (adr->host) {		/* ignore group syntax */				/* enforce SMTP limits to protect the buffer */      if (adr->adl && (strlen (adr->adl) > SMTPMAXPATH)) {	adr->error = cpystr ("501 Path too long");	*error = T;      }      else if (strlen (adr->mailbox) > MAXLOCALPART) {	adr->error = cpystr ("501 Recipient name too long");	*error = T;      }      if ((strlen (adr->host) > SMTPMAXDOMAIN)) {	adr->error = cpystr ("501 Recipient domain too long");	*error = T;      }      else {	strcpy (tmp,"TO:<");	/* compose "RCPT TO:<return-path>" */	rfc822_address (tmp,adr);	strcat (tmp,">");				/* want notifications */	if (ESMTP.ok && ESMTP.dsn.ok && ESMTP.dsn.want) {				/* yes, start with prefix */	  strcat (tmp," NOTIFY=");	  s = tmp + strlen (tmp);	  if (ESMTP.dsn.notify.failure) strcat (s,"FAILURE,");	  if (ESMTP.dsn.notify.delay) strcat (s,"DELAY,");	  if (ESMTP.dsn.notify.success) strcat (s,"SUCCESS,");				/* tie off last comma */	  if (*s) s[strlen (s) - 1] = '\0';	  else strcat (tmp,"NEVER");	}				/* send "RCPT TO" command */	if (!(smtp_send (stream,"RCPT",tmp) == SMTPOK)) {	  *error = T;		/* note that an error occurred */	  adr->error = cpystr (stream->reply);	}      }    }    adr = adr->next;		/* do any subsequent recipients */  }}/* Simple Mail Transfer Protocol send command * Accepts: SMTP stream *	    text * Returns: reply code */long smtp_send (SENDSTREAM *stream,char *command,char *args){  long ret;  do ret = smtp_send_work (stream,command,args);  while (ESMTP.auth && smtp_send_auth (stream,ret));  return ret;}/* SMTP send command worker routine * Accepts: SEND stream *	    text * Returns: reply code */long smtp_send_work (SENDSTREAM *stream,char *command,char *args){  long ret;  char *s = (char *) fs_get (strlen (command) + (args ? strlen (args) + 1 : 0)			     + 3);				/* build the complete command */  if (args) sprintf (s,"%s %s",command,args);  else strcpy (s,command);  if (stream->debug) mm_dlog (s);  strcat (s,"\015\012");				/* send the command */  if (!net_soutr (stream->netstream,s))    ret = smtp_fake (stream,SMTPSOFTFATAL,"SMTP connection broken (command)");  else {    do stream->replycode = smtp_reply (stream);    while ((stream->replycode < 100) || (stream->reply[3] == '-'));    ret = stream->replycode;  }  fs_give ((void **) &s);  return ret;}/* SMTP send authentication if needed * Accepts: SEND stream *	    code from previous command * Returns: T if need to redo command, NIL otherwise */long smtp_send_auth (SENDSTREAM *stream,long code){  NETMBX mb;  char tmp[MAILTMPLEN];  switch (code) {  case SMTPWANTAUTH: case SMTPWANTAUTH2:    sprintf (tmp,"{%.200s/smtp",net_host (stream->netstream));    if (stream->netstream->dtb ==	(NETDRIVER *) mail_parameters (NIL,GET_ALTDRIVER,NIL))      sprintf (tmp + strlen (tmp),"/%.200s",	       (char *) mail_parameters (NIL,GET_ALTDRIVERNAME,NIL));    strcat (tmp,"}<none>");    mail_valid_net_parse (tmp,&mb);    return smtp_auth (stream,&mb,tmp);  }  return NIL;			/* no auth needed */}/* Simple Mail Transfer Protocol get reply * Accepts: SMTP stream * Returns: reply code */long smtp_reply (SENDSTREAM *stream){  smtpverbose_t pv = (smtpverbose_t) mail_parameters (NIL,GET_SMTPVERBOSE,NIL);  long reply;				/* flush old reply */  if (stream->reply) fs_give ((void **) &stream->reply);  				/* get reply */  if (!(stream->reply = net_getline (stream->netstream)))    return smtp_fake (stream,SMTPSOFTFATAL,"SMTP connection went away!");  if (stream->debug) mm_dlog (stream->reply);  reply = atol (stream->reply);	/* return response code */  if (pv && (reply < 100)) (*pv) (stream->reply);  return reply;}/* Simple Mail Transfer Protocol send EHLO * Accepts: SMTP stream *	    host name to use in EHLO *	    NETMBX structure * Returns: reply code */long smtp_ehlo (SENDSTREAM *stream,char *host,NETMBX *mb){  unsigned long i;  unsigned int j;  long flags = (mb->secflag ? AU_SECURE : NIL) |    (mb->authuser[0] ? AU_AUTHUSER : NIL);  char *s,tmp[MAILTMPLEN];  sprintf (tmp,"EHLO %s",host);	/* build the complete command */  if (stream->debug) mm_dlog (tmp);  strcat (tmp,"\015\012");				/* send the command */  if (!net_soutr (stream->netstream,tmp))    return smtp_fake (stream,SMTPSOFTFATAL,"SMTP connection broken (EHLO)");				/* got an OK reply? */  do if ((i = smtp_reply (stream)) == SMTPOK) {    ucase (strncpy (tmp,stream->reply+4,MAILTMPLEN-1));    tmp[MAILTMPLEN-1] = '\0';				/* note EHLO options */    if ((tmp[0] == '8') && (tmp[1] == 'B') && (tmp[2] == 'I') &&	(tmp[3] == 'T') && (tmp[4] == 'M') && (tmp[5] == 'I') &&	(tmp[6] == 'M') && (tmp[7] == 'E') && !tmp[8]) ESMTP.eightbit.ok = T;    else if ((tmp[0] == 'S') && (tmp[1] == 'I') && (tmp[2] == 'Z') &&	     (tmp[3] == 'E') && (!tmp[4] || tmp[4] == ' ')) {      if (tmp[4]) ESMTP.size.limit = atoi (tmp+5);      ESMTP.size.ok = T;    }    else if ((tmp[0] == 'A') && (tmp[1] == 'U') && (tmp[2] == 'T') &&	     (tmp[3] == 'H') && ((tmp[4] == ' ') || (tmp[4] == '='))) {      for (s = strtok (tmp+5," "); s && *s; s = strtok (NIL," "))	if ((j = mail_lookup_auth_name (s,flags)) &&	    (--j < (8 * sizeof (ESMTP.auth)))) ESMTP.auth |= (1 << j);    }    else if ((tmp[0] == 'D') && (tmp[1] == 'S') && (tmp[2] == 'N') && !tmp[3])      ESMTP.dsn.ok = T;    else if ((tmp[0] == 'S') && (tmp[1] == 'E') && (tmp[2] == 'N') &&	     (tmp[3] == 'D') && !tmp[4]) ESMTP.service.send = T;    else if ((tmp[0] == 'S') && (tmp[1] == 'O') && (tmp[2] == 'M') &&	     (tmp[3] == 'L') && !tmp[4]) ESMTP.service.soml = T;    else if ((tmp[0] == 'S') && (tmp[1] == 'A') && (tmp[2] == 'M') &&	     (tmp[3] == 'L') && !tmp[4]) ESMTP.service.saml = T;    else if ((tmp[0] == 'E') && (tmp[1] == 'X') && (tmp[2] == 'P') &&	     (tmp[3] == 'N') && !tmp[4]) ESMTP.service.expn = T;    else if ((tmp[0] == 'H') && (tmp[1] == 'E') && (tmp[2] == 'L') &&	     (tmp[3] == 'P') && !tmp[4]) ESMTP.service.help = T;    else if ((tmp[0] == 'T') && (tmp[1] == 'U') && (tmp[2] == 'R') &&	     (tmp[3] == 'N') && !tmp[4]) ESMTP.service.turn = T;    else if ((tmp[0] == 'E') && (tmp[1] == 'T') && (tmp[2] == 'R') &&	     (tmp[3] == 'N') && !tmp[4]) ESMTP.service.etrn = T;    else if ((tmp[0] == 'R') && (tmp[1] == 'E') && (tmp[2] == 'L') &&	     (tmp[3] == 'A') && (tmp[4] == 'Y') && !tmp[5])      ESMTP.service.relay = T;    else if ((tmp[0] == 'P') && (tmp[1] == 'I') && (tmp[2] == 'P') &&	     (tmp[3] == 'E') && (tmp[4] == 'L') && (tmp[5] == 'I') &&	     (tmp[6] == 'N') && (tmp[7] == 'I') && (tmp[8] == 'N') &&	     (tmp[9] == 'G') && !tmp[10]) ESMTP.service.pipe = T;    else if ((tmp[0] == 'E') && (tmp[1] == 'N') && (tmp[2] == 'H') &&	     (tmp[3] == 'A') && (tmp[4] == 'N') && (tmp[5] == 'C') &&	     (tmp[6] == 'E') && (tmp[7] == 'D') && (tmp[8] == 'S') &&	     (tmp[9] == 'T') && (tmp[10] == 'A') && (tmp[11] == 'T') &&	     (tmp[12] == 'U') && (tmp[13] == 'S') && (tmp[14] == 'C') &&	     (tmp[15] == 'O') && (tmp[16] == 'D') && (tmp[17] == 'E') &&	     (tmp[18] == 'S') && !tmp[19]) ESMTP.service.ensc = T;  }  while ((i < 100) || (stream->reply[3] == '-'));  return i;			/* return the response code */}/* Simple Mail Transfer Protocol set fake error * Accepts: SMTP stream *	    SMTP error code *	    error text * Returns: error code */long smtp_fake (SENDSTREAM *stream,long code,char *text){				/* flush any old reply */  if (stream->reply ) fs_give ((void **) &stream->reply);  				/* set up pseudo-reply string */  stream->reply = (char *) fs_get (20+strlen (text));  sprintf (stream->reply,"%ld %s",code,text);  return code;			/* return error code */}/* Simple Mail Transfer Protocol filter mail * Accepts: stream *	    string * Returns: T on success, NIL on failure */long smtp_soutr (void *stream,char *s){  char c,*t;				/* "." on first line */  if (s[0] == '.') net_sout (stream,".",1);				/* find lines beginning with a "." */  while (t = strstr (s,"\015\012.")) {    c = *(t += 3);		/* remember next character after "." */    *t = '\0';			/* tie off string */				/* output prefix */    if (!net_sout (stream,s,t-s)) return NIL;    *t = c;			/* restore delimiter */    s = t - 1;			/* push pointer up to the "." */  }				/* output remainder of text */  return *s ? net_soutr (stream,s) : T;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -