static void rset_done(int unused_event, char *context) { SESSION *session = (SESSION *) context; RESPONSE *resp; int except; /* * Get response to RSET command. */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending message", exception_text(except)); if ((resp = response(session->stream, buffer))->code / 100 == 2) { /* void */ } else if (allow_reject) { msg_warn("rset rejected: %d %s", resp->code, resp->str); if (resp->code == 421 || resp->code == 521) { close_session(session); return; } } else { msg_fatal("rset rejected: %d %s", resp->code, resp->str); } /* * Say goodbye or send the next message. */ if (disconnect || message_count < 1) { send_quit(session); } else { event_disable_readwrite(vstream_fileno(session->stream)); start_another(session); } }
static void send_rcpt(int unused_event, char *context) { SESSION *session = (SESSION *) context; int except; /* * Send envelope recipient address. */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending recipient", exception_text(except)); if (session->rcpt_count > 1 || number_rcpts > 0) command(session->stream, "RCPT TO:<%d%s>", number_rcpts ? number_rcpts++ : session->rcpt_count, recipient); else command(session->stream, "RCPT TO:<%s>", recipient); session->rcpt_count--; session->rcpt_done++; /* * Prepare for the next event. */ event_enable_read(vstream_fileno(session->stream), rcpt_done, (char *) session); }
static void rcpt_done(int unused, char *context) { SESSION *session = (SESSION *) context; RESPONSE *resp; int except; /* * Get response to RCPT command. */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending recipient", exception_text(except)); if ((resp = response(session->stream, buffer))->code / 100 == 2) { session->rcpt_accepted++; } else if (allow_reject) { msg_warn("recipient rejected: %d %s", resp->code, resp->str); if (resp->code == 421 || resp->code == 521) { close_session(session); return; } } else { msg_fatal("recipient rejected: %d %s", resp->code, resp->str); } /* * Send another RCPT command or send DATA. */ if (session->rcpt_count > 0) send_rcpt(unused, context); else if (session->rcpt_accepted > 0) send_data(unused, context); else send_rset(unused, context); }
static void helo_done(int unused_event, char *context) { SESSION *session = (SESSION *) context; RESPONSE *resp; int except; const char *protocol = (talk_lmtp ? "LHLO" : "HELO"); /* * Get response to HELO command. */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending %s", exception_text(except), protocol); if ((resp = response(session->stream, buffer))->code / 100 == 2) { /* void */ ; } else if (allow_reject) { msg_warn("%s rejected: %d %s", protocol, resp->code, resp->str); if (resp->code == 421 || resp->code == 521) { close_session(session); return; } } else { msg_fatal("%s rejected: %d %s", protocol, resp->code, resp->str); } send_mail(session); }
static void mail_done(int unused, char *context) { SESSION *session = (SESSION *) context; RESPONSE *resp; int except; /* * Get response to MAIL command. */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending sender", exception_text(except)); if ((resp = response(session->stream, buffer))->code / 100 == 2) { session->rcpt_count = recipients; session->rcpt_done = 0; session->rcpt_accepted = 0; send_rcpt(unused, context); } else if (allow_reject) { msg_warn("sender rejected: %d %s", resp->code, resp->str); if (resp->code == 421 || resp->code == 521) { close_session(session); return; } send_rset(unused, context); } else { msg_fatal("sender rejected: %d %s", resp->code, resp->str); } }
static void read_banner(int unused_event, char *context) { SESSION *session = (SESSION *) context; RESPONSE *resp; int except; /* * Prepare for disaster. */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while reading server greeting", exception_text(except)); /* * Read and parse the server's SMTP greeting banner. */ if (((resp = response(session->stream, buffer))->code / 100) == 2) { /* void */ ; } else if (allow_reject) { msg_warn("rejected at server banner: %d %s", resp->code, resp->str); } else { msg_fatal("rejected at server banner: %d %s", resp->code, resp->str); } /* * Send helo or send the envelope sender address. */ if (send_helo_first) send_helo(session); else send_mail(session); }
static void send_data(SESSION *session) { int fd = vstream_fileno(session->stream); int except; /* * Prepare for disaster. */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending message", exception_text(except)); /* * Send the message content, by wrapping three netstrings into an * over-all netstring. * * XXX This should be done more carefully to avoid blocking when sending * large messages over slow networks. */ netstring_put_multi(session->stream, STR(message_buffer), LEN(message_buffer), STR(sender_buffer), LEN(sender_buffer), STR(recipient_buffer), LEN(recipient_buffer), (char *) 0); netstring_fflush(session->stream); /* * Wake me up when the server replies or when something bad happens. */ event_enable_read(fd, receive_reply, (char *) session); }
static void send_data(int unused_event, char *context) { SESSION *session = (SESSION *) context; int except; /* * Request data transmission. */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending DATA command", exception_text(except)); command(session->stream, "DATA"); /* * Prepare for the next event. */ event_enable_read(vstream_fileno(session->stream), data_done, (char *) session); }
static void send_mail(SESSION *session) { int except; /* * Send the envelope sender address. */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending sender", exception_text(except)); command(session->stream, "MAIL FROM:<%s>", sender); /* * Prepare for the next event. */ event_enable_read(vstream_fileno(session->stream), mail_done, (char *) session); }
static void send_helo(SESSION *session) { int except; const char *NOCLOBBER protocol = (talk_lmtp ? "LHLO" : "HELO"); /* * Send the standard greeting with our hostname */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending %s", exception_text(except), protocol); command(session->stream, "%s %s", protocol, var_myhostname); /* * Prepare for the next event. */ event_enable_read(vstream_fileno(session->stream), helo_done, (char *) session); }
static void receive_reply(int unused_event, char *context) { SESSION *session = (SESSION *) context; int except; /* * Prepare for disaster. */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while receiving server reply", exception_text(except)); /* * Receive and process the server reply. */ netstring_get(session->stream, buffer, var_line_limit); if (msg_verbose) vstream_printf("<< %.*s\n", (int) LEN(buffer), STR(buffer)); if (STR(buffer)[0] != QMQP_STAT_OK) msg_fatal("%s error: %.*s", STR(buffer)[0] == QMQP_STAT_RETRY ? "recoverable" : STR(buffer)[0] == QMQP_STAT_HARD ? "unrecoverable" : "unknown", (int) LEN(buffer) - 1, STR(buffer) + 1); /* * Update the optional running counter. */ if (count) { counter++; vstream_printf("%d\r", counter); vstream_fflush(VSTREAM_OUT); } /* * Finish this session. QMQP sends only one message per session. */ event_disable_readwrite(vstream_fileno(session->stream)); vstream_fclose(session->stream); session->stream = 0; start_another(session); }
static void data_done(int unused, char *context) { SESSION *session = (SESSION *) context; RESPONSE *resp; int except; static const char *mydate; static int mypid; /* * Get response to DATA command. */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending DATA command", exception_text(except)); if ((resp = response(session->stream, buffer))->code == 354) { /* see below */ ; } else if (allow_reject) { msg_warn("data rejected: %d %s", resp->code, resp->str); if (resp->code == 421 || resp->code == 521) { close_session(session); return; } send_rset(unused, context); return; } else { msg_fatal("data rejected: %d %s", resp->code, resp->str); } /* * Send basic header to keep mailers that bother to examine them happy. */ if (send_headers) { if (mydate == 0) { mydate = mail_date(time((time_t *) 0)); mypid = getpid(); } smtp_printf(session->stream, "From: <%s>", sender); smtp_printf(session->stream, "To: <%s>", recipient); smtp_printf(session->stream, "Date: %s", mydate); smtp_printf(session->stream, "Message-Id: <%04x.%04x.%04x@%s>", mypid, vstream_fileno(session->stream), message_count, var_myhostname); if (subject) smtp_printf(session->stream, "Subject: %s", subject); smtp_fputs("", 0, session->stream); } /* * Send some garbage. */ if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending message", exception_text(except)); if (message_length == 0) { smtp_fputs("La de da de da 1.", 17, session->stream); smtp_fputs("La de da de da 2.", 17, session->stream); smtp_fputs("La de da de da 3.", 17, session->stream); smtp_fputs("La de da de da 4.", 17, session->stream); } else { /* * XXX This may cause the process to block with message content * larger than VSTREAM_BUFIZ bytes. */ smtp_fputs(message_data, message_length, session->stream); } /* * Send end of message and process the server response. */ command(session->stream, "."); /* * Update the running counter. */ if (count) { counter++; vstream_printf("%d\r", counter); vstream_fflush(VSTREAM_OUT); } /* * Prepare for the next event. */ event_enable_read(vstream_fileno(session->stream), dot_done, (char *) session); }