masqmail
changeset 246:4cff8638dd9b
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)
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Thu, 28 Oct 2010 16:40:02 -0300 |
parents | 2f5e2b6a3a39 |
children | 3c40f86d50e4 |
files | src/smtp_out.c src/smtp_out.h |
diffstat | 2 files changed, 47 insertions(+), 50 deletions(-) [+] |
line diff
1.1 --- a/src/smtp_out.c Wed Oct 27 11:31:14 2010 -0300 1.2 +++ b/src/smtp_out.c Thu Oct 28 16:40:02 2010 -0300 1.3 @@ -121,7 +121,6 @@ 1.4 1.5 psb->sock = sock; 1.6 1.7 - psb->use_esmtp = FALSE; 1.8 psb->use_size = FALSE; 1.9 psb->use_pipelining = FALSE; 1.10 psb->use_auth = FALSE; 1.11 @@ -199,19 +198,6 @@ 1.12 } 1.13 } 1.14 1.15 -static gboolean 1.16 -check_init_response(smtp_base * psb) 1.17 -{ 1.18 - if (check_response(psb, FALSE)) { 1.19 - psb->use_esmtp = (strstr(psb->buffer, "ESMTP") != NULL); 1.20 - 1.21 - DEBUG(4) debugf(psb->use_esmtp ? "uses esmtp\n" : "no esmtp\n"); 1.22 - 1.23 - return TRUE; 1.24 - } 1.25 - return FALSE; 1.26 -} 1.27 - 1.28 static gchar* 1.29 get_response_arg(gchar * response) 1.30 { 1.31 @@ -297,42 +283,58 @@ 1.32 return TRUE; 1.33 } 1.34 1.35 +/* 1.36 +We first try EHLO, but if it fails HELO in a second fall back try. 1.37 +This is what is requested by RFC 2821 (sec 3.2): 1.38 + 1.39 + Once the server has sent the welcoming message and 1.40 + the client has received it, the client normally sends 1.41 + the EHLO command to the server, [...] 1.42 + For a particular connection attempt, if the server 1.43 + returns a "command not recognized" response to EHLO, 1.44 + the client SHOULD be able to fall back and send HELO. 1.45 + 1.46 +Up to and including version 0.3.0 masqmail used ESMTP only if the 1.47 +string ``ESMTP'' appeared within the server's greeting message. This 1.48 +made it impossible to use AUTH with servers that would send odd 1.49 +greeting messages. 1.50 +*/ 1.51 static gboolean 1.52 smtp_helo(smtp_base * psb, gchar * helo) 1.53 { 1.54 - while (TRUE) { 1.55 - if (psb->use_esmtp) { 1.56 - fprintf(psb->out, "EHLO %s\r\n", helo); 1.57 - fflush(psb->out); 1.58 + fprintf(psb->out, "EHLO %s\r\n", helo); 1.59 + fflush(psb->out); 1.60 + DEBUG(4) debugf("C: EHLO %s\r\n", helo); 1.61 1.62 - DEBUG(4) debugf("C: EHLO %s\r\n", helo); 1.63 + if (!read_response(psb, SMTP_CMD_TIMEOUT)) { 1.64 + return FALSE; 1.65 + } 1.66 + if (check_helo_response(psb)) { 1.67 + DEBUG(4) debugf("uses esmtp\n"); 1.68 + return TRUE; 1.69 + } 1.70 1.71 - } else { 1.72 - fprintf(psb->out, "HELO %s\r\n", helo); 1.73 - fflush(psb->out); 1.74 + if (psb->error != smtp_fail) { 1.75 + return FALSE; 1.76 + } 1.77 1.78 - DEBUG(4) debugf("C: HELO %s\r\n", helo); 1.79 + /* our guess that server understands EHLO could have been wrong, 1.80 + try again with HELO */ 1.81 1.82 - } 1.83 + fprintf(psb->out, "HELO %s\r\n", helo); 1.84 + fflush(psb->out); 1.85 + DEBUG(4) debugf("C: HELO %s\r\n", helo); 1.86 1.87 - if (!read_response(psb, SMTP_CMD_TIMEOUT)) 1.88 - return FALSE; 1.89 + if (!read_response(psb, SMTP_CMD_TIMEOUT)) { 1.90 + return FALSE; 1.91 + } 1.92 + if (check_helo_response(psb)) { 1.93 + DEBUG(4) debugf("uses smtp\n"); 1.94 + return TRUE; 1.95 + } 1.96 1.97 - if (check_helo_response(psb)) 1.98 - return TRUE; 1.99 - else { 1.100 - if (psb->error == smtp_fail) { 1.101 - if (psb->use_esmtp) { 1.102 - /* our guess that server understands EHLO was wrong, try again with HELO */ 1.103 - psb->use_esmtp = FALSE; 1.104 - } else { 1.105 - /* what sort of server ist THAT ?! give up... */ 1.106 - return FALSE; 1.107 - } 1.108 - } else 1.109 - return FALSE; 1.110 - } 1.111 - } 1.112 + /* what sort of server ist THAT ?! give up... */ 1.113 + return FALSE; 1.114 } 1.115 1.116 static void 1.117 @@ -691,13 +693,9 @@ 1.118 1.119 logwrite(LOG_INFO, "smtp_out_init(): instant_helo:%d\n", instant_helo); 1.120 1.121 - if (instant_helo) { 1.122 - /* we say hello right away, hence we don't know if 1.123 - ESMTP is supported; we just assume it */ 1.124 - psb->use_esmtp = 1; 1.125 - } else { 1.126 + if (!instant_helo) { 1.127 if ((ok = read_response(psb, SMTP_INITIAL_TIMEOUT))) { 1.128 - ok = check_init_response(psb); 1.129 + ok = check_response(psb, FALSE); 1.130 } 1.131 if (!ok) { 1.132 smtp_out_log_failure(psb, NULL); 1.133 @@ -885,8 +883,8 @@ 1.134 for (rcpt_node = g_list_first(rcpt_list); rcpt_node; rcpt_node = g_list_next(rcpt_node)) { 1.135 address *rcpt = (address *) (rcpt_node->data); 1.136 if (addr_is_delivered(rcpt)) 1.137 - logwrite(LOG_NOTICE, "%s => %s host=%s with %s\n", msg->uid, addr_string(rcpt), 1.138 - psb->remote_host, psb->use_esmtp ? "esmtp" : "smtp"); 1.139 + logwrite(LOG_NOTICE, "%s => %s host=%s\n", 1.140 + msg->uid, addr_string(rcpt), psb->remote_host); 1.141 } 1.142 } else { 1.143 /* if something went wrong,