-/* $OpenBSD: smtp_session.c,v 1.315 2017/11/18 08:23:14 eric Exp $ */
+/* $OpenBSD: smtp_session.c,v 1.316 2018/02/09 09:29:03 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
static void smtp_queue_commit(struct smtp_session *);
static void smtp_queue_rollback(struct smtp_session *);
-static void smtp_dataline(struct smtp_session *, const char *);
+static int smtp_dataline(struct smtp_session *, const char *);
static struct { int code; const char *cmd; } commands[] = {
{ CMD_HELO, "HELO" },
struct smtp_session *s = arg;
char *line;
size_t len;
+ int eom;
log_trace(TRACE_IO, "smtp: %p: %s %s", s, io_strevent(evt),
io_strio(io));
return;
/* Message body */
- if (s->state == STATE_BODY && strcmp(line, ".")) {
- smtp_dataline(s, line);
- goto nextline;
+ eom = 0;
+ if (s->state == STATE_BODY) {
+ eom = smtp_dataline(s, line);
+ if (eom == 0)
+ goto nextline;
}
/* Pipelining not supported */
return;
}
- /* End of body */
- if (s->state == STATE_BODY) {
- log_trace(TRACE_SMTP, "<<< [EOM]");
-
- rfc2822_parser_flush(&s->tx->rfc2822_parser);
-
- io_set_write(io);
-
+ if (eom) {
smtp_message_end(s);
+ io_set_write(io);
return;
}
m_close(p_queue);
}
-static void
+static int
smtp_dataline(struct smtp_session *s, const char *line)
{
int ret;
log_trace(TRACE_SMTP, "<<< [MSG] %s", line);
+ if (!strcmp(line, ".")) {
+ log_trace(TRACE_SMTP, "<<< [EOM]");
+ if (!s->tx->error)
+ rfc2822_parser_flush(&s->tx->rfc2822_parser);
+ return 1;
+ }
+
/* ignore data line if an error is set */
if (s->tx->error)
- return;
+ return 0;
/* escape lines starting with a '.' */
if (line[0] == '.')
s->tx->datain += strlen(line) + 1;
if (s->tx->datain > env->sc_maxsize) {
s->tx->error = TX_ERROR_SIZE;
- return;
+ return 0;
}
if (!s->tx->hdrdone) {
/* folded header that must be skipped */
if (isspace((unsigned char)line[0]) && s->tx->skiphdr)
- return;
+ return 0;
s->tx->skiphdr = 0;
/* BCC should be stripped from headers */
if (strncasecmp("bcc:", line, 4) == 0) {
s->tx->skiphdr = 1;
- return;
+ return 0;
}
/* check for loop */
if (s->tx->rcvcount == MAX_HOPS_COUNT) {
s->tx->error = TX_ERROR_LOOP;
log_warnx("warn: loop detected");
- return;
+ return 0;
}
if (line[0] == '\0')
}
ret = rfc2822_parser_feed(&s->tx->rfc2822_parser, line);
- if (ret == -1) {
+ if (ret == -1)
s->tx->error = TX_ERROR_RESOURCES;
- return;
- }
- if (ret == 0) {
+ if (ret == 0)
s->tx->error = TX_ERROR_MALFORMED;
- return;
- }
+
+ return 0;
}
#define CASE(x) case x : return #x