Applied a modified version of Brad Jorsch's patch for "message" with
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Tue, 14 Nov 2006 16:40:36 +0000 (16:40 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Tue, 14 Nov 2006 16:40:36 +0000 (16:40 +0000)
"accept".

16 files changed:
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/ACKNOWLEDGMENTS
src/src/acl.c
src/src/functions.h
src/src/receive.c
src/src/smtp_in.c
test/confs/0023
test/confs/0546 [new file with mode: 0644]
test/log/0546 [new file with mode: 0644]
test/paniclog/0546 [new file with mode: 0644]
test/runtest
test/scripts/0000-Basic/0546 [new file with mode: 0644]
test/stderr/0546 [new file with mode: 0644]
test/stdout/0023
test/stdout/0546 [new file with mode: 0644]

index 01ff8dc3cd6a5e3462db2987a9d53f469385fe41..295ae7bb1035de992ce6412f274b6937aa7b0687 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.433 2006/11/13 12:29:30 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.434 2006/11/14 16:40:36 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -274,6 +274,9 @@ PH/43 Renamed the variables $interface_address and $interface_port as
 PH/44 There was no timeout on the connect() call when using a Unix domain
       socket in the ${readsocket expansion. There now is.
 
 PH/44 There was no timeout on the connect() call when using a Unix domain
       socket in the ${readsocket expansion. There now is.
 
+PH/45 Applied a modified version of Brad Jorsch's patch to allow "message" to
+      be meaningful with "accept".
+
 
 Exim version 4.63
 -----------------
 
 Exim version 4.63
 -----------------
index 564d76df202eae24e419025f74249991962a6758..67901a28c7f4c9577aba3a4abc3f8604af6b0aed 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.122 2006/11/13 12:07:46 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.123 2006/11/14 16:40:36 ph10 Exp $
 
 New Features in Exim
 --------------------
 
 New Features in Exim
 --------------------
@@ -197,6 +197,51 @@ Version 4.64
     relate to message reception rather than delivery. (The old names remain
     available for compatibility.)
 
     relate to message reception rather than delivery. (The old names remain
     available for compatibility.)
 
+12. The "message" modifier can now be used on acl verbs to vary the message
+    that is sent when an SMTP command. For example, in a RCPT ACL you could
+    have:
+
+      accept  <some conditions>
+              message = OK, I'll allow you through today
+
+    Previously, this message modifier would have had no effect whatsoever.
+
+    IMPORTANT: The new behaviour applies to "accept" (and "discard") only if
+    there is no occurrence of "endpass" in the statement. If "endpass" is
+    present, the behaviour reverts to the old case, where "message" applies to
+    rejection. This is for backwards compatibility.
+
+    It is always possible to rewrite ACL statements so that "endpass" is not
+    needed (and indeed it is no longer used in the default configuration, and
+    is somewhat not recommended nowadays because it causes confusion.)
+
+    It is now generally true that the "message" modifier sets up a text string
+    that is expanded and used as a response message if the current statement
+    terminates the ACL. The expansion happens at the time Exim decides that the
+    ACL is to end, not at the time it processes "message". If the expansion
+    fails, or generates an empty string, the modifier is ignored.
+
+    For ACLs that are triggered by SMTP commands, the message is returned as
+    part of the SMTP response. In this situation, the message may begin with an
+    overriding SMTP response code, optionally followed by an "extended response
+    code". However, the first digit of the supplied response code must be the
+    same as would be sent by default. A panic occurs if it is not. For the
+    predata ACL, note that the default success code is 354, not 2xx.
+
+    However, notwithstanding the previous paragraph, for the QUIT ACL, unlike
+    the others, the message modifier cannot override the 221 response code.
+
+    In the case of the "connect" ACL, accepting with a message modifier
+    overrides the value of smtp_banner.
+
+    The ACL test specified by acl_smtp_helo happens when the client issues the
+    HELO or EHLO commands, after the tests specified by helo_accept_junk_hosts,
+    helo_allow_chars and helo(_try)_verify_hosts. An acceptance message
+    modifier for EHLO/HELO may not contain more than one line (it will be
+    truncated at the first newline and a panic logged), and it cannot affect
+    the EHLO options.
+
+
 
 Version 4.63
 ------------
 
 Version 4.63
 ------------
index 2491260bf2ebcddd4996892f3db181e1a6361a59..b2552d7de8529caf5f91d8fc59c2e3c44ccf8301 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.63 2006/11/13 11:26:37 ph10 Exp $
+$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.64 2006/11/14 16:40:36 ph10 Exp $
 
 EXIM ACKNOWLEDGEMENTS
 
 
 EXIM ACKNOWLEDGEMENTS
 
@@ -20,7 +20,7 @@ relatively small patches.
 Philip Hazel
 
 Lists created: 20 November 2002
 Philip Hazel
 
 Lists created: 20 November 2002
-Last updated:  13 November 2006
+Last updated:  14 November 2006
 
 
 THE OLD LIST
 
 
 THE OLD LIST
@@ -174,6 +174,7 @@ John Jetmore              Writing and maintaining the 'exipick' utility
 Bob Johannessen           Patch for Sieve envelope tests bug
                           Patch for negative uid/gid bug
 Brad Jorsch               Patch for bitwise logical operators
 Bob Johannessen           Patch for Sieve envelope tests bug
                           Patch for negative uid/gid bug
 Brad Jorsch               Patch for bitwise logical operators
+                          Patch for using "message" on acceptance
 Christian Kellner         Patch for LDAP dereferencing
 Alex Kiernan              Patches for libradius
                           Diagnosis of milliwait clock-backwards bug
 Christian Kellner         Patch for LDAP dereferencing
 Alex Kiernan              Patches for libradius
                           Diagnosis of milliwait clock-backwards bug
index 8274e0c73f00704467b8d985284ecb25ce82d736..a79c31cb52800722498f9bcd574a9302b5427fd4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/acl.c,v 1.66 2006/09/25 10:14:20 ph10 Exp $ */
+/* $Cambridge: exim/src/src/acl.c,v 1.67 2006/11/14 16:40:36 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -27,9 +27,20 @@ static uschar *verbs[] =
   { US"accept", US"defer", US"deny", US"discard", US"drop", US"require",
     US"warn" };
 
   { US"accept", US"defer", US"deny", US"discard", US"drop", US"require",
     US"warn" };
 
-/* For each verb, the condition for which "message" is used */
-
-static int msgcond[] = { FAIL, OK, OK, FAIL, OK, FAIL, OK };
+/* For each verb, the conditions for which "message" or "log_message" are used
+are held as a bitmap. This is to avoid expanding the strings unnecessarily. For
+"accept", the FAIL case is used only after "endpass", but that is selected in
+the code. */
+
+static int msgcond[] = {
+  (1<<OK) | (1<<FAIL) | (1<<FAIL_DROP),  /* accept */
+  (1<<OK),                               /* defer */
+  (1<<OK),                               /* deny */
+  (1<<OK) | (1<<FAIL) | (1<<FAIL_DROP),  /* discard */
+  (1<<OK),                               /* drop */
+  (1<<FAIL) | (1<<FAIL_DROP),            /* require */
+  (1<<OK)                                /* warn */
+  };
 
 /* ACL condition and modifier codes - keep in step with the table that
 follows, and the cond_expand_at_top and uschar cond_modifiers tables lower
 
 /* ACL condition and modifier codes - keep in step with the table that
 follows, and the cond_expand_at_top and uschar cond_modifiers tables lower
@@ -3035,13 +3046,8 @@ for (; cb != NULL; cb = cb->next)
 
 
 /* If the result is the one for which "message" and/or "log_message" are used,
 
 
 /* If the result is the one for which "message" and/or "log_message" are used,
-handle the values of these options. Most verbs have but a single return for
-which the messages are relevant, but for "discard", it's useful to have the log
-message both when it succeeds and when it fails. Also, for an "accept" that
-appears in a QUIT ACL, we want to handle the user message. Since only "accept"
-and "warn" are permitted in that ACL, we don't need to test the verb.
-
-These modifiers act in different ways:
+handle the values of these modifiers. If there isn't a log message set, we make
+it the same as the user message.
 
 "message" is a user message that will be included in an SMTP response. Unless
 it is empty, it overrides any previously set user message.
 
 "message" is a user message that will be included in an SMTP response. Unless
 it is empty, it overrides any previously set user message.
@@ -3049,23 +3055,29 @@ it is empty, it overrides any previously set user message.
 "log_message" is a non-user message, and it adds to any existing non-user
 message that is already set.
 
 "log_message" is a non-user message, and it adds to any existing non-user
 message that is already set.
 
-If there isn't a log message set, we make it the same as the user message. */
+Most verbs have but a single return for which the messages are relevant, but
+for "discard", it's useful to have the log message both when it succeeds and
+when it fails. For "accept", the message is used in the OK case if there is no
+"endpass", but (for backwards compatibility) in the FAIL case if "endpass" is
+present. */
 
 
-if (((rc == FAIL_DROP)? FAIL : rc) == msgcond[verb] ||
-    (verb == ACL_DISCARD && rc == OK) ||
-    (where == ACL_WHERE_QUIT))
+if (*epp && rc == OK) user_message = NULL;
+
+if (((1<<rc) & msgcond[verb]) != 0)
   {
   uschar *expmessage;
   {
   uschar *expmessage;
+  uschar *old_user_msgptr = *user_msgptr;
+  uschar *old_log_msgptr = (*log_msgptr != NULL)? *log_msgptr : old_user_msgptr;
 
   /* If the verb is "warn", messages generated by conditions (verification or
 
   /* If the verb is "warn", messages generated by conditions (verification or
-  nested ACLs) are discarded. Only messages specified at this level are used.
+  nested ACLs) are always discarded. This also happens for acceptance verbs
+  when they actually do accept. Only messages specified at this level are used.
   However, the value of an existing message is available in $acl_verify_message
   during expansions. */
 
   However, the value of an existing message is available in $acl_verify_message
   during expansions. */
 
-  uschar *old_user_msgptr = *user_msgptr;
-  uschar *old_log_msgptr = (*log_msgptr != NULL)? *log_msgptr : old_user_msgptr;
-
-  if (verb == ACL_WARN) *log_msgptr = *user_msgptr = NULL;
+  if (verb == ACL_WARN ||
+      (rc == OK && (verb == ACL_ACCEPT || verb == ACL_DISCARD)))
+    *log_msgptr = *user_msgptr = NULL;
 
   if (user_message != NULL)
     {
 
   if (user_message != NULL)
     {
@@ -3595,10 +3607,10 @@ if (rc == FAIL_DROP && where == ACL_WHERE_MAILAUTH)
   return ERROR;
   }
 
   return ERROR;
   }
 
-/* Before giving an error response, take a look at the length of any user
-message, and split it up into multiple lines if possible. */
+/* Before giving a response, take a look at the length of any user message, and
+split it up into multiple lines if possible. */
 
 
-if (rc != OK && *user_msgptr != NULL && Ustrlen(*user_msgptr) > 75)
+if (*user_msgptr != NULL && Ustrlen(*user_msgptr) > 75)
   {
   uschar *s = *user_msgptr = string_copy(*user_msgptr);
   uschar *ss = s;
   {
   uschar *s = *user_msgptr = string_copy(*user_msgptr);
   uschar *ss = s;
index b91ca274d307a43939aece82d88590071643eb8a..0e806055557b47fec5b234d08e4a8725ed9f7830 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/functions.h,v 1.30 2006/10/24 12:56:06 ph10 Exp $ */
+/* $Cambridge: exim/src/src/functions.h,v 1.31 2006/11/14 16:40:36 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -269,6 +269,7 @@ extern BOOL    smtp_get_interface(uschar *, int, address_item *, BOOL *,
 extern BOOL    smtp_get_port(uschar *, address_item *, int *, uschar *);
 extern int     smtp_getc(void);
 extern int     smtp_handle_acl_fail(int, int, uschar *, uschar *);
 extern BOOL    smtp_get_port(uschar *, address_item *, int *, uschar *);
 extern int     smtp_getc(void);
 extern int     smtp_handle_acl_fail(int, int, uschar *, uschar *);
+extern void    smtp_message_code(uschar **, int *, uschar **, uschar **);
 extern BOOL    smtp_read_response(smtp_inblock *, uschar *, int, int, int);
 extern void    smtp_respond(uschar *, int, BOOL, uschar *);
 extern void    smtp_send_prohibition_message(int, uschar *);
 extern BOOL    smtp_read_response(smtp_inblock *, uschar *, int, int, int);
 extern void    smtp_respond(uschar *, int, BOOL, uschar *);
 extern void    smtp_send_prohibition_message(int, uschar *);
index 73675bee209f44a37f7fc045a3f8788737200013..8fba1caeb8774287b38c37112b86311b0c3866b8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/receive.c,v 1.30 2006/10/10 15:36:50 ph10 Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.31 2006/11/14 16:40:36 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1042,18 +1042,21 @@ memset(CS rfc822_file_path,0,2048);
 
 /* check if it is a MIME message */
 my_headerlist = header_list;
 
 /* check if it is a MIME message */
 my_headerlist = header_list;
-while (my_headerlist != NULL) {
+while (my_headerlist != NULL)
+  {
   /* skip deleted headers */
   /* skip deleted headers */
-  if (my_headerlist->type == '*') {
+  if (my_headerlist->type == '*')
+    {
     my_headerlist = my_headerlist->next;
     continue;
     my_headerlist = my_headerlist->next;
     continue;
-  };
-  if (strncmpic(my_headerlist->text, US"Content-Type:", 13) == 0) {
+    }
+  if (strncmpic(my_headerlist->text, US"Content-Type:", 13) == 0)
+    {
     DEBUG(D_receive) debug_printf("Found Content-Type: header - executing acl_smtp_mime.\n");
     goto DO_MIME_ACL;
     DEBUG(D_receive) debug_printf("Found Content-Type: header - executing acl_smtp_mime.\n");
     goto DO_MIME_ACL;
-  };
+    }
   my_headerlist = my_headerlist->next;
   my_headerlist = my_headerlist->next;
-};
+  }
 
 DEBUG(D_receive) debug_printf("No Content-Type: header - presumably not a MIME message.\n");
 return TRUE;
 
 DEBUG(D_receive) debug_printf("No Content-Type: header - presumably not a MIME message.\n");
 return TRUE;
@@ -1080,18 +1083,21 @@ mime_part_count = -1;
 rc = mime_acl_check(acl, mbox_file, NULL, &user_msg, &log_msg);
 (void)fclose(mbox_file);
 
 rc = mime_acl_check(acl, mbox_file, NULL, &user_msg, &log_msg);
 (void)fclose(mbox_file);
 
-if (Ustrlen(rfc822_file_path) > 0) {
+if (Ustrlen(rfc822_file_path) > 0)
+  {
   mime_part_count = mime_part_count_buffer;
 
   mime_part_count = mime_part_count_buffer;
 
-  if (unlink(CS rfc822_file_path) == -1) {
+  if (unlink(CS rfc822_file_path) == -1)
+    {
     log_write(0, LOG_PANIC,
          "acl_smtp_mime: can't unlink RFC822 spool file, skipping.");
       goto END_MIME_ACL;
     log_write(0, LOG_PANIC,
          "acl_smtp_mime: can't unlink RFC822 spool file, skipping.");
       goto END_MIME_ACL;
-  };
-};
+    }
+  }
 
 /* check if we must check any message/rfc822 attachments */
 
 /* check if we must check any message/rfc822 attachments */
-if (rc == OK) {
+if (rc == OK)
+  {
   uschar temp_path[1024];
   int n;
   struct dirent *entry;
   uschar temp_path[1024];
   int n;
   struct dirent *entry;
@@ -1100,33 +1106,37 @@ if (rc == OK) {
   (void)string_format(temp_path, 1024, "%s/scan/%s", spool_directory,
     message_id);
 
   (void)string_format(temp_path, 1024, "%s/scan/%s", spool_directory,
     message_id);
 
- tempdir = opendir(CS temp_path);
- n = 0;
- do {
-   entry = readdir(tempdir);
-   if (entry == NULL) break;
-    if (strncmpic(US entry->d_name,US"__rfc822_",9) == 0) {
+  tempdir = opendir(CS temp_path);
+  n = 0;
+  do
+    {
+    entry = readdir(tempdir);
+    if (entry == NULL) break;
+    if (strncmpic(US entry->d_name,US"__rfc822_",9) == 0)
+      {
       (void)string_format(rfc822_file_path, 2048,"%s/scan/%s/%s", spool_directory, message_id, entry->d_name);
       (void)string_format(rfc822_file_path, 2048,"%s/scan/%s/%s", spool_directory, message_id, entry->d_name);
-     debug_printf("RFC822 attachment detected: running MIME ACL for '%s'\n", rfc822_file_path);
-     break;
-    };
- } while (1);
- closedir(tempdir);
+      debug_printf("RFC822 attachment detected: running MIME ACL for '%s'\n", rfc822_file_path);
+      break;
+      }
   } while (1);
 closedir(tempdir);
 
 
-  if (entry != NULL) {
+  if (entry != NULL)
+    {
     mbox_file = Ufopen(rfc822_file_path,"rb");
     mbox_file = Ufopen(rfc822_file_path,"rb");
-    if (mbox_file == NULL) {
+    if (mbox_file == NULL)
+      {
       log_write(0, LOG_PANIC,
          "acl_smtp_mime: can't open RFC822 spool file, skipping.");
       unlink(CS rfc822_file_path);
       goto END_MIME_ACL;
       log_write(0, LOG_PANIC,
          "acl_smtp_mime: can't open RFC822 spool file, skipping.");
       unlink(CS rfc822_file_path);
       goto END_MIME_ACL;
-    };
+      }
     /* set RFC822 expansion variable */
     mime_is_rfc822 = 1;
     mime_part_count_buffer = mime_part_count;
     goto MIME_ACL_CHECK;
     /* set RFC822 expansion variable */
     mime_is_rfc822 = 1;
     mime_part_count_buffer = mime_part_count;
     goto MIME_ACL_CHECK;
-  };
-};
+    }
+  }
 
 END_MIME_ACL:
 add_acl_headers(US"MIME");
 
 END_MIME_ACL:
 add_acl_headers(US"MIME");
@@ -1144,7 +1154,7 @@ else if (rc != OK)
   *smtp_reply_ptr = US"";       /* Indicate reply already sent */
   message_id[0] = 0;            /* Indicate no message accepted */
   return FALSE;                 /* Cause skip to end of receive function */
   *smtp_reply_ptr = US"";       /* Indicate reply already sent */
   message_id[0] = 0;            /* Indicate no message accepted */
   return FALSE;                 /* Cause skip to end of receive function */
-  };
+  }
 
 return TRUE;
 }
 
 return TRUE;
 }
@@ -1276,9 +1286,10 @@ uschar *queued_by = NULL;
 uschar *errmsg, *s;
 struct stat statbuf;
 
 uschar *errmsg, *s;
 struct stat statbuf;
 
-/* Final message to give to SMTP caller */
+/* Final message to give to SMTP caller, and messages from ACLs */
 
 uschar *smtp_reply = NULL;
 
 uschar *smtp_reply = NULL;
+uschar *user_msg, *log_msg;
 
 /* Working header pointers */
 
 
 /* Working header pointers */
 
@@ -2902,6 +2913,7 @@ $message_body_end can be extracted if needed. Allow $recipients in expansions.
 */
 
 deliver_datafile = data_fd;
 */
 
 deliver_datafile = data_fd;
+user_msg = NULL;
 
 if (recipients_count == 0)
   {
 
 if (recipients_count == 0)
   {
@@ -2931,7 +2943,6 @@ else
 
     if (acl_smtp_data != NULL && recipients_count > 0)
       {
 
     if (acl_smtp_data != NULL && recipients_count > 0)
       {
-      uschar *user_msg, *log_msg;
       rc = acl_check(ACL_WHERE_DATA, NULL, acl_smtp_data, &user_msg, &log_msg);
       add_acl_headers(US"DATA");
       if (rc == DISCARD)
       rc = acl_check(ACL_WHERE_DATA, NULL, acl_smtp_data, &user_msg, &log_msg);
       add_acl_headers(US"DATA");
       if (rc == DISCARD)
@@ -3491,12 +3502,28 @@ if (smtp_input)
       if (fake_response != OK)
         smtp_respond((fake_response == DEFER)? US"450" : US"550", 3, TRUE,
           fake_response_text);
       if (fake_response != OK)
         smtp_respond((fake_response == DEFER)? US"450" : US"550", 3, TRUE,
           fake_response_text);
+
+      /* An OK response is required; use "message" text if present. */
+
+      else if (user_msg != NULL)
+        {
+        uschar *code = US"250";
+        int len = 3;
+        smtp_message_code(&code, &len, &user_msg, NULL);
+        smtp_respond(code, len, TRUE, user_msg);
+        }
+
+      /* Default OK response */
+
       else
         smtp_printf("250 OK id=%s\r\n", message_id);
       if (host_checking)
         fprintf(stdout,
           "\n**** SMTP testing: that is not a real message id!\n\n");
       }
       else
         smtp_printf("250 OK id=%s\r\n", message_id);
       if (host_checking)
         fprintf(stdout,
           "\n**** SMTP testing: that is not a real message id!\n\n");
       }
+
+    /* smtp_reply was previously set */
+
     else if (smtp_reply[0] != 0)
       {
       if (fake_response != OK && (smtp_reply[0] == '2'))
     else if (smtp_reply[0] != 0)
       {
       if (fake_response != OK && (smtp_reply[0] == '2'))
index c75b2b207ebd8bb876c41017c206a8b87e3130f4..97b721e550530a8e978b7dab72bb9a86aae9d84b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/smtp_in.c,v 1.46 2006/10/23 10:55:10 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_in.c,v 1.47 2006/11/14 16:40:36 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -874,7 +874,7 @@ if (message_body_end != NULL)
 
 /* Warning log messages are also saved in malloc store. They are saved to avoid
 repetition in the same message, but it seems right to repeat them for different
 
 /* Warning log messages are also saved in malloc store. They are saved to avoid
 repetition in the same message, but it seems right to repeat them for different
-messagess. */
+messages. */
 
 while (acl_warn_logged != NULL)
   {
 
 while (acl_warn_logged != NULL)
   {
@@ -1141,7 +1141,9 @@ BOOL
 smtp_start_session(void)
 {
 int size = 256;
 smtp_start_session(void)
 {
 int size = 256;
-int ptr;
+int ptr, esclen;
+uschar *user_msg, *log_msg;
+uschar *code, *esc;
 uschar *p, *s, *ss;
 
 /* Default values for certain variables */
 uschar *p, *s, *ss;
 
 /* Default values for certain variables */
@@ -1571,10 +1573,10 @@ if (smtp_batched_input) return TRUE;
 
 /* Run the ACL if it exists */
 
 
 /* Run the ACL if it exists */
 
+user_msg = NULL;
 if (acl_smtp_connect != NULL)
   {
   int rc;
 if (acl_smtp_connect != NULL)
   {
   int rc;
-  uschar *user_msg, *log_msg;
   rc = acl_check(ACL_WHERE_CONNECT, NULL, acl_smtp_connect, &user_msg,
     &log_msg);
   if (rc != OK)
   rc = acl_check(ACL_WHERE_CONNECT, NULL, acl_smtp_connect, &user_msg,
     &log_msg);
   if (rc != OK)
@@ -1587,10 +1589,28 @@ if (acl_smtp_connect != NULL)
 /* Output the initial message for a two-way SMTP connection. It may contain
 newlines, which then cause a multi-line response to be given. */
 
 /* Output the initial message for a two-way SMTP connection. It may contain
 newlines, which then cause a multi-line response to be given. */
 
-s = expand_string(smtp_banner);
-if (s == NULL)
-  log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Expansion of \"%s\" (smtp_banner) "
-    "failed: %s", smtp_banner, expand_string_message);
+code = US"220";   /* Default status code */
+esc = US"";       /* Default extended status code */
+esclen = 0;       /* Length of esc */
+
+if (user_msg == NULL)
+  {
+  s = expand_string(smtp_banner);
+  if (s == NULL)
+    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Expansion of \"%s\" (smtp_banner) "
+      "failed: %s", smtp_banner, expand_string_message);
+  }
+else
+  {
+  int codelen = 3;
+  s = user_msg;
+  smtp_message_code(&code, &codelen, &s, NULL);
+  if (codelen > 3)
+    {
+    esc = code + 4;
+    esclen = codelen - 4;
+    }
+  }
 
 /* Remove any terminating newlines; might as well remove trailing space too */
 
 
 /* Remove any terminating newlines; might as well remove trailing space too */
 
@@ -1615,16 +1635,18 @@ do       /* At least once, in case we have an empty string */
   {
   int len;
   uschar *linebreak = Ustrchr(p, '\n');
   {
   int len;
   uschar *linebreak = Ustrchr(p, '\n');
+  ss = string_cat(ss, &size, &ptr, code, 3);
   if (linebreak == NULL)
     {
     len = Ustrlen(p);
   if (linebreak == NULL)
     {
     len = Ustrlen(p);
-    ss = string_cat(ss, &size, &ptr, US"220 ", 4);
+    ss = string_cat(ss, &size, &ptr, US" ", 1);
     }
   else
     {
     len = linebreak - p;
     }
   else
     {
     len = linebreak - p;
-    ss = string_cat(ss, &size, &ptr, US"220-", 4);
+    ss = string_cat(ss, &size, &ptr, US"-", 1);
     }
     }
+  ss = string_cat(ss, &size, &ptr, esc, esclen);
   ss = string_cat(ss, &size, &ptr, p, len);
   ss = string_cat(ss, &size, &ptr, US"\r\n", 2);
   p += len;
   ss = string_cat(ss, &size, &ptr, p, len);
   ss = string_cat(ss, &size, &ptr, US"\r\n", 2);
   p += len;
@@ -1771,7 +1793,7 @@ output nothing for non-final calls, and only the first line for anything else.
 
 Arguments:
   code          SMTP code, may involve extended status codes
 
 Arguments:
   code          SMTP code, may involve extended status codes
-  codelen       length of smtp code; uf > 3 there's an ESC
+  codelen       length of smtp code; if > 3 there's an ESC
   final         FALSE if the last line isn't the final line
   msg           message text, possibly containing newlines
 
   final         FALSE if the last line isn't the final line
   msg           message text, possibly containing newlines
 
@@ -1818,6 +1840,62 @@ for (;;)
 
 
 
 
 
 
+/*************************************************
+*            Parse user SMTP message             *
+*************************************************/
+
+/* This function allows for user messages overriding the response code details
+by providing a suitable response code string at the start of the message
+user_msg. Check the message for starting with a response code and optionally an
+extended status code. If found, check that the first digit is valid, and if so,
+change the code pointer and length to use the replacement. An invalid code
+causes a panic log; in this case, if the log messages is the same as the user
+message, we must also adjust the value of the log message to show the code that
+is actually going to be used (the original one).
+
+This function is global because it is called from receive.c as well as within
+this module.
+
+Arguments:
+  code          SMTP code, may involve extended status codes
+  codelen       length of smtp code; if > 3 there's an ESC
+  msg           message text
+  log_msg       optional log message, to be adjusted with the new SMTP code
+
+Returns:        nothing
+*/
+
+void
+smtp_message_code(uschar **code, int *codelen, uschar **msg, uschar **log_msg)
+{
+int n;
+int ovector[3];
+
+if (msg == NULL || *msg == NULL) return;
+
+n = pcre_exec(regex_smtp_code, NULL, CS *msg, Ustrlen(*msg), 0,
+  PCRE_EOPT, ovector, sizeof(ovector)/sizeof(int));
+if (n < 0) return;
+
+if ((*msg)[0] != (*code)[0])
+  {
+  log_write(0, LOG_MAIN|LOG_PANIC, "configured error code starts with "
+    "incorrect digit (expected %c) in \"%s\"", (*code)[0], *msg);
+  if (log_msg != NULL && *log_msg == *msg)
+    *log_msg = string_sprintf("%s %s", *code, *log_msg + ovector[1]);
+  }
+else
+  {
+  *code = *msg;
+  *codelen = ovector[1];    /* Includes final space */
+  }
+*msg += ovector[1];         /* Chop the code off the message */
+return;
+}
+
+
+
+
 /*************************************************
 *           Handle an ACL failure                *
 *************************************************/
 /*************************************************
 *           Handle an ACL failure                *
 *************************************************/
@@ -1858,7 +1936,6 @@ smtp_handle_acl_fail(int where, int rc, uschar *user_msg, uschar *log_msg)
 {
 BOOL drop = rc == FAIL_DROP;
 int codelen = 3;
 {
 BOOL drop = rc == FAIL_DROP;
 int codelen = 3;
-int ovector[3];
 uschar *smtp_code;
 uschar *lognl;
 uschar *sender_info = US"";
 uschar *smtp_code;
 uschar *lognl;
 uschar *sender_info = US"";
@@ -1874,40 +1951,10 @@ uschar *what =
 
 if (drop) rc = FAIL;
 
 
 if (drop) rc = FAIL;
 
-/* Set the default SMTP code */
+/* Set the default SMTP code, and allow a user message to change it. */
 
 smtp_code = (rc != FAIL)? US"451" : acl_wherecodes[where];
 
 smtp_code = (rc != FAIL)? US"451" : acl_wherecodes[where];
-
-/* Check a user message for starting with a response code and optionally an
-extended status code. If found, check that the first digit is valid, and if so,
-use it instead of the default code. */
-
-if (user_msg != NULL)
-  {
-  int n = pcre_exec(regex_smtp_code, NULL, CS user_msg, Ustrlen(user_msg), 0,
-    PCRE_EOPT, ovector, sizeof(ovector)/sizeof(int));
-  if (n >= 0)
-    {
-    if (user_msg[0] != smtp_code[0])
-      {
-      log_write(0, LOG_MAIN|LOG_PANIC, "configured error code starts with "
-        "incorrect digit (expected %c) in \"%s\"", smtp_code[0], user_msg);
-
-      /* If log_msg == user_msg (the default set in acl.c if no log message is
-      specified, we must adjust the log message to show the code that is
-      actually going to be used. */
-
-      if (log_msg == user_msg)
-        log_msg = string_sprintf("%s %s", smtp_code, log_msg + ovector[1]);
-      }
-    else
-      {
-      smtp_code = user_msg;
-      codelen = ovector[1];    /* Includes final space */
-      }
-    user_msg += ovector[1];    /* Chop the code off the message */
-    }
-  }
+smtp_message_code(&smtp_code, &codelen, &user_msg, &log_msg);
 
 /* We used to have sender_address here; however, there was a bug that was not
 updating sender_address after a rewrite during a verify. When this bug was
 
 /* We used to have sender_address here; however, there was a bug that was not
 updating sender_address after a rewrite during a verify. When this bug was
@@ -2156,6 +2203,33 @@ return yield;
 
 
 
 
 
 
+/*************************************************
+*        Send user response message              *
+*************************************************/
+
+/* This function is passed a default response code and a user message. It calls
+smtp_message_code() to check and possibly modify the response code, and then
+calls smtp_respond() to transmit the response. I put this into a function
+just to avoid a lot of repetition.
+
+Arguments:
+  code         the response code
+  user_msg     the user message
+
+Returns:       nothing
+*/
+
+static void
+smtp_user_msg(uschar *code, uschar *user_msg)
+{
+int len = 3;
+smtp_message_code(&code, &len, &user_msg, NULL);
+smtp_respond(code, len, TRUE, user_msg);
+}
+
+
+
+
 /*************************************************
 *       Initialize for SMTP incoming message     *
 *************************************************/
 /*************************************************
 *       Initialize for SMTP incoming message     *
 *************************************************/
@@ -2226,7 +2300,8 @@ while (done <= 0)
   uschar *etrn_command;
   uschar *etrn_serialize_key;
   uschar *errmess;
   uschar *etrn_command;
   uschar *etrn_serialize_key;
   uschar *errmess;
-  uschar *user_msg, *log_msg;
+  uschar *log_msg, *smtp_code;
+  uschar *user_msg = NULL;
   uschar *recipient = NULL;
   uschar *hello = NULL;
   uschar *set_id = NULL;
   uschar *recipient = NULL;
   uschar *hello = NULL;
   uschar *set_id = NULL;
@@ -2563,26 +2638,11 @@ while (done <= 0)
         }
       }
 
         }
       }
 
-    /* The EHLO/HELO command is acceptable. Reset the protocol and the state,
-    abandoning any previous message. */
-
-    received_protocol = (esmtp?
-      protocols[pextend +
-        ((sender_host_authenticated != NULL)? pauthed : 0) +
-        ((tls_active >= 0)? pcrpted : 0)]
-      :
-      protocols[pnormal + ((tls_active >= 0)? pcrpted : 0)])
-      +
-      ((sender_host_address != NULL)? pnlocal : 0);
-
-    smtp_reset(reset_point);
-    toomany = FALSE;
-
-    /* Generate an OK reply, including the ident if present, and also
-    the IP address if present. Reflecting back the ident is intended
-    as a deterrent to mail forgers. For maximum efficiency, and also
-    because some broken systems expect each response to be in a single
-    packet, arrange that it is sent in one write(). */
+    /* Generate an OK reply. The default string includes the ident if present,
+    and also the IP address if present. Reflecting back the ident is intended
+    as a deterrent to mail forgers. For maximum efficiency, and also because
+    some broken systems expect each response to be in a single packet, arrange
+    that the entire reply is sent in one write(). */
 
     auth_advertised = FALSE;
     pipelining_advertised = FALSE;
 
     auth_advertised = FALSE;
     pipelining_advertised = FALSE;
@@ -2590,21 +2650,44 @@ while (done <= 0)
     tls_advertised = FALSE;
     #endif
 
     tls_advertised = FALSE;
     #endif
 
-    s = string_sprintf("250 %s Hello %s%s%s",
-      smtp_active_hostname,
-      (sender_ident == NULL)?  US"" : sender_ident,
-      (sender_ident == NULL)?  US"" : US" at ",
-      (sender_host_name == NULL)? sender_helo_name : sender_host_name);
+    smtp_code = US"250";        /* Default response code */
+    if (user_msg == NULL)
+      {
+      s = string_sprintf("%.3s %s Hello %s%s%s",
+        smtp_code,
+        smtp_active_hostname,
+        (sender_ident == NULL)?  US"" : sender_ident,
+        (sender_ident == NULL)?  US"" : US" at ",
+        (sender_host_name == NULL)? sender_helo_name : sender_host_name);
+
+      ptr = Ustrlen(s);
+      size = ptr + 1;
 
 
-    ptr = Ustrlen(s);
-    size = ptr + 1;
+      if (sender_host_address != NULL)
+        {
+        s = string_cat(s, &size, &ptr, US" [", 2);
+        s = string_cat(s, &size, &ptr, sender_host_address,
+          Ustrlen(sender_host_address));
+        s = string_cat(s, &size, &ptr, US"]", 1);
+        }
+      }
+
+    /* A user-supplied EHLO greeting may not contain more than one line */
 
 
-    if (sender_host_address != NULL)
+    else
       {
       {
-      s = string_cat(s, &size, &ptr, US" [", 2);
-      s = string_cat(s, &size, &ptr, sender_host_address,
-        Ustrlen(sender_host_address));
-      s = string_cat(s, &size, &ptr, US"]", 1);
+      char *ss;
+      int codelen = 3;
+      smtp_message_code(&smtp_code, &codelen, &user_msg, NULL);
+      s = string_sprintf("%.*s %s", codelen, smtp_code, user_msg);
+      if ((ss = strpbrk(CS s, "\r\n")) != NULL)
+        {
+        log_write(0, LOG_MAIN|LOG_PANIC, "EHLO/HELO response must not contain "
+          "newlines: message truncated: %s", string_printing(s));
+        *ss = 0;
+        }
+      ptr = Ustrlen(s);
+      size = ptr + 1;
       }
 
     s = string_cat(s, &size, &ptr, US"\r\n", 2);
       }
 
     s = string_cat(s, &size, &ptr, US"\r\n", 2);
@@ -2624,12 +2707,14 @@ while (done <= 0)
 
       if (thismessage_size_limit > 0)
         {
 
       if (thismessage_size_limit > 0)
         {
-        sprintf(CS big_buffer, "250-SIZE %d\r\n", thismessage_size_limit);
+        sprintf(CS big_buffer, "%.3s-SIZE %d\r\n", smtp_code,
+          thismessage_size_limit);
         s = string_cat(s, &size, &ptr, big_buffer, Ustrlen(big_buffer));
         }
       else
         {
         s = string_cat(s, &size, &ptr, big_buffer, Ustrlen(big_buffer));
         }
       else
         {
-        s = string_cat(s, &size, &ptr, US"250-SIZE\r\n", 10);
+        s = string_cat(s, &size, &ptr, smtp_code, 3);
+        s = string_cat(s, &size, &ptr, US"-SIZE\r\n", 7);
         }
 
       /* Exim does not do protocol conversion or data conversion. It is 8-bit
         }
 
       /* Exim does not do protocol conversion or data conversion. It is 8-bit
@@ -2640,14 +2725,18 @@ while (done <= 0)
       provided as an option. */
 
       if (accept_8bitmime)
       provided as an option. */
 
       if (accept_8bitmime)
-        s = string_cat(s, &size, &ptr, US"250-8BITMIME\r\n", 14);
+        {
+        s = string_cat(s, &size, &ptr, smtp_code, 3);
+        s = string_cat(s, &size, &ptr, US"-8BITMIME\r\n", 11);
+        }
 
       /* Advertise ETRN if there's an ACL checking whether a host is
       permitted to issue it; a check is made when any host actually tries. */
 
       if (acl_smtp_etrn != NULL)
         {
 
       /* Advertise ETRN if there's an ACL checking whether a host is
       permitted to issue it; a check is made when any host actually tries. */
 
       if (acl_smtp_etrn != NULL)
         {
-        s = string_cat(s, &size, &ptr, US"250-ETRN\r\n", 10);
+        s = string_cat(s, &size, &ptr, smtp_code, 3);
+        s = string_cat(s, &size, &ptr, US"-ETRN\r\n", 7);
         }
 
       /* Advertise EXPN if there's an ACL checking whether a host is
         }
 
       /* Advertise EXPN if there's an ACL checking whether a host is
@@ -2655,7 +2744,8 @@ while (done <= 0)
 
       if (acl_smtp_expn != NULL)
         {
 
       if (acl_smtp_expn != NULL)
         {
-        s = string_cat(s, &size, &ptr, US"250-EXPN\r\n", 10);
+        s = string_cat(s, &size, &ptr, smtp_code, 3);
+        s = string_cat(s, &size, &ptr, US"-EXPN\r\n", 7);
         }
 
       /* Exim is quite happy with pipelining, so let the other end know that
         }
 
       /* Exim is quite happy with pipelining, so let the other end know that
@@ -2663,7 +2753,8 @@ while (done <= 0)
 
       if (verify_check_host(&pipelining_advertise_hosts) == OK)
         {
 
       if (verify_check_host(&pipelining_advertise_hosts) == OK)
         {
-        s = string_cat(s, &size, &ptr, US"250-PIPELINING\r\n", 16);
+        s = string_cat(s, &size, &ptr, smtp_code, 3);
+        s = string_cat(s, &size, &ptr, US"-PIPELINING\r\n", 13);
         sync_cmd_limit = NON_SYNC_CMD_PIPELINING;
         pipelining_advertised = TRUE;
         }
         sync_cmd_limit = NON_SYNC_CMD_PIPELINING;
         pipelining_advertised = TRUE;
         }
@@ -2693,7 +2784,8 @@ while (done <= 0)
               int saveptr;
               if (first)
                 {
               int saveptr;
               if (first)
                 {
-                s = string_cat(s, &size, &ptr, US"250-AUTH", 8);
+                s = string_cat(s, &size, &ptr, smtp_code, 3);
+                s = string_cat(s, &size, &ptr, US"-AUTH", 5);
                 first = FALSE;
                 auth_advertised = TRUE;
                 }
                 first = FALSE;
                 auth_advertised = TRUE;
                 }
@@ -2719,14 +2811,16 @@ while (done <= 0)
       if (tls_active < 0 &&
           verify_check_host(&tls_advertise_hosts) != FAIL)
         {
       if (tls_active < 0 &&
           verify_check_host(&tls_advertise_hosts) != FAIL)
         {
-        s = string_cat(s, &size, &ptr, US"250-STARTTLS\r\n", 14);
+        s = string_cat(s, &size, &ptr, smtp_code, 3);
+        s = string_cat(s, &size, &ptr, US"-STARTTLS\r\n", 11);
         tls_advertised = TRUE;
         }
       #endif
 
       /* Finish off the multiline reply with one that is always available. */
 
         tls_advertised = TRUE;
         }
       #endif
 
       /* Finish off the multiline reply with one that is always available. */
 
-      s = string_cat(s, &size, &ptr, US"250 HELP\r\n", 10);
+      s = string_cat(s, &size, &ptr, smtp_code, 3);
+      s = string_cat(s, &size, &ptr, US" HELP\r\n", 7);
       }
 
     /* Terminate the string (for debug), write it, and note that HELO/EHLO
       }
 
     /* Terminate the string (for debug), write it, and note that HELO/EHLO
@@ -2747,6 +2841,20 @@ while (done <= 0)
       debug_printf("SMTP>> %s", s);
       }
     helo_seen = TRUE;
       debug_printf("SMTP>> %s", s);
       }
     helo_seen = TRUE;
+
+    /* Reset the protocol and the state, abandoning any previous message. */
+
+    received_protocol = (esmtp?
+      protocols[pextend +
+        ((sender_host_authenticated != NULL)? pauthed : 0) +
+        ((tls_active >= 0)? pcrpted : 0)]
+      :
+      protocols[pnormal + ((tls_active >= 0)? pcrpted : 0)])
+      +
+      ((sender_host_address != NULL)? pnlocal : 0);
+
+    smtp_reset(reset_point);
+    toomany = FALSE;
     break;   /* HELO/EHLO */
 
 
     break;   /* HELO/EHLO */
 
 
@@ -3024,12 +3132,12 @@ while (done <= 0)
 
     if (rc == OK || rc == DISCARD)
       {
 
     if (rc == OK || rc == DISCARD)
       {
-      smtp_printf("250 OK\r\n");
+      if (user_msg == NULL) smtp_printf("250 OK\r\n");
+        else smtp_user_msg(US"250", user_msg);
       smtp_delay_rcpt = smtp_rlr_base;
       recipients_discarded = (rc == DISCARD);
       was_rej_mail = FALSE;
       }
       smtp_delay_rcpt = smtp_rlr_base;
       recipients_discarded = (rc == DISCARD);
       was_rej_mail = FALSE;
       }
-
     else
       {
       done = smtp_handle_acl_fail(ACL_WHERE_MAIL, rc, user_msg, log_msg);
     else
       {
       done = smtp_handle_acl_fail(ACL_WHERE_MAIL, rc, user_msg, log_msg);
@@ -3184,7 +3292,8 @@ while (done <= 0)
 
     if (rc == OK)
       {
 
     if (rc == OK)
       {
-      smtp_printf("250 Accepted\r\n");
+      if (user_msg == NULL) smtp_printf("250 Accepted\r\n");
+        else smtp_user_msg(US"250", user_msg);
       receive_add_recipient(recipient, -1);
       }
 
       receive_add_recipient(recipient, -1);
       }
 
@@ -3192,7 +3301,8 @@ while (done <= 0)
 
     else if (rc == DISCARD)
       {
 
     else if (rc == DISCARD)
       {
-      smtp_printf("250 Accepted\r\n");
+      if (user_msg == NULL) smtp_printf("250 Accepted\r\n");
+        else smtp_user_msg(US"250", user_msg);
       rcpt_fail_count++;
       discarded = TRUE;
       log_write(0, LOG_MAIN|LOG_REJECT, "%s F=<%s> rejected RCPT %s: "
       rcpt_fail_count++;
       discarded = TRUE;
       log_write(0, LOG_MAIN|LOG_REJECT, "%s F=<%s> rejected RCPT %s: "
@@ -3259,7 +3369,9 @@ while (done <= 0)
 
     if (rc == OK)
       {
 
     if (rc == OK)
       {
-      smtp_printf("354 Enter message, ending with \".\" on a line by itself\r\n");
+      if (user_msg == NULL)
+        smtp_printf("354 Enter message, ending with \".\" on a line by itself\r\n");
+      else smtp_user_msg(US"354", user_msg);
       done = 3;
       message_ended = END_NOTENDED;   /* Indicate in middle of data */
       }
       done = 3;
       message_ended = END_NOTENDED;   /* Indicate in middle of data */
       }
@@ -3461,12 +3573,11 @@ while (done <= 0)
         log_write(0, LOG_MAIN|LOG_PANIC, "ACL for QUIT returned ERROR: %s",
           log_msg);
       }
         log_write(0, LOG_MAIN|LOG_PANIC, "ACL for QUIT returned ERROR: %s",
           log_msg);
       }
-    else user_msg = NULL;
 
     if (user_msg == NULL)
       smtp_printf("221 %s closing connection\r\n", smtp_active_hostname);
     else
 
     if (user_msg == NULL)
       smtp_printf("221 %s closing connection\r\n", smtp_active_hostname);
     else
-      smtp_printf("221 %s\r\n", user_msg);
+      smtp_respond(US"221", 3, TRUE, user_msg);
 
     #ifdef SUPPORT_TLS
     tls_close(TRUE);
 
     #ifdef SUPPORT_TLS
     tls_close(TRUE);
@@ -3606,7 +3717,8 @@ while (done <= 0)
         debug_printf("ETRN command is: %s\n", etrn_command);
         debug_printf("ETRN command execution skipped\n");
         }
         debug_printf("ETRN command is: %s\n", etrn_command);
         debug_printf("ETRN command execution skipped\n");
         }
-      smtp_printf("250 OK\r\n");
+      if (user_msg == NULL) smtp_printf("250 OK\r\n");
+        else smtp_user_msg(US"250", user_msg);
       break;
       }
 
       break;
       }
 
@@ -3682,7 +3794,11 @@ while (done <= 0)
       smtp_printf("458 Unable to fork process\r\n");
       if (smtp_etrn_serialize) enq_end(etrn_serialize_key);
       }
       smtp_printf("458 Unable to fork process\r\n");
       if (smtp_etrn_serialize) enq_end(etrn_serialize_key);
       }
-    else smtp_printf("250 OK\r\n");
+    else
+      {
+      if (user_msg == NULL) smtp_printf("250 OK\r\n");
+        else smtp_user_msg(US"250", user_msg);
+      }
 
     signal(SIGCHLD, oldsignal);
     break;
 
     signal(SIGCHLD, oldsignal);
     break;
index be99eb00fa9b5d8841cd34a2be4203ed0904ccef..ac6d8f7e27ba958cff28cdf867dc9550afbd0607 100644 (file)
@@ -203,7 +203,7 @@ acl_56_56_56:
   accept
 
 acl_56_56_57:
   accept
 
 acl_56_56_57:
-  accept  message = denied by condition
+  accept  message = accepted by condition
           condition = ${substr_5:$local_part}
 
 acl_56_56_58:
           condition = ${substr_5:$local_part}
 
 acl_56_56_58:
diff --git a/test/confs/0546 b/test/confs/0546
new file mode 100644 (file)
index 0000000..736c126
--- /dev/null
@@ -0,0 +1,46 @@
+# Exim test configuration 0546
+
+HELO_MSG=One line
+RCPT_MSG=RCPT is OK
+
+exim_path = EXIM_PATH
+host_lookup_order = bydns
+rfc1413_query_timeout = 0s
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+
+# ----- Main settings -----
+
+acl_smtp_helo = check_helo
+acl_smtp_mail = check_mail
+acl_smtp_rcpt = check_rcpt
+acl_smtp_data = check_data
+acl_smtp_predata = check_predata
+
+qualify_domain = test.ex
+queue_only
+
+
+# ----- ACLs -----
+
+begin acl
+
+check_helo:
+  accept     message = HELO_MSG
+
+check_mail:
+  accept     message = 299 MAIL is\nOK
+
+check_rcpt:
+  accept     message = RCPT_MSG
+
+check_data:
+  accept     message = 288 I like the data
+
+check_predata:
+  accept     message = 300 Funny, but OK code
+
+
+# End
diff --git a/test/log/0546 b/test/log/0546
new file mode 100644 (file)
index 0000000..f1b6d35
--- /dev/null
@@ -0,0 +1,3 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@test.ex U=CALLER P=local-esmtp S=sss
+1999-03-02 09:44:33 EHLO/HELO response must not contain newlines: message truncated: 250 Two\nlines
+1999-03-02 09:44:33 configured error code starts with incorrect digit (expected 2) in "450 Bad number"
diff --git a/test/paniclog/0546 b/test/paniclog/0546
new file mode 100644 (file)
index 0000000..e21dfb1
--- /dev/null
@@ -0,0 +1,2 @@
+1999-03-02 09:44:33 EHLO/HELO response must not contain newlines: message truncated: 250 Two\nlines
+1999-03-02 09:44:33 configured error code starts with incorrect digit (expected 2) in "450 Bad number"
index a169d1550ad73f63ab54f2e3d6cd844f720beeb1..aee2697adcff1b0421d795fcfedf4dbc89c60ad2 100755 (executable)
@@ -1,6 +1,6 @@
 #! /usr/bin/perl -w
 
 #! /usr/bin/perl -w
 
-# $Cambridge: exim/test/runtest,v 1.18 2006/11/07 15:11:34 ph10 Exp $
+# $Cambridge: exim/test/runtest,v 1.19 2006/11/14 16:40:36 ph10 Exp $
 
 ###############################################################################
 # This is the controlling script for the "new" test suite for Exim. It should #
 
 ###############################################################################
 # This is the controlling script for the "new" test suite for Exim. It should #
@@ -1514,7 +1514,7 @@ if (/^server\s+(.*)$/)
   # This gives the server time to get started; otherwise the next
   # process may not find it there when it expects it.
 
   # This gives the server time to get started; otherwise the next
   # process may not find it there when it expects it.
 
-  select(undef, undef, undef, 0.05);
+  select(undef, undef, undef, 0.5);
   return 3;
   }
 
   return 3;
   }
 
diff --git a/test/scripts/0000-Basic/0546 b/test/scripts/0000-Basic/0546
new file mode 100644 (file)
index 0000000..1486d35
--- /dev/null
@@ -0,0 +1,19 @@
+# User messages for "accept" verbs
+need_ipv4
+#
+exim -bs
+ehlo a.b.c
+mail from:<>
+rcpt to:<userx@test.ex>
+data
+This is a test
+.
+quit
+****
+exim -bs -DHELO_MSG='Two\nlines' -DRCPT_MSG='450 Bad number'
+ehlo a.b.c
+mail from:<>
+rcpt to:<userx@test.ex>
+quit
+****
+no_msglog_check
diff --git a/test/stderr/0546 b/test/stderr/0546
new file mode 100644 (file)
index 0000000..e21dfb1
--- /dev/null
@@ -0,0 +1,2 @@
+1999-03-02 09:44:33 EHLO/HELO response must not contain newlines: message truncated: 250 Two\nlines
+1999-03-02 09:44:33 configured error code starts with incorrect digit (expected 2) in "450 Bad number"
index e7eb769ee0c3624a4c4e1978bf17951dd96988bc..266184af0a6406216504cbf784c90a3e45dab721 100644 (file)
 221 myhost.test.ex closing connection\r
 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
 250 OK\r
 221 myhost.test.ex closing connection\r
 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
 250 OK\r
-250 Accepted\r
+250 accepted by condition\r
 354 Enter message, ending with "." on a line by itself\r
 250 OK id=10HmbK-0005vi-00\r
 250 OK\r
 354 Enter message, ending with "." on a line by itself\r
 250 OK id=10HmbK-0005vi-00\r
 250 OK\r
diff --git a/test/stdout/0546 b/test/stdout/0546
new file mode 100644 (file)
index 0000000..0865c5f
--- /dev/null
@@ -0,0 +1,20 @@
+220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250-One line\r
+250-SIZE 52428800\r
+250-PIPELINING\r
+250 HELP\r
+299-MAIL is\r
+299 OK\r
+250 RCPT is OK\r
+300 Funny, but OK code\r
+288 I like the data\r
+221 the.local.host.name closing connection\r
+220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250-Two\r
+250-SIZE 52428800\r
+250-PIPELINING\r
+250 HELP\r
+299-MAIL is\r
+299 OK\r
+250 Bad number\r
+221 the.local.host.name closing connection\r