masqmail

changeset 222:8cddc65765bd

added support for STARTTLS wrappers added the route config option `instant_helo' which causes masqmail, as SMTP client, not to wait for the server's 220 greeting. Instead if says EHLO right at once. You'll need this for STARTTLS wrappers that usually eat the greeting line.
author meillo@marmaro.de
date Fri, 23 Jul 2010 10:57:53 +0200
parents 8742d2cee364
children 9814e75de61c
files man/masqmail.route.5 src/conf.c src/deliver.c src/masqmail.h src/smtp_out.c src/smtp_out.h
diffstat 6 files changed, 58 insertions(+), 16 deletions(-) [+]
line diff
     1.1 --- a/man/masqmail.route.5	Fri Jul 23 10:53:04 2010 +0200
     1.2 +++ b/man/masqmail.route.5	Fri Jul 23 10:57:53 2010 +0200
     1.3 @@ -74,6 +74,23 @@
     1.4  the \fBhelo_name\fR (see above) will be used.
     1.5  
     1.6  .TP
     1.7 +\fBinstant_helo\fR = \fIboolean\fR
     1.8 +
     1.9 +If this is set, masqmail does not wait for the greeting of the SMTP server
    1.10 +after opening the connection.
    1.11 +Instead it says EHLO right away (ESMTP is assumed).
    1.12 +Use this option with wrappers that eat the 220 greeting of the SMTP server.
    1.13 +Common examples are STARTTLS wrappers, like `openssl -starttls smtp ...'.
    1.14 +
    1.15 +If this option is set and a 220 greeting is received though,
    1.16 +everything should still work.
    1.17 +Please don't rely on that and keep in mind that RFC 2821 says that the client
    1.18 +SHOULD wait for the 220 greeting of the server.
    1.19 +
    1.20 +Default: false
    1.21 +
    1.22 +
    1.23 +.TP
    1.24  \fBdo_pipelining\fR = \fIboolean\fR
    1.25  
    1.26  If this is set to false, masqmail will not use ESMTP PIPELINING,
     2.1 --- a/src/conf.c	Fri Jul 23 10:53:04 2010 +0200
     2.2 +++ b/src/conf.c	Fri Jul 23 10:57:53 2010 +0200
     2.3 @@ -651,6 +651,8 @@
     2.4  			route->connect_error_fail = parse_boolean(rval);
     2.5  		else if (strcmp(lval, "do_correct_helo") == 0)
     2.6  			route->do_correct_helo = parse_boolean(rval);
     2.7 +		else if (strcmp(lval, "instant_helo") == 0)
     2.8 +			route->instant_helo = parse_boolean(rval);
     2.9  		else if (strcmp(lval, "do_pipelining") == 0)
    2.10  			route->do_pipelining = parse_boolean(rval);
    2.11  		else if (strcmp(lval, "allowed_return_paths") == 0)
     3.1 --- a/src/deliver.c	Fri Jul 23 10:53:04 2010 +0200
     3.2 +++ b/src/deliver.c	Fri Jul 23 10:57:53 2010 +0200
     3.3 @@ -330,7 +330,7 @@
     3.4  		if ((route->auth_name) && (route->auth_login) && (route->auth_secret))
     3.5  			set_auth(psb, route->auth_name, route->auth_login, route->auth_secret);
     3.6  #endif
     3.7 -		if (smtp_out_init(psb)) {
     3.8 +		if (smtp_out_init(psb, route->instant_helo)) {
     3.9  
    3.10  			if (!route->do_pipelining)
    3.11  				psb->use_pipelining = FALSE;
     4.1 --- a/src/masqmail.h	Fri Jul 23 10:53:04 2010 +0200
     4.2 +++ b/src/masqmail.h	Fri Jul 23 10:57:53 2010 +0200
     4.3 @@ -99,6 +99,7 @@
     4.4  
     4.5  	gchar *helo_name;
     4.6  	gboolean do_correct_helo;
     4.7 +	gboolean instant_helo;
     4.8  	gboolean do_pipelining;
     4.9  
    4.10  	gchar *set_h_from_domain;
     5.1 --- a/src/smtp_out.c	Fri Jul 23 10:53:04 2010 +0200
     5.2 +++ b/src/smtp_out.c	Fri Jul 23 10:57:53 2010 +0200
     5.3 @@ -234,11 +234,22 @@
     5.4  static gboolean
     5.5  check_helo_response(smtp_base * psb)
     5.6  {
     5.7 -	gchar *ptr = psb->buffer;
     5.8 +	gchar *ptr;
     5.9  
    5.10  	if (!check_response(psb, FALSE))
    5.11  		return FALSE;
    5.12  
    5.13 +	if (psb->last_code == 220) {
    5.14 +		logwrite(LOG_NOTICE, "received a 220 greeting after sending EHLO,\n");
    5.15 +		logwrite(LOG_NOTICE, "please remove `instant_helo' from your route config\n");
    5.16 +		/* read the next response, cause that's the actual helo response */
    5.17 +		if (!read_response(psb, SMTP_CMD_TIMEOUT) || !check_response(psb, FALSE)) {
    5.18 +			return FALSE;
    5.19 +		}
    5.20 +	}
    5.21 +
    5.22 +	ptr = psb->buffer;
    5.23 +
    5.24  	while (*ptr) {
    5.25  		if (strncasecmp(&(ptr[4]), "SIZE", 4) == 0) {
    5.26  			gchar *arg;
    5.27 @@ -676,24 +687,35 @@
    5.28  #endif
    5.29  
    5.30  gboolean
    5.31 -smtp_out_init(smtp_base * psb)
    5.32 +smtp_out_init(smtp_base * psb, gboolean instant_helo)
    5.33  {
    5.34  	gboolean ok;
    5.35  
    5.36 -	if ((ok = read_response(psb, SMTP_INITIAL_TIMEOUT))) {
    5.37 -		if ((ok = check_init_response(psb))) {
    5.38 +	logwrite(LOG_INFO, "smtp_out_init(): instant_helo:%d\n", instant_helo);
    5.39  
    5.40 -			if ((ok = smtp_helo(psb, psb->helo_name))) {
    5.41 +	if (instant_helo) {
    5.42 +		/* we say hello right away, hence we don't know if
    5.43 +		   ESMTP is supported; we just assume it */
    5.44 +		psb->use_esmtp = 1;
    5.45 +	} else {
    5.46 +		if ((ok = read_response(psb, SMTP_INITIAL_TIMEOUT))) {
    5.47 +			ok = check_init_response(psb);
    5.48 +		}
    5.49 +		if (!ok) {
    5.50 +			smtp_out_log_failure(psb, NULL);
    5.51 +			return ok;
    5.52 +		}
    5.53 +	}
    5.54 +
    5.55 +	if ((ok = smtp_helo(psb, psb->helo_name))) {
    5.56  #ifdef ENABLE_AUTH
    5.57 -				if (psb->auth_name && psb->use_auth) {
    5.58 -					/* we completely disregard the response of server here. If
    5.59 -					   authentication fails, the server will complain later
    5.60 -					   anyway. I know, this is not polite... */
    5.61 -					smtp_out_auth(psb);
    5.62 -				}
    5.63 +		if (psb->auth_name && psb->use_auth) {
    5.64 +			/* we completely disregard the response of server here. If
    5.65 +			   authentication fails, the server will complain later
    5.66 +			   anyway. I know, this is not polite... */
    5.67 +			smtp_out_auth(psb);
    5.68 +		}
    5.69  #endif
    5.70 -			}
    5.71 -		}
    5.72  	}
    5.73  	if (!ok)
    5.74  		smtp_out_log_failure(psb, NULL);
    5.75 @@ -907,7 +929,7 @@
    5.76  	if ((psb = smtp_out_open(host, port, resolve_list))) {
    5.77  		set_heloname(psb, return_path->domain, TRUE);
    5.78  		/* initiate connection, send message and quit: */
    5.79 -		if (smtp_out_init(psb)) {
    5.80 +		if (smtp_out_init(psb, FALSE)) {
    5.81  			smtp_out_msg(psb, msg, return_path, rcpt_list, NULL);
    5.82  			if (psb->error == smtp_ok || (psb->error == smtp_fail) || (psb->error == smtp_trylater)
    5.83  			    || (psb->error == smtp_syntax) || (psb->error == smtp_cancel))
     6.1 --- a/src/smtp_out.h	Fri Jul 23 10:53:04 2010 +0200
     6.2 +++ b/src/smtp_out.h	Fri Jul 23 10:57:53 2010 +0200
     6.3 @@ -77,7 +77,7 @@
     6.4  smtp_base *smtp_out_open(gchar * host, gint port, GList * resolve_list);
     6.5  smtp_base *smtp_out_open_child(gchar * cmd);
     6.6  gboolean smtp_out_rset(smtp_base * psb);
     6.7 -gboolean smtp_out_init(smtp_base * psb);
     6.8 +gboolean smtp_out_init(smtp_base * psb, gboolean instant_helo);
     6.9  gint smtp_out_msg(smtp_base * psb, message * msg, address * return_path, GList * rcpt_list, GList * hdr_list);
    6.10  gboolean smtp_out_quit(smtp_base * psb);
    6.11