Friday, January 30, 2009

Sending mail with multiple attachments from Perl

It always annoys me a whole lot, when I'm writing some Unix/Linux shell script and I need to send an email with attachments - there simply isn't an easy way.

Standard mail doesn't support any attachments whatsoever, in some versions of mailx one attachment is supported and mpack is generally not available at all.

Since I found out, that some of the servers, I need to deploy my script to, don't even have uuencode installed, I decided to write myself a small standalone utility in Perl for sending multi-attachment emails.

There are lots of existing solutions in CPAN for this, but I specifically needed something, that's using only core Perl modules and sendmail - things I can count to find on every server.

#!/usr/bin/perl
use strict;
use MIME::Base64;

if ($#ARGV < 2)
{
        print(STDERR "Not enough parameters\n\n");
        print(STDERR "Usage:\n");
        print(STDERR "\t./send.pl e\@mail \"Subject\" file1 file2 ...\n");
        print(STDERR "\t./send.pl \"e\@mail,a\@ddress\" \"Subject\" file1 file2 ...\n\n");
        exit -1;
}

#Sendmail requires email addresses to be separated by comma AND space
my $to = $ARGV[0];
$to =~ s/,/, /g;

open STDOUT, "|/usr/sbin/sendmail -t";

my $boundary = "_----------=_10167391557129230";

print("Content-Transfer-Encoding: 7bit\n");
print("Content-Type: multipart/mixed; boundary=\"$boundary\"\n");
print("MIME-Version: 1.0\n");
print("Date: ".`date`);
print("To: $to\n");
print("Subject: $ARGV[1]\n\n");

for (my $i = 2; $i <= $#ARGV; $i++)
{
        my $basename = `basename $ARGV[$i]`;
        $basename =~ s/\s//g;
        print("\n--".$boundary."\n");
        print("Content-Transfer-Encoding: base64\n");
        print("Content-Type: application/octet-stream; name=\"$basename\"\n\n");

        local $/=undef;
        open FILE, $ARGV[$i] or die "Couldn't open file $ARGV[$i]";
        binmode FILE;
        my $content = <FILE>;
        close FILE;

        print encode_base64($content)."\n\n";
}

print("--$boundary\n.\n");

The code depends on two things:

  1. sendmail being available in /usr/sbin
  2. Perl core module MIME::Base64 - every standard Perl installation has this.

There is a little issue in the code - the MIME boundary is hard coded and not checked for uniqueness, but since we're using Base64 there is not much possibility of a clash.

Sunday, January 11, 2009

Free Desktop At Last

When reinstalling my Gentoo, I decided to give the radeon - open source ATI driver - a try. I have Radeon 9600XT and I always had issues with the closed source fglrx driver from ATI.

I wasn't expecting much from the free driver, but the current functionality simply blew me away - dual monitors, 3D acceleration, video playback - everything works nicely. I can't honestly think of anything more I could ask for.

Thank you guys so much!!!

Currently the stable xorg-server is version 1.3 and xorg-x11 is at version 7.2, but since I like my software freshly build (plus I wanted to give the compiz fusing a try), I had to accept the unstable packages when compiling.

ACCEPT_KEYWORDS="~x86" emerge xorg-x11 xorg-server

Gentoo is a distribution for power users/developers, so I sometimes find the release process little too conservative. I would mark packages as stable much sooner, but that's probably just me :).

So now I'm just moving wobbly windows around my desktop and grinning :))

Freedom at last.

Tuesday, January 6, 2009

Bringing Gentoo into 2009

I was forced to use Windows exclusively for past couple of months due to various reasons and I was missing my Gentoo installation a lot. As a New Year's gift to my computer I decided to reinstall the whole thing, because the installation has been quite dated with lot of unused packages, many obsolete flags and still on gcc 3.4

I was thinking how to do the installation most conveniently, but eventually decided to wipe the whole installation away and keep only

  1. /etc/passwd
  2. /etc/shadow
  3. /etc/fstab
  4. /home/

Accidentally I managed to delete my /lib folder while doing the cleanup and was left with non working system :)

Because my computer doesn't have any working CD/DVD drives and can't boot from USB, I was really happy Grub can find kernel images on FAT32 partitions

So I downloaded the Gentoo LiveCD, unpacked it to my Windows harddrive and restarted the computer

 kernel (hd0,0)/gentoo_livecd/isolinux/gentoo
 initrd (hd0,0)/gentoo_livecd/isolinux/gentoo.igz
 boot

The kernel got loaded and to my extreme surprise the gentoo.igz ramdisk contains a minimal shell with busybox, so I was able to do all the mounting, deleting and copying files I needed. Yeey from Gentoo and Linux.

So guess what I'm doing now? Compiling... :)