You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by "Prucha, Brett A" <Br...@scrb.navy.mil> on 2004/12/15 15:37:50 UTC

RE: [PATCH] Python mailer hook script for Windows (2nd attempt)

A patch for tools/hook-scripts/mailer/mailer.py adding os specific cases so it will work for Windows

* If the subject line is longer than 200 characters truncate the subject
  and add ... to the end.  Exchange server was not sending out the email
  because the subject line was too long.
* Added windows specific cases for SMTPOutput, StandardOutput and
  PipeOutput.  The PipeOutput was tested using IndigoMail
  (http://www.indigostar.com/sendmail.htm) where mail_command in the conf
  file was "sendmail.exe -t"

The mailer_orig.py is based off of the 1.1.1 release source code located in the downloaded zip file at subversion-1.1.1\tools\hook-scripts\mailer\mailer.py

=========================================================================
--- mailer_orig.py	Mon Aug 09 17:32:32 2004
+++ mailer.py	Wed Dec 15 10:31:39 2004
@@ -48,6 +48,13 @@
 
   messenger.generate()
 
+if sys.platform == "win32":
+  def escape_shell_arg(str):
+    str = string.replace(str, '"', '"^""')
+    if re.search("[ ,\t]", str) != None:
+      return "\"" + str + "\""
+    else:
+      return str
 
 class MailedOutput:
   def __init__(self, cfg, repos, prefix_param):
@@ -69,6 +76,8 @@
       subject = prefix + ' ' + self.subject
     else:
       subject = self.subject
+    if len(subject) > 200:
+      subject = subject[:197] + "..."
     hdrs = 'From: %s\n'    \
            'To: %s\n'      \
            'Subject: %s\n' \
@@ -94,11 +103,16 @@
   def run(self, cmd):
     # we're holding everything in memory, so we may as well read the
     # entire diff into memory and stash that into the buffer
-    pipe_ob = popen2.Popen3(cmd)
-    self.write(pipe_ob.fromchild.read())
+    if sys.platform == "win32":
+      cmd = string.join(map(escape_shell_arg, cmd))
+      ps = os.popen(cmd)
+      self.write(ps.read())
+    else:
+      pipe_ob = popen2.Popen3(cmd)
+      self.write(pipe_ob.fromchild.read())
 
-    # wait on the child so we don't end up with a billion zombies
-    pipe_ob.wait()
+      # wait on the child so we don't end up with a billion zombies
+      pipe_ob.wait()
 
   def finish(self):
     server = smtplib.SMTP(self.cfg.general.smtp_hostname)
@@ -129,19 +143,23 @@
     sys.stdout.flush()
     sys.stderr.flush()
 
-    # we can simply fork and exec the diff, letting it generate all the
-    # output to our stdout (and stderr, if necessary).
-    pid = os.fork()
-    if pid:
-      # in the parent. we simply want to wait for the child to finish.
-      ### should we deal with the return values?
-      os.waitpid(pid, 0)
+    if sys.platform == "win32":
+      cmd = string.join(map(escape_shell_arg, cmd))
+      ps = os.popen(cmd)
     else:
-      # in the child. run the diff command.
-      try:
-        os.execvp(cmd[0], cmd)
-      finally:
-        os._exit(1)
+      # we can simply fork and exec the diff, letting it generate all the
+      # output to our stdout (and stderr, if necessary).
+      pid = os.fork()
+      if pid:
+        # in the parent. we simply want to wait for the child to finish.
+        ### should we deal with the return values?
+        os.waitpid(pid, 0)
+      else:
+        # in the child. run the diff command.
+        try:
+          os.execvp(cmd[0], cmd)
+        finally:
+          os._exit(1)
 
 
 class PipeOutput(MailedOutput):
@@ -153,8 +171,9 @@
     # figure out the command for delivery
     self.cmd = string.split(cfg.general.mail_command)
 
-    # we want a descriptor to /dev/null for hooking up to the diffs' stdin
-    self.null = os.open('/dev/null', os.O_RDONLY)
+    if sys.platform != "win32":
+      # we want a descriptor to /dev/null for hooking up to the diffs' stdin
+      self.null = os.open('/dev/null', os.O_RDONLY)
 
   def start(self, group, params, **args):
     MailedOutput.start(self, group, params, **args)
@@ -163,17 +182,28 @@
     ### mailwrapper program. should be able to use option param substitution
     cmd = self.cmd + [ '-f', self.from_addr ] + self.to_addrs
 
-    # construct the pipe for talking to the mailer
-    self.pipe = popen2.Popen3(cmd)
-    self.write = self.pipe.tochild.write
+    if sys.platform == "win32":
+      cmd = string.join(map(escape_shell_arg, cmd))
+      self.pipe = os.popen(cmd, 'w')
+      self.write = self.pipe.write
+    else:
+      # construct the pipe for talking to the mailer
+      self.pipe = popen2.Popen3(cmd)
+      self.write = self.pipe.tochild.write
 
-    # we don't need the read-from-mailer descriptor, so close it
-    self.pipe.fromchild.close()
+      # we don't need the read-from-mailer descriptor, so close it
+      self.pipe.fromchild.close()
 
     # start writing out the mail message
     self.write(self.mail_headers(group, params))
 
   def run(self, cmd):
+    if sys.platform == "win32":
+      cmd = string.join(map(escape_shell_arg, cmd))
+      ps = os.popen(cmd)
+      self.write(ps.read())
+      return
+
     # flush the buffers that write to the mailer. we're about to fork, and
     # we don't want data sitting in both copies of the buffer. we also
     # want to ensure the parts are delivered to the mailer in the right order.
@@ -207,11 +237,14 @@
       os._exit(1)
 
   def finish(self):
-    # signal that we're done sending content
-    self.pipe.tochild.close()
+    if sys.platform == "win32":
+    	self.pipe.close()
+    else:
+      # signal that we're done sending content
+      self.pipe.tochild.close()
 
-    # wait to avoid zombies
-    self.pipe.wait()
+      # wait to avoid zombies
+      self.pipe.wait()
 
 
 class Messenger:

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org


Re: [PATCH] Python mailer hook script for Windows (2nd attempt)

Posted by Branko Čibej <br...@xbc.nu>.
Prucha, Brett A wrote:

>A patch for tools/hook-scripts/mailer/mailer.py adding os specific cases so it will work for Windows
>
>* If the subject line is longer than 200 characters truncate the subject
>  and add ... to the end.  Exchange server was not sending out the email
>  because the subject line was too long.
>* Added windows specific cases for SMTPOutput, StandardOutput and
>  PipeOutput.  The PipeOutput was tested using IndigoMail
>  (http://www.indigostar.com/sendmail.htm) where mail_command in the conf
>  file was "sendmail.exe -t"
>  
>
Actually, I'd just forbid piping to any kind of sendmail program on 
Windows. You don't need it, since you can use Python's mail class and 
use SMTP (even if you do use some kind of sendmail clone, you can SMTP 
to localhost).

Looking at the patch below, the number of "if ...win32" tests gives me 
the shudders.
-1, all those conditionals can be avoided if you use an OS-specific 
helper class.

>+if sys.platform == "win32":
>+  def escape_shell_arg(str):
>+    str = string.replace(str, '"', '"^""')
>+    if re.search("[ ,\t]", str) != None:
>  
>
Wha's that comma doing in the regular expression pattern? Why would you 
quote parameters that contain a comma?

>+      return "\"" + str + "\""
>+    else:
>+      return str
>  
>

-- Brane

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org