2
* This file is part of libESMTP, a library for submission of RFC 2822
3
* formatted electronic mail messages using the SMTP protocol described
6
* Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net>
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2.1 of the License, or (at your option) any later version.
13
* This library is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
/* The SMTP protocol engine and handler functions for the core SMTP
24
commands and their extended parameters. Extended commands are mostly
25
in files of their own. */
38
#include <missing.h> /* declarations for missing library functions */
40
#include <sys/socket.h>
41
#if HAVE_LWRES_NETDB_H
42
# include <lwres/netdb.h>
43
#elif !HAVE_GETADDRINFO
44
# include "getaddrinfo.h"
50
#include <sys/utsname.h>
53
#include "libesmtp-private.h"
54
#include "message-source.h"
60
struct protocol_states
62
void (*cmd) (siobuf_t conn, smtp_session_t session);
63
void (*rsp) (siobuf_t conn, smtp_session_t session);
66
/* The following array of state handlers is indexed by the state (!) */
67
struct protocol_states protocol_states[] =
69
#define S(x) { cmd_##x, rsp_##x, },
70
#include "protocol-states.h"
74
set_first_recipient (smtp_session_t session)
76
smtp_recipient_t recipient;
78
if (session->current_message == NULL)
81
for (recipient = session->current_message->recipients;
83
recipient = recipient->next)
84
if (!recipient->complete)
86
session->cmd_recipient = session->rsp_recipient = recipient;
87
return recipient != NULL;
90
/* Return a pointer to the next unsent recipient. This can't operate
91
on the session structure directly as the other first/next functions
92
do since there are two variables for the current recipient due to
93
the implementation of PIPELINING. */
94
static smtp_recipient_t
95
next_recipient (smtp_recipient_t recipient)
97
while ((recipient = recipient->next) != NULL)
98
if (!recipient->complete)
103
/* Return a pointer to the next unsent message.
106
next_message (smtp_session_t session)
108
while ((session->current_message = session->current_message->next) != NULL)
109
if (set_first_recipient (session))
114
/* Set the current message to the first unsent message in the
117
set_first_message (smtp_session_t session)
119
for (session->current_message = session->messages;
120
session->current_message != NULL;
121
session->current_message = session->current_message->next)
122
if (set_first_recipient (session))
127
/*****************************************************************************
128
* The main protocol engine.
129
*****************************************************************************/
132
do_session (smtp_session_t session)
134
struct addrinfo hints, *res, *addrs;
138
int nresp, status, want_flush, fast;
142
if (session->localhost == NULL)
146
if (uname (&name) < 0)
151
session->localhost = strdup (name.nodename);
152
if (session->localhost == NULL)
158
#elif HAVE_GETHOSTNAME
159
if (session->localhost == NULL)
163
if (gethostname (host, sizeof host) < 0)
168
session->localhost = strdup (host);
169
if (session->localhost == NULL)
177
/* Initialise the current message and recipient variables in the
178
session. This returns zero if there is no work to do. */
180
if (!set_first_message (session))
182
if (!set_first_message (session) && session->etrn_nodes == NULL)
185
set_error (SMTP_ERR_NOTHING_TO_DO);
189
/* Create a message source only if it is needed.
191
if (session->msg_source == NULL && session->current_message != NULL)
193
session->msg_source = msg_source_create ();
194
if (session->msg_source == NULL)
201
/* Connect to the SMTP server. The following code will only work for
202
socket connections at present. This will eventually change to
203
permit connections on any type of file descriptor, e.g. for LMTP
204
servers or forking an SMTP server which can run the protocol on
205
its standard input. */
208
nodename = (session->host == NULL || *session->host == '\0') ? NULL
210
/* Use the RFC 2553/Posix resolver interface. This allows for much
211
cleaner code, protocol independence and thread safety. */
212
memset (&hints, 0, sizeof hints);
213
hints.ai_family = PF_UNSPEC;
214
hints.ai_socktype = SOCK_STREAM;
215
err = getaddrinfo (nodename, session->port, &hints, &res);
222
/* Try to establish an SMTP session with each host in turn until one
224
for (addrs = res; addrs != NULL; addrs = addrs->ai_next)
226
sd = socket (addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
232
if (connect (sd, addrs->ai_addr, addrs->ai_addrlen) < 0)
234
/* Failed to connect. Close the socket and try again. */
240
/* Add buffering to the socket */
241
conn = sio_attach (sd, sd, SIO_BUFSIZE);
250
/* If monitoring the protocol, pass the callback on to the sio_
252
if (session->monitor_cb != NULL)
253
sio_set_monitorcb (conn, session->monitor_cb, session->monitor_cb_arg);
255
if (session->event_cb != NULL)
256
(*session->event_cb) (session, SMTP_EV_CONNECT, session->event_cb_arg);
258
/* Outer loop of the protocol. This is trickier than superficial
259
examination of RFC 821 would suggest, however the complexity is
260
required to handle batched commands and responses. RFC 821 makes
261
no comment on the underlying transport so it cannot be assumed that
262
each command and its response is transported in a single packet on
263
the network or that the network preserves packet boundaries (or,
264
for that matter, that the underlying transport is even a network,
265
e.g. it might be a pipe or a AF_UNIX socket). Multiple commands
266
may be sent in a single packet and similarly multiple responses
267
may be returned in a single packet. RFC 2920 which describes the
268
PIPELINING SMTP extension clarifies this for the case where the
269
underlying transport is TCP/IP.
271
In this implementation the outer loop will batch together as many
272
commands as possible until the remote server sends a response (this
273
will normally happen after the local transmit buffer is flushed)
274
or a command has been sent which requires a response before the
277
In order not to break certain SMTP server implementations, flushing
278
is done after every command unless the PIPELINING keyword is received
279
in response to the EHLO command. Even when PIPELINING is in force
280
certain commands *always* flush the transmit buffer.
282
One good reason for wanting PIPELINING is that when submitting mail
283
to an ISP's sluggish server, there will be a big performance boost
284
since many round trips are eliminated.
286
As the protocol engine advances through its states, it will walk
287
through the messages and recipients within the session.
289
The protocol functions set a few timeouts as they progress. The
290
values set are those reccommended in RFC 2821.
292
[is it just me, or does everybody find that it's easier to implement
293
protocols on the server side?]
296
/* Reset variables to their initial state before entering the protocol
298
session->extensions = 0;
299
session->try_fallback_server = 0;
300
reset_status (&session->mta_status);
301
destroy_auth_mechanisms (session);
302
session->authenticated = 0;
304
session->using_tls = 0;
308
session->cmd_state = session->rsp_state = 0;
309
while (session->rsp_state >= 0)
311
if (session->cmd_state == -1)
312
session->cmd_state = session->rsp_state;
313
(*protocol_states[session->cmd_state].cmd) (conn, session);
315
if (!(session->extensions & EXT_PIPELINING))
316
session->cmd_state = -1;
319
if (session->rsp_state < 0)
322
/* The following loop polls the server and reads or writes
325
When the command state is set to -1, this signals that no
326
more commands can be issued until the response to the most
327
recent command has been processed, therefore the write
328
buffer must be explicitly flushed. If the command state is
329
not -1, more commands may be issued however, pending
330
responses from the server should be processed. When this
331
is the case, sio_poll should return immediately if there is
332
nothing to read. `fast' requests this non-blocking poll.
334
`want_flush' indicates that the write buffer should be
335
sent to the server. This flag remains set until the buffer
338
After explicitly flushing the buffer, sio_poll blocks
339
waiting to read data from the server since the server may
340
take some time to complete the pending commands.
342
want_flush = (session->cmd_state == -1);
343
fast = (session->cmd_state != -1);
344
while ((status = sio_poll (conn, nresp > 0, want_flush, fast)) > 0)
346
if (status & SIO_READ)
350
/* TODO: change so that the response line is parsed
351
here. This means that the server 421
352
response which can be issued at any time may
353
be checked for here. */
355
/* When reading from the server in the response state
356
handlers the read call blocks. Complete responses
357
must be read from the server before processing and
358
an individual response may be larger than the read
360
(*protocol_states[session->rsp_state].rsp) (conn, session);
362
/* XXX - Here I assume that once the write fd becomes
363
available for writing, it stays that way until
364
it is written to. I.e. a blocking read() or a
365
subsequent poll() will not revoke the writable
366
status. Could somebody confirm that this is the
368
if (status & SIO_WRITE)
376
set_error (SMTP_ERR_DROPPED_CONNECTION);
384
if (session->event_cb != NULL)
385
(*session->event_cb) (session, SMTP_EV_DISCONNECT,
386
session->event_cb_arg);
388
/* This flag will be set if the server was reached OK but was the
389
wrong kind of server or the client is told to go away. So if
390
not set the protocol must have concluded sucessfully. */
391
if (!session->try_fallback_server)
398
/* If the loop terminated, couldn't work with any servers. */
403
/*****************************************************************************
405
*****************************************************************************/
408
parse_status_triplet (char *p, char **ep, struct smtp_status *triplet)
410
triplet->enh_class = strtol (p, &p, 10);
413
triplet->enh_subject = strtol (p, &p, 10);
416
triplet->enh_detail = strtol (p, &p, 10);
422
compare_status_triplet (struct smtp_status *a, struct smtp_status *b)
424
return a->enh_class == b->enh_class
425
&& a->enh_subject == b->enh_subject
426
&& a->enh_detail == b->enh_detail;
429
/* Free memory allocated in read_smtp_response()
430
and clear the status structure */
432
reset_status (struct smtp_status *status)
434
if (status->text != NULL)
435
free ((void *) status->text);
436
memset (status, 0, sizeof (struct smtp_status));
439
/* All SMTP responses have standard syntax. This function could be
440
called by the protocol engine above and the results from the parsed
441
response passed to the response handler functions. However certain
442
commands involve extra intermediate exchanges with the server that
443
may not correspond to the standard syntax. The response handlers
444
must therefore call this function themselves. */
446
read_smtp_response (siobuf_t conn, smtp_session_t session,
447
struct smtp_status *status,
448
int (*cb) (smtp_session_t, char *))
453
int code, more, want_enhanced, textlen;
454
struct smtp_status triplet;
456
/* First line of an SMTP response is the normal one. Put it in a buffer.
457
Save the status code and the enhanced status triplet if ENHSTATUSCODES
458
is set. The remainder of the line is the message from the server.
459
If there are any continuation lines, get the status code and enhanced
460
status triplet and check that they are the same as the first response
461
line. If not there is a protocol error. Process the extra lines
462
by calling a callback. If not supplied, concatenate the lines
463
(excluding the status info) with the first line. */
465
reset_status (status);
466
if ((p = sio_gets (conn, buf, sizeof buf)) == NULL)
468
set_error (SMTP_ERR_DROPPED_CONNECTION);
471
status->code = strtol (p, &p, 10);
472
if (!(*p == ' ' || *p == '-'))
474
set_error (SMTP_ERR_INVALID_RESPONSE_SYNTAX);
479
/* RFC 2034 states that only 2xx, 4xx and 5xx responses are accompanied
480
by enhanced status codes. */
481
code = status->code / 100;
482
want_enhanced = (session->extensions & EXT_ENHANCEDSTATUSCODES);
483
if (code != 2 && code != 4 && code != 5)
486
if (want_enhanced && !parse_status_triplet (p, &p, status))
488
set_error (SMTP_ERR_INVALID_RESPONSE_SYNTAX);
494
/* p points to the remainder of the line. This is the text of the
496
cat_init (&text, 128);
497
concatenate (&text, p, -1);
501
if ((p = sio_gets (conn, buf, sizeof buf)) == NULL)
504
set_error (SMTP_ERR_DROPPED_CONNECTION);
507
code = strtol (p, &p, 10);
508
if (code != status->code)
511
set_error (SMTP_ERR_STATUS_MISMATCH);
514
if (!(*p == ' ' || *p == '-'))
517
set_error (SMTP_ERR_INVALID_RESPONSE_SYNTAX);
523
if (!parse_status_triplet (p, &p, &triplet))
526
set_error (SMTP_ERR_INVALID_RESPONSE_SYNTAX);
529
if (!compare_status_triplet (status, &triplet))
532
set_error (SMTP_ERR_STATUS_MISMATCH);
537
/* Skip whitespace but don't wander over the CRLF */
538
while (isspace (*p) && isprint (*p))
541
/* Check that the line is correctly terminated. */
542
nul = strchr (p, '\0');
543
if (nul == NULL || nul == p || nul[-1] != '\n')
546
set_error (SMTP_ERR_UNTERMINATED_RESPONSE);
550
/* `p' points to the remainder of the line. Either process with the
551
callback or concatenate with the first line. */
555
concatenate (&text, p, nul - p);
557
/* Check if the total text returned in a multiline response
558
exceeds 4k. Abort if this happens, this might be a DoS attack
559
or a broken server. */
561
cat_buffer (&text, &textlen);
565
set_error (SMTP_ERR_UNTERMINATED_RESPONSE);
570
/* Terminate and save the response text */
571
concatenate (&text, "", 1);
572
status->text = cat_shrink (&text, NULL);
574
return status->code / 100;
577
/*****************************************************************************
578
* Command and response handlers. Return value is the next send/response
579
* state. If a cmd_xxxx() function returns -1, the response determines
580
* the next state, implying that a flush is needed.
581
*****************************************************************************/
583
/*****************************************************************************
585
*****************************************************************************/
587
/* If the response to the server greeting is not a 2xx status code,
588
issue the QUIT command and terminate the session. */
590
cmd_greeting (siobuf_t conn, smtp_session_t session)
592
/* Set a five minute timeout. */
593
sio_set_timeout (conn, 5 * 60 * 1000);
594
session->cmd_state = -1;
598
rsp_greeting (siobuf_t conn, smtp_session_t session)
602
code = read_smtp_response (conn, session, &session->mta_status, NULL);
603
if (code == 2 && session->mta_status.code == 220)
604
session->rsp_state = S_ehlo;
605
else if (code == 4 || code == 5)
607
session->rsp_state = S_quit; /* Graceful exit using QUIT */
608
session->try_fallback_server = 1;
612
session->rsp_state = -1; /* Drop the connection and run */
613
session->try_fallback_server = 1;
616
/* TODO: certain broken servers may break when the EHLO command is
617
issued. For example, one known behaviour is to close the
618
connection after returning the 501 response. This is wrong
621
An API option is needed to avoid using EHLO!
625
/*****************************************************************************
627
*****************************************************************************/
629
/* EHLO is the preferred client greeting to the server. The parameter is
630
the FQDN of the client host. The server response is the greeting line
631
followed by extra lines listing the server capabilities. The additional
632
lines are parsed and set the session capability flags. If the response
633
is "501 command not implemented", the HELO command should be used instead.
634
Since the next command issued depends on the server response the output
637
Next state is one of Auth, Helo, Mail.
640
cmd_ehlo (siobuf_t conn, smtp_session_t session)
642
sio_printf (conn, "EHLO %s\r\n", session->localhost);
643
session->cmd_state = -1;
646
#define no_required_extension(s,e) \
647
(((s)->required_extensions & (e)) && !((s)->extensions & (e)))
650
report_extensions (smtp_session_t session)
653
unsigned long exts = 0;
655
/* Report extensions that are required but not available.
657
if (no_required_extension (session, EXT_DSN))
660
if (session->event_cb != NULL)
661
(*session->event_cb) (session, SMTP_EV_EXTNA_DSN,
662
session->event_cb_arg, &quit_now);
666
if (no_required_extension (session, EXT_8BITMIME))
669
if (session->event_cb != NULL)
670
(*session->event_cb) (session, SMTP_EV_EXTNA_8BITMIME,
671
session->event_cb_arg);
673
exts |= EXT_8BITMIME;
676
if (no_required_extension (session, EXT_ETRN))
679
if (session->event_cb != NULL)
680
(*session->event_cb) (session, SMTP_EV_EXTNA_ETRN,
681
session->event_cb_arg, &quit_now);
690
cb_ehlo (smtp_session_t session, char *buf)
695
if (!read_atom (skipblank (buf), &p, token, sizeof token))
697
/* expecting an atom - do nothing */
701
/* Since the session structure mostly just carries a bit for each of
702
the extensions, there is no point #ifdefing out the extension
703
keywords for omitted features. Also extensions may be added
704
in the future so it is not an error to have an unrecognised
705
extension keyword. */
707
if (strcasecmp (token, "ENHANCEDSTATUSCODES") == 0) /* RFC 1893, RFC 2034 */
708
session->extensions |= EXT_ENHANCEDSTATUSCODES;
709
else if (strcasecmp (token, "PIPELINING") == 0) /* RFC 2920 */
710
session->extensions |= EXT_PIPELINING;
711
else if (strcasecmp (token, "DSN") == 0) /* RFC 1891 */
712
session->extensions |= EXT_DSN;
713
else if (strcasecmp (token, "AUTH") == 0) /* RFC 2554 */
715
session->extensions |= EXT_AUTH;
716
set_auth_mechanisms (session, p);
719
else if (strncasecmp (token, "AUTH=", 5) == 0) /* non-standard syntax */
721
session->extensions |= EXT_AUTH;
722
set_auth_mechanisms (session, token + 5);
723
set_auth_mechanisms (session, p);
726
else if (strcasecmp (token, "STARTTLS") == 0) /* RFC 2487 */
727
session->extensions |= EXT_STARTTLS;
728
else if (strcasecmp (token, "SIZE") == 0) /* RFC 1870 */
730
session->extensions |= EXT_SIZE;
731
session->size_limit = strtol (p, NULL, 10);
733
else if (strcasecmp (token, "CHUNKING") == 0) /* RFC 3030 */
734
session->extensions |= EXT_CHUNKING;
735
else if (strcasecmp (token, "BINARYMIME") == 0) /* RFC 3030 */
736
session->extensions |= EXT_BINARYMIME;
737
else if (strcasecmp (token, "8BITMIME") == 0) /* RFC 1652 */
738
session->extensions |= EXT_8BITMIME;
739
else if (strcasecmp (token, "DELIVERBY") == 0) /* RFC 2852 */
741
session->extensions |= EXT_DELIVERBY;
742
session->min_by_time = strtol (p, NULL, 10);
744
else if (strcasecmp (token, "ETRN") == 0) /* RFC 1985 */
745
session->extensions |= EXT_ETRN;
747
else if (strcasecmp (token, "XUSR") == 0) /* sendmail (I feel ill) */
748
session->extensions |= EXT_XUSR;
755
rsp_ehlo (siobuf_t conn, smtp_session_t session)
759
session->extensions = 0;
760
destroy_auth_mechanisms (session);
761
code = read_smtp_response (conn, session, &session->mta_status, cb_ehlo);
764
set_error (SMTP_ERR_INVALID_RESPONSE_SYNTAX);
765
session->rsp_state = S_quit;
770
session->extensions = 0;
774
/* 4xx failure code. Something is temporarily wrong. Fail the
775
entire session and let the application retry later. */
776
session->rsp_state = S_quit;
777
session->try_fallback_server = 1;
782
/* 5xx failure code. Something is permanently wrong. There are
783
a number of codes indicating that HELO is worth a try since
784
the server did not understand EHLO. Otherwise fail the entire
785
session. The application must correct something and retry later. */
786
if (session->mta_status.code == 500 || session->mta_status.code == 501
787
|| session->mta_status.code == 502 || session->mta_status.code == 504)
788
session->rsp_state = S_helo;
790
session->rsp_state = S_quit;
795
/* Response must be 2xx, 4xx or 5xx */
796
set_error (SMTP_ERR_INVALID_RESPONSE_STATUS);
797
session->rsp_state = S_quit;
802
/* Totally ignore the TLS stuff if it's already in use */
803
if (!session->using_tls && session->starttls_enabled != Starttls_DISABLED)
805
if (select_starttls (session))
807
session->rsp_state = S_starttls;
810
if (session->starttls_enabled == Starttls_REQUIRED)
812
if (session->event_cb != NULL)
813
(*session->event_cb) (session, SMTP_EV_EXTNA_STARTTLS,
814
session->event_cb_arg, NULL);
815
session->rsp_state = S_quit;
816
set_error (SMTP_ERR_EXTENSION_NOT_AVAILABLE);
821
/* If AUTH is enabled but no mechanisms can be selected, move on to the
822
MAIL command since the MTA is required to accept mail for its own
824
if ((session->extensions & EXT_AUTH) && select_auth_mechanism (session))
826
session->rsp_state = S_auth;
830
/* Report extensions *after* starting TLS or doing AUTH since either
831
of these can restart the session with different SMTP extensions
832
being offered by the server. */
833
if (!report_extensions (session))
835
set_error (SMTP_ERR_EXTENSION_NOT_AVAILABLE);
836
session->rsp_state = S_quit;
841
session->rsp_state = check_etrn (session)
842
? S_etrn : initial_transaction_state (session);
844
session->rsp_state = initial_transaction_state (session);
848
/* Select the correct initial state after reading the EHLO response or
849
after DATA or RSET in the previous transaction. */
851
initial_transaction_state (smtp_session_t session)
854
if (session->extensions & EXT_XUSR)
860
/*****************************************************************************
862
*****************************************************************************/
864
/* HELO is absolutely *not* the preferred client greeting to the server.
865
The parameter is the FQDN of the client host. The server response is
866
the greeting line. No capabilities are reported so all extensions
872
cmd_helo (siobuf_t conn, smtp_session_t session)
874
sio_printf (conn, "HELO %s\r\n", session->localhost);
875
session->cmd_state = -1;
879
rsp_helo (siobuf_t conn, smtp_session_t session)
883
session->extensions = 0;
884
destroy_auth_mechanisms (session);
885
code = read_smtp_response (conn, session, &session->mta_status, NULL);
888
set_error (SMTP_ERR_INVALID_RESPONSE_SYNTAX);
889
session->try_fallback_server = 1;
890
session->rsp_state = S_quit;
895
if (code != 4 || code != 5)
896
set_error (SMTP_ERR_INVALID_RESPONSE_STATUS);
897
session->try_fallback_server = 1;
898
session->rsp_state = S_quit;
902
/* There are no extensions. Make sure none were required.
904
if (!report_extensions (session))
906
set_error (SMTP_ERR_EXTENSION_NOT_AVAILABLE);
907
session->rsp_state = S_quit;
911
/* Unlike EHLO, the only next state can be Mail, since there are
912
no extensions to check for message acceptability or options to set
913
before proceeding. */
914
session->rsp_state = initial_transaction_state (session);
917
/*****************************************************************************
919
*****************************************************************************/
921
/* MAIL FROM: is the first step in sending a message. Select the first
922
or a subsequent message from the session structure. The message sender
923
is taken from the message structure.
925
Next state is always Rcpt, therefore this command need not be flushed.
928
cmd_mail (siobuf_t conn, smtp_session_t session)
931
smtp_message_t message;
934
/* Set a five minute timeout. This stays in force until the DATA
936
sio_set_timeout (conn, 5 * 60 * 1000);
938
message = session->current_message;
939
mailbox = message->reverse_path_mailbox;
940
sio_printf (conn, "MAIL FROM:<%s>", (mailbox != NULL) ? mailbox : "");
942
/* SIZE: SIZE=message-size-estimate */
943
if ((session->extensions & EXT_SIZE) && message->size_estimate > 0)
944
sio_printf (conn, " SIZE=%lu", message->size_estimate);
946
/* DSN: RET=FULL/HDRS ENVID=xtext */
947
if (session->extensions & EXT_DSN)
949
static const char *ret[] = { NULL, "FULL", "HDRS" };
951
if (message->dsn_ret != Ret_NOTSET)
952
sio_printf (conn, " RET=%s", ret[message->dsn_ret]);
954
if (message->dsn_envid != NULL)
955
sio_printf (conn, " ENVID=%s",
956
encode_xtext (xtext, sizeof xtext, message->dsn_envid));
959
/* 8BITMIME: RET=FULL/HDRS ENVID=xtext */
960
if ((session->extensions & EXT_8BITMIME)
961
&& message->e8bitmime != E8bitmime_NOTSET)
963
sio_write (conn, " BODY=", -1);
964
if (message->e8bitmime == E8bitmime_8BITMIME)
965
sio_write (conn, "8BITMIME", -1);
966
else if (message->e8bitmime == E8bitmime_7BIT)
967
sio_write (conn, "7BIT", -1);
970
if ((session->extensions & EXT_DELIVERBY) && message->by_mode != By_NOTSET)
972
static char mode[] = { 'N', 'R', };
975
by_time = message->by_time;
976
/* If the by_time is greater than the server's min_by_time, ask the
977
application what to do. If adjust is set > 0, the message's
978
deliver by time is adjusted to be acceptable to the server.
979
If not, the MAIL command will be failed by the server. */
980
if (session->min_by_time > 0 && by_time < session->min_by_time)
984
if (session->event_cb != NULL)
985
(*session->event_cb) (session, SMTP_EV_DELIVERBY_EXPIRED,
986
session->event_cb_arg,
987
session->min_by_time - by_time, &adjust);
989
by_time = session->min_by_time + adjust;
991
sio_printf (conn, " BY=%ld%c%s", by_time,
992
mode[message->by_mode], (message->by_trace) ? "T" : "");
995
sio_write (conn, "\r\n", 2);
996
/* TODO: until code to prevent issuing of further RCPT commands and to
997
discard RCPT responses cascading from an error response to
998
MAIL is in place, flush the mail command even when pipelining. */
1000
session->cmd_state = S_rcpt;
1002
session->cmd_state = -1;
1007
rsp_mail (siobuf_t conn, smtp_session_t session)
1010
smtp_message_t message;
1012
message = session->current_message;
1013
code = read_smtp_response (conn, session,
1014
&message->reverse_path_status, NULL);
1016
/* Notify the MAIL FROM: status */
1017
if (session->event_cb != NULL)
1018
(*session->event_cb) (session, SMTP_EV_MAILSTATUS, session->event_cb_arg,
1019
message->reverse_path_mailbox, message);
1022
if (next_message (session))
1023
session->rsp_state = initial_transaction_state (session);
1025
session->rsp_state = S_quit;
1029
message->valid_recipients = 0;
1030
#ifdef USE_REQUIRE_ALL_RECIPIENTS
1031
message->failed_recipients = 0;
1033
session->rsp_state = S_rcpt;
1037
/*****************************************************************************
1039
*****************************************************************************/
1041
/* Specify one message recipient. This is taken from the recipient
1042
parameters. Many parameters are possible depending on the extensions
1043
enabled. For errors such as unknown recipient, or cannot relay,
1044
just mark the offending recipient as failing and continue normally.
1046
Next state is Rcpt, Data or Bdat. This depends on the number of
1047
recipients for the message and the extensions enabled. This selection
1048
can be made without waiting for the server response therefore this
1049
command need not be flushed.
1052
cmd_rcpt (siobuf_t conn, smtp_session_t session)
1054
static struct { enum notify_flags mask; const char *flag; } masks[] =
1056
{ Notify_SUCCESS, "SUCCESS", },
1057
{ Notify_FAILURE, "FAILURE", },
1058
{ Notify_DELAY, "DELAY", },
1060
smtp_recipient_t recipient;
1061
enum notify_flags notify;
1065
recipient = session->cmd_recipient;
1066
sio_printf (conn, "RCPT TO:<%s>", recipient->mailbox);
1068
if (session->extensions & EXT_DSN)
1070
/* DSN: NOTIFY=NEVER/SUCCESS,FAILURE,DELAY */
1071
notify = recipient->dsn_notify;
1072
if (notify != Notify_NOTSET)
1074
sio_write (conn, " NOTIFY=", -1);
1075
if (notify == Notify_NEVER)
1076
sio_write (conn, "NEVER", -1);
1078
for (i = 0; i < (int) (sizeof masks / sizeof masks[0]); i++)
1079
if (notify & masks[i].mask)
1081
notify &= ~masks[i].mask;
1082
sio_write (conn, masks[i].flag, -1);
1084
sio_write (conn, ",", 1);
1088
/* DSN: ORCPT=type;address */
1089
if (recipient->dsn_orcpt != NULL)
1090
sio_printf (conn, " ORCPT=%s;%s", recipient->dsn_addrtype,
1091
encode_xtext (xtext, sizeof xtext, recipient->dsn_orcpt));
1093
sio_write (conn, "\r\n", 2);
1095
session->cmd_recipient = next_recipient (session->cmd_recipient);
1096
if (session->cmd_recipient != NULL)
1097
session->cmd_state = S_rcpt;
1099
#ifdef USE_REQUIRE_ALL_RECIPIENTS
1100
/* Ugly hack: if requiring all recpients to succeed the decision can't
1101
be made here. So PIPELINING's improvement is lost. */
1102
if (session->require_all_recipients)
1103
session->cmd_state = -1;
1107
session->cmd_state = (session->extensions & EXT_CHUNKING) ? S_bdat : S_data;
1109
session->cmd_state = S_data;
1114
rsp_rcpt (siobuf_t conn, smtp_session_t session)
1118
code = read_smtp_response (conn, session,
1119
&session->rsp_recipient->status, NULL);
1121
session->current_message->valid_recipients += 1;
1122
#ifdef USE_REQUIRE_ALL_RECIPIENTS
1124
session->current_message->failed_recipients += 1;
1127
/* MTA will never accept this recipient. Make sure it isn't used
1130
session->rsp_recipient->complete = 1;
1132
/* Notify the RCPT TO: status */
1133
if (session->event_cb != NULL)
1134
(*session->event_cb) (session, SMTP_EV_RCPTSTATUS, session->event_cb_arg,
1135
session->rsp_recipient->mailbox,
1136
session->rsp_recipient);
1138
session->rsp_recipient = next_recipient (session->rsp_recipient);
1139
if (session->rsp_recipient != NULL)
1140
session->rsp_state = S_rcpt;
1142
#ifdef USE_REQUIRE_ALL_RECIPIENTS
1143
/* Ugly hack: if requiring all recpients to succeed make the decision to
1144
proceed now. Using this option may make it impossible
1145
to send mail at all if some recipients are experiencing
1146
transient errors. */
1147
if (session->require_all_recipients
1148
&& session->current_message->failed_recipients > 0)
1150
reset_status (&session->current_message->message_status);
1151
session->rsp_state = next_message (session) ? S_rset : S_quit;
1156
session->rsp_state = (session->extensions & EXT_CHUNKING) ? S_bdat : S_data;
1158
session->rsp_state = S_data;
1162
/*****************************************************************************
1164
*****************************************************************************/
1167
cmd_data (siobuf_t conn, smtp_session_t session)
1169
sio_set_timeout (conn, 2 * 60 * 1000);
1170
sio_write (conn, "DATA\r\n", -1);
1171
session->cmd_state = -1;
1175
rsp_data (siobuf_t conn, smtp_session_t session)
1178
smtp_message_t message;
1180
message = session->current_message;
1181
code = read_smtp_response (conn, session, &message->message_status, NULL);
1182
if (code == 4 || code == 5)
1184
/* The server will not accept this message.
1187
/* N.B. This is a bit tricky. RFC 821 isn't clear and I can't
1188
find any information in RFC 2821 either but what state is the
1189
SMTP server supposed to be in when the DATA command fails a)
1190
when the 354 response is expected and b) after the message is
1191
copied to the server.
1193
Play safe and issue the RSET command. */
1194
if (next_message (session))
1195
session->rsp_state = S_rset;
1197
session->rsp_state = S_quit;
1201
set_error (SMTP_ERR_INVALID_RESPONSE_STATUS);
1202
session->rsp_state = S_quit;
1205
session->rsp_state = S_data2;
1207
/* Notify end of message here if not transferring anything */
1208
if (code != 3 && session->event_cb != NULL)
1209
(*session->event_cb) (session, SMTP_EV_MESSAGESENT,
1210
session->event_cb_arg, message);
1213
/* Read the message from the application using the callback.
1214
Break into lines and copy to the server. */
1216
cmd_data2 (siobuf_t conn, smtp_session_t session)
1218
const char *line, *header, *pline, *p;
1221
/* RFC 2920 - some servers may return a 354 response to DATA even
1222
if there are no valid recipients. If this happens just send a
1223
line containing .\r\n to terminate the command. It will then
1224
fail as expected. */
1225
if (session->current_message->valid_recipients == 0)
1227
sio_write (conn, ".\r\n", 3);
1228
session->cmd_state = -1;
1232
sio_set_timeout (conn, 3 * 60 * 1000);
1234
/* Arrange to read the current message from the application. */
1235
msg_source_set_cb (session->msg_source,
1236
session->current_message->cb,
1237
session->current_message->cb_arg);
1239
/* Arrange *not* to have the message contents monitored. This is
1240
purely to avoid overwhelming the application with data. */
1241
sio_set_monitorcb (conn, NULL, NULL);
1243
/* Make sure we read the message from the beginning and get
1244
the header processing right. */
1245
msg_rewind (session->msg_source);
1246
reset_header_table (session->current_message);
1248
/* Read and process header lines from the application.
1249
This step in processing
1250
i) removes headers provided by the application that should not be
1251
present in the message, e.g. Return-Path: which is added by
1252
an MTA during delivery but should not be present in a message
1253
being submitted or which is in transit.
1254
ii) copies certain headers verbatim, e.g. MIME headers.
1255
iii) alters the content of certain headers. This will happen
1256
according to library options set up by the application.
1259
while ((line = msg_gets (session->msg_source, &len, 0)) != NULL)
1261
/* Header processing stops at a line containing only CRLF */
1262
if (len == 2 && line[0] == '\r' && line[1] == '\n')
1265
/* Check for continuation lines indicated by a blank or tab
1266
at the start of the next line. */
1267
while ((c = msg_nextc (session->msg_source)) != -1)
1269
if (c != ' ' && c != '\t')
1271
line = msg_gets (session->msg_source, &len, 1);
1276
/* Line points to one or more lines of text forming an RFC 2822
1279
/* Header processing. This function takes the "raw" header from
1280
the application and returns a header which is to be written
1281
to the remote MTA. If header is NULL this header has been
1282
deleted by the library. If header == line it is passed
1283
unchanged otherwise, header must be freed after use. */
1284
header = process_header (session->current_message, line, &len);
1287
/* Notify byte count to the application. */
1288
if (session->event_cb != NULL)
1289
(*session->event_cb) (session, SMTP_EV_MESSAGEDATA,
1290
session->event_cb_arg,
1291
session->current_message, len);
1293
/* During data transfer, if we are monitoring the message
1294
headers, call the monitor callback directly, once per header.
1295
We don't bother with monitoring the dot stuffing. Also set
1296
the value of the writing parameter to 2 so that the app can
1297
distinguish headers from data written in the sio_ package. */
1298
if (session->monitor_cb && session->monitor_cb_headers)
1299
(*session->monitor_cb) (header, len, SMTP_CB_HEADERS,
1300
session->monitor_cb_arg);
1302
/* Write the header using dot stuffing. N.B. because of
1303
dot stuffing, it is necessary to find the line breaks
1305
for (pline = header; pline < header + len; pline = p)
1307
p = memchr (pline, '\n', header + len - pline);
1311
session->cmd_state = session->rsp_state = -1;
1314
if (pline[0] == '.')
1315
sio_write (conn, ".", 1);
1316
sio_write (conn, pline, ++p - pline);
1324
/* An error occurred during processing. The only thing that can
1325
be done is to drop the connection to the server since SMTP has
1326
no way to recover gracefully from client errors while transferring
1329
session->cmd_state = session->rsp_state = -1;
1333
/* Now send missing headers. This completes the processing started
1334
above. If the application did not supply certain headers that
1335
should be present, the library will supply them here, e.g. Date:,
1336
Message-Id: or To:/Cc:/Bcc: headers. In the most extreme case the
1337
application might just send a CRLF followed by the message body.
1338
Libesmtp will then provide all the necessary headers. */
1339
while ((header = missing_header (session->current_message, &len)) != NULL)
1341
/* Notify byte count to the application. */
1342
if (session->event_cb != NULL)
1343
(*session->event_cb) (session, SMTP_EV_MESSAGEDATA,
1344
session->event_cb_arg,
1345
session->current_message, len);
1347
if (session->monitor_cb && session->monitor_cb_headers)
1348
(*session->monitor_cb) (header, len, SMTP_CB_HEADERS,
1349
session->monitor_cb_arg);
1350
for (pline = header; pline < header + len; pline = p)
1352
p = memchr (pline, '\n', header + len - pline);
1356
session->cmd_state = session->rsp_state = -1;
1359
if (pline[0] == '.')
1360
sio_write (conn, ".", 1);
1361
sio_write (conn, pline, ++p - pline);
1365
/* ... and finally terminate the message headers */
1366
sio_write (conn, "\r\n", 2);
1368
/* Read message body lines from the application and write them
1369
to the remote MTA using dot stuffing. */
1371
while ((line = msg_gets (session->msg_source, &len, 0)) != NULL)
1373
/* Notify byte count to the application. */
1374
if (session->event_cb != NULL)
1375
(*session->event_cb) (session, SMTP_EV_MESSAGEDATA,
1376
session->event_cb_arg,
1377
session->current_message, len);
1380
sio_write (conn, ".", 1);
1381
sio_write (conn, line, len);
1387
session->cmd_state = session->rsp_state = -1;
1391
/* Terminate the DATA command. Explicitly flush the buffer here.
1392
This would have happened in the protocol loop anyway but doing it
1393
here makes the output of strace more intuitive. */
1394
sio_write (conn, ".\r\n", 3);
1397
sio_set_timeout (conn, 10 * 60 * 1000);
1398
session->cmd_state = -1;
1402
rsp_data2 (siobuf_t conn, smtp_session_t session)
1405
smtp_recipient_t recipient;
1407
/* Reinstate the protocol monitor. */
1408
if (session->monitor_cb != NULL)
1409
sio_set_monitorcb (conn, session->monitor_cb, session->monitor_cb_arg);
1411
code = read_smtp_response (conn, session,
1412
&session->current_message->message_status,
1417
/* Mark all the recipients complete for which the MTA has accepted
1418
responsibility for delivery. */
1419
for (recipient = session->current_message->recipients;
1421
recipient = recipient->next)
1422
if (!recipient->complete
1423
&& recipient->status.code >= 200 && recipient->status.code <= 299)
1424
recipient->complete = 1;
1428
/* Mark all the recipients complete. This message cannot be
1429
accepted for any recipients. */
1430
for (recipient = session->current_message->recipients;
1432
recipient = recipient->next)
1433
recipient->complete = 1;
1437
if (session->event_cb != NULL)
1438
(*session->event_cb) (session, SMTP_EV_MESSAGESENT,
1439
session->event_cb_arg, session->current_message);
1441
if (next_message (session))
1442
session->rsp_state = (code == 2) ? initial_transaction_state (session)
1445
session->rsp_state = S_quit;
1448
/*****************************************************************************
1450
*****************************************************************************/
1453
cmd_rset (siobuf_t conn, smtp_session_t session)
1455
sio_write (conn, "RSET\r\n", 6);
1456
if (session->current_message != NULL)
1457
session->cmd_state = initial_transaction_state (session);
1459
session->cmd_state = S_quit;
1463
rsp_rset (siobuf_t conn, smtp_session_t session)
1465
struct smtp_status status;
1467
/* The RSET command should always succeed, since this client never
1468
attempts to sent trailing whitespace or parameters to the command */
1469
memset (&status, 0, sizeof status);
1470
read_smtp_response (conn, session, &status, NULL);
1471
reset_status (&status);
1472
if (session->current_message != NULL)
1473
session->rsp_state = initial_transaction_state (session);
1475
session->rsp_state = S_quit;
1478
/*****************************************************************************
1480
*****************************************************************************/
1483
cmd_quit (siobuf_t conn, smtp_session_t session)
1485
sio_write (conn, "QUIT\r\n", 6);
1486
session->cmd_state = -1;
1490
rsp_quit (siobuf_t conn, smtp_session_t session)
1492
struct smtp_status status;
1494
/* The QUIT command should always succeed.
1496
memset (&status, 0, sizeof status);
1497
read_smtp_response (conn, session, &status, NULL);
1498
reset_status (&status);
1499
session->rsp_state = -1;
1502
/*****************************************************************************
1504
*****************************************************************************/
1508
cmd_xusr (siobuf_t conn, smtp_session_t session)
1510
sio_write (conn, "XUSR\r\n", 6);
1511
session->cmd_state = -1;
1515
rsp_xusr (siobuf_t conn, smtp_session_t session)
1517
struct smtp_status status;
1519
/* The XUSR command should always succeed? */
1520
memset (&status, 0, sizeof status);
1521
read_smtp_response (conn, session, &status, NULL);
1522
reset_status (&status);
1523
session->rsp_state = S_mail;