Maintenant que j'avais mon serveur IMAP et les bases de RSS, je voulais combiner les deux en perl. J'ai écrit IMAP2RSS pour générer un fil RSS qui serait le mirroir de l'activité d'une boîte aux lettres IMAP.
Par exemple, je suis membre d'une liste de diffusion qui arrive sur mon serveur IMAP dans un boîte spéciale. Si je veux attirer de nouveaux lecteurs vers cette liste, ce peut être une bonne idée de fournir un fil RSS. Les nouveaux peuvent ainsi voir de quoi on discute avant même de s'inscrire (donner leur adresse e-mail) et il n'y a rien d'autre à faire que de laisser tourner le script automatiquement et placer le fil sur un serveur.
Ce script peut être utilisé pour beaucoup d'autres chose comme des sauvegardes ou tout partage d'informations que vous avez.
Ce script n'a pas été long à écrire car il dépends de la présence d'un certain nombre de modules perl. J'ai choisi XML::RSS pour générer les fils et Net::IMAP::Simple pour parler au serveur de messagerie. Ensuite, j'ai pris MIME::Words pour manipuler les entités MIME qu'on trouve dans les e-mails (spécialement si la discussion est en français), et le duo Date::Parse - Date::Format pour ne pas me prendre la tête avec les dates.
Nous savons qu'en entrée nous avons une boîte IMAP sur un serveur désigné mais pour ce qui est de la sortie, il y avait des choix à faire. J'ai décidé de faire du RSS 1.0 avec le module content car il permet le niveau de formatage dont nous avons besoin et le Dublin Core nous laisse transmettre des informations utiles. J'en suis resté à l'encodage ISO-8859-1 pour rester simple.
A la fin, on se retrouve avec un fil RSS qui montre les messages sous une forme basique avec auteur, date et sujet. La manière dont je gère les rdf:resource comme liées aux Message-ID est discutable mais c'est une astuce mineure pour obtenir une référence plutôt que rien du tout.
#!perl -w
# IMAP2RSS
use strict;
use Net::IMAP::Simple;
use MIME::Words qw(decode_mimewords);
use XML::RSS;
use Date::Parse;
use Date::Format;
# le fil que l'on génère
my $feed = new XML::RSS(
version => '1.0',
encoding => 'ISO-8859-1'
);
$feed->channel(
title => 'TITRE DU FIL',
link => 'URL DE LA MAISON DU FIL',
description => 'DESCRIPTION DU FIL',
language => 'LANGUE DES MESSAGES',
syn => {
updatePeriod => 'daily',
updateFrequency => '1',
updateBase => '1970-01-01T00:00+00:00'
}
);
$feed->add_module(
prefix => 'content',
uri => 'http://purl.org/rss/1.0/modules/content/'
);
# serveur IMAP où l'on se connecte
my $server = new Net::IMAP::Simple('192.168.0.21');
$server->login('MYLOGIN','MYPASSWORD') or die "Can't login";
# boîte IMAP
my $nbmsg = $server->select('MAILBOX');
# boucle dans les 15 derniers messages
for (my $i = $nbmsg; $i > $nbmsg-15; $i--) {
# réception du message
my $lines = $server->get($i);
my ($d, $subject, $date, $from, $ref);
my $inbody = 0;
my $body = "";
# boucle dans le message
foreach my $l (@$lines) {
$l =~ s/(?:\012\015|\012|\015)//;
# décodage des entités MIME
$d = decode_mimewords($l,);
# récupération des en-têtes éssentiels
if ($d =~ /Subject: (.*)/i) { $subject = $1; }
if ($d =~ /From: (.*)/i) { $from = $1; }
if ($d =~ /Message-ID: <(.*)>/i) { $ref=$1; }
if ($d =~ /Date: (.*)/i) { $date = str2time ($1); }
# récupération du corps du message
$body .= $d if ($inbody == 1);
$inbody = 1 if (length $d < 2);
}
# conversion de la date au format Dublin Core
$date = time2str("%Y-%m-%dT%T%z",$date);
$date =~ s/(\d\d)$/:$1/;
$from =~ s/ <.*>//;
$from =~ s/"//g;
# ajout du message en tant qu'élément du fil
$feed->add_item(
title => $subject,
link => $ref,
description => $body,
dc => {
date => $date,
creator => $from
}, content => {
encoded => $body
}
);
}
$server->quit();
# sauvegarde du fil avec simple formatage
my $file = $feed->as_string;
$file =~ s/(<content:encoded>)/$1<![CDATA[\n<pre>/g;
$file =~ s/(<\/content:encoded>)/<\/pre>\n]]>$1/g;
open (FILE, '> armada.rss');
print FILE $file;
close(FILE);
Rendre ce fil n'est pas plus compliqué que de le sauvegarder au bon endroit ou de l'envoyer par FTP sur un autre serveur.
Si je décidais qu'il faut gérer les e-mails en HTML, ce ne serait pas compliqué car j'ai opté pour une solution où ce marquage du contenu est déjà employé. Je pourais essayer de gérer les attachements mais cela n'a pas beaucoup de sens dans un contexte de fil RSS. J'aimerais pouvoir prendre en compte plus d'encodage car même si ISO-8859-1 est suffisant maintenant, le futur appartient à UTF-8. Je pourais aussi détecter et lier les URLs.