First import into BZR of attachment checker. tmp
author<mako@bork.hampshire.edu> <>
Sun, 3 Jul 2005 10:00:18 +0000 (06:00 -0400)
committer<mako@bork.hampshire.edu> <>
Sun, 3 Jul 2005 10:00:18 +0000 (06:00 -0400)
attachment_checker [new file with mode: 0644]
test-data/forgotten_attachment-signed.msg [new file with mode: 0644]
test-data/forgotten_attachment.msg [new file with mode: 0644]
test-data/normal_message.msg [new file with mode: 0644]
test-data/remembered_attachment.msg [new file with mode: 0644]

diff --git a/attachment_checker b/attachment_checker
new file mode 100644 (file)
index 0000000..cc3785e
--- /dev/null
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+
+# (c) 2004 -- Benjamin Mako Hill <mako@bork.hampshire.edu>
+
+__copyright__ = "Copyright (c) 2004 Benjamin Mako Hill"
+__author__ = "Benjamin Mako Hill <mako@debian.org>" 
+
+import sys
+import os
+import re
+import email
+
+# location of the sendmail binary
+sendmail = "/usr/sbin/sendmail"
+
+# list of mimetype which are, for the sake of this program, not
+# attachments
+ignored_types = ( "applica/pgp-signat", "application/pgp-signature" ) 
+
+def send_message(): 
+    mailpipe = os.popen("%s -t" % sendmail, 'w')
+    mailpipe.write( message_string )
+    sys.exit( mailpipe.close() )
+
+# get the mail from stdin
+message_string = sys.stdin.read()
+message = email.message_from_string( message_string )
+
+attachment_expected = False
+attachment_seen = False
+text_seen = False
+
+for part in message.walk():
+
+    # check to see if this part is a plain text entry
+    if part.get_content_type() == "text/plain":
+
+        # if this is the second text block, we should interrate
+        # through things
+        if text_seen:
+            attachment_seen = True
+        # otherwise, mark that we've now seen one text field
+        else:
+            text_seen = True
+
+        # search for the word "attach" or "attached" or "attachment"
+        # in the body of the message
+        if re.search( r'\battach(ed|ment)?\b(?im)',
+                      part.get_payload() ):
+            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
+           part.get_content_type() in ignored_types ):
+        continue
+
+    # if it's not text and it's an ignored type, it's a seen attachment
+    else:
+        attachment_seen = True
+
+# now check to see if we are expecting an attachment
+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()
+
+    # 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()
+
+        else:
+            print >>sys.stderr, "Your message mentions attachments but does not include any."
+            print >>sys.stderr
+            print >>sys.stderr, "Either add an attachment or add \"CONFIRM\" (in ALLCAPS)"
+            print >>sys.stderr, "to beginning of the subject of the message and resend."
+            print >>sys.stderr
+            print >>sys.stderr, "\"CONFIRM\" will be stripped from your message subject before"
+            print >>sys.stderr, "the message is sent."
+            sys.exit( 1 )
+
+##    else:
+##        answer = ''
+##        while not answer:
+
+##            answer = 'n'
+##            answer = raw_input( "No attachment detected.\n"
+##                                "Are you sure you want to send this?"
+##                                " [Y/N]: " )
+
+                
+##            # send the mail without the attachment
+##             if answer == "y":
+##                 send_message()
+
+##             # go back and let us reattach the message
+##             elif answer == "n":
+##                 sys.exit( 1 )
+
+##             # no good answer ask again
+##             else:
+##                 answer = ''
+
+
+# if we are not expecting anything more, we should send the message
+else:
+    send_message()
diff --git a/test-data/forgotten_attachment-signed.msg b/test-data/forgotten_attachment-signed.msg
new file mode 100644 (file)
index 0000000..ab41e08
--- /dev/null
@@ -0,0 +1,45 @@
+From mako@atdot.cc Sat Jul  2 15:30:08 2005
+Date: Sat, 2 Jul 2005 15:30:08 +0200
+From: "Benj. Mako Hill" <mako@atdot.cc>
+To: mako@atdot.cc
+Subject: CONFIRM forgotten attachment (signed)
+Message-ID: <20050702133008.GC18291@yukidoke.org>
+Mime-Version: 1.0
+Content-Type: multipart/signed; micalg=pgp-sha1;
+       protocol="application/pgp-signature"; boundary="mYYhpFXgKVw71fwr"
+Content-Disposition: inline
+User-Agent: Mutt/1.5.6+20040907i
+Status: RO
+Content-Length: 668
+
+
+--mYYhpFXgKVw71fwr
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+Content-Transfer-Encoding: quoted-printable
+
+attached
+
+--=20
+Benjamin Mako Hill
+mako@atdot.cc
+http://mako.cc/
+
+Creativity can be a social contribution, but only in so
+far as society is free to use the results. --RMS
+
+--mYYhpFXgKVw71fwr
+Content-Type: application/pgp-signature; name="signature.asc"
+Content-Description: Digital signature
+Content-Disposition: inline
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.2.5 (GNU/Linux)
+
+iD8DBQFCxpbgic1LIWB1WeYRAiqXAKCNEXlhCgDx9N5SXuDfRcmuQrZfFACgzihb
+kvM5gTRPDzdPgcKAIaWGCHk=
+=f0Xi
+-----END PGP SIGNATURE-----
+
+--mYYhpFXgKVw71fwr--
+
diff --git a/test-data/forgotten_attachment.msg b/test-data/forgotten_attachment.msg
new file mode 100644 (file)
index 0000000..d2a0124
--- /dev/null
@@ -0,0 +1,23 @@
+From mako@atdot.cc Sat Jul  2 15:28:52 2005
+Date: Sat, 2 Jul 2005 15:28:52 +0200
+From: "Benj. Mako Hill" <mako@atdot.cc>
+To: mako@atdot.cc
+Subject: forgotten attachment
+Message-ID: <20050702132852.GD10386@yukidoke.org>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+User-Agent: Mutt/1.5.6+20040907i
+Status: RO
+Content-Length: 169
+
+attached
+
+-- 
+Benjamin Mako Hill
+mako@atdot.cc
+http://mako.cc/
+
+Creativity can be a social contribution, but only in so
+far as society is free to use the results. --RMS
+
diff --git a/test-data/normal_message.msg b/test-data/normal_message.msg
new file mode 100644 (file)
index 0000000..f8a6f47
--- /dev/null
@@ -0,0 +1,23 @@
+From mako@atdot.cc Sat Jul  2 15:28:52 2005
+Date: Sat, 2 Jul 2005 15:28:52 +0200
+From: "Benj. Mako Hill" <mako@atdot.cc>
+To: mako@atdot.cc
+Subject: forgotten attachment
+Message-ID: <20050702132852.GD10386@yukidoke.org>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+User-Agent: Mutt/1.5.6+20040907i
+Status: RO
+Content-Length: 169
+
+don't attack me
+
+-- 
+Benjamin Mako Hill
+mako@atdot.cc
+http://mako.cc/
+
+Creativity can be a social contribution, but only in so
+far as society is free to use the results. --RMS
+
diff --git a/test-data/remembered_attachment.msg b/test-data/remembered_attachment.msg
new file mode 100644 (file)
index 0000000..dd54f73
--- /dev/null
@@ -0,0 +1,42 @@
+From mako@atdot.cc Sat Jul  2 15:30:47 2005
+Date: Sat, 2 Jul 2005 15:30:47 +0200
+From: "Benj. Mako Hill" <mako@atdot.cc>
+To: mako@atdot.cc
+Subject: remembered attachment
+Message-ID: <20050702133047.GD18291@yukidoke.org>
+Mime-Version: 1.0
+Content-Type: multipart/mixed; boundary="RwxaKO075aXzzOz0"
+Content-Disposition: inline
+Content-Transfer-Encoding: 8bit
+User-Agent: Mutt/1.5.6+20040907i
+Status: RO
+Content-Length: 624
+
+
+--RwxaKO075aXzzOz0
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+
+attached!
+
+-- 
+Benjamin Mako Hill
+mako@atdot.cc
+http://mako.cc/
+
+Creativity can be a social contribution, but only in so
+far as society is free to use the results. --RMS
+
+--RwxaKO075aXzzOz0
+Content-Type: text/plain; charset=utf-8
+Content-Disposition: attachment; filename=test
+Content-Transfer-Encoding: 8bit
+
+;; This buffer is for notes you don't want to save, and for Lisp evaluation.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer.
+
+dögiisp
+
+--RwxaKO075aXzzOz0--
+

Benjamin Mako Hill || Want to submit a patch?