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,
     2.1 --- a/src/smtp_out.h	Wed Oct 27 11:31:14 2010 -0300
     2.2 +++ b/src/smtp_out.h	Thu Oct 28 16:40:02 2010 -0300
     2.3 @@ -54,7 +54,6 @@
     2.4  	gchar *buffer;
     2.5  	gint last_code;
     2.6  
     2.7 -	gboolean use_esmtp;
     2.8  	gboolean use_size;
     2.9  	gboolean use_pipelining;
    2.10  	gboolean use_auth;