procmail
[Top] [All Lists]

Re: splitting large mail msgs.

1999-12-12 00:45:50

FWIW, here's a Perl script that should do most of the work required
to split a mail message into parts of size < $SPLITSIZE, without
resorting to writing a series of MIME compliant multipart attachments.
Usual disclaimers apply - I didn't test it exhaustively, and it
will likely fail on poorly formed email messages/headers.

WARNING: as written, this script calls sendmail, so it would
be best to make sure the from: and to: headers are the way
you want them before feeding the e-mail message to this
script.  For testing, just change $mail_cmd to "cat".

#!/usr/bin/perl -w
use strict;

my $splitsize   = exists $ENV{'SPLITSIZE'} ? int($ENV{'SPLITSIZE'}) : 250000;
my $sendmail = exists $ENV{'SENDMAIL'} ? $ENV{'SENDMAIL'}
                        : '/usr/sbin/sendmail';
my $mail_cmd = "$sendmail -oi -t";
my $part_overhead = 50;
my ($hdr, $newhdr, @body, $bodypart);
my ($subj, $msglen, $lastpart, $msgnum);
my ($msgid, $msgdomain);

##
## Output $bodypart, changing the subject and message id as needed.
##
sub sendmsg() {
      ++$msgnum;
      $newhdr = $hdr;
      $newhdr =~
          s/Subject:[^\n]*\n/Subject: $subj (part $msgnum or $lastpart)\n/mi;
      $newhdr =~ s[Message-Id:[ ]*<[^(_at_)]*@[^>]*>\n]
                  [Message-Id: 
<${msgid}(_dot_)${msgnum}\(_at_)${msgdomain}>\n]mi;
      open(MSGOUT, "| $mail_cmd");
      print MSGOUT $newhdr;
      print MSGOUT $bodypart;
      close(MSGOUT);
}

##
## Collect the original message header,
## and extract the original subject and message id.
##
while (<>) {
    last if (/^\n$/);
    $hdr .= $_;
    $subj = $1 if (m/^Subject:[ ]*([^\n]*)\n$/i);
    if (m/^Message-Id:[ ]*<([^(_at_)]*)@([^>]*)>\n$/i) {
       $msgid = $1;
       $msgdomain = $2;
    }
}
$hdr .= "\n";
if (! $subj ) { $subj = '<none>'; }
if (! $msgid ) { $msgid = 'foo'; }
if (! $msgdomain ) { $msgdomain = 'bar'; }

##
## save each line in the body, and count the total number of
## message parts that will be produced.
##
$msglen = length($hdr) + $part_overhead;
while (<>) {
  if (($msglen + length()) > $splitsize) {
      ++$lastpart;
      $msglen = length($hdr) + $part_overhead + length();
  }
  $msglen += length();
  push @body, $_;
}
++$lastpart;

##
## output each message part
##
$msglen = length($hdr) + $part_overhead;
$bodypart = '';
foreach (@body) {
  if (($msglen + length()) > $splitsize) {
      sendmsg();
      $msglen = length($hdr) + $part_overhead + length();
      $bodypart = '';
  }
  $msglen += length();
  $bodypart .= $_;
}
sendmsg();
<Prev in Thread] Current Thread [Next in Thread>