Exemple #1
0
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);
    }
}
Exemple #2
0
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);
}
Exemple #3
0
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);
}
Exemple #4
0
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);
}
Exemple #5
0
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);
    }
}
Exemple #6
0
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);
}
Exemple #7
0
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);
}
Exemple #8
0
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);
}
Exemple #9
0
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);
}
Exemple #10
0
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);
}
Exemple #11
0
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);
}
Exemple #12
0
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);
}