#!/usr/bin/perl -T # tinymail.pl: a tiny webmail script for mobile devices (e.g. cellphone) # features: pagination of output, gzip compression, minimalist screen footprint # see rfc3501.txt for IMAP syntax # Andrew Daviel TRIUMF Jun 2007 # released under Apache Licence 2.0 http://www.apache.org/licenses/LICENSE-2.0 # version 0.2 $domain = 'example.com' ; $method = $ENV{'REQUEST_METHOD'} ; $path = $ENV{'PATH_INFO'} ; $agent = $ENV{'HTTP_USER_AGENT'} ; $content_type = $ENV{'CONTENT_TYPE'} ; $content_length = $ENV{'CONTENT_LENGTH'} ; $cookie = $ENV{'HTTP_COOKIE'} ; $query = $ENV{'QUERY_STRING'} ; $referer = $ENV{'HTTP_REFERER'}; $len = $ENV{'CONTENT_LENGTH'}; $script = $ENV{'SCRIPT_NAME'}; $auth = $ENV{'AUTH_TYPE'} ; $SSL = $ENV{'HTTPS'} ; if ($ENV{'REMOTE_USER'} =~ /^([\w\-]+)$/) { $user = $1 ; # untaint my ($name,$passwd,$uid,$gid, $quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam ($user) ; chdir ($dir) ; } else { $user = 'nobody'; } $debug = 0 ; $ENV{'PATH'} = "/usr/local/sbin:/usr/sbin:/bin:/usr/local/bin:" ; $gzip = ($ENV{'HTTP_ACCEPT_ENCODING'} =~ /gzip/) ; $gzip = 1 ; #$| = 1 ; # lengths to trim index fields to: $nowidth = 4 ; $flagwidth = 2 ; $fromwidth = 15 ; $datewidth = 8; $subjwidth = 25 ; $soft = 50 ; $hard = 80 ; $ppage0 = 20 ; # default lines per page $format = '%'.$nowidth.'d ' ; $format .= '%'.$flagwidth.'.'.$flagwidth.'s ' ; $format .= '%-'.$fromwidth.'.'.$fromwidth.'s ' ; $format .= '%-'.$datewidth.'.'.$datewidth.'s ' ; $format .= '%-'.$subjwidth.'.'.$subjwidth."s\n" ; $spaces = ' ' ; if ($method eq 'POST') { read(STDIN, $buffer, $len) ; } elsif ($method eq 'GET') { $buffer = $query ; } foreach $pair (split(/&/, $buffer)) { $pair =~ tr/+/ /; $pair =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; ($name, $value) = split(/=/, $pair); $F{$name} = $value ; } $debug = $F{'debug'} ; $table = $F{'table'} ; $ppage = $F{'ppage'} ; unless ($ppage) { $ppage = $ppage0 ; } $msg = $F{'msg'} ; $op = $F{'op'} ; $part = $F{'part'} ; $type = $F{'type'} ; $start=$F{'start'} ; $code = $F{'code'} ; if ($F{'submit'} eq 'Prev' or $F{'submit'} eq 'Back') { $start = $F{'prev'} ; } $mailbox = $F{'mailbox'} ; if ($F{'to'} =~ /^([\w\-\.]+\@[\w\-\.]+)$/ or $F{'to'} =~ /<([\w\-\.]+\@[\w\-\.]+)>/) { $recip = $1 ; } use IPC::Open2; $SIG{'TERM'} = "clean" ; $SIG{'INT'} = "clean" ; unless ($mailbox) { $mailbox = 'INBOX' ; } if ($op eq 'Read' and $type and $msg and $part) { if ($type =~ /^image/i or !$gzip) { print "Content-Type: $type\nVary: Accept-Encoding\n\n" ; } else { print "Content-Type: $type\nContent-Encoding: x-gzip\nVary: Accept-Encoding\n\n" ; } $| = 1 ; print STDERR "Content-Type: $type msg $msg part $part\n" ; $pid = open2(\*RDRFH, \*WTRFH, "imapd") ; $seq = 0 ; &send("SELECT $mailbox") ; &rdselect ; &send("FETCH $msg BODY[$part]") ; $body = '' ; while () { chomp ; tr/\r//d ; if (/^$seq OK/) { last ; } if (/^[\d]+ NO/ or /^[\d]+ BAD/) { $body .= "Error: $_
\n" ; &logout ; } if (/^\* [\d]+ FETCH/) { next ; } if (/^\)$/) { next ; } if ($type =~ /text.html/i) { s/