#!/usr/bin/perl # Filename: forge # Author: David Ljung # Description: Forges email # TODO: Get the headers out of the email in case they've changed # (Such as a new from address changes the from_machine) use strict; use English; $ENV{'PATH'} = '/bin:/usr/bin'; delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; my ($SAVE_UID,$SAVE_GID) = ($UID,$GID); ($UID,$GID) = ($EUID,$EGID); # XXX: initgroups() not called umask 022; ################################################## # Setup the variables ################################################## my $PROGNAME = $0; $PROGNAME =~ s|.*/||; # Where to save mail my $OUTBOUND = "/home/madison/Mail/OUTBOUND/new"; # Sendmail method: my $SENDMAIL="/usr/lib/sendmail"; # Port 25 method: Where we normally send mail through my $DEFAULT_MAILHOST="localhost"; my $TELNET="/usr/bin/telnet"; # Choose an editor my $EDITOR = "/bin/vim"; $EDITOR = "/usr/bin/vim" if (!$EDITOR || ! -x $EDITOR); $EDITOR = "/bin/vi" if (!$EDITOR || ! -x $EDITOR); $EDITOR = "/usr/bin/vi" if (!$EDITOR || ! -x $EDITOR); die("[$PROGNAME] Couldn't find editor to use\n") if (!$EDITOR || ! -x $EDITOR); # Sig file (or a directory of sigs - we'll pick one randomly) my $SIG="~/.sig"; #my $SIG="~/.elm/sigs"; my $DEFAULT_SIG = "-- \nDavid Ljung Madison http://GetDave.com\n"; ################################################## # Usage ################################################## sub usage { my $msg; foreach $msg (@_) { print "ERROR: $msg\n"; } print "\n"; print "Usage:\t$MAIN::PROGNAME [-f from] [-F name] [-s subject] [-t to]\n"; print " \t\t[-d] [-25 [mail_host]]\n"; print "\tForges a mail message\n"; print "\t-f\tFrom address\n"; print "\t-F\tFrom full name\n"; print "\t-t\tTo address\n"; print "\t-s\tSubject\n"; print "\n"; print "\t-d\tSet debug mode\n"; print "\t-25\tUse port 25 method\n"; print "\n"; exit -1; } sub parse_args { my $host; my ($from,$from_full,$to,$subject); # DEFAULTS $from = "some.com\@daveola.com"; $from_full = "David Ljung Madison"; #$to = "svlug\@lists.svlug.org"; $to = "madison"; while ($#ARGV>=0) { $a=shift(@ARGV); if($a =~ /^-h$/) { &usage; } if($a =~ /^-d$/) { $MAIN::DEBUG=1; next; } if($a =~ /^-25$/) { $MAIN::PORT25=1; next; } if($a =~ /^-f$/) { $from=shift(@ARGV); next; } if($a =~ /^-F$/) { $from_full=shift(@ARGV); next; } if($a =~ /^-t$/) { $to=shift(@ARGV); next; } if($a =~ /^-s$/) { $subject=shift(@ARGV); next; } if($a =~ /^-/) { &usage("Unknown option: $a"); } &usage("You can only specify one mailhost [$a and $host]") if(defined($host)); $host=$a; } $host=$DEFAULT_MAILHOST if(!defined($host)); ($host,$from,$from_full,$to,$subject); } ################################################## # Char-by-char mode ################################################## sub char_mode { my $ttyname=`/usr/bin/tty`; $ttyname =~ /(.+)/; $ttyname = $1; # Ignore taint warnings system "/bin/stty -icanon -echo min 1 < $ttyname " if (! $?); } sub line_mode { my $ttyname=`/usr/bin/tty`; $ttyname =~ /(.+)/; $ttyname = $1; # Ignore taint warnings `/usr/bin/tty -s`; system "/bin/stty icanon echo < $ttyname " if (! $? ); } sub get_char { my $ans; read(STDIN,$ans,1); return $ans; } ################################################## # Get the header fields ################################################## sub get_header { my ($query,$default) = @_; my $ret; print STDERR $default ? "$query [$default]: " : "$query: "; chomp($ret = <>); $ret || $default; } ################################################## # Get the signature file ################################################## sub get_sig { my $txt; my $sig_file=$SIG; # Handle '~' in path $sig_file =~ s/\~/$ENV{HOME}/g if (defined($ENV{HOME})); # If it's a directory then pick one file if (-d $sig_file) { if (!opendir(SIG,$sig_file)) { print STDERR "Couldn't open sig directory: $sig_file\n"; sleep 1; return ""; } my @sigs=grep(!/^\.{1,2}$/,readdir(SIG)); closedir(SIGS); $sig_file="$sig_file/".$sigs[int(rand(scalar(@sigs)))]; } # Read the file and return the text if (open(SIG,"<$sig_file")) { $txt=join('',); close(SIG); return $txt; } return $DEFAULT_SIG; # print STDERR "Couldn't open sig file: $sig_file\n"; # sleep 1; # return ""; } ################################################## # Main code ################################################## sub main { my ($host,$from,$from_full,$to,$subject) = parse_args(); my $file = "${PROGNAME}.$$"; die unless $file =~ /^([-\w.]+)$/; $file = $1; $file = "/tmp/$file"; ######################### # Get the mail information ######################### $from=get_header("From address",$from); $from_full=get_header("From name",$from_full); $to=get_header("To",$to); $subject=get_header("Subject",$subject); my $date = gmtime(); my $sig=get_sig(); my $from_machine=$from; $from_machine =~ s/.*\@//; ######################### # Create the file ######################### open(FILE,">$file") || die("Couldn't write $file\n"); # Headers print FILE "From: $from_full <$from>\n"; print FILE "Subject: $subject\n"; print FILE "To: $to\n"; print FILE "Date: $date\n"; print FILE "X-Mailer: DaveMail [version 6.0]\n"; print FILE "In-Reply-To: your_mom\n"; print FILE "\n"; # Body print FILE "EMAIL_TEXT_GOES_HERE\n"; # Sig print FILE "\n$sig"; close(FILE); ######################### # Edit loop ######################### while(1) { system("$EDITOR $file"); print STDERR "S)end the message, E)dit it again, F)orget it (saved), X)eXit\n"; print STDERR "\nWhat is your choice? s"; char_mode(); my $ans=get_char; line_mode(); print "$ans\n"; if ($ans =~ /X/i) { unlink($file); exit; } if ($ans =~ /F/i) { print "File saved in: $file\n"; chown $SAVE_UID, $SAVE_GID, $file; exit; } next if ($ans =~ /E/i); last if ($ans =~ /S/i || $ans =~ /\n/); } ######################### # Mail it ######################### if ($MAIN::PORT25) { open(FILE,"<$file") || die("Couldn't open mail file! $file\n"); open(MAIL,"|$TELNET $host 25 > /dev/null") || die("Couldn't open socket to $host\n"); print MAIL "helo $from_machine\n"; print MAIL "mail from: $from\n"; print MAIL "rcpt to: $to\n"; print MAIL "data\n"; while() { # Make sure we don't die early s/^\.$/. /g; print MAIL; } print MAIL ".\n"; print MAIL "quit\n"; close(MAIL); close(FILE); } else { system("$SENDMAIL -i -f $from -F \"$from_full\" $to < $file"); } ($UID,$GID) = ($SAVE_UID,$SAVE_GID); # Save a copy (hack!) if ($OUTBOUND && open(OUT,">>$OUTBOUND")) { if (open(MAIL,"<$file")) { print OUT "\nFrom $from $date\n"; while () { print OUT; } close(MAIL); } close(OUT); } # Delete the file unlink($file); } &main;