#!/usr/bin/perl # Filename: Mail.cgi # Author: David Ljung Madison # See License: http://MarginalHacks.com/License # Version: 1.01 # use strict; umask 0022; my $HOST = $ENV{HTTP_HOST} || $ENV{SERVER_NAME} || "GetDave.com"; $HOST="lo:3001" if $ENV{PWD} eq "/data/proj/Mail"; # Development kludge! my $CGI = $ENV{REQUEST_URI} || "/cgi-bin/DaVite.cgi"; # Guess if REFERER not found $CGI =~ s/[\&\?][^\/]+$//; my $URL = "http://$HOST$CGI"; # Theme directory (absolute filesystem path, *not* a URL) my $THEME_DIR = "/WWW/cgi-bin/Mail.Themes"; # Theme. Does %substitution if desired. If file not found, use Default # Example: http://Bob.GetDave.com/Mail.cgi # %s -> subdomain Bob # %d -> domain GetDave.com # %h -> host Bob.GetDave.com # %c -> CGI Mail # my $THEME = "%h"; # Now create files: (To, Header, Footer) in $THEME_DIR/$THEME/ # Header and Footer contain exactly what you would expect. # 'To' contains the destination and an optional name. It is of the format: # # # You can also create a file 'sig' to use as a signature. ######################### # Where is sendmail? (forge_pipe is best!) ######################### my $SENDMAIL = "/usr/local/sbin/forge_pipe"; # See http://MarginalHacks.com/#forge $SENDMAIL = "/usr/bin/forge_pipe" unless -x $SENDMAIL; $SENDMAIL = "/usr/sbin/forge_pipe" unless -x $SENDMAIL; $SENDMAIL = "/usr/sbin/sendmail" unless -x $SENDMAIL; $SENDMAIL = "/usr/lib/sendmail" unless -x $SENDMAIL; $SENDMAIL = "/usr/bin/sendmail" unless -x $SENDMAIL; # Do we wrap the $SENDMAIL call in sudo? # Requires an entry in /etc/sudoers: # = NOPASSWD: # For example: # apache getdave = NOPASSWD: /usr/local/sbin/forge_pipe my $USE_SUDO = 0; # And where is sudo? my $SUDO = "/usr/bin/sudo"; $USE_SUDO = 0 unless -x $SUDO; ################################################## # Query ################################################## sub from_url($) { my ($str) = @_; $str =~ s/\+/ /g; $str =~ s/%([0-9a-f]{2})/chr(hex($1))/eig; $str; } sub to_url($) { my ($str) = @_; $str =~ s/([^ a-zA-Z0-9\.])/"%".sprintf("%0.2x",ord($1))/eg; $str =~ s/ /+/g; $str; } sub parse_query { # Get query my $query_string; if ($ENV{REQUEST_METHOD} eq "POST") { read(STDIN,$query_string,$ENV{CONTENT_LENGTH}); } elsif ($ENV{QUERY_STRING}) { $query_string = $ENV{QUERY_STRING}; } chomp($query_string); # Split query # $query_string is of the form: "variable=value&var2=val2&.." my @querys=split(/[\&\?]/,$query_string); my (%query,$var,$val); foreach my $str (@querys) { $var = $str if (!(($var,$val) = ($str =~ /([^=]*)=(.*)/))); $val = 1 unless defined $val; $query{$var} = from_url($val) unless $var eq "RAW"; $query{RAW}{$var} = $val; } #header(1); show_values(\%query); \%query; } sub show_values { my ($query) = @_; header(); print "


\n\n"; foreach my $q ( keys %$query ) { print "yo $q -> $query->{$q}
\n"; } } ################################################## # HTML ################################################## my $DID_HEADER=0; sub header { my ($theme) = @_; return if $DID_HEADER++; print <{Header} HEADER } sub ERROR { header(); print "

ERROR: @_

\n"; undef; } sub FATAL { header($_[1]); print "

ERROR: $_[0]

\n"; footer($_[1]); exit(0); } sub footer { my ($theme) = @_; my $foot = $theme->{Footer}; $foot .= "\n\n" unless $foot =~ m|
$me by Dave's Marginal Hacks
NOTE $foot =~ s| Subject: $subject To: $to X-Mailer: $URL $msg MAIL_MESSAGE close MAIL; return 1; } ################################################## # Theme code ################################################## sub slurp($) { my ($file) = @_; open(SLURP,"<$file") || return ""; my @c = ; close SLURP; wantarray ? @c : join("",@c); } sub get_theme() { my %theme; (-d $THEME_DIR) || FATAL("Can't read theme directory!"); my $theme = $THEME; my ($sub,$dom) = ($HOST=~/((.*)\.)?([^\.]+\.[^\.]+)/) ? ($2,$3) : ("",$HOST); my $cgi = $CGI; $cgi =~ s|.*/||g; $cgi =~ s|\.cgi||g; $theme =~ s/%s/$sub/g; $theme =~ s/%d/$dom/g; $theme =~ s/%h/$HOST/g; $theme =~ s/%c/$cgi/g; my $save = $theme; (-d "$THEME_DIR/$theme") || ($theme="Default"); (-d "$THEME_DIR/$theme") || FATAL("Couldn't find theme or default [$THEME_DIR/$save]!"); foreach my $slurp ( qw(Header Footer To sig) ) { $theme{$slurp} = slurp "$THEME_DIR/$theme/$slurp"; } my @to = split(/\n/,$theme{To}); $theme{to_mail} = $to[0]; $theme{to_name} = $to[1] || $to[0]; $theme{sig} = $theme{sig} || <{from}; my $subject = $query->{subject}; $subject =~ s/"/"/g; my $message = $query->{message}; $message =~ s|
From:
To: $theme->{to_name}
Subject:
Message:
MAIL_FORM } sub handle_mail { my ($query,$theme) = @_; # Avoid long emails that can be used to figure out the key my $from = $query->{from}; $from =~ s/^\s+//; $from =~ s/\s+$//; if ($from !~ /(\S+)\@\S+\.\S\S/) { ERROR("Please enter a valid email address"); return mail_form($query,$theme); } unless ($query->{subject}) { ERROR("Please enter a subject"); return mail_form($query,$theme); } unless ($query->{message}) { ERROR("Please enter a message"); return mail_form($query,$theme); } my $n = "&n=".to_url $query->{n}; send_mail($theme->{to_mail},0,"[Contact] $query->{subject}",$from,"Contact Mailer",<{message} $theme->{sig} MESSAGE_URL print <Mail sent!

You have sent a mail to $theme->{to_name}

Thanks!

SENT_URL } ################################################## # Do it ################################################## sub main { my $theme = get_theme; my $query = parse_query(); if ($query->{from}) { handle_mail($query,$theme); } else { mail_form($query,$theme); } footer($theme); # If we need did the default header } main();