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

📄 smtp.c

📁 Vovida 社区开源的 SIP 协议源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Program:	Simple Mail Transfer Protocol (SMTP) routines * * Author:	Mark Crispin *		Networks and Distributed Computing *		Computing & Communications *		University of Washington *		Administration Building, AG-44 *		Seattle, WA  98195 *		Internet: MRC@CAC.Washington.EDU * * Date:	27 July 1988 * Last Edited:	10 October 2000 * * Sponsorship:	The original version of this work was developed in the *		Symbolic Systems Resources Group of the Knowledge Systems *		Laboratory at Stanford University in 1987-88, and was funded *		by the Biomedical Research Technology Program of the National *		Institutes of Health under grant number RR-00785. * * Original version Copyright 1988 by The Leland Stanford Junior University * Copyright 2000 by the University of Washington * *  Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notices appear in all copies and that both the * above copyright notices and this permission notice appear in supporting * documentation, and that the name of the University of Washington or The * Leland Stanford Junior University not be used in advertising or publicity * pertaining to distribution of the software without specific, written prior * permission.  This software is made available "as is", and * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE, * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */#include <ctype.h>#include <stdio.h>#include "mail.h"#include "osdep.h"#include "smtp.h"#include "rfc822.h"#include "misc.h"/* Mailer parameters */static unsigned long smtp_maxlogintrials = MAXLOGINTRIALS;static long smtp_port = 0;	/* default port override */static long smtp_altport = 0;static char *smtp_altname = NIL;/* SMTP limits, current as of most recent draft */#define SMTPMAXLOCALPART 64#define SMTPMAXDOMAIN 255#define SMTPMAXPATH 256/* I have seen local parts of more than 64 octets, in spite of the SMTP * limits.  So, we'll have a more generous limit that's still guaranteed * not to pop the buffer, and let the server worry about it.  As of this * writing, it comes out to 240.  Anyone with a mailbox name larger than * that is in serious need of a life or at least a new ISP!  23 June 1998 */#define MAXLOCALPART ((MAILTMPLEN - (SMTPMAXDOMAIN + SMTPMAXPATH + 32)) / 2)/* Mail Transfer Protocol manipulate driver parameters * Accepts: function code *	    function-dependent value * Returns: function-dependent return value */void *smtp_parameters (long function,void *value){  switch ((int) function) {  case SET_MAXLOGINTRIALS:    smtp_maxlogintrials = (unsigned long) value;    break;  case GET_MAXLOGINTRIALS:    value = (void *) smtp_maxlogintrials;    break;  case SET_SMTPPORT:    smtp_port = (long) value;    break;  case GET_SMTPPORT:    value = (void *) smtp_port;    break;  case SET_ALTSMTPPORT:    smtp_altport = (long) value;    break;  case GET_ALTSMTPPORT:    value = (void *) smtp_altport;    break;  case SET_ALTSMTPNAME:    smtp_altname = (char *) value;    break;  case GET_ALTSMTPNAME:    value = (void *) smtp_altname;    break;  default:    value = NIL;		/* error case */    break;  }  return value;}/* Mail Transfer Protocol open connection * Accepts: network driver *	    service host list *	    port number *	    service name *	    SMTP open options * Returns: SEND stream on success, NIL on failure */SENDSTREAM *smtp_open_full (NETDRIVER *dv,char **hostlist,char *service,			    unsigned long port,long options){  SENDSTREAM *stream = NIL;  long reply;  char *s,tmp[MAILTMPLEN];  NETSTREAM *netstream;  NETMBX mb;  if (!(hostlist && *hostlist)) mm_log ("Missing SMTP service host",ERROR);				/* maximum domain name is 64 characters */  else do if (strlen (*hostlist) < SMTPMAXDOMAIN) {    sprintf (tmp,"{%.1000s/%.20s}",*hostlist,service ? service : "smtp");    if (!mail_valid_net_parse (tmp,&mb) || mb.anoflag) {      sprintf (tmp,"Invalid host specifier: %.80s",*hostlist);      mm_log (tmp,ERROR);    }    else {				/* light tryalt flag if requested */      mb.tryaltflag = (options & SOP_TRYALT) ? T : NIL;      if (netstream =		/* try to open ordinary connection */	  net_open (&mb,dv,smtp_port ? smtp_port : port,		    (NETDRIVER *) mail_parameters (NIL,GET_ALTDRIVER,NIL),		    (char *) mail_parameters (NIL,GET_ALTSMTPNAME,NIL),		    (unsigned long)mail_parameters(NIL,GET_ALTSMTPPORT,NIL))) {	stream = (SENDSTREAM *) memset (fs_get (sizeof (SENDSTREAM)),0,					sizeof (SENDSTREAM));	stream->netstream = netstream;	stream->debug = (mb.dbgflag || (options & OP_DEBUG)) ? T : NIL;	if (options & SOP_SECURE) mb.secflag = T;	if (options &(SOP_DSN | SOP_DSN_NOTIFY_FAILURE | SOP_DSN_NOTIFY_DELAY |		      SOP_DSN_NOTIFY_SUCCESS | SOP_DSN_RETURN_FULL)) {	  ESMTP.dsn.want = T;	  if (options & SOP_DSN_NOTIFY_FAILURE) ESMTP.dsn.notify.failure = T;	  if (options & SOP_DSN_NOTIFY_DELAY) ESMTP.dsn.notify.delay = T;	  if (options & SOP_DSN_NOTIFY_SUCCESS) ESMTP.dsn.notify.success = T;	  if (options & SOP_DSN_RETURN_FULL) ESMTP.dsn.full = T;	}	if (options & SOP_8BITMIME) ESMTP.eightbit.want = T;				/* get name of local host to use */	s = strcmp ("localhost",lcase (strcpy (tmp,mb.host))) ?	  net_localhost (netstream) : "localhost";	do reply = smtp_reply (stream);	while ((reply < 100) || (stream->reply[3] == '-'));	if (reply != SMTPGREET){/* get SMTP greeting */	  sprintf (tmp,"SMTP greeting failure: %.80s",stream->reply);	  mm_log (tmp,ERROR);	  stream = smtp_close (stream);	}	else if ((reply = smtp_ehlo (stream,s,&mb)) == SMTPOK) {	  ESMTP.ok = T;	  if (mb.secflag || mb.user[0]) {	    if (ESMTP.auth) {	/* have authenticators? */	      if (!smtp_auth (stream,&mb,tmp)) stream = smtp_close(stream);	    }	    else {		/* no available authenticators */	      sprintf (tmp,"%sSMTP authentication not available: %.80s",		       mb.secflag ? "Secure " : "",mb.host);	      mm_log (tmp,ERROR);	      stream = smtp_close (stream);	    }	  }	}	else if (mb.secflag || mb.user[0]) {	  sprintf (tmp,"ESMTP failure: %.80s",stream->reply);	  mm_log (tmp,ERROR);	  stream = smtp_close (stream);	}				/* try ordinary SMTP then */	else if ((reply = smtp_send_work (stream,"HELO",s)) != SMTPOK) {	  sprintf (tmp,"SMTP hello failure: %.80s",stream->reply);	  mm_log (tmp,ERROR);	  stream = smtp_close (stream);	}      }    }  } while (!stream && *++hostlist);  return stream;}/* SMTP authenticate * Accepts: stream to login *	    parsed network mailbox structure *	    scratch buffer *	    place to return user name * Returns: T on success, NIL on failure */long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp){  unsigned long trial,auths;  char *lsterr = NIL;  char usr[MAILTMPLEN];  AUTHENTICATOR *at;  for (auths = ESMTP.auth; stream->netstream && auths &&       (at = mail_lookup_auth (find_rightmost_bit (&auths) + 1)); ) {    if (lsterr) {		/* previous authenticator failed? */      sprintf (tmp,"Retrying using %s authentication after %s",	       at->name,lsterr);      mm_log (tmp,NIL);      fs_give ((void **) &lsterr);    }    trial = 0;			/* initial trial count */    tmp[0] = '\0';		/* empty buffer */    if (stream->netstream) do {      if (tmp[0]) mm_log (tmp,WARN);      if (smtp_send_work (stream,"AUTH",at->name) &&	  (*at->client) (smtp_challenge,smtp_response,mb,stream,&trial,usr)) {	if (stream->replycode == SMTPAUTHED) return LONGT;	if (!trial) {		/* if main program requested cancellation */	  mm_log ("SMTP Authentication cancelled",ERROR);	  return NIL;	}      }      lsterr = cpystr (stream->reply);      sprintf (tmp,"Retrying %s authentication after %s",at->name,lsterr);    } while (stream->netstream && trial && (trial < smtp_maxlogintrials));  }  if (lsterr) {			/* previous authenticator failed? */    sprintf (tmp,"Can not authenticate to SMTP server: %s",lsterr);    mm_log (tmp,ERROR);    fs_give ((void **) &lsterr);  }  return NIL;			/* authentication failed */}/* Get challenge to authenticator in binary * Accepts: stream *	    pointer to returned size * Returns: challenge or NIL if not challenge */void *smtp_challenge (void *s,unsigned long *len){  SENDSTREAM *stream = (SENDSTREAM *) s;  return (stream->replycode == SMTPAUTHREADY) ?    rfc822_base64 ((unsigned char *) stream->reply+4,		   strlen (stream->reply+4),len) : NIL;}/* Send authenticator response in BASE64 * Accepts: MAIL stream *	    string to send *	    length of string * Returns: T, always */long smtp_response (void *s,char *response,unsigned long size){  SENDSTREAM *stream = (SENDSTREAM *) s;  unsigned long i,j;  char *t,*u;  if (response) {		/* make CRLFless BASE64 string */    if (size) {      for (t = (char *) rfc822_binary ((void *) response,size,&i),u = t,j = 0;	   j < i; j++) if (t[j] > ' ') *u++ = t[j];      *u = '\0';		/* tie off string */      i = smtp_send_work (stream,t,NIL);      fs_give ((void **) &t);    }    else i = smtp_send_work (stream,"",NIL);  }				/* abort requested */  else i = smtp_send_work (stream,"*",NIL);  return LONGT;}/* Mail Transfer Protocol close connection * Accepts: SEND stream * Returns: NIL always */SENDSTREAM *smtp_close (SENDSTREAM *stream){  if (stream) {			/* send "QUIT" */    smtp_send_work (stream,"QUIT",NIL);				/* close TCP connection */    net_close (stream->netstream);    if (stream->reply) fs_give ((void **) &stream->reply);    fs_give ((void **) &stream);/* flush the stream */  }  return NIL;}/* Mail Transfer Protocol deliver mail * Accepts: SEND stream *	    delivery option (MAIL, SEND, SAML, SOML) *	    message envelope *	    message body

⌨️ 快捷键说明

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