We have used Vonage as our phone provider for a couple years now and have loved the service. One of the many features they add at no extra charge is the ability to have all voicemail messages sent as an email attachment. Unfortunately, they only send these attachments in WAV format, which means they take up a ton of room.
I like to store all voicemails I receive in case I need them later, and so I was looking for a way to shrink those emails down. I found this post describing how to do just that using Perl and LAME to convert the attachments to MP3.
Unfortunately, that script didn’t work quite right for me. I have cleaned it up a bit and posted it here for anyone interested.
You need to call this script from your MTA as an “external filter”. The details of how to do this depend on your implementation. It will read the current email (with WAV attachment) on STDIN, and write the email with an MP3 attachment on STDOUT. It will also change the subject line to include the Caller ID info of the caller.
Up until sometime towards the end of 2005, I used the popular LAME MP3 encoder which is available for most Linux distros. However, Vonage then changed the format of their WAV files to use an algorithm called “CCITT μ-Law”, which LAME is unable to handle. So I switched to a new program called SOX, which bills itself as the “swiss army knife of sound processing programs”.
Requirements:
- SOX
- Perl with MIME::Parser module
As written, this script will convert Vonage WAV files to MP3. Converting to Ogg Vorbis or any other standard instead should be rather simple; simply read the SOX man page or website.
In the event that the incoming email does not contain an attachment, or the attachment is not WAV format, it will be written to STDOUT unchanged. In either case, the return status will be 0. But the best solution is to send only Vonage voicemail emails through this filter. Your MTA software may have a way to do server-side header checks and conditional filtering. Currently, voicemail emails come from an address which ends with “vm.vonage.com”.
This script differs from the one mentioned above in that it uses a tempfile instead of IPC::Open2. I was unable to get IPC::Open2 to work correctly, since it deadlocked when attempting to write to it. According to the author of IPC::Open2, this is a danger in using it with “streamy” programs such as LAME or SOX.
Because this script uses a tempfile for the SOX output before reading it back it, there’s a possibility of someone reading this tempfile while the script is running. This is a security problem if you have untrusted users. This isn’t an issue for me, since this is on a private server, but if it is for you (i.e. you have users which you don’t want listening to your voicemails) then be sure to create the tempfile in a directory which only your MTA has read/write access to (instead of /tmp), and/or use “umask” to ensure that only your MTA can read/write the file.
UPDATE 9/15/2006: I have also written a Perl script to grab Caller ID information from Switchboard.com, which can be used to add this info to your emails as well.
#!/usr/bin/perl
use MIME::Parser;
$parser = new MIME::Parser;
$parser->output_to_core(1);
$email = $parser->parse(\*STDIN);
$time = time();
$tmp_file = "/tmp/wavmailtomp3-$time.$$.tmp.mp3";
$attachment = $email->parts(1);
if (!defined $attachment or $attachment->effective_type() ne 'audio/wav') {
# no attachment or non-WAV attachment; print original mail and quit
$email->print;
exit(0);
}
open(PIPE, "|/usr/bin/sox -t .wav - $tmp_file");
print PIPE $attachment->bodyhandle->as_string;
close PIPE;
if( open(PIPE,"<:bytes",$tmp_file) ) {
if( $fh = $attachment->bodyhandle->open("w") ) {
my $buffer;
while( read(PIPE, $buffer, 10240) > 0 ) { ### read chunks of 10KB at a time
$fh->print($buffer);
}
$fh->close;
} else {
warn "Error opening MIME part for writing: $!";
}
close PIPE;
} else {
warn "Error opening mp3 file $tmp_file: $!";
}
$attachment->head->replace("Content-type","audio/mpeg");
$attachment->head->mime_attr("content-type.name"=>"voicemail.mp3");
$email->parts(0)->bodyhandle->as_string =~ m/From: (.*)/m;
$from = $1 || 'UNKNOWN';
$b=$email->head->replace("Subject","$from -- new voicemail");
$email->sync_headers(Length=>"COMPUTE");
$email->print;
unlink($tmp_file);



Seth Green | 31-May-06 at 3:51 pm | Permalink
This is exactly what I’m looking for, but when I try invoking it via maildrop and the xfilter command I end up w/gibberish in my mail queue — it looks like it’s trying to pass the entire delivery history of the message as a single TO: header.
Any help/suggestions would be greatly appreciated…..
Here’s a sample logentry:
May 31 15:44:18 [domain snipped] postfix/pipe[10082]: 9C0EF4C136: to=, relay=maildrop, delay=2, status=deferred (temporary failure. Co mmand output: bash: -c: line 1: syntax error near unexpected token `(’ bash: -c: line 1: `Return-Path: Delivered-To: [recipient snipped] Received: from localhost [domain snipped] [127.0.0.1]) by [domain snipped] (Postfix) with ESMTP id 9C0EF4C136 for ; Wed, 31 May 2006 15:44:16 -0400 (EDT) Received: from [domain snipped] ([127.0.0.1]) by localhost (DebServer [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 09764-03 for ; Wed, 31 May 2006 15:44:13 -04 00 (EDT) Received: from [sender snipped] by baruchgreen.net (Postfix) with ESMTP id 056C44C135 for ; Wed, 31 May 2006 15:44:08 -0400 (EDT) Received: from [sender snipped] [127.0.0.1]) by [sender snipped] (8.12.8/8.12.8)
toby | 31-May-06 at 4:27 pm | Permalink
maildrop/xfilter is exactly how I’m running this, so I know it works… it looks like it’s trying to run the script through bash instead of perl.
My maildrop entry looks like:
(Where wavmailtomp3 contains the script from above, and _voicemail is my IMAP folder where I filter voicemails to).
Are you sure you included the shebang line (#!/usr/bin/perl), that the path to perl specified there is correct (check with /usr/bin/perl -v), and that the script is marked as executable as the user that maildrop runs as?
The PumaCode.org Blog :: adding caller id information to vonage voicemail emails | 15-Sep-06 at 10:17 am | Permalink
[...] A few months ago I wrote about a Perl script I use to convert the .wav attachments on my Vonage voicemail emails to .mp3, in order to save mailbox space. One other thing that has always annoyed me about those Vonage emails is that they don’t contain Caller ID information. Vonage already has this data, so why not put it on the email? [...]