minor tweak to make the last patch actually land...
[attachcheck] / attachcheck
old mode 100644 (file)
new mode 100755 (executable)
index ebcd6be..19159e4
@@ -1,22 +1,32 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 # AttachCheck -- A MTA wrapper to help check outgoing email for
 # forgotten attachments.
 
-# (c) 2005 -- Benjamin Mako Hill <mako@bork.hampshire.edu>
-# Author/Software Homepage at: http://mako.cc
+# (c) 2004-2009 -- Benjamin Mako Hill <mako@atdot.cc>
+# Software Homepage at: http://mako.cc/projects/attachcheck
 
-# This software comes with ABSOLUTELY NO WARRANTY.
-# This is free software and is licensed under the GNU GPL.
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or (at
+# your option) any later version.
 
-__copyright__ = "Copyright (c) 2004 Benjamin Mako Hill"
-__author__ = "Benjamin Mako Hill <mako@debian.org>" 
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+__copyright__ = "Copyright (c) 2004-2009 Benjamin Mako Hill"
+__author__ = "Benjamin Mako Hill <mako@atdot.cc>" 
 
 ### Configuration Options
 ###########################################
 
 # location of the sendmail binary
-sendmail = "/usr/sbin/sendmail -oi"
+sendmail = "/usr/sbin/sendmail"
 
 # list of mimetype which are, for the sake of this program, not
 # attachments
@@ -24,9 +34,11 @@ ignored_types = ( "applica/pgp-signat", "application/pgp-signature" )
 
 # list of regular expressions which we will view as being indicative
 # of an attachment
-attachment_regexes = [ r'\battach(ed|ment|ing)?\b(?im)',
+attachment_regexes = [ r'\battach(ed|ment|ing)?\b',
                        r'\balleg(o|at[oaie]|ando)' ]
 
+# ignore quoted text (which might refer to attachments in previous emails)
+attachment_regexes = [ r'(?im)(^|^[^\n>].*)' + x for x in attachment_regexes ]
 
 ### No Edit Below This Line
 ###########################################
@@ -37,18 +49,24 @@ import email
 import re
 
 ## SUB: send message
-def send_message(): 
+def send_message(message):
 
     global sendmail
-    sendmail = sendmail + " " + " ".join( sys.argv[1:] )
-   
-    mailpipe = os.popen("%s -t" % sendmail_with_args, 'w')
-    mailpipe.write( message_string )
-    sys.exit( mailpipe.close() )
+
+    # construct the sendmail pipe more safely (thanks iain murray!)
+    cmd = sys.argv[:]
+    cmd[0] = sendmail
+
+    from subprocess import Popen, PIPE
+    process = Popen(cmd, stdin=PIPE)
+    mailpipe = process.stdin
+    mailpipe.write( message.as_string().encode() )
+    mailpipe.close()
+    sys.exit( process.wait() )
 
 ## SUB: print error message
 def print_error():
-    print >>sys.stderr, \
+    print(\
 """(Your message mentions attachments but does not include any.
 
 Either:
@@ -60,11 +78,11 @@ Either:
 
  (2) Add a \"X-AttachCheck-Override: Yes\" header the message.
 
-Read the documentation for AttachCheck for more details."""
+Read the documentation for AttachCheck for more details.""", file=sys.stderr)
     
 # get the mail from stdin
-message_string = sys.stdin.read()
-message = email.message_from_string( message_string )
+message_bytes = sys.stdin.buffer.read()
+message = email.message_from_bytes( message_bytes )
 
 attachment_expected = False
 attachment_seen = False
@@ -91,8 +109,8 @@ for part in message.walk():
                 attachment_expected = True
 
     # check to see if this mime-type is something we can ignore
-    elif ( re.match( r'message/(?m)', part.get_content_type() ) or
-           re.match( r'multipart/(?m)', part.get_content_type() ) or
+    elif ( re.match( r'(?m)message/', part.get_content_type() ) or
+           re.match( r'(?m)multipart/', part.get_content_type() ) or
            part.get_content_type() in ignored_types ):
         continue
 
@@ -106,21 +124,22 @@ if attachment_expected:
     # if we are expecting an attachment and we've seen one, we should
     # send the file and be done with things
     if attachment_seen:
-        send_message()
+        send_message(message)
 
     # if we are expected have not seen it, we need to check to see if
     # the mail has been confirmed
 
     else:
         # check for the confirmation
-
-        if re.search( r'Subject: CONFIRM', message_string ):
-            message_string = re.sub( r'(Subject: )(CONFIRM )(.*?)\n',
-                                     r'\1\3\n', message_string )
-            send_message()
-
-        elif message.get( 'X-AttachCheck-Override' ) == "Yes":
-            send_message()
+        subject_string = message['Subject']
+        print(subject_string)
+        if re.search( r'^\s*CONFIRM', subject_string ):
+            subject_string = re.sub( r'(CONFIRM )(.*?)', r'\2', subject_string )
+            message['Subject'] = subject_string
+            send_message(message)
+
+        elif message['X-AttachCheck-Override'] == "Yes":
+            send_message(message)
             
         else:
             print_error()
@@ -129,4 +148,4 @@ if attachment_expected:
 
 # if we are not expecting anything more, we should send the message
 else:
-    send_message()
+    send_message(message)

Benjamin Mako Hill || Want to submit a patch?