Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Monday November 08, 2004
03:51 PM

blosmail.pl

[ #21768 ]

My other weblog is Blosxom-based. I find I don't update it as often as I could/should, mostly because it's a pain to update - log in to the remote server, write the entry, save it ... it just loses the immediacy for me. I've tried a couple of the Bloxsom plugins to make it easier, but I haven't been happy with any of them.

I saw blosmail.pl go by on del.icio.us today. It's a little Perl script that parses a mail message and posts it to your Blosxom weblog. Immediately alarms began to go off - the EMUSIC-L weblog isn't exactly BoingBoing in terms of traffic, but I could just see my poor little weblog getting spammed up the wazoo. Okay, so there's a password-protection feature. You put the password in the mail and send it. This didn't strike me as a whole lot better - I wanted something that would be easy to do, but hard enough to crack that it really wouldn't be worth it.

So the following code code does an MD5 hash of the body of the message with a secret string stored on the server. If the hashes match, the post is accepted. At the moment, it still takes a little more work than I'd like: I have to run the message text through an external script and then paste the resultant hash back into the message. What this really wants is a drag-and-drop applet (probably doable with Platypus) or a full-fledged OS X service.

Anyway, here's blosmail-md5.pl.
Update: After seeing this happen to someone, I separated the blosmail config directory from the Blosxom data directory. (Yes, I did drop them a note.)

#!/usr/bin/perl -w
 
# blosmail
# Allows you to post (and modify) blosxom entries via email
# Version 0+1a
# DJ Adams June 2002
 
# See http://www.pipetree.com/testwiki/Blosmail
# Changes
# 0+1b fixed secret mechanism
# 0+1a added -secret parameter
# 0+1  original version
#
# Modified 8-Nov-2004 by Joe McMahon
# - folded in Doug Alcorn's 'category and title from subject' extension
# - added security via MD5 hash of content
 
use strict;
use File::Path;
use File::Temp qw/ tempfile /;
use FileHandle;
use CGI qw/:standard :debug/;
use Digest::MD5;
 
# --- Configurable variables -----
 
# Where are my blog entries kept?
my $datadir = "/Users/joe/blosxomdata";
my $configdir = "/Users/joe/blosmail_config";
 
# --------------------------------
 
$datadir = "$datadir/".param('-blog') if param('-blog');
my $fh = new FileHandle;
 
# Get the list of valid email addresses
my @validEmail = $fh->open("< $configdir/blosmail.dat") ? (<$fh>) : ();
chomp @validEmail;
 
# Read in whole mail and split into headers and body
my ($headers, $body);
{
  local $/ = undef;
  ($headers, $body) = split("\n\n", <STDIN>, 2);
}
 
# Check MD5 sums: combine the local copy of the password and the post text
# and sum them. Should match the sum that appears on the first line.
if (param('-sum')) {
  (my $incoming_sum, $body) = split(/\n/, $body, 2);
  chomp $incoming_sum;
  $fh->open("< $configdir/secret.dat") or die "No local secret\n";
  my $local_secret = <$fh>;
  chomp $local_secret;
  my $ctx = Digest::MD5->new();
  $ctx->add($local_secret.$body);
  my $local_sum = $ctx->hexdigest;
  die "Incorrect checksum" if $local_sum
   ne $incoming_sum;
}
 
# Check it's from a valid email address
my ($from) = $headers =~ /^From:\s.*?<([^>]+)>.*?$/m;
die "Entry from invalid email address" unless grep(/$from/, @validEmail);
 
# Determine filename and write entry
my ($category, $title) =
   ($headers =~ /^Subject:\s+BLOG\/([^\s]*)\s*(.*)$/m)
      ? ($1, $2)
      : "";
die "No title supplied\n" unless ($title);
 
unless (-d "$datadir/$category") {
    mkpath ("$datadir/$category", 0, 02775) or
        die "Can't create '$category' directory, $!\n";
}
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year +=1900;
$mon += 1;
my $filename;
($fh, $filename) = tempfile("${year}${mon}${mday}XXXXXX", SUFFIX => ".txt", DIR => "$datadir/$category", UNLINK => 0);
print $fh $title, "\n";
foreach my $line (split /\n/, $body) {
    last if ($line =~ /^--/);
    print $fh $line, "\n";
}
$fh->close;
 
chmod 0644, "$datadir/$filename";

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.