1: # include <ctype.h>
   2: # include <sysexits.h>
   3: # include "sendmail.h"
   4: 
   5: # ifndef SMTP
   6: SCCSID(@(#)usersmtp.c	4.2		8/31/83	(no SMTP));
   7: # else SMTP
   8: 
   9: SCCSID(@(#)usersmtp.c	4.2		8/31/83);
  10: 
  11: 
  12: 
  13: /*
  14: **  USERSMTP -- run SMTP protocol from the user end.
  15: **
  16: **	This protocol is described in RFC821.
  17: */
  18: 
  19: #define REPLYTYPE(r)    ((r) / 100)     /* first digit of reply code */
  20: #define REPLYCLASS(r)   (((r) / 10) % 10)   /* second digit of reply code */
  21: #define SMTPCLOSING 421         /* "Service Shutting Down" */
  22: 
  23: char    SmtpReplyBuffer[MAXLINE];   /* buffer for replies */
  24: FILE    *SmtpOut;           /* output file */
  25: FILE    *SmtpIn;            /* input file */
  26: int SmtpPid;            /* pid of mailer */
  27: 
  28: /* following represents the state of the SMTP connection */
  29: int SmtpState;          /* connection state, see below */
  30: 
  31: #define SMTP_CLOSED 0       /* connection is closed */
  32: #define SMTP_OPEN   1       /* connection is open for business */
  33: #define SMTP_SSD    2       /* service shutting down */
  34: /*
  35: **  SMTPINIT -- initialize SMTP.
  36: **
  37: **	Opens the connection and sends the initial protocol.
  38: **
  39: **	Parameters:
  40: **		m -- mailer to create connection to.
  41: **		pvp -- pointer to parameter vector to pass to
  42: **			the mailer.
  43: **
  44: **	Returns:
  45: **		appropriate exit status -- EX_OK on success.
  46: **
  47: **	Side Effects:
  48: **		creates connection and sends initial protocol.
  49: */
  50: 
  51: jmp_buf CtxGreeting;
  52: 
  53: smtpinit(m, pvp)
  54:     struct mailer *m;
  55:     char **pvp;
  56: {
  57:     register int r;
  58:     EVENT *gte;
  59:     char buf[MAXNAME];
  60:     extern greettimeout();
  61: 
  62:     /*
  63: 	**  Open the connection to the mailer.
  64: 	*/
  65: 
  66: #ifdef DEBUG
  67:     if (SmtpState == SMTP_OPEN)
  68:         syserr("smtpinit: already open");
  69: #endif DEBUG
  70: 
  71:     SmtpIn = SmtpOut = NULL;
  72:     SmtpState = SMTP_CLOSED;
  73:     SmtpPid = openmailer(m, pvp, (ADDRESS *) NULL, TRUE, &SmtpOut, &SmtpIn);
  74:     if (SmtpPid < 0)
  75:     {
  76: # ifdef DEBUG
  77:         if (tTd(18, 1))
  78:             printf("smtpinit: cannot open %s: stat %d errno %d\n",
  79:                pvp[0], ExitStat, errno);
  80: # endif DEBUG
  81:         return (ExitStat);
  82:     }
  83:     SmtpState = SMTP_OPEN;
  84: 
  85:     /*
  86: 	**  Get the greeting message.
  87: 	**	This should appear spontaneously.  Give it two minutes to
  88: 	**	happen.
  89: 	*/
  90: 
  91:     if (setjmp(CtxGreeting) != 0)
  92:         return (EX_TEMPFAIL);
  93:     gte = setevent((time_t) 120, greettimeout, 0);
  94:     r = reply(m);
  95:     clrevent(gte);
  96:     if (r < 0 || REPLYTYPE(r) != 2)
  97:         return (EX_TEMPFAIL);
  98: 
  99:     /*
 100: 	**  Send the HELO command.
 101: 	**	My mother taught me to always introduce myself.
 102: 	*/
 103: 
 104:     smtpmessage("HELO %s", m, HostName);
 105:     r = reply(m);
 106:     if (r < 0)
 107:         return (EX_TEMPFAIL);
 108:     else if (REPLYTYPE(r) == 5)
 109:         return (EX_UNAVAILABLE);
 110:     else if (REPLYTYPE(r) != 2)
 111:         return (EX_TEMPFAIL);
 112: 
 113:     /*
 114: 	**  If this is expected to be another sendmail, send some internal
 115: 	**  commands.
 116: 	*/
 117: 
 118:     if (bitnset(M_INTERNAL, m->m_flags))
 119:     {
 120:         /* tell it to be verbose */
 121:         smtpmessage("VERB", m);
 122:         r = reply(m);
 123:         if (r < 0)
 124:             return (EX_TEMPFAIL);
 125: 
 126:         /* tell it we will be sending one transaction only */
 127:         smtpmessage("ONEX", m);
 128:         r = reply(m);
 129:         if (r < 0)
 130:             return (EX_TEMPFAIL);
 131:     }
 132: 
 133:     /*
 134: 	**  Send the MAIL command.
 135: 	**	Designates the sender.
 136: 	*/
 137: 
 138:     expand("$g", buf, &buf[sizeof buf - 1], CurEnv);
 139:     if (CurEnv->e_from.q_mailer == LocalMailer ||
 140:         !bitnset(M_FROMPATH, m->m_flags))
 141:     {
 142:         smtpmessage("MAIL From:<%s>", m, buf);
 143:     }
 144:     else
 145:     {
 146:         smtpmessage("MAIL From:<@%s%c%s>", m, HostName,
 147:             buf[0] == '@' ? ',' : ':', buf);
 148:     }
 149:     r = reply(m);
 150:     if (r < 0 || REPLYTYPE(r) == 4)
 151:         return (EX_TEMPFAIL);
 152:     else if (r == 250)
 153:         return (EX_OK);
 154:     else if (r == 552)
 155:         return (EX_UNAVAILABLE);
 156:     return (EX_PROTOCOL);
 157: }
 158: 
 159: 
 160: static
 161: greettimeout()
 162: {
 163:     /* timeout reading the greeting message */
 164:     longjmp(CtxGreeting, 1);
 165: }
 166: /*
 167: **  SMTPRCPT -- designate recipient.
 168: **
 169: **	Parameters:
 170: **		to -- address of recipient.
 171: **		m -- the mailer we are sending to.
 172: **
 173: **	Returns:
 174: **		exit status corresponding to recipient status.
 175: **
 176: **	Side Effects:
 177: **		Sends the mail via SMTP.
 178: */
 179: 
 180: smtprcpt(to, m)
 181:     ADDRESS *to;
 182:     register MAILER *m;
 183: {
 184:     register int r;
 185:     extern char *remotename();
 186: 
 187:     smtpmessage("RCPT To:<%s>", m, remotename(to->q_user, m, FALSE, TRUE));
 188: 
 189:     r = reply(m);
 190:     if (r < 0 || REPLYTYPE(r) == 4)
 191:         return (EX_TEMPFAIL);
 192:     else if (REPLYTYPE(r) == 2)
 193:         return (EX_OK);
 194:     else if (r == 550 || r == 551 || r == 553)
 195:         return (EX_NOUSER);
 196:     else if (r == 552 || r == 554)
 197:         return (EX_UNAVAILABLE);
 198:     return (EX_PROTOCOL);
 199: }
 200: /*
 201: **  SMTPDATA -- send the data and clean up the transaction.
 202: **
 203: **	Parameters:
 204: **		m -- mailer being sent to.
 205: **		e -- the envelope for this message.
 206: **
 207: **	Returns:
 208: **		exit status corresponding to DATA command.
 209: **
 210: **	Side Effects:
 211: **		none.
 212: */
 213: 
 214: smtpdata(m, e)
 215:     struct mailer *m;
 216:     register ENVELOPE *e;
 217: {
 218:     register int r;
 219: 
 220:     /*
 221: 	**  Send the data.
 222: 	**	First send the command and check that it is ok.
 223: 	**	Then send the data.
 224: 	**	Follow it up with a dot to terminate.
 225: 	**	Finally get the results of the transaction.
 226: 	*/
 227: 
 228:     /* send the command and check ok to proceed */
 229:     smtpmessage("DATA", m);
 230:     r = reply(m);
 231:     if (r < 0 || REPLYTYPE(r) == 4)
 232:         return (EX_TEMPFAIL);
 233:     else if (r == 554)
 234:         return (EX_UNAVAILABLE);
 235:     else if (r != 354)
 236:         return (EX_PROTOCOL);
 237: 
 238:     /* now output the actual message */
 239:     (*e->e_puthdr)(SmtpOut, m, CurEnv);
 240:     putline("\n", SmtpOut, m);
 241:     (*e->e_putbody)(SmtpOut, m, CurEnv);
 242: 
 243:     /* terminate the message */
 244:     fprintf(SmtpOut, ".%s", m->m_eol);
 245:     if (Verbose && !HoldErrs)
 246:         nmessage(Arpa_Info, ">>> .");
 247: 
 248:     /* check for the results of the transaction */
 249:     r = reply(m);
 250:     if (r < 0 || REPLYTYPE(r) == 4)
 251:         return (EX_TEMPFAIL);
 252:     else if (r == 250)
 253:         return (EX_OK);
 254:     else if (r == 552 || r == 554)
 255:         return (EX_UNAVAILABLE);
 256:     return (EX_PROTOCOL);
 257: }
 258: /*
 259: **  SMTPQUIT -- close the SMTP connection.
 260: **
 261: **	Parameters:
 262: **		name -- name of mailer we are quitting.
 263: **
 264: **	Returns:
 265: **		none.
 266: **
 267: **	Side Effects:
 268: **		sends the final protocol and closes the connection.
 269: */
 270: 
 271: smtpquit(name, m)
 272:     char *name;
 273:     register MAILER *m;
 274: {
 275:     int i;
 276: 
 277:     /* if the connection is already closed, don't bother */
 278:     if (SmtpIn == NULL)
 279:         return;
 280: 
 281:     /* send the quit message if not a forced quit */
 282:     if (SmtpState == SMTP_OPEN || SmtpState == SMTP_SSD)
 283:     {
 284:         smtpmessage("QUIT", m);
 285:         (void) reply(m);
 286:         if (SmtpState == SMTP_CLOSED)
 287:             return;
 288:     }
 289: 
 290:     /* now actually close the connection */
 291:     (void) fclose(SmtpIn);
 292:     (void) fclose(SmtpOut);
 293:     SmtpIn = SmtpOut = NULL;
 294:     SmtpState = SMTP_CLOSED;
 295: 
 296:     /* and pick up the zombie */
 297:     i = endmailer(SmtpPid, name);
 298:     if (i != EX_OK)
 299:         syserr("smtpquit %s: stat %d", name, i);
 300: }
 301: /*
 302: **  REPLY -- read arpanet reply
 303: **
 304: **	Parameters:
 305: **		m -- the mailer we are reading the reply from.
 306: **
 307: **	Returns:
 308: **		reply code it reads.
 309: **
 310: **	Side Effects:
 311: **		flushes the mail file.
 312: */
 313: 
 314: reply(m)
 315:     MAILER *m;
 316: {
 317:     (void) fflush(SmtpOut);
 318: 
 319:     if (tTd(18, 1))
 320:         printf("reply\n");
 321: 
 322:     /*
 323: 	**  Read the input line, being careful not to hang.
 324: 	*/
 325: 
 326:     for (;;)
 327:     {
 328:         register int r;
 329:         register char *p;
 330: 
 331:         /* actually do the read */
 332:         if (CurEnv->e_xfp != NULL)
 333:             (void) fflush(CurEnv->e_xfp);   /* for debugging */
 334: 
 335:         /* if we are in the process of closing just give the code */
 336:         if (SmtpState == SMTP_CLOSED)
 337:             return (SMTPCLOSING);
 338: 
 339:         /* get the line from the other side */
 340:         p = sfgets(SmtpReplyBuffer, sizeof SmtpReplyBuffer, SmtpIn);
 341:         if (p == NULL)
 342:         {
 343:             extern char MsgBuf[];       /* err.c */
 344:             extern char Arpa_TSyserr[]; /* conf.c */
 345: 
 346:             message(Arpa_TSyserr, "reply: read error");
 347: # ifdef DEBUG
 348:             /* if debugging, pause so we can see state */
 349:             if (tTd(18, 100))
 350:                 pause();
 351: # endif DEBUG
 352: # ifdef LOG
 353:             syslog(LOG_ERR, "%s", &MsgBuf[4]);
 354: # endif LOG
 355:             SmtpState = SMTP_CLOSED;
 356:             smtpquit("reply error", m);
 357:             return (-1);
 358:         }
 359:         fixcrlf(SmtpReplyBuffer, TRUE);
 360: 
 361:         /* log the input in the transcript for future error returns */
 362:         if (Verbose && !HoldErrs)
 363:             nmessage(Arpa_Info, "%s", SmtpReplyBuffer);
 364:         else if (CurEnv->e_xfp != NULL)
 365:             fprintf(CurEnv->e_xfp, "%s\n", SmtpReplyBuffer);
 366: 
 367:         /* if continuation is required, we can go on */
 368:         if (SmtpReplyBuffer[3] == '-' || !isdigit(SmtpReplyBuffer[0]))
 369:             continue;
 370: 
 371:         /* decode the reply code */
 372:         r = atoi(SmtpReplyBuffer);
 373: 
 374:         /* extra semantics: 0xx codes are "informational" */
 375:         if (r < 100)
 376:             continue;
 377: 
 378:         /* reply code 421 is "Service Shutting Down" */
 379:         if (r == SMTPCLOSING && SmtpState != SMTP_SSD)
 380:         {
 381:             /* send the quit protocol */
 382:             SmtpState = SMTP_SSD;
 383:             smtpquit("SMTP Shutdown", m);
 384:         }
 385: 
 386:         return (r);
 387:     }
 388: }
 389: /*
 390: **  SMTPMESSAGE -- send message to server
 391: **
 392: **	Parameters:
 393: **		f -- format
 394: **		m -- the mailer to control formatting.
 395: **		a, b, c -- parameters
 396: **
 397: **	Returns:
 398: **		none.
 399: **
 400: **	Side Effects:
 401: **		writes message to SmtpOut.
 402: */
 403: 
 404: /*VARARGS1*/
 405: smtpmessage(f, m, a, b, c)
 406:     char *f;
 407:     MAILER *m;
 408: {
 409:     char buf[MAXLINE];
 410: 
 411:     (void) sprintf(buf, f, a, b, c);
 412:     if (tTd(18, 1) || (Verbose && !HoldErrs))
 413:         nmessage(Arpa_Info, ">>> %s", buf);
 414:     else if (CurEnv->e_xfp != NULL)
 415:         fprintf(CurEnv->e_xfp, ">>> %s\n", buf);
 416:     if (SmtpOut != NULL)
 417:         fprintf(SmtpOut, "%s%s", buf, m->m_eol);
 418: }
 419: 
 420: # endif SMTP

Defined functions

greettimeout defined in line 160; used 2 times
reply defined in line 314; used 9 times
smtpdata defined in line 214; used 1 times
smtpinit defined in line 53; used 1 times
smtpmessage defined in line 405; used 8 times
smtpquit defined in line 271; used 3 times
smtprcpt defined in line 180; used 1 times

Defined variables

CtxGreeting defined in line 51; used 2 times
SmtpPid defined in line 26; used 3 times
SmtpReplyBuffer defined in line 23; used 8 times
SmtpState defined in line 29; used 11 times

Defined macros

REPLYCLASS defined in line 20; never used
REPLYTYPE defined in line 19; used 8 times
SMTPCLOSING defined in line 21; used 2 times
SMTP_CLOSED defined in line 31; used 5 times
SMTP_OPEN defined in line 32; used 3 times
SMTP_SSD defined in line 33; used 3 times
Last modified: 1984-03-19
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1338
Valid CSS Valid XHTML 1.0 Strict