From 84587935cb07f6c7f71f6c602fa9e72c3f6c4e9b Mon Sep 17 00:00:00 2001 From: Date: Sun, 3 Jul 2005 06:00:18 -0400 Subject: [PATCH] First import into BZR of attachment checker. --- attachment_checker | 117 ++++++++++++++++++++++ test-data/forgotten_attachment-signed.msg | 45 +++++++++ test-data/forgotten_attachment.msg | 23 +++++ test-data/normal_message.msg | 23 +++++ test-data/remembered_attachment.msg | 42 ++++++++ 5 files changed, 250 insertions(+) create mode 100644 attachment_checker create mode 100644 test-data/forgotten_attachment-signed.msg create mode 100644 test-data/forgotten_attachment.msg create mode 100644 test-data/normal_message.msg create mode 100644 test-data/remembered_attachment.msg diff --git a/attachment_checker b/attachment_checker new file mode 100644 index 0000000..cc3785e --- /dev/null +++ b/attachment_checker @@ -0,0 +1,117 @@ +#!/usr/bin/env python + +# (c) 2004 -- Benjamin Mako Hill + +__copyright__ = "Copyright (c) 2004 Benjamin Mako Hill" +__author__ = "Benjamin Mako Hill " + +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 index 0000000..ab41e08 --- /dev/null +++ b/test-data/forgotten_attachment-signed.msg @@ -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" +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 index 0000000..d2a0124 --- /dev/null +++ b/test-data/forgotten_attachment.msg @@ -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" +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 index 0000000..f8a6f47 --- /dev/null +++ b/test-data/normal_message.msg @@ -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" +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 index 0000000..dd54f73 --- /dev/null +++ b/test-data/remembered_attachment.msg @@ -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" +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-- + -- 2.30.2