#!/usr/bin/perl -s # # $dotat: scripts/imap-to-link-log,v 1.9 2011/06/15 10:01:25 fanf2 Exp $ use warnings; use strict; use IPC::Open2; use vars qw( $d $t ); my $USER = 'XXXXX'; my $PASS = 'XXXXXXXX'; my $SERVER = "imap.hermes.cam.ac.uk"; my $MAILBOX = "to-link-log"; # sockets my ($sr,$sw); $| = 1; my $re2047 = qr/=[?]([^? ]+)[?]([^? ]+)[?]([^? ]+)[?]=/; sub un2047($$$) { my ($charset,$enc,$text) = @_; return "=?$charset?$enc?$text?=" if $enc !~ /^q$/i or $charset !~ /^utf-8$/i; $text =~ s/=([0-9a-f]{2})/chr hex $1/gei; $text =~ s/_/ /g; $text =~ s/“/"/g; $text =~ s/”/"/g; $text =~ s/’/\x27/g; return $text; } sub get () { my $l = <$sr>; return if not defined $l; print "get< $l" if $d; return $l; } sub put (@) { print "put> @_\n" if $d; print $sw "@_\r\n"; } my $cmd_num = 0; sub raw_cmd (@) { put ++$cmd_num, @_; my @r; for (;;) { my $r = get; die "connection lost" unless defined $r; push @r, $r; return @r if $r =~ /^$cmd_num /; } } sub bugout (@) { raw_cmd "LOGOUT"; die @_; } sub cmd (@) { my @r = raw_cmd @_; my $r = join "", @r; return $r if $r[$#r] =~ /^\d+ OK /; bugout "failed command @_\nresponse:\n$r"; } # make s_client properly quiet open OLDERR, ">&", \*STDERR; my $pid = eval { open STDERR, ">/dev/null" unless $d; open2 $sr, $sw, "openssl s_client -quiet -CApath /etc/ssl/certs -verify 0 -connect $SERVER:imaps"; }; open STDERR, ">&", \*OLDERR; die $@ unless defined $pid; my $r = get; die "could not connect to $SERVER" if not defined $r; die "unwelcoming banner $r" unless $r =~ /^[*] OK /; cmd "LOGIN $USER $PASS"; cmd "SELECT $MAILBOX"; my $s = cmd "SEARCH ALL"; while ($s =~ s/^([*] SEARCH) (\d+)/$1/m) { my $n = $2; $r = cmd "FETCH $n BODY[]"; $r =~ s/^[*] $n FETCH [(](\S+\s+)*BODY[[][]] [{](\d+)[}]\s*//s or bugout "cannot parse fetch response:\n$r"; my $len = $2; my $m = substr $r, 0, $len, ""; $r =~ /^[)]\r\n/s or bugout "cannot parse fetch response:\n$m$r"; print $m if $d; unless ($m =~ m/^From: Tony Finch \s*$/m) { print "skipping: mismatched From:\n" if $d; next; } unless ($m =~ m/^\s+with esmtps?a [(]PLAIN:fanf2[)] /m) { print "skipping: mismatched auth\n" if $d; next; } unless ($m =~ m/^Subject: ([^\n]+(\n[ \t]+[^\n]+)*)\n/ms) { print "skipping: missing subject\n" if $d; next; } my $text = $1; $text =~ s/[ \t\n\r]+/ /sg; $text =~ s/^ +//; $text =~ s/ +$//; $text =~ s/[?]= =[?]/?==?/g; $text =~ s/$re2047/un2047($1,$2,$3)/geo; if ($text =~ m/$re2047/o) { print "skipping: bad RFC 2047 encoding\n" if $d; next; } $m =~ s/=\r\n//g; unless ($m =~ m{\r\n\r\n((https?|ftp)://\S+)\r\n}ms) { print "skipping: missing link\n" if $d; next; } my $link = $1; $link =~ s/=([0-9a-f]{2})/chr hex $1/gei if $m =~ /^Content-Transfer-Encoding: quoted-printable/m; print "LINK $link\nTEXT $text\n" if $d or $t; if (!$t && 0 != system "/home/fanf2/bin/blog", $link, $text) { print "failed to blog $link $text\n" if $d; next; } cmd "STORE $n +FLAGS (\\Deleted)" unless $t; } cmd "EXPUNGE"; cmd "LOGOUT"; exit;