Procmail and MIME attachement handling

Procmail and MIME attachement handling

Post by <jari.aa.. » Tue, 16 Jun 1998 04:00:00



Preface

        There are several MIME aware Mail User Agents (MUAs) that can
        decode and upack the mime attachements that you receive. If
        you don't have such MUA yes, consider getting one.

Procmail solution

        First, procmail is not the right tool to handle MIME messages,
        but nonetheless there exists couple of procmail mime modules
        that can solve _some_ of the mime issues. This post's intention is to
        introduce you to those modules and to explain when you would
        use them

Overview

        o   to kill unwanted mime garbage from the message,
            choose pm-jamime-kill.rc
        o   to save file attachement from a message, choose pm-jamime-save.rc
        o   to decode qp or base64, choose pm-jamime-decode.rc

        The all available modules are available at:


            Subject: send pm-code.shar  (also "send help" "send ls-l.txt")

        Description of the modules in the shar file can be viewed at:

            ftp://cs.uta.fi/pub/ssjaaa/pm-code.html

module: pm-jamime-kill.rc

       Microsoft Explorer has a bad habbit of including 7k
       application/ms-tnef attachement to the end of message. If you don't
       want to see that additional ms-tnef attachement, then plug in this
       module and you no longer see MS Explorer cruft.

       This recipe works like this: If email's structure is

           --boundary
           message-text (maybe quoted-printable)
           --boundary
           some-unwanted-mime-attachement
           --boundary

       then the attachement is killed from the body. The message-text part
       is also decoded if it was quoted printable. This leaves clean text;
       with no MIME anywhere. MIME headers have been modified as needed
       (due to conversion from multipart and possibly quoted printable to
       plain text):

           message

    Applications for other mime attachements

       Lotus Notes sends similar extra attachement and you can use this
       same recipe to kill it. See example section.

       Microsoft Express sends a copy of message in html format in the
       attachement, you can kill that too, see example section.

       Netscape's Mozilla sends a copy of message in html. See example.
       Also it sends `vcards'

module: pm-jamime-save.rc

        This includerc reads saves _one_ simple file attachement (MIME)
        from he message. The message must define following MIME headers.
        If "filename=" does not exists, then the message will not be
        handled.

            Mime-Version: <version>
            Content-Type: <type>
            Content-Disposition: attachment; filename="file.txt"

        Procmail is not very suitable for saving MIME attachements and
        you should not think that this the right tool for you.
        If you receive anything more than 1 attachement, this recipe
        does nothing, because that's out of our league and you need some
        more heavy weight mime tools. Eg. Perl CPAN has MIME libraries.

        _Note_: When the attachement is in the body, it is simply written
        to a disk and the place is replaced with message

            Extracted to file:/users/jaalto/junk/file.txt.1998-03-30

module: pm-jamime-decode.rc

        The original father of the decoding scheme used here was

        procmail mailing list somewhere at the end of 1997.

        This includerc supposes that the header has MIME header
        Content-Type: text/plain and performs qp or base64 decoding
        on the whole message. Note, that if you receive messages that
        have many mime attachements, then this recipe is not suitable
        for it.

        Procmail is not designed to handle mime attachements and this
        recipe only applies to whole _body_.

end

 
 
 

Procmail and MIME attachement handling

Post by Eli the Bearde » Tue, 16 Jun 1998 04:00:00


[Posted and mailed since you set followups to poster, but I really
wanted to post this instead.]


> Procmail solution

>    First, procmail is not the right tool to handle MIME messages,
>    but nonetheless there exists couple of procmail mime modules
>    that can solve _some_ of the mime issues. This post's intention
>    is to introduce you to those modules and to explain when you
>    would use them

Maybe. But procmail really just is not a tool for *modifying* email
at all, and removing/decoding/inlining MIME is a modification of the
email. Procmail is best at sorting email and proving the framework
for body or header filtering.

> Overview
...
>    o   to decode qp or base64, choose pm-jamime-decode.rc
...
> module: pm-jamime-decode.rc

>         The original father of the decoding scheme used here was

>         procmail mailing list somewhere at the end of 1997.

>         This includerc supposes that the header has MIME header
>         Content-Type: text/plain and performs qp or base64 decoding
>         on the whole message. Note, that if you receive messages that
>         have many mime attachements, then this recipe is not suitable
>         for it.

If you have a mime decoder already, such as metamail, it is very
easy to decode all of the attachments. Someday I'll probably write
the whole thing in perl, but I have not needed to yet.

Here's what I do:

# begin procmailrc excerpt
# Decode MIME quoted-printable and base64, so long as all "Content-Type"s are
# text/plain. (RE on second line could be better)

# conditions act on 'B'ody and 'H'eaders
:0BH
* ^Content-T(ransfer-Encoding|ype):\/.*(quoted-print|base64|multipart/mixed)
* !^Content-Type: *(x-)?(text/([^p]|p[^l]|pl[^a]|pla[^i]|plai[^n])|application|image|message)
{
  # The MIME stuff is still experimental, so keep a backup ('c'opy)
  :0c:
  $MAIL/mime-backup

  # Prevent CPU contention
  LOCKFILE=mime.lock

  LOG="Decoding:$MATCH
"

  # Moves MIME headers to the body and cleans up some broken MIME headers.
  # ('f'ilter, action acts on 'b'ody and 'h'eaders, 'w'ait for exit)
  # (see below for this perl script)
  :0fbhw
  | unmime

  # Deocdes MIME: -q quiet, -d don't ask questions, -w write out to stream
  # ('f'ilter, action acts on 'b'ody, 'w'ait for exit)
  :0fbw
  | metamail -qdw

  # Clear lock
  LOCKFILE

Quote:}

# end procmailrc excerpt

Quote:>         Procmail is not designed to handle mime attachements and this
>         recipe only applies to whole _body_.

MIME attachements are not distinguished from any other content by
procmail.

Elijah
------
unmime:

#!/usr/local/bin/perl5.004
#
# Put mime headers in body for easier :0fb processing
# Lower perl5s will work, but 4.036 is almost certainly out.
# by Eli the Bearded    24/June/97
#

# Eat "From " psuedo-header

$_=<>;

# Used to deal with multiline headers properly. Preload with
# something that will get stripped in case the first header is
# broken and looks like a multiline.
$headline="Bogus: header\n";
$inhead=1;

while(defined($inhead)) {
 if (/^$/) {
  $inhead=undef;
  # Note the :\s* allows cannonicalizing whitespace in headers. The
  # (.+) will soak up the newline of a blank header.
  $headline =~ /(^[^\s]+):\s*(.+)/s;
  $contents = $2;

  if ( ($headname=$1) =~ /^(Content-(?!Length$)|MIME-)/i ) {
    # Fix broken MIME type
    $contents =~ s:^txt/plain:text/plain:i;

  } else {

                $headline=~/^(Bogus|X-MIME-Autoconverted): /i;
  }

 }
 elsif (/^\s/) {
  # Preserve original whitespace on multiline header.
  $headline="$headline$_";
  $_=<>;
 }
 else {
  # Note the :\s* allows cannonicalizing whitespace in headers. The
  # (.+) will soak up the newline of a blank header.
  $headline =~ /(^[^\s]+):\s*(.+)/s;
  $contents = $2;

  if ( ($headname=$1) =~ /^(Content-(?!Length$)|MIME-)/i ) {
    # Fix broken MIME type
    $contents =~ s:^txt/plain:text/plain:i;

  } else {

                $headline=~/^(Bogus|X-MIME-Autoconverted): /i;
  }

  $headline = $_;
  $_=<>;
 }

Quote:}


print STDOUT "\n";

print STDOUT "\n";

# Now process body.
while(<>) {
  # Fix broken MIME type
  s!^Content-Type:\s*txt/plain!Content-Type: text/plain!i;
  print;

Quote:}