The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl -w

=head1 NAME

mimesend - send files via MIME mail, from the command line

=head1 USAGE

Pretty basic:

    mimesend [-n] [-t to] [-s subj] (-f file [-m type])+
        -n        Don't actually send it; just print it to stdout.
        -t to     The "to" address.
        -s subj   The subject of the message.
        -f file   Path to attached file, or - for STDIN.
        -m type   MIME type of previous -f; therefore -m must follow -f.

For example:

    mimesend -t you@yourhost.com -s "Hello, nurse!" 
          -f greetings.htm -f foo.gif 

=head1 AUTHOR

Eryq, eryq@zeegee.com

8 Jan 1997

=cut

use lib "./lib";
use MIME::Entity;

# Lookup table:
my %TypeFor = qw(
    txt   text/plain
    sh    text/x-sh
    csh   text/x-csh
    pm    text/x-perl
    pl    text/x-perl
    jpg   image/jpeg
    jpeg  image/jpeg
    gif   image/gif
    tif   image/tiff
    tiff  image/tiff
    xbm   image/xbm
    pdf   application/pdf
    );

# Usage:
@ARGV or die <<EOF;
Usage:
    mimesend [-t to] [-s subj] (-f file [-m type])+
        -n        Don't actually send it; just print it to stdout.
        -t to     The "to" address.
        -s subj   The subject of the message.
        -f file   Path to attached file.
        -m type   MIME type of most recent attached file.

EOF

# Type:
sub type_for {
    my $path = shift;

    my ($ext) = ($path =~ /\.([a-z0-9]+)\Z/i);
    ($ext and $TypeFor{lc($ext)}) or
	(-T $path ? 'text/plain' : 'application/octet-stream');
}

# Get args:
my $nosend;
my @files;
ARG: while (@ARGV) {
    $_ = shift @ARGV;
    /^-n/ and do {
	$nosend = 1;
        next ARG;
    };
    /^-t(.*)/ and do {
	$to = $1 || shift @ARGV;
        next ARG;
    };
    /^-s(.*)/ and do {
	$subj = $1 || shift @ARGV;
        next ARG;
    };
    /^-f(.*)/ and do {
        push @files, [$1||shift @ARGV];
        next ARG;
    };
    /^-m(.*)/ and do {
        $files[-1][1] = $1 || shift @ARGV;
        next ARG;
    };
    die "$0: bad usage: <$_>.\n";
}

# Verify destination:
$to or die "$0: missing [-t to]\n";

# Verify subject:
$subj or die "$0: missing [-s subject]\n";

# Start with top-level entity:
my $top;
if (!@files) {
    die "$0: no files specified!\n";
}
elsif (@files == 1) {
   my ($path, $type) = @{$files[0]};

   # Build:
   $top =  build MIME::Entity 
       Type     => ($type || type_for($path)),
       $path eq '-' ? (Data => [<>]) : (Path => $path),
       Encoding => '-SUGGEST';
   $top->head->add('To', $to);
   $top->head->add('Subject', $subj);
}
else {

    # Start with top:
    $top =  build MIME::Entity Type=>"multipart/mixed";
    $top->head->add('To', $to);
    $top->head->add('Subject', $subj);

    # Attach files:
    foreach (@files) {
	my ($path, $type) = @{$_};
	$top->attach(Type     => ($type || type_for($path)),
		     Path     => $path,
		     Encoding => '-SUGGEST');
    }
}

# Launch mailer and send message?
if (!$nosend) {
   open SENDMAIL, "|/usr/lib/sendmail -t -oi -oem" 
       or die "$0: open sendmail: $!\n";
   $top->print(\*SENDMAIL);
   close SENDMAIL;
   die "sendmail failed" if ($? >> 255);
}
else {
   $top->print(\*STDOUT);
}
1;