[exim-cvs] Support moving messages across named queues. Bug…

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] Support moving messages across named queues. Bug 2456
Gitweb: https://git.exim.org/exim.git/commitdiff/fc7bae7f2fa3668ada9bd173e9f24c7166e1dd13
Commit:     fc7bae7f2fa3668ada9bd173e9f24c7166e1dd13
Parent:     444163417b289354b53d4708760f31d947ac6fd1
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Thu Oct 24 23:34:19 2019 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Fri Oct 25 00:55:45 2019 +0100


    Support moving messages across named queues.  Bug 2456
---
 doc/doc-docbook/spec.xfpt    | 14 ++++++++++++++
 doc/doc-txt/NewStuff         |  2 ++
 src/src/exim.c               | 25 ++++++++++++++-----------
 src/src/functions.h          | 21 +++++++++++++++++----
 src/src/globals.c            |  1 +
 src/src/globals.h            |  1 +
 src/src/macros.h             |  2 +-
 src/src/queue.c              |  8 ++++++++
 src/src/spool_out.c          | 26 ++++++++++++++++----------
 test/log/0576                |  8 ++++++++
 test/runtest                 | 17 ++++++++++++++++-
 test/scripts/0000-Basic/0576 | 40 ++++++++++++++++++++++++++++++++++++++++
 test/stdout/0576             | 29 +++++++++++++++++++++++++++++
 13 files changed, 167 insertions(+), 27 deletions(-)


diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 4fa87ff..7cd3e86 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -3963,6 +3963,20 @@ is sent to the sender, containing the text &"cancelled by administrator"&.
Bounce messages are just discarded. This option can be used only by an admin
user.

+.new
+.vitem &%-MG%&&~<&'queue&~name'&&~<&'message&~id'&>&~<&'message&~id'&>&~...
+.oindex "&%-MG%&"
+.cindex queue named
+.cindex "named queues"
+.cindex "queue" "moving messages"
+This option requests that each listed message be moved from its current
+queue to the given named queue.
+The destination queue name argument is required, but can be an empty
+string to define the default queue.
+If the messages are not currently located in the default queue,
+a &%-qG<name>%& option will be required to define the source queue.
+.wen
+
 .vitem &%-Mmad%&&~<&'message&~id'&>&~<&'message&~id'&>&~...
 .oindex "&%-Mmad%&"
 .cindex "delivery" "cancelling all"
diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index 7317696..5d0c8bd 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -48,6 +48,8 @@ Version 4.93
     GnuTLS was already there, being done purely by the library (server side
     only, and exim must be run as root).


+16: Command-line option to move messages from one named queue to another.
+

 Version 4.92
 --------------
diff --git a/src/src/exim.c b/src/src/exim.c
index 2b6297b..3290d63 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -2787,6 +2787,11 @@ for (i = 1; i < argc; i++)
       msg_action = MSG_DELIVER;
       deliver_give_up = TRUE;
       }
+   else if (Ustrcmp(argrest, "G") == 0)
+      {
+      msg_action = MSG_SETQUEUE;
+      queue_name_dest = argv[++i];
+      }
     else if (Ustrcmp(argrest, "mad") == 0)
       {
       msg_action = MSG_MARK_ALL_DELIVERED;
@@ -4064,11 +4069,13 @@ count. Only an admin user can use the test interface to scan for email
 if (!f.admin_user)
   {
   BOOL debugset = (debug_selector & ~D_v) != 0;
-  if (deliver_give_up || f.daemon_listen || malware_test_file ||
-     (count_queue && queue_list_requires_admin) ||
-     (list_queue && queue_list_requires_admin) ||
-     (queue_interval >= 0 && prod_requires_admin) ||
-     (debugset && !f.running_in_test_harness))
+  if (  deliver_give_up || f.daemon_listen || malware_test_file
+     || count_queue && queue_list_requires_admin
+     || list_queue && queue_list_requires_admin
+     || queue_interval >= 0 && prod_requires_admin
+     || queue_name_dest && prod_requires_admin
+     || debugset && !f.running_in_test_harness
+     )
     exim_fail("exim:%s permission denied\n", debugset? " debugging" : "");
   }


@@ -4165,13 +4172,9 @@ now for those OS that require the first call to os_getloadavg() to be done as
root. There will be further calls later for each message received. */

 #ifdef LOAD_AVG_NEEDS_ROOT
-if (receiving_message &&
-      (queue_only_load >= 0 ||
-        (f.is_inetd && smtp_load_reserve >= 0)
-      ))
-  {
+if (  receiving_message
+   && (queue_only_load >= 0 || (f.is_inetd && smtp_load_reserve >= 0)))
   load_average = OS_GETLOADAVG();
-  }
 #endif


/* The queue_only configuration option can be overridden by -odx on the command
diff --git a/src/src/functions.h b/src/src/functions.h
index 8905d02..3b3a12b 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -878,20 +878,33 @@ return string_sprintf("%s/%s/%s/%s",
# endif

 static inline uschar *
-spool_sname(const uschar * purpose, uschar * subdir)
+spool_q_sname(const uschar * purpose, const uschar * q, uschar * subdir)
 {
 return string_sprintf("%s%s%s%s%s",
-            queue_name, *queue_name ? "/" : "",
+            q, *q ? "/" : "",
             purpose,
             *subdir ? "/" : "", subdir);
 }


 static inline uschar *
+spool_sname(const uschar * purpose, uschar * subdir)
+{
+return spool_q_sname(purpose, queue_name, subdir);
+}
+
+static inline uschar *
+spool_q_fname(const uschar * purpose, const uschar * q,
+    const uschar * subdir, const uschar * fname, const uschar * suffix)
+{
+return string_sprintf("%s/%s/%s/%s/%s%s",
+    spool_directory, q, purpose, subdir, fname, suffix);
+}
+
+static inline uschar *
 spool_fname(const uschar * purpose, const uschar * subdir, const uschar * fname,
            const uschar * suffix)
 {
-return string_sprintf("%s/%s/%s/%s/%s%s",
-    spool_directory, queue_name, purpose, subdir, fname, suffix);
+return spool_q_fname(purpose, queue_name, subdir, fname, suffix);
 }


 static inline void
diff --git a/src/src/globals.c b/src/src/globals.c
index 677c03e..07665bf 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -1194,6 +1194,7 @@ uschar *qualify_domain_sender  = NULL;
 uschar *queue_domains          = NULL;
 int     queue_interval         = -1;
 uschar *queue_name             = US"";
+uschar *queue_name_dest        = NULL;
 uschar *queue_only_file        = NULL;
 int     queue_only_load        = -1;
 uschar *queue_run_max          = US"5";
diff --git a/src/src/globals.h b/src/src/globals.h
index e4725a7..0466da5 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -787,6 +787,7 @@ extern pid_t   queue_run_pid;          /* PID of the queue running process or 0
 extern int     queue_run_pipe;         /* Pipe for synchronizing */
 extern int     queue_interval;         /* Queue running interval */
 extern uschar *queue_name;             /* Name of queue, if nondefault spooling */
+extern uschar *queue_name_dest;           /* Destination queue, for moving messages */
 extern BOOL    queue_only;             /* TRUE to disable immediate delivery */
 extern int     queue_only_load;        /* Max load before auto-queue */
 extern BOOL    queue_only_load_latch;  /* Latch queue_only_load TRUE */
diff --git a/src/src/macros.h b/src/src/macros.h
index e36c09c..76913d6 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -845,7 +845,7 @@ enum {


 enum { MSG_DELIVER, MSG_FREEZE, MSG_REMOVE, MSG_THAW, MSG_ADD_RECIPIENT,
        MSG_MARK_ALL_DELIVERED, MSG_MARK_DELIVERED, MSG_EDIT_SENDER,
-       MSG_SHOW_COPY, MSG_LOAD,
+       MSG_SHOW_COPY, MSG_LOAD, MSG_SETQUEUE,
        /* These ones must be last: a test for >= MSG_SHOW_BODY is used
        to test for actions that list individual spool files. */
        MSG_SHOW_BODY, MSG_SHOW_HEADER, MSG_SHOW_LOG };
diff --git a/src/src/queue.c b/src/src/queue.c
index 670f51c..d9ff133 100644
--- a/src/src/queue.c
+++ b/src/src/queue.c
@@ -1265,6 +1265,14 @@ switch(action)
     }



+  case MSG_SETQUEUE:
+    /* The global "queue_name_dest" is used as destination, "queue_name"
+    as source */
+
+    spool_move_message(id, message_subdir, US"", US"");
+    break;
+
+
   case MSG_MARK_ALL_DELIVERED:
   for (int i = 0; i < recipients_count; i++)
     tree_add_nonrecipient(recipients_list[i].address);
diff --git a/src/src/spool_out.c b/src/src/spool_out.c
index acc6c7b..463961f 100644
--- a/src/src/spool_out.c
+++ b/src/src/spool_out.c
@@ -417,6 +417,7 @@ start-up time.


 Arguments:
   dir        base directory name
+  dq         destiinationqueue name
   subdir     subdirectory name
   id         message id
   suffix     suffix to add to id
@@ -429,11 +430,11 @@ Returns:     TRUE if all went well
 */


 static BOOL
-make_link(uschar *dir, uschar *subdir, uschar *id, uschar *suffix, uschar *from,
-  uschar *to, BOOL noentok)
+make_link(uschar *dir, uschar * dq, uschar *subdir, uschar *id, uschar *suffix,
+  uschar *from, uschar *to, BOOL noentok)
 {
 uschar * fname = spool_fname(string_sprintf("%s%s", from, dir), subdir, id, suffix);
-uschar * tname = spool_fname(string_sprintf("%s%s", to,   dir), subdir, id, suffix);
+uschar * tname = spool_q_fname(string_sprintf("%s%s", to,   dir), dq, subdir, id, suffix);
 if (Ulink(fname, tname) < 0 && (!noentok || errno != ENOENT))
   {
   log_write(0, LOG_MAIN|LOG_PANIC, "link(\"%s\", \"%s\") failed while moving "
@@ -503,13 +504,15 @@ Returns:      TRUE if all is well
 BOOL
 spool_move_message(uschar *id, uschar *subdir, uschar *from, uschar *to)
 {
+uschar * dest_qname = queue_name_dest ? queue_name_dest : queue_name;
+
 /* Create any output directories that do not exist. */


(void) directory_make(spool_directory,
- spool_sname(string_sprintf("%sinput", to), subdir),
+ spool_q_sname(string_sprintf("%sinput", to), dest_qname, subdir),
INPUT_DIRECTORY_MODE, TRUE);
(void) directory_make(spool_directory,
- spool_sname(string_sprintf("%smsglog", to), subdir),
+ spool_q_sname(string_sprintf("%smsglog", to), dest_qname, subdir),
INPUT_DIRECTORY_MODE, TRUE);

/* Move the message by first creating new hard links for all the files, and
@@ -521,9 +524,9 @@ rule of waiting for a -H file before doing anything. When moving messages off
the mail spool, the -D file should be open and locked at the time, thus keeping
Exim's hands off. */

-if (!make_link(US"msglog", subdir, id, US"", from, to, TRUE) ||
-    !make_link(US"input",  subdir, id, US"-D", from, to, FALSE) ||
-    !make_link(US"input",  subdir, id, US"-H", from, to, FALSE))
+if (!make_link(US"msglog", dest_qname, subdir, id, US"", from, to, TRUE) ||
+    !make_link(US"input",  dest_qname, subdir, id, US"-D", from, to, FALSE) ||
+    !make_link(US"input",  dest_qname, subdir, id, US"-H", from, to, FALSE))
   return FALSE;


 if (!break_link(US"input",  subdir, id, US"-H", from, FALSE) ||
@@ -531,8 +534,11 @@ if (!break_link(US"input",  subdir, id, US"-H", from, FALSE) ||
     !break_link(US"msglog", subdir, id, US"", from, TRUE))
   return FALSE;


-log_write(0, LOG_MAIN, "moved from %sinput, %smsglog to %sinput, %smsglog",
- from, from, to, to);
+log_write(0, LOG_MAIN, "moved from %s%s%s%sinput, %smsglog to %s%s%s%sinput, %smsglog",
+ *queue_name?"(":"", *queue_name?queue_name:US"", *queue_name?") ":"",
+ from, from,
+ *dest_qname?"(":"", *dest_qname?dest_qname:US"", *dest_qname?") ":"",
+ to, to);

return TRUE;
}
diff --git a/test/log/0576 b/test/log/0576
index 8c1cb73..246b105 100644
--- a/test/log/0576
+++ b/test/log/0576
@@ -20,6 +20,14 @@
1999-03-02 09:44:33 10HmbA-0005vi-00 => alternate <alternate@???> F=<CALLER@???> R=all T=dump
1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
1999-03-02 09:44:33 End queue run: pid=pppp
+1999-03-02 09:44:33 using queue ''
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@??? U=CALLER P=local-smtp S=sss for normal@???
+1999-03-02 09:44:33 using queue 'alternate'
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@??? U=CALLER P=local-smtp S=sss Q=alternate for alternate@???
+1999-03-02 09:44:33 10HmbB-0005vi-00 moved from input, msglog to (third) input, msglog
+1999-03-02 09:44:33 10HmbC-0005vi-00 moved from (alternate) input, msglog to (third) input, msglog
+1999-03-02 09:44:33 10HmbB-0005vi-00 moved from (third) input, msglog to input, msglog
+1999-03-02 09:44:33 10HmbC-0005vi-00 moved from (third) input, msglog to input, msglog

******** SERVER ********
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, -qGlowpri/3s, not listening for SMTP
diff --git a/test/runtest b/test/runtest
index 0d6bcd1..db855ba 100755
--- a/test/runtest
+++ b/test/runtest
@@ -2546,9 +2546,24 @@ elsif (/^((?i:[A-Z\d_]+=\S+\s+)+)?(\d+)?\s*(sudo(?:\s+-u\s+(\w+))?\s+)?exim(_\S+

   if ($args =~ /\$msg/)
     {
-    my @listcmd  = ("$parm_cwd/eximdir/exim", '-bp',
+    my($queuespec);
+    if ($args =~ /-qG\w+/) { $queuespec = $&; }
+
+    my @listcmd;
+
+    if (defined $queuespec)
+      {
+      @listcmd  = ("$parm_cwd/eximdir/exim", '-bp',
+           $queuespec,
                    "-DEXIM_PATH=$parm_cwd/eximdir/exim",
                    -C => "$parm_cwd/test-config");
+      }
+    else
+      {
+      @listcmd  = ("$parm_cwd/eximdir/exim", '-bp',
+                   "-DEXIM_PATH=$parm_cwd/eximdir/exim",
+                   -C => "$parm_cwd/test-config");
+      }
     print ">> Getting queue list from:\n>>    @listcmd\n" if $debug;
     # We need the message ids sorted in ascending order.
     # Message id is: <timestamp>-<pid>-<fractional-time>. On some systems (*BSD) the
diff --git a/test/scripts/0000-Basic/0576 b/test/scripts/0000-Basic/0576
index dedc73d..becd160 100644
--- a/test/scripts/0000-Basic/0576
+++ b/test/scripts/0000-Basic/0576
@@ -72,4 +72,44 @@ sudo mv DIR/spool/alternate/input/* DIR/spool/input/
 exim -q
 ****
 #
+#
+# Native queue transfer
+exim -bs
+MAIL FROM:<CALLER@???>
+RCPT TO: <normal@???>
+DATA
+Subject: test
+
+foo
+.
+RSET
+MAIL FROM:<CALLER@???>
+RCPT TO: <alternate@???>
+DATA
+Subject: test
+
+foo
+.
+QUIT
+****
+exim -bp
+****
+exim -bp -qGalternate
+****
+#
+exim -MG third $msg1
+****
+exim -qGalternate -MG third $msg1
+****
+exim -bp -qGthird
+****
+exim -qGthird -MG '' $msg1 $msg2
+****
+exim -bp
+****
+exim -bp -qGalternate
+****
+exim -bp -qGthird
+****
+#
 no_stderr_check
diff --git a/test/stdout/0576 b/test/stdout/0576
index a15ecdd..91c57a2 100644
--- a/test/stdout/0576
+++ b/test/stdout/0576
@@ -29,6 +29,35 @@
 354 Enter message, ending with "." on a line by itself
 250 OK id=10HmbA-0005vi-00
 221 the.local.host.name closing connection
+220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250 OK
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmbB-0005vi-00
+250 Reset OK
+250 OK
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmbC-0005vi-00
+221 the.local.host.name closing connection
+ 0m   sss 10HmbB-0005vi-00 <CALLER@???>
+          normal@???
+
+ 0m   sss 10HmbC-0005vi-00 <CALLER@???>
+          alternate@???
+
+Message 10HmbB-0005vi-00 Message 10HmbC-0005vi-00  0m   323 10HmbB-0005vi-00 <CALLER@???>
+          normal@???
+
+ 0m   sss 10HmbC-0005vi-00 <CALLER@???>
+          alternate@???
+
+Message 10HmbB-0005vi-00 Message 10HmbC-0005vi-00  0m   323 10HmbB-0005vi-00 <CALLER@???>
+          normal@???
+
+ 0m   sss 10HmbC-0005vi-00 <CALLER@???>
+          alternate@???
+


******** SERVER ********
### default q