# HG changeset patch # User markus schnalke # Date 1288294802 10800 # Node ID 4cff8638dd9b88cab23740ce38a36b5c1536f60d # Parent 2f5e2b6a3a39551912d0ff1e3e881a39ef4dfa1d SMTP client: tries EHLO now always first Changed the behavior of the SMTP client. Now always an EHLO greeting is sent, no matter what kind of greeting text the server had sent. If the EHLO failed, an HELO greeting is tried as fall back. This is the behavior RFC 2821 requires (section 3.2). This change will fix setups that were not possible to sent to a server because that requires AUTH but hadn't said ``ESMTP'' in its greeting message. See also: Debian bug #349211 Thanks to Steffen (inne) diff -r 2f5e2b6a3a39 -r 4cff8638dd9b src/smtp_out.c --- a/src/smtp_out.c Wed Oct 27 11:31:14 2010 -0300 +++ b/src/smtp_out.c Thu Oct 28 16:40:02 2010 -0300 @@ -121,7 +121,6 @@ psb->sock = sock; - psb->use_esmtp = FALSE; psb->use_size = FALSE; psb->use_pipelining = FALSE; psb->use_auth = FALSE; @@ -199,19 +198,6 @@ } } -static gboolean -check_init_response(smtp_base * psb) -{ - if (check_response(psb, FALSE)) { - psb->use_esmtp = (strstr(psb->buffer, "ESMTP") != NULL); - - DEBUG(4) debugf(psb->use_esmtp ? "uses esmtp\n" : "no esmtp\n"); - - return TRUE; - } - return FALSE; -} - static gchar* get_response_arg(gchar * response) { @@ -297,42 +283,58 @@ return TRUE; } +/* +We first try EHLO, but if it fails HELO in a second fall back try. +This is what is requested by RFC 2821 (sec 3.2): + + Once the server has sent the welcoming message and + the client has received it, the client normally sends + the EHLO command to the server, [...] + For a particular connection attempt, if the server + returns a "command not recognized" response to EHLO, + the client SHOULD be able to fall back and send HELO. + +Up to and including version 0.3.0 masqmail used ESMTP only if the +string ``ESMTP'' appeared within the server's greeting message. This +made it impossible to use AUTH with servers that would send odd +greeting messages. +*/ static gboolean smtp_helo(smtp_base * psb, gchar * helo) { - while (TRUE) { - if (psb->use_esmtp) { - fprintf(psb->out, "EHLO %s\r\n", helo); - fflush(psb->out); + fprintf(psb->out, "EHLO %s\r\n", helo); + fflush(psb->out); + DEBUG(4) debugf("C: EHLO %s\r\n", helo); - DEBUG(4) debugf("C: EHLO %s\r\n", helo); + if (!read_response(psb, SMTP_CMD_TIMEOUT)) { + return FALSE; + } + if (check_helo_response(psb)) { + DEBUG(4) debugf("uses esmtp\n"); + return TRUE; + } - } else { - fprintf(psb->out, "HELO %s\r\n", helo); - fflush(psb->out); + if (psb->error != smtp_fail) { + return FALSE; + } - DEBUG(4) debugf("C: HELO %s\r\n", helo); + /* our guess that server understands EHLO could have been wrong, + try again with HELO */ - } + fprintf(psb->out, "HELO %s\r\n", helo); + fflush(psb->out); + DEBUG(4) debugf("C: HELO %s\r\n", helo); - if (!read_response(psb, SMTP_CMD_TIMEOUT)) - return FALSE; + if (!read_response(psb, SMTP_CMD_TIMEOUT)) { + return FALSE; + } + if (check_helo_response(psb)) { + DEBUG(4) debugf("uses smtp\n"); + return TRUE; + } - if (check_helo_response(psb)) - return TRUE; - else { - if (psb->error == smtp_fail) { - if (psb->use_esmtp) { - /* our guess that server understands EHLO was wrong, try again with HELO */ - psb->use_esmtp = FALSE; - } else { - /* what sort of server ist THAT ?! give up... */ - return FALSE; - } - } else - return FALSE; - } - } + /* what sort of server ist THAT ?! give up... */ + return FALSE; } static void @@ -691,13 +693,9 @@ logwrite(LOG_INFO, "smtp_out_init(): instant_helo:%d\n", instant_helo); - if (instant_helo) { - /* we say hello right away, hence we don't know if - ESMTP is supported; we just assume it */ - psb->use_esmtp = 1; - } else { + if (!instant_helo) { if ((ok = read_response(psb, SMTP_INITIAL_TIMEOUT))) { - ok = check_init_response(psb); + ok = check_response(psb, FALSE); } if (!ok) { smtp_out_log_failure(psb, NULL); @@ -885,8 +883,8 @@ for (rcpt_node = g_list_first(rcpt_list); rcpt_node; rcpt_node = g_list_next(rcpt_node)) { address *rcpt = (address *) (rcpt_node->data); if (addr_is_delivered(rcpt)) - logwrite(LOG_NOTICE, "%s => %s host=%s with %s\n", msg->uid, addr_string(rcpt), - psb->remote_host, psb->use_esmtp ? "esmtp" : "smtp"); + logwrite(LOG_NOTICE, "%s => %s host=%s\n", + msg->uid, addr_string(rcpt), psb->remote_host); } } else { /* if something went wrong, diff -r 2f5e2b6a3a39 -r 4cff8638dd9b src/smtp_out.h --- a/src/smtp_out.h Wed Oct 27 11:31:14 2010 -0300 +++ b/src/smtp_out.h Thu Oct 28 16:40:02 2010 -0300 @@ -54,7 +54,6 @@ gchar *buffer; gint last_code; - gboolean use_esmtp; gboolean use_size; gboolean use_pipelining; gboolean use_auth;