Steven McCanne did kvm, renmae packet filter to bpf
[unix-history] / usr / src / usr.sbin / sendmail / src / usersmtp.c
CommitLineData
b2a81223 1/*
dc45ba8c 2 * Copyright (c) 1983 Eric P. Allman
bee79b64
KB
3 * Copyright (c) 1988 Regents of the University of California.
4 * All rights reserved.
5 *
0d77f9d8 6 * %sccs.include.redist.c%
bee79b64 7 */
b2a81223 8
e6b0a75b 9# include "sendmail.h"
d2eb2478 10
bee79b64
KB
11#ifndef lint
12#ifdef SMTP
a9bac7a9 13static char sccsid[] = "@(#)usersmtp.c 6.22 (Berkeley) %G% (with SMTP)";
bee79b64 14#else
a9bac7a9 15static char sccsid[] = "@(#)usersmtp.c 6.22 (Berkeley) %G% (without SMTP)";
bee79b64
KB
16#endif
17#endif /* not lint */
80482eb5 18
bee79b64
KB
19# include <sysexits.h>
20# include <errno.h>
80482eb5 21
bee79b64 22# ifdef SMTP
d2eb2478
EA
23
24/*
80482eb5
EA
25** USERSMTP -- run SMTP protocol from the user end.
26**
27** This protocol is described in RFC821.
28*/
29
30#define REPLYTYPE(r) ((r) / 100) /* first digit of reply code */
31#define REPLYCLASS(r) (((r) / 10) % 10) /* second digit of reply code */
32#define SMTPCLOSING 421 /* "Service Shutting Down" */
33
d7dbe85b 34char SmtpMsgBuffer[MAXLINE]; /* buffer for commands */
d0729491 35char SmtpReplyBuffer[MAXLINE]; /* buffer for replies */
46f6ec52 36char SmtpError[MAXLINE] = ""; /* save failure error messages */
d0729491 37int SmtpPid; /* pid of mailer */
16133a1c
EA
38
39#ifdef __STDC__
40extern smtpmessage(char *f, MAILER *m, MCI *mci, ...);
41#endif
80482eb5 42\f/*
e6b0a75b 43** SMTPINIT -- initialize SMTP.
d2eb2478 44**
e6b0a75b 45** Opens the connection and sends the initial protocol.
d2eb2478
EA
46**
47** Parameters:
e6b0a75b
EA
48** m -- mailer to create connection to.
49** pvp -- pointer to parameter vector to pass to
50** the mailer.
d2eb2478
EA
51**
52** Returns:
f2e44ded 53** none.
d2eb2478
EA
54**
55** Side Effects:
e6b0a75b 56** creates connection and sends initial protocol.
d2eb2478
EA
57*/
58
f2e44ded 59smtpinit(m, mci, e)
e6b0a75b 60 struct mailer *m;
f2e44ded 61 register MCI *mci;
e62e1144 62 ENVELOPE *e;
d2eb2478 63{
e6b0a75b 64 register int r;
a9bac7a9 65 register char *p;
140717b5 66 extern STAB *stab();
d2eb2478 67
474bc899
EA
68 if (tTd(17, 1))
69 {
70 printf("smtpinit ");
71 mci_dump(mci);
72 }
73
e6b0a75b
EA
74 /*
75 ** Open the connection to the mailer.
76 */
d2eb2478 77
46f6ec52 78 SmtpError[0] = '\0';
474bc899 79 CurHostName = mci->mci_host; /* XXX UGLY XXX */
f2e44ded 80 switch (mci->mci_state)
1ea752a1 81 {
f2e44ded
EA
82 case MCIS_ACTIVE:
83 /* need to clear old information */
84 smtprset(m, mci, e);
263c5860 85 /* fall through */
46f6ec52 86
f2e44ded
EA
87 case MCIS_OPEN:
88 return;
89
90 case MCIS_ERROR:
91 case MCIS_SSD:
92 /* shouldn't happen */
93 smtpquit(m, mci, e);
263c5860 94 /* fall through */
f2e44ded
EA
95
96 case MCIS_CLOSED:
b6edea3d 97 syserr("451 smtpinit: state CLOSED");
f2e44ded
EA
98 return;
99
100 case MCIS_OPENING:
101 break;
1ea752a1 102 }
d2eb2478 103
474bc899 104 SmtpPhase = mci->mci_phase = "user open";
f2e44ded
EA
105 mci->mci_state = MCIS_OPENING;
106
e6b0a75b
EA
107 /*
108 ** Get the greeting message.
057a9c5d 109 ** This should appear spontaneously. Give it five minutes to
e4581b86 110 ** happen.
e6b0a75b 111 */
3c6123ce 112
474bc899 113 SmtpPhase = mci->mci_phase = "greeting wait";
e62e1144 114 setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
7f5e2eef 115 r = reply(m, mci, e, TimeOuts.to_initial);
3ff6d543 116 if (r < 0 || REPLYTYPE(r) != 2)
07cb6633 117 goto tempfail1;
42281a7d 118
4a4ebe09
EA
119 /*
120 ** Send the HELO command.
4672197a 121 ** My mother taught me to always introduce myself.
4a4ebe09
EA
122 */
123
e62e1144 124 smtpmessage("HELO %s", m, mci, MyHostName);
474bc899 125 SmtpPhase = mci->mci_phase = "HELO wait";
e62e1144 126 setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
7f5e2eef 127 r = reply(m, mci, e, TimeOuts.to_helo);
3ff6d543 128 if (r < 0)
07cb6633 129 goto tempfail1;
3ff6d543 130 else if (REPLYTYPE(r) == 5)
057a9c5d 131 goto unavailable;
4672197a 132 else if (REPLYTYPE(r) != 2)
07cb6633 133 goto tempfail1;
4a4ebe09 134
a9bac7a9
EA
135 /*
136 ** Check to see if we actually ended up talking to ourself.
137 ** This means we didn't know about an alias or MX, or we managed
138 ** to connect to an echo server.
139 */
140
141 p = strchr(SmtpReplyBuffer, ' ');
142 if (p != NULL)
143 *p == '\0';
144 if (strcasecmp(SmtpReplyBuffer, MyHostName) == 0)
145 {
146 syserr("553 %s config error: mail loops back to myself",
147 MyHostName);
148 mci->mci_exitstat = EX_CONFIG;
149 mci->mci_errno = 0;
150 smtpquit(m, mci, e);
151 return;
152 }
153
8fe4fb9b
EA
154 /*
155 ** If this is expected to be another sendmail, send some internal
156 ** commands.
157 */
158
1dbda134 159 if (bitnset(M_INTERNAL, m->m_flags))
8fe4fb9b
EA
160 {
161 /* tell it to be verbose */
e62e1144 162 smtpmessage("VERB", m, mci);
7f5e2eef 163 r = reply(m, mci, e, TimeOuts.to_miscshort);
8fe4fb9b 164 if (r < 0)
07cb6633 165 goto tempfail2;
8fe4fb9b
EA
166 }
167
e62e1144 168 mci->mci_state = MCIS_OPEN;
f2e44ded 169 return;
e62e1144
EA
170
171 tempfail1:
172 tempfail2:
173 mci->mci_exitstat = EX_TEMPFAIL;
474bc899
EA
174 if (mci->mci_errno == 0)
175 mci->mci_errno = errno;
176 if (mci->mci_state != MCIS_CLOSED)
177 smtpquit(m, mci, e);
f2e44ded 178 return;
e62e1144
EA
179
180 unavailable:
181 mci->mci_exitstat = EX_UNAVAILABLE;
182 mci->mci_errno = errno;
183 smtpquit(m, mci, e);
f2e44ded 184 return;
e62e1144
EA
185}
186
187smtpmailfrom(m, mci, e)
188 struct mailer *m;
f2e44ded 189 MCI *mci;
e62e1144
EA
190 ENVELOPE *e;
191{
192 int r;
193 char buf[MAXNAME];
194
322eceee
EA
195 if (tTd(17, 2))
196 printf("smtpmailfrom: CurHost=%s\n", CurHostName);
197
7d7fdf93
EA
198 /*
199 ** Send the HOPS command.
200 ** This is non-standard and may give an "unknown command".
201 ** This is not an error.
202 ** It can give a "bad hop count" error if the hop
203 ** count is exceeded.
204 */
205
e6b0a75b
EA
206 /*
207 ** Send the MAIL command.
208 ** Designates the sender.
209 */
42281a7d 210
e62e1144
EA
211 mci->mci_state = MCIS_ACTIVE;
212
bc854e30
EA
213 if (bitset(EF_RESPONSE, e->e_flags))
214 (void) strcpy(buf, "");
215 else
216 expand("\201g", buf, &buf[sizeof buf - 1], e);
e62e1144 217 if (e->e_from.q_mailer == LocalMailer ||
1dbda134 218 !bitnset(M_FROMPATH, m->m_flags))
6abb7b86 219 {
e62e1144 220 smtpmessage("MAIL From:<%s>", m, mci, buf);
6abb7b86
EA
221 }
222 else
223 {
e62e1144 224 smtpmessage("MAIL From:<@%s%c%s>", m, mci, MyHostName,
532c9874 225 buf[0] == '@' ? ',' : ':', buf);
6abb7b86 226 }
474bc899 227 SmtpPhase = mci->mci_phase = "MAIL wait";
e62e1144 228 setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
7f5e2eef 229 r = reply(m, mci, e, TimeOuts.to_mail);
3ff6d543 230 if (r < 0 || REPLYTYPE(r) == 4)
e62e1144
EA
231 {
232 mci->mci_exitstat = EX_TEMPFAIL;
233 mci->mci_errno = errno;
234 smtpquit(m, mci, e);
e62e1144
EA
235 return EX_TEMPFAIL;
236 }
4672197a 237 else if (r == 250)
e62e1144
EA
238 {
239 mci->mci_exitstat = EX_OK;
240 return EX_OK;
241 }
4672197a 242 else if (r == 552)
e62e1144
EA
243 {
244 /* signal service unavailable */
245 mci->mci_exitstat = EX_UNAVAILABLE;
246 smtpquit(m, mci, e);
e62e1144
EA
247 return EX_UNAVAILABLE;
248 }
057a9c5d 249
51d9cc47 250#ifdef LOG
68f7099c 251 if (LogLevel > 1)
51d9cc47
EA
252 {
253 syslog(LOG_CRIT, "%s: SMTP MAIL protocol error: %s",
254 e->e_id, SmtpReplyBuffer);
255 }
256#endif
257
057a9c5d 258 /* protocol error -- close up */
e62e1144
EA
259 smtpquit(m, mci, e);
260 mci->mci_exitstat = EX_PROTOCOL;
e62e1144 261 return EX_PROTOCOL;
d2eb2478
EA
262}
263\f/*
4a4ebe09 264** SMTPRCPT -- designate recipient.
3c6123ce
EA
265**
266** Parameters:
e6b0a75b 267** to -- address of recipient.
4db45bf1 268** m -- the mailer we are sending to.
474bc899
EA
269** mci -- the connection info for this transaction.
270** e -- the envelope for this transaction.
3c6123ce
EA
271**
272** Returns:
e6b0a75b 273** exit status corresponding to recipient status.
3c6123ce
EA
274**
275** Side Effects:
e6b0a75b 276** Sends the mail via SMTP.
3c6123ce
EA
277*/
278
e62e1144 279smtprcpt(to, m, mci, e)
e6b0a75b 280 ADDRESS *to;
4db45bf1 281 register MAILER *m;
f2e44ded 282 MCI *mci;
e62e1144 283 ENVELOPE *e;
3c6123ce
EA
284{
285 register int r;
286
e62e1144 287 smtpmessage("RCPT To:<%s>", m, mci, to->q_user);
e6b0a75b 288
474bc899 289 SmtpPhase = mci->mci_phase = "RCPT wait";
e62e1144 290 setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
7f5e2eef 291 r = reply(m, mci, e, TimeOuts.to_rcpt);
3ff6d543 292 if (r < 0 || REPLYTYPE(r) == 4)
e6b0a75b 293 return (EX_TEMPFAIL);
4672197a
EA
294 else if (REPLYTYPE(r) == 2)
295 return (EX_OK);
977ccbaf
EA
296 else if (r == 550 || r == 551 || r == 553)
297 return (EX_NOUSER);
298 else if (r == 552 || r == 554)
299 return (EX_UNAVAILABLE);
51d9cc47
EA
300
301#ifdef LOG
68f7099c 302 if (LogLevel > 1)
51d9cc47
EA
303 {
304 syslog(LOG_CRIT, "%s: SMTP RCPT protocol error: %s",
305 e->e_id, SmtpReplyBuffer);
306 }
307#endif
308
977ccbaf 309 return (EX_PROTOCOL);
3c6123ce
EA
310}
311\f/*
4db45bf1 312** SMTPDATA -- send the data and clean up the transaction.
d2eb2478
EA
313**
314** Parameters:
e6b0a75b 315** m -- mailer being sent to.
dd1fe05b 316** e -- the envelope for this message.
d2eb2478
EA
317**
318** Returns:
4a4ebe09 319** exit status corresponding to DATA command.
d2eb2478
EA
320**
321** Side Effects:
e6b0a75b 322** none.
d2eb2478
EA
323*/
324
06771186 325smtpdata(m, mci, e)
e6b0a75b 326 struct mailer *m;
f2e44ded 327 register MCI *mci;
dd1fe05b 328 register ENVELOPE *e;
d2eb2478
EA
329{
330 register int r;
d2eb2478 331
3c6123ce
EA
332 /*
333 ** Send the data.
4db45bf1
EA
334 ** First send the command and check that it is ok.
335 ** Then send the data.
336 ** Follow it up with a dot to terminate.
337 ** Finally get the results of the transaction.
3c6123ce
EA
338 */
339
4db45bf1 340 /* send the command and check ok to proceed */
e62e1144 341 smtpmessage("DATA", m, mci);
474bc899 342 SmtpPhase = mci->mci_phase = "DATA wait";
e62e1144 343 setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
7f5e2eef 344 r = reply(m, mci, e, TimeOuts.to_datainit);
3ff6d543 345 if (r < 0 || REPLYTYPE(r) == 4)
c6f2ede6
EA
346 {
347 smtpquit(m, mci, e);
3c6123ce 348 return (EX_TEMPFAIL);
c6f2ede6 349 }
4672197a 350 else if (r == 554)
c6f2ede6
EA
351 {
352 smtprset(m, mci, e);
4672197a 353 return (EX_UNAVAILABLE);
c6f2ede6 354 }
4672197a 355 else if (r != 354)
c6f2ede6 356 {
51d9cc47 357#ifdef LOG
68f7099c 358 if (LogLevel > 1)
51d9cc47
EA
359 {
360 syslog(LOG_CRIT, "%s: SMTP DATA-1 protocol error: %s",
361 e->e_id, SmtpReplyBuffer);
362 }
363#endif
c6f2ede6 364 smtprset(m, mci, e);
977ccbaf 365 return (EX_PROTOCOL);
c6f2ede6 366 }
4db45bf1
EA
367
368 /* now output the actual message */
e62e1144 369 (*e->e_puthdr)(mci->mci_out, m, e);
06771186 370 putline("\n", mci->mci_out, m);
e62e1144 371 (*e->e_putbody)(mci->mci_out, m, e);
4db45bf1
EA
372
373 /* terminate the message */
06771186 374 fprintf(mci->mci_out, ".%s", m->m_eol);
dc2cd20f 375 if (Verbose)
b6edea3d 376 nmessage(">>> .");
4db45bf1
EA
377
378 /* check for the results of the transaction */
474bc899 379 SmtpPhase = mci->mci_phase = "result wait";
e62e1144 380 setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
7f5e2eef 381 r = reply(m, mci, e, TimeOuts.to_datafinal);
e62e1144 382 if (r < 0)
c6f2ede6
EA
383 {
384 smtpquit(m, mci, e);
e62e1144 385 return (EX_TEMPFAIL);
c6f2ede6 386 }
e62e1144 387 mci->mci_state = MCIS_OPEN;
614b4258 388 e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
e62e1144 389 if (REPLYTYPE(r) == 4)
3c6123ce 390 return (EX_TEMPFAIL);
4672197a
EA
391 else if (r == 250)
392 return (EX_OK);
393 else if (r == 552 || r == 554)
394 return (EX_UNAVAILABLE);
51d9cc47 395#ifdef LOG
68f7099c 396 if (LogLevel > 1)
51d9cc47
EA
397 {
398 syslog(LOG_CRIT, "%s: SMTP DATA-2 protocol error: %s",
399 e->e_id, SmtpReplyBuffer);
400 }
401#endif
977ccbaf 402 return (EX_PROTOCOL);
d2eb2478
EA
403}
404\f/*
e6b0a75b
EA
405** SMTPQUIT -- close the SMTP connection.
406**
407** Parameters:
e009f4f4 408** m -- a pointer to the mailer.
e6b0a75b
EA
409**
410** Returns:
411** none.
412**
413** Side Effects:
414** sends the final protocol and closes the connection.
415*/
416
e62e1144 417smtpquit(m, mci, e)
06771186 418 register MAILER *m;
f2e44ded 419 register MCI *mci;
e62e1144 420 ENVELOPE *e;
e6b0a75b 421{
80482eb5 422 int i;
e6b0a75b 423
f2e44ded 424 /* send the quit message if we haven't gotten I/O error */
e62e1144 425 if (mci->mci_state != MCIS_ERROR)
044ab67a 426 {
e62e1144 427 smtpmessage("QUIT", m, mci);
7f5e2eef 428 (void) reply(m, mci, e, TimeOuts.to_quit);
06771186 429 if (mci->mci_state == MCIS_CLOSED)
11957f11 430 return;
80482eb5
EA
431 }
432
2ae0e0ed 433 /* now actually close the connection and pick up the zombie */
ffc1c1a0 434 i = endmailer(mci, e, m->m_argv);
80482eb5 435 if (i != EX_OK)
b6edea3d 436 syserr("451 smtpquit %s: stat %d", m->m_argv[0], i);
e6b0a75b
EA
437}
438\f/*
f2e44ded
EA
439** SMTPRSET -- send a RSET (reset) command
440*/
441
442smtprset(m, mci, e)
443 register MAILER *m;
444 register MCI *mci;
445 ENVELOPE *e;
446{
447 int r;
448
449 smtpmessage("RSET", m, mci);
7f5e2eef 450 r = reply(m, mci, e, TimeOuts.to_rset);
263c5860
EA
451 if (r < 0)
452 mci->mci_state = MCIS_ERROR;
f2e44ded 453 else if (REPLYTYPE(r) == 2)
263c5860
EA
454 {
455 mci->mci_state = MCIS_OPEN;
456 return;
457 }
458 smtpquit(m, mci, e);
f2e44ded
EA
459}
460\f/*
c428b1b2 461** SMTPPROBE -- check the connection state
f2e44ded
EA
462*/
463
c428b1b2 464smtpprobe(mci)
f2e44ded
EA
465 register MCI *mci;
466{
467 int r;
468 MAILER *m = mci->mci_mailer;
469 extern ENVELOPE BlankEnvelope;
470 ENVELOPE *e = &BlankEnvelope;
471
c428b1b2 472 smtpmessage("RSET", m, mci);
7f5e2eef 473 r = reply(m, mci, e, TimeOuts.to_miscshort);
5d41b806 474 if (r < 0 || REPLYTYPE(r) != 2)
f2e44ded
EA
475 smtpquit(m, mci, e);
476 return r;
477}
478\f/*
d2eb2478
EA
479** REPLY -- read arpanet reply
480**
481** Parameters:
4db45bf1 482** m -- the mailer we are reading the reply from.
474bc899
EA
483** mci -- the mailer connection info structure.
484** e -- the current envelope.
485** timeout -- the timeout for reads.
d2eb2478
EA
486**
487** Returns:
488** reply code it reads.
489**
490** Side Effects:
491** flushes the mail file.
492*/
493
474bc899 494reply(m, mci, e, timeout)
1dbda134 495 MAILER *m;
f2e44ded 496 MCI *mci;
e62e1144 497 ENVELOPE *e;
d2eb2478 498{
a9bac7a9
EA
499 char *bufp = SmtpReplyBuffer;
500 char junkbuf[MAXLINE];
501
474bc899
EA
502 if (mci->mci_out != NULL)
503 (void) fflush(mci->mci_out);
42281a7d 504
9678c96d 505 if (tTd(18, 1))
42281a7d 506 printf("reply\n");
d2eb2478 507
37eaaadb
EA
508 /*
509 ** Read the input line, being careful not to hang.
510 */
511
a9bac7a9 512 for (;; bufp = junkbuf)
d2eb2478 513 {
d2eb2478 514 register int r;
37eaaadb 515 register char *p;
e62e1144 516 extern time_t curtime();
37eaaadb 517
37eaaadb 518 /* actually do the read */
e62e1144
EA
519 if (e->e_xfp != NULL)
520 (void) fflush(e->e_xfp); /* for debugging */
d0729491
EA
521
522 /* if we are in the process of closing just give the code */
06771186 523 if (mci->mci_state == MCIS_CLOSED)
d0729491
EA
524 return (SMTPCLOSING);
525
bc854e30
EA
526 if (mci->mci_out != NULL)
527 fflush(mci->mci_out);
528
d0729491 529 /* get the line from the other side */
a9bac7a9 530 p = sfgets(bufp, MAXLINE, mci->mci_in, timeout);
e62e1144
EA
531 mci->mci_lastuse = curtime();
532
d0729491 533 if (p == NULL)
ed7382d3 534 {
044ab67a 535 extern char MsgBuf[]; /* err.c */
044ab67a 536
46f6ec52
EA
537 /* if the remote end closed early, fake an error */
538 if (errno == 0)
539# ifdef ECONNRESET
540 errno = ECONNRESET;
f3d8f6d6 541# else /* ECONNRESET */
46f6ec52 542 errno = EPIPE;
f3d8f6d6 543# endif /* ECONNRESET */
46f6ec52 544
474bc899 545 mci->mci_errno = errno;
6e99f903 546 mci->mci_exitstat = EX_TEMPFAIL;
b6edea3d 547 message("451 %s: reply: read error from %s",
6e99f903 548 e->e_id == NULL ? "NOQUEUE" : e->e_id,
b8e5fc1b 549 mci->mci_host);
9759fb92
EA
550 /* if debugging, pause so we can see state */
551 if (tTd(18, 100))
552 pause();
044ab67a 553# ifdef LOG
68f7099c 554 if (LogLevel > 1)
b8e5fc1b 555 syslog(LOG_INFO, "%s", &MsgBuf[4]);
f3d8f6d6 556# endif /* LOG */
f2e44ded 557 mci->mci_state = MCIS_ERROR;
e62e1144 558 smtpquit(m, mci, e);
d0729491 559 return (-1);
ed7382d3 560 }
a9bac7a9 561 fixcrlf(bufp, TRUE);
37eaaadb 562
f3d8f6d6 563 if (e->e_xfp != NULL && strchr("45", SmtpReplyBuffer[0]) != NULL)
d7dbe85b
EA
564 {
565 /* serious error -- log the previous command */
a9bac7a9
EA
566 if (bufp[0] != '\0')
567 fprintf(e->e_xfp, ">>> %s\n", bufp);
568 bufp[0] = '\0';
d7dbe85b
EA
569
570 /* now log the message as from the other side */
a9bac7a9 571 fprintf(e->e_xfp, "<<< %s\n", bufp);
d7dbe85b
EA
572 }
573
574 /* display the input for verbose mode */
dc2cd20f 575 if (Verbose)
a9bac7a9 576 nmessage("%s", bufp);
37eaaadb
EA
577
578 /* if continuation is required, we can go on */
a9bac7a9
EA
579 if (bufp[3] == '-' ||
580 !(isascii(bufp[0]) && isdigit(bufp[0])))
d2eb2478 581 continue;
37eaaadb
EA
582
583 /* decode the reply code */
80482eb5 584 r = atoi(SmtpReplyBuffer);
37eaaadb
EA
585
586 /* extra semantics: 0xx codes are "informational" */
d2eb2478
EA
587 if (r < 100)
588 continue;
37eaaadb 589
5d41b806
EA
590 /* save temporary failure messages for posterity */
591 if (SmtpReplyBuffer[0] == '4' && SmtpError[0] == '\0')
592 (void) strcpy(SmtpError, SmtpReplyBuffer);
593
80482eb5 594 /* reply code 421 is "Service Shutting Down" */
06771186 595 if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD)
80482eb5 596 {
d0729491 597 /* send the quit protocol */
06771186 598 mci->mci_state = MCIS_SSD;
e62e1144 599 smtpquit(m, mci, e);
80482eb5
EA
600 }
601
d2eb2478
EA
602 return (r);
603 }
604}
42281a7d 605\f/*
e6b0a75b 606** SMTPMESSAGE -- send message to server
42281a7d
EA
607**
608** Parameters:
609** f -- format
4db45bf1 610** m -- the mailer to control formatting.
42281a7d
EA
611** a, b, c -- parameters
612**
613** Returns:
614** none.
615**
616** Side Effects:
06771186 617** writes message to mci->mci_out.
42281a7d
EA
618*/
619
e6b0a75b 620/*VARARGS1*/
6e99f903
EA
621#ifdef __STDC__
622smtpmessage(char *f, MAILER *m, MCI *mci, ...)
623#else
624smtpmessage(f, m, mci, va_alist)
42281a7d 625 char *f;
4db45bf1 626 MAILER *m;
f2e44ded 627 MCI *mci;
6e99f903
EA
628 va_dcl
629#endif
42281a7d 630{
5229f34d
EA
631 VA_LOCAL_DECL
632
07b49560 633 VA_START(mci);
5229f34d
EA
634 (void) vsprintf(SmtpMsgBuffer, f, ap);
635 VA_END;
bc854e30 636
dc2cd20f 637 if (tTd(18, 1) || Verbose)
b6edea3d 638 nmessage(">>> %s", SmtpMsgBuffer);
06771186 639 if (mci->mci_out != NULL)
bc854e30 640 {
06771186 641 fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer,
f2e44ded 642 m == NULL ? "\r\n" : m->m_eol);
bc854e30
EA
643 }
644 else
0852beb8 645 {
bc854e30 646 syserr("smtpmessage: NULL mci_out");
0852beb8 647 }
42281a7d 648}
884a20cb 649
f3d8f6d6 650# endif /* SMTP */