Index: auto/modules =================================================================== RCS file: /spool1/cvs/nginx/nginx/auto/modules,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- auto/modules 19 Apr 2007 17:54:23 -0000 1.1.1.1 +++ auto/modules 18 Jul 2007 00:47:53 -0000 1.2 @@ -348,6 +348,8 @@ modules="$modules $MAIL_PROXY_MODULE" MAIL_SRCS="$MAIL_SRCS $MAIL_PROXY_SRCS" + + NGX_ADDON_DEPS="$NGX_ADDON_DEPS \$(MAIL_DEPS)" fi Index: src/mail/ngx_mail.h =================================================================== RCS file: /spool1/cvs/nginx/nginx/src/mail/ngx_mail.h,v retrieving revision 1.1.1.2 retrieving revision 1.6 diff -u -r1.1.1.2 -r1.6 --- src/mail/ngx_mail.h 20 Jul 2007 19:38:08 -0000 1.1.1.2 +++ src/mail/ngx_mail.h 23 Jul 2007 23:30:01 -0000 1.6 @@ -68,6 +68,7 @@ ngx_array_t listen; /* ngx_mail_listen_t */ } ngx_mail_core_main_conf_t; +typedef void (*ngx_mail_handler_pt)(ngx_connection_t *c); #define NGX_MAIL_POP3_PROTOCOL 0 #define NGX_MAIL_IMAP_PROTOCOL 1 @@ -107,6 +108,34 @@ ngx_array_t imap_capabilities; ngx_array_t smtp_capabilities; + /* + * Handlers: + * + * - handler_init_session + * + * Init new session after client connects. Protocol greetings printed + * from here, so you need to define this if you need custom greeting + * (or pause before greeting printed). + * + * - handler_init_protocol + * + * Initialize protocol-specific data after client sent first command. + * Notably, this is re-called after STARTTLS negotiation. + * + * - handler_read + * + * Read client command. Could be the only handler used by simple + * modules. + * + * NB: handler_read is re-used after auth_http module work (if it was + * called throgh ngx_mail_auth_http_init()) in case of error returned + * by auth server, so you should set this if you use auth_http. + */ + + ngx_mail_handler_pt handler_init_session; + ngx_event_handler_pt handler_init_protocol; + ngx_event_handler_pt handler_read; + /* server ctx */ ngx_mail_conf_ctx_t *ctx; } ngx_mail_core_srv_conf_t; @@ -152,8 +181,12 @@ ngx_smtp_auth_plain, ngx_smtp_auth_cram_md5, ngx_smtp_helo, - ngx_smtp_noxclient, - ngx_smtp_xclient + ngx_smtp_helo_xclient, + ngx_smtp_helo_from, + ngx_smtp_xclient, + ngx_smtp_xclient_from, + ngx_smtp_from, + ngx_smtp_to } ngx_smtp_state_e; @@ -187,7 +220,7 @@ unsigned no_sync_literal:1; unsigned starttls:1; unsigned esmtp:1; - unsigned auth_method:2; + unsigned auth_method:3; unsigned auth_wait:1; ngx_str_t login; @@ -199,6 +232,8 @@ ngx_str_t *addr_text; ngx_str_t smtp_helo; + ngx_str_t smtp_from; + ngx_str_t smtp_to; ngx_uint_t command; ngx_array_t args; @@ -268,12 +303,14 @@ #define NGX_MAIL_AUTH_LOGIN 1 #define NGX_MAIL_AUTH_APOP 2 #define NGX_MAIL_AUTH_CRAM_MD5 3 +#define NGX_MAIL_AUTH_NONE 4 #define NGX_MAIL_AUTH_PLAIN_ENABLED 0x0002 #define NGX_MAIL_AUTH_LOGIN_ENABLED 0x0004 #define NGX_MAIL_AUTH_APOP_ENABLED 0x0008 #define NGX_MAIL_AUTH_CRAM_MD5_ENABLED 0x0010 +#define NGX_MAIL_AUTH_NONE_ENABLED 0x0020 #define NGX_MAIL_PARSE_INVALID_COMMAND 20 @@ -312,10 +349,15 @@ void ngx_mail_close_connection(ngx_connection_t *c); void ngx_mail_session_internal_server_error(ngx_mail_session_t *s); +ngx_int_t ngx_mail_read_command(ngx_mail_session_t *s); + ngx_int_t ngx_pop3_parse_command(ngx_mail_session_t *s); ngx_int_t ngx_imap_parse_command(ngx_mail_session_t *s); ngx_int_t ngx_smtp_parse_command(ngx_mail_session_t *s); +#if (NGX_MAIL_SSL) +void ngx_mail_starttls_handler(ngx_event_t *rev); +#endif /* STUB */ void ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_peer_addr_t *peer); Index: src/mail/ngx_mail_auth_http_module.c =================================================================== RCS file: /spool1/cvs/nginx/nginx/src/mail/ngx_mail_auth_http_module.c,v retrieving revision 1.1.1.1 retrieving revision 1.4 diff -u -r1.1.1.1 -r1.4 --- src/mail/ngx_mail_auth_http_module.c 10 Jul 2007 21:26:51 -0000 1.1.1.1 +++ src/mail/ngx_mail_auth_http_module.c 23 Jul 2007 23:30:01 -0000 1.4 @@ -137,7 +137,8 @@ ngx_string("plain"), ngx_string("plain"), ngx_string("apop"), - ngx_string("cram-md5") + ngx_string("cram-md5"), + ngx_string("none") }; static ngx_str_t ngx_mail_smtp_errcode = ngx_string("535 5.7.0"); @@ -897,6 +898,10 @@ ngx_add_timer(rev, cscf->timeout); + if (cscf->handler_read) { + s->connection->read->handler = cscf->handler_read; + } + if (rev->ready) { s->connection->read->handler(rev); return; @@ -1169,6 +1174,9 @@ + sizeof(CRLF) - 1 + sizeof("Client-IP: ") - 1 + s->connection->addr_text.len + sizeof(CRLF) - 1 + + sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + + sizeof("Auth-SMTP-From: ") - 1 + s->smtp_from.len + + sizeof("Auth-SMTP-To: ") - 1 + s->smtp_to.len + ahcf->header.len + sizeof(CRLF) - 1; @@ -1223,6 +1231,27 @@ s->connection->addr_text.len); *b->last++ = CR; *b->last++ = LF; + if (s->auth_method == NGX_MAIL_AUTH_NONE) { + + /* HELO / MAIL FROM / RCPT TO can't contain CRLF, no need to escape */ + + b->last = ngx_cpymem(b->last, "Auth-SMTP-Helo: ", + sizeof("Auth-SMTP-Helo: ") - 1); + b->last = ngx_copy(b->last, s->smtp_helo.data, s->smtp_helo.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_cpymem(b->last, "Auth-SMTP-From: ", + sizeof("Auth-SMTP-From: ") - 1); + b->last = ngx_copy(b->last, s->smtp_from.data, s->smtp_from.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_cpymem(b->last, "Auth-SMTP-To: ", + sizeof("Auth-SMTP-To: ") - 1); + b->last = ngx_copy(b->last, s->smtp_to.data, s->smtp_to.len); + *b->last++ = CR; *b->last++ = LF; + + } + if (ahcf->header.len) { b->last = ngx_copy(b->last, ahcf->header.data, ahcf->header.len); } Index: src/mail/ngx_mail_core_module.c =================================================================== RCS file: /spool1/cvs/nginx/nginx/src/mail/ngx_mail_core_module.c,v retrieving revision 1.1.1.2 retrieving revision 1.7 diff -u -r1.1.1.2 -r1.7 --- src/mail/ngx_mail_core_module.c 20 Jul 2007 19:38:08 -0000 1.1.1.2 +++ src/mail/ngx_mail_core_module.c 24 Jul 2007 00:28:22 -0000 1.7 @@ -66,6 +66,7 @@ { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED }, { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED }, { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, + { ngx_string("none"), NGX_MAIL_AUTH_NONE_ENABLED }, { ngx_null_string, 0 } }; @@ -74,7 +75,8 @@ ngx_string("AUTH=PLAIN"), ngx_string("AUTH=LOGIN"), ngx_null_string, /* APOP */ - ngx_string("AUTH=CRAM-MD5") + ngx_string("AUTH=CRAM-MD5"), + ngx_null_string /* NONE */ }; @@ -82,7 +84,8 @@ ngx_string("PLAIN"), ngx_string("LOGIN"), ngx_null_string, /* APOP */ - ngx_string("CRAM-MD5") + ngx_string("CRAM-MD5"), + ngx_null_string /* NONE */ }; @@ -301,10 +304,10 @@ ngx_mail_core_srv_conf_t *prev = parent; ngx_mail_core_srv_conf_t *conf = child; - u_char *p, *auth; + u_char *p, *auth, *last; size_t size, stls_only_size; ngx_str_t *c, *d; - ngx_uint_t i, m; + ngx_uint_t i, m, smtp_auth_enabled; ngx_conf_merge_size_value(conf->imap_client_buffer_size, prev->imap_client_buffer_size, @@ -599,23 +602,28 @@ conf->smtp_capabilities = prev->smtp_capabilities; } - size = sizeof("250-") - 1 + conf->server_name.len + sizeof(CRLF) - 1 - + sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; + size = sizeof("250-") - 1 + conf->server_name.len + sizeof(CRLF) - 1; c = conf->smtp_capabilities.elts; for (i = 0; i < conf->smtp_capabilities.nelts; i++) { size += sizeof("250 ") - 1 + c[i].len + sizeof(CRLF) - 1; } + smtp_auth_enabled = 0; for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; m <<= 1, i++) { if (m & conf->smtp_auth_methods) { size += 1 + ngx_smtp_auth_methods_names[i].len; + smtp_auth_enabled = 1; } } + if (smtp_auth_enabled) { + size += sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; + } + p = ngx_palloc(cf->pool, size); if (p == NULL) { return NGX_CONF_ERROR; @@ -624,11 +632,13 @@ conf->smtp_capability.len = size; conf->smtp_capability.data = p; + last = p; *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); *p++ = CR; *p++ = LF; for (i = 0; i < conf->smtp_capabilities.nelts; i++) { + last = p; *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; p = ngx_cpymem(p, c[i].data, c[i].len); *p++ = CR; *p++ = LF; @@ -636,21 +646,28 @@ auth = p; - *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; - *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H'; + if (smtp_auth_enabled) { + last = p; - for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; - m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; - m <<= 1, i++) - { - if (m & conf->smtp_auth_methods) { - *p++ = ' '; - p = ngx_cpymem(p, ngx_smtp_auth_methods_names[i].data, - ngx_smtp_auth_methods_names[i].len); + *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; + *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H'; + + for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; + m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; + m <<= 1, i++) + { + if (m & conf->smtp_auth_methods) { + *p++ = ' '; + p = ngx_cpymem(p, ngx_smtp_auth_methods_names[i].data, + ngx_smtp_auth_methods_names[i].len); + } } - } - *p++ = CR; *p = LF; + *p++ = CR; *p = LF; + + } else { + last[3] = ' '; + } size += sizeof("250 STARTTLS" CRLF) - 1; @@ -669,7 +686,7 @@ *p++ = CR; *p = LF; p = conf->smtp_starttls_capability.data - + (auth - conf->smtp_capability.data) + 3; + + (last - conf->smtp_capability.data) + 3; *p = '-'; size = (auth - conf->smtp_capability.data) @@ -688,6 +705,12 @@ ngx_memcpy(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); + if (last < auth) { + p = conf->smtp_starttls_only_capability.data + + (last - conf->smtp_capability.data) + 3; + *p = '-'; + } + return NGX_CONF_OK; } Index: src/mail/ngx_mail_handler.c =================================================================== RCS file: /spool1/cvs/nginx/nginx/src/mail/ngx_mail_handler.c,v retrieving revision 1.1.1.2 retrieving revision 1.8 diff -u -r1.1.1.2 -r1.8 --- src/mail/ngx_mail_handler.c 20 Jul 2007 19:38:08 -0000 1.1.1.2 +++ src/mail/ngx_mail_handler.c 23 Jul 2007 23:30:01 -0000 1.8 @@ -15,7 +15,6 @@ static ngx_int_t ngx_mail_decode_auth_plain(ngx_mail_session_t *s, ngx_str_t *encoded); static void ngx_mail_do_auth(ngx_mail_session_t *s); -static ngx_int_t ngx_mail_read_command(ngx_mail_session_t *s); static u_char *ngx_mail_log_error(ngx_log_t *log, u_char *buf, size_t len); #if (NGX_MAIL_SSL) @@ -56,6 +55,7 @@ static u_char smtp_invalid_command[] = "500 5.5.1 Invalid command" CRLF; static u_char smtp_invalid_argument[] = "501 5.5.4 Invalid argument" CRLF; static u_char smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF; +static u_char smtp_bad_sequence[] = "503 5.5.1 Bad sequence of commands" CRLF; void @@ -172,7 +172,7 @@ #if (NGX_MAIL_SSL) -static void +void ngx_mail_starttls_handler(ngx_event_t *rev) { ngx_connection_t *c; @@ -269,6 +269,11 @@ return; } + if (cscf->handler_init_session) { + cscf->handler_init_session(c); + return; + } + if (s->protocol == NGX_MAIL_SMTP_PROTOCOL) { s->out = cscf->smtp_greeting; @@ -411,6 +416,12 @@ } s = c->data; + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + if (cscf->handler_init_protocol) { + cscf->handler_init_protocol(rev); + return; + } switch (s->protocol) { @@ -421,7 +432,6 @@ break; case NGX_MAIL_IMAP_PROTOCOL: - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); size = cscf->imap_client_buffer_size; s->mail_state = ngx_imap_start; c->read->handler = ngx_imap_auth_state; @@ -449,6 +459,10 @@ } } + if (cscf->handler_read) { + c->read->handler = cscf->handler_read; + } + c->read->handler(rev); } @@ -1535,6 +1549,11 @@ ngx_memcpy(s->smtp_helo.data, arg[0].data, arg[0].len); + s->smtp_from.len = 0; + s->smtp_from.data = NULL; + s->smtp_to.len = 0; + s->smtp_to.data = NULL; + if (s->command == NGX_SMTP_HELO) { size = cscf->smtp_server_name.len; text = cscf->smtp_server_name.data; @@ -1567,6 +1586,17 @@ break; + case NGX_SMTP_RSET: + + s->smtp_from.len = 0; + s->smtp_from.data = NULL; + s->smtp_to.len = 0; + s->smtp_to.data = NULL; + + text = smtp_ok; + size = sizeof(smtp_ok) - 1; + break; + case NGX_SMTP_AUTH: #if (NGX_MAIL_SSL) @@ -1693,8 +1723,12 @@ break; case NGX_SMTP_MAIL: + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); - if (s->connection->log->log_level >= NGX_LOG_INFO) { + if (s->connection->log->log_level >= NGX_LOG_INFO + || (cscf->smtp_auth_methods + & NGX_MAIL_AUTH_NONE_ENABLED)) + { l.len = s->buffer->last - s->buffer->start; l.data = s->buffer->start; @@ -1718,16 +1752,91 @@ l.len = i; - ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, - "client was rejected: \"%V\"", &l); + if (!(cscf->smtp_auth_methods + & NGX_MAIL_AUTH_NONE_ENABLED)) + { + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "client was rejected: \"%V\"", &l); + } + + } + + if (!(cscf->smtp_auth_methods & NGX_MAIL_AUTH_NONE_ENABLED)) + { + text = smtp_auth_required; + size = sizeof(smtp_auth_required) - 1; + break; + } + + /* auth none */ + + if (s->smtp_from.len) { + text = smtp_bad_sequence; + size = sizeof(smtp_bad_sequence) - 1; + break; + } + + s->smtp_from.len = l.len; + + s->smtp_from.data = ngx_palloc(c->pool, l.len); + if (s->smtp_from.data == NULL) { + ngx_mail_session_internal_server_error(s); + return; } - text = smtp_auth_required; - size = sizeof(smtp_auth_required) - 1; + ngx_memcpy(s->smtp_from.data, l.data, l.len); + + text = smtp_ok; + size = sizeof(smtp_ok) - 1; break; + case NGX_SMTP_RCPT: + + if (s->smtp_from.len == 0) { + text = smtp_bad_sequence; + size = sizeof(smtp_bad_sequence) - 1; + break; + } + + l.len = s->buffer->last - s->buffer->start; + l.data = s->buffer->start; + + for (i = 0; i < l.len; i++) { + ch = l.data[i]; + + if (ch != CR && ch != LF) { + continue; + } + + l.data[i] = ' '; + } + + while (i) { + if (l.data[i - 1] != ' ') { + break; + } + + i--; + } + + l.len = i; + + s->smtp_to.len = l.len; + + s->smtp_to.data = ngx_palloc(c->pool, l.len); + if (s->smtp_to.data == NULL) { + ngx_mail_session_internal_server_error(s); + return; + } + + ngx_memcpy(s->smtp_to.data, l.data, l.len); + + s->auth_method = NGX_MAIL_AUTH_NONE; + + ngx_mail_do_auth(s); + return; + case NGX_SMTP_NOOP: - case NGX_SMTP_RSET: text = smtp_ok; size = sizeof(smtp_ok) - 1; break; @@ -1748,6 +1857,10 @@ s->smtp_helo.len = 0; s->smtp_helo.data = NULL; + s->smtp_from.len = 0; + s->smtp_from.data = NULL; + s->smtp_to.len = 0; + s->smtp_to.data = NULL; text = smtp_ok; size = sizeof(smtp_ok) - 1; @@ -1999,7 +2112,7 @@ } -static ngx_int_t +ngx_int_t ngx_mail_read_command(ngx_mail_session_t *s) { ssize_t n; Index: src/mail/ngx_mail_parse.c =================================================================== RCS file: /spool1/cvs/nginx/nginx/src/mail/ngx_mail_parse.c,v retrieving revision 1.1.1.2 retrieving revision 1.5 diff -u -r1.1.1.2 -r1.5 --- src/mail/ngx_mail_parse.c 20 Jul 2007 19:38:08 -0000 1.1.1.2 +++ src/mail/ngx_mail_parse.c 23 Jul 2007 22:45:18 -0000 1.5 @@ -739,7 +739,7 @@ s->arg_end = p; goto done; default: - if (s->args.nelts <= 2) { + if (s->args.nelts <= 10) { state = sw_argument; s->arg_start = p; break; Index: src/mail/ngx_mail_proxy_module.c =================================================================== RCS file: /spool1/cvs/nginx/nginx/src/mail/ngx_mail_proxy_module.c,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- src/mail/ngx_mail_proxy_module.c 18 Apr 2007 15:21:28 -0000 1.1.1.1 +++ src/mail/ngx_mail_proxy_module.c 23 Jul 2007 23:30:01 -0000 1.3 @@ -102,7 +102,8 @@ }; -static u_char smtp_ok[] = "235 2.0.0 OK" CRLF; +static u_char smtp_auth_ok[] = "235 2.0.0 OK" CRLF; +static u_char smtp_ok[] = "250 2.0.0 OK" CRLF; void @@ -516,11 +517,13 @@ p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len); *p++ = CR; *p = LF; - s->mail_state = pcf->xclient ? ngx_smtp_helo: ngx_smtp_noxclient; + s->mail_state = pcf->xclient ? ngx_smtp_helo_xclient : + s->auth_method == NGX_MAIL_AUTH_NONE ? + ngx_smtp_helo_from : ngx_smtp_helo; break; - case ngx_smtp_helo: + case ngx_smtp_helo_xclient: ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send xclient"); @@ -537,31 +540,77 @@ return; } - if (s->smtp_helo.len) { - line.len = ngx_sprintf(line.data, - "XCLIENT PROTO=%sSMTP HELO=%V ADDR=%V LOGIN=%V " - "NAME=[UNAVAILABLE]" CRLF, - (s->esmtp ? "E" : ""), &s->smtp_helo, - &s->connection->addr_text, &s->login) - - line.data; - } else { - line.len = ngx_sprintf(line.data, - "XCLIENT PROTO=SMTP ADDR=%V LOGIN=%V " - "NAME=[UNAVAILABLE]" CRLF, - &s->connection->addr_text, &s->login) - - line.data; + line.len = ngx_sprintf(line.data, + "XCLIENT PROTO=%sSMTP%s%V ADDR=%V%s%V " + "NAME=[UNAVAILABLE]" CRLF, + (s->esmtp ? "E" : ""), + (s->smtp_helo.len ? " HELO=" : ""), &s->smtp_helo, + &s->connection->addr_text, + (s->login.len ? " LOGIN=" : ""), &s->login) + - line.data; + + s->mail_state = s->auth_method == NGX_MAIL_AUTH_NONE ? + ngx_smtp_xclient_from : ngx_smtp_xclient; + + break; + + case ngx_smtp_helo_from: + case ngx_smtp_xclient_from: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy send mail from"); + + s->connection->log->action = "sending MAIL FROM to upstream"; + + line.len = s->smtp_from.len + sizeof(CRLF) - 1; + line.data = ngx_palloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + p = ngx_cpymem(line.data, s->smtp_from.data, s->smtp_from.len); + *p++ = CR; *p = LF; + + s->mail_state = ngx_smtp_from; + + break; + + case ngx_smtp_from: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy send rcpt to"); + + s->connection->log->action = "sending RCPT TO to upstream"; + + line.len = s->smtp_to.len + sizeof(CRLF) - 1; + line.data = ngx_palloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; } - s->mail_state = ngx_smtp_xclient; + p = ngx_cpymem(line.data, s->smtp_to.data, s->smtp_to.len); + *p++ = CR; *p = LF; + + s->mail_state = ngx_smtp_to; + break; - case ngx_smtp_noxclient: + case ngx_smtp_helo: case ngx_smtp_xclient: + case ngx_smtp_to: - ngx_memcpy(s->proxy->buffer->start, smtp_ok, sizeof(smtp_ok) - 1); + if (s->auth_method == NGX_MAIL_AUTH_NONE) { + ngx_memcpy(s->proxy->buffer->start, smtp_ok, sizeof(smtp_ok) - 1); + s->proxy->buffer->last = s->proxy->buffer->start + + sizeof(smtp_ok) - 1; + } else { + ngx_memcpy(s->proxy->buffer->start, smtp_auth_ok, + sizeof(smtp_auth_ok) - 1); + s->proxy->buffer->last = s->proxy->buffer->start + + sizeof(smtp_auth_ok) - 1; + } s->proxy->buffer->pos = s->proxy->buffer->start; - s->proxy->buffer->last = s->proxy->buffer->start + sizeof(smtp_ok) - 1; s->connection->read->handler = ngx_mail_proxy_handler; s->connection->write->handler = ngx_mail_proxy_handler; @@ -701,18 +750,27 @@ switch (state) { case ngx_smtp_helo: - case ngx_smtp_noxclient: + case ngx_smtp_helo_from: + case ngx_smtp_helo_xclient: + case ngx_smtp_from: + case ngx_smtp_to: if (p[0] == '2' && p[1] == '5' && p[2] == '0') { return NGX_OK; } break; case ngx_smtp_start: - case ngx_smtp_xclient: if (p[0] == '2' && p[1] == '2' && p[2] == '0') { return NGX_OK; } break; + + case ngx_smtp_xclient: + case ngx_smtp_xclient_from: + if (p[0] == '2' && (p[1] == '2' || p[1] == '5') && p[2] == '0') { + return NGX_OK; + } + break; } break;