Cookie Notice

As far as I know, and as far as I remember, nothing in this page does anything with Cookies.

2009/07/07

Send Gmail With Perl

I don't want to run an MTA on my desktop. MTAs are known vectors for hackers looking for buffer overflows, so leave it the the mail admin or Google to handle it.

But you want the ability to send mail from the command line. It's just so convenient!

cat code.pl | mail -s "The script in question" target@someplace.edu

Beyond that, well, Google has that GMail thing down. Down so well, it's out of Beta. Finally! Large quotas, high availability, POP and IMAP (IMAP is the best!)

Perl to the rescue!

I saw a blog post about sending Gmail email with Perl, using Net::SMTP::TLS. I then decided to write a program that behaves nearly like the mail command line program. (I added a -t flag for Getopt::Long completeness, rather than trying to fish an email address out of @ARGV.)


#!/usr/bin/perl

# usage: cat foo | mail.pl -subject "subject line" -to mail@mail.com

use Modern::Perl ;
use Net::SMTP::TLS ;
use Getopt::Long ;
use IO::Interactive qw{ interactive } ;
use subs qw{ send_mail get_credentials } ;

my %msg ;
my $to = '' ;
my $cc = '' ;
my $bcc = '' ;
my $header = '' ;
my $subject = '' ;
my $body = '' ;

GetOptions( 'header=s' => \$header,
'subject=s' => \$subject,
'to=s' => \$to,
'cc=s' => \$cc,
'bcc=s' => \$bcc,
) ;

while ( my $line = <STDIN> ) { $body .= $line ; }

$msg{ body } = $body ;
$msg{ subject } = $subject ;
$msg{ to } = $to ;
$msg{ bcc } = $bcc ;
$msg{ cc } = $cc ;
$msg{ header } = $header ;

send_mail %msg ;

exit ;

sub get_credentials {
#this is the point where my setup sucks
my %creds ;
$creds{ username } = 'NO' ;
$creds{ password } = 'A Thousand Times NO' ;
return %creds ;
}

sub send_mail {
my %msg = @_ ;
my %creds = get_credentials ;
my $mailer = new Net::SMTP::TLS(
'smtp.gmail.com',
Hello => 'smtp.gmail.com',
Port => 587,
User => $creds{ username } ,
Password=> $creds{ password } ,
);
$mailer->mail('jacoby.david@gmail.com');
$mailer->to( $msg{to} ) ;
$mailer->cc( $msg{cc} ) if $msg{cc} =~ /\w/ ;
$mailer->bcc( $msg{bcc} ) if $msg{bcc} =~ /\w/ ;
$mailer->data;
$mailer->datasend( "Subject: $msg{subject} \n" );
$mailer->datasend( "\n" );
$mailer->datasend( $msg{body} );
$mailer->dataend;
$mailer->quit;
}


I still do not have the store username and password in a secured config file part done. That's the part waiting for the Google Talk script, the Google status script, the Twitter stuff, etc. If you have ideas, I'd be glad to hear 'em.

2009/07/06

Fun with Filters

I came about this in a kinda roundabout way. I work in Genomics, a home of freakin' huge data sets. I'm involved in trying to extract and usable QC data from the huge dumps of data coming from our sequencers. Specifically, at the moment I'm trying to make a tree showing all the data and the size of each directory, so I can tell what to copy and what to keep still. I'm using stat to get the file sizes, but that's in bytes, and once you get a few dozen digits in, it kinda gets hairy.

Complicating issues, the code is run on the sequencer, which I (rightly) do not have root privileges for. I took the output from the machine (thanks, SSHFS) and used this code to get human-readable output.
#!/usr/bin/perl
use Modern::Perl ;
use Number::Bytes::Human qw(format_bytes) ;

while ( my $a = <STDIN> ) {
$a =~ s{\b(\d+)\b}{ format_bytes( $1 ) }egmx ;
say $a ;
}

I love filters. So easy. And Number::Bytes::Human kept me from having to write my own code to convert. Yay, CPAN!