X-Git-Url: http://git.vanrenterghem.biz/www.vanrenterghem.biz.git/blobdiff_plain/4b1ce0d83844cfd7c55e75a60ccb239882cd62e3..83ab5456767602f2a9860a7db7247f002ec96945:/gmailsmtp.pl diff --git a/gmailsmtp.pl b/gmailsmtp.pl deleted file mode 100644 index 7d3c2e3..0000000 --- a/gmailsmtp.pl +++ /dev/null @@ -1,462 +0,0 @@ -#!/usr/bin/perl -#--------------------------------------------------------------------------------# -# PROGRAM: gmailsmtp.pl # -# This program was designed to act as a proxy SMTP server on a # -# linux system that relays its outbound mail through a gmail # -# account via HTTPS. # -# # -# Copyright (C) 2005 Frederik Vanrenterghem # -# # -# This program is free software; you can redistribute it and/or # -# modify it under the terms of the GNU General Public License # -# as published by the Free Software Foundation; either version 2 # -# of the License, or (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program; if not, write to the Free Software # -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.# -# # -# CREATED: 2005/05/21 by Frederik Vanrenterghem # -# # -# VERSION: 0.1.0 # -# # -# CREDITS: James C. Specht, Jr. # -# For his gsr.pl v.0.8.0, which supplied the majority # -# of the code for v.0.1.0 # -# # -#--------------------------------------------------------------------------------# - -use Mail::Webmail::Gmail; -use Net::SMTP::Server; -use Net::SMTP::Server::Client; -use IO::Socket::INET; -use IO::Socket::SSL; -use Net::SSLeay; -use Digest::HMAC_MD5 qw(hmac_md5_hex); -use MIME::Base64 qw(encode_base64 decode_base64); -use Getopt::Long; -use Term::ReadKey; -use Proc::Daemon; -use Sys::Syslog; - -$SIG{CHLD} = 'IGNORE'; - -my ($configfile,$ehlo_ok,$from,@to,$msgsrc,$dohelp,$sock,$code,$text,$more, - %features,$server,$conn,$verbose,$version,$daemon,$relayfile,@relayIP, - $pidfile,$client); - -$configfile="/usr/local/etc/gmailsmtp.conf"; -$relayfile="/usr/local/etc/gmailsmtp.relay"; -$pidfile="/usr/local/var/run/gmailsmtp.pid"; -$verbose=0; -$daemon=0; -$version="0.1.0"; - -# Get command line options. -GetOptions ('config-file=s' => \$configfile, - 'relay-file=s' => \$relayfile, - 'verbose:1' => \$verbose, - 'daemon:1' => \$daemon, - 'help:1' => \$dohelp ); - -require "$configfile"; - -if ($dohelp == 1 ) {&usage();} - -# Force this process out as a daemon. -if ($daemon >= 1) { - Proc::Daemon::Init; - # Since we are a daemon process log to syslog facility. - openlog('gmailsmtp','pid','mail'); - syslog('info','gmailsmtp.pl daemon process loading'); - $verbose=0; - # Write our pid out. - open(FPID, ">$pidfile"); - print FPID "$$"; - close(FPID); -} - -$ehlo_ok = 1; - -if ($gmailserver =~ /^(.*):(.*)$/) { - $gmailserver = $1; - $gmailport = $2; -} - -if ($daemon >= 1) - { syslog('info',"Gmail relay set to $gmailserver:$gmailport"); } - -if (!defined ($gmailusername)) { - dienice ("Missing \$gmailusername in $configfile!"); -} - -syslog('info',"Gmail user account is $gmailusername") if ($daemon >= 1); - -if ($gmailpassword eq "") { - # We are a daemon so we can't asked for the gmail account password! - if ($daemon >= 1) { - syslog('info',"Missing \$gmailpassword in $configile!"); - syslog('info','Aborting startup!'); - exit; - } - printf ("Enter password for %s : ", $gmailusername); - # Set echo off. - ReadMode (2); - $gmailpassword = <>; - # Restore echo. - ReadMode (0); - printf ("\n"); - - exit if (! defined ($gmailpassword)); - chop ($gmailpassword); -} - -# Build the relayIP table -BuildRelayIPTable(); - -&StartSMTPServer(); -closelog(); -exit(); - -sub StartSMTPServer -{ - my $i, $IPaddr, $size, $nrcpt; - - $server = new Net::SMTP::Server($localserver,$localport) || - dienice ("Unable to start SMTP Server on $localserver:$localport!"); - - while($conn = $server->accept()) { - printf("\nNew connection!\n\n") if ($verbose >= 1); - - my $pid = fork(); - - if ($pid) {undef($conn);} # this is the parent process - dienice ("Can't create child process!") unless defined $pid; - unless($pid) { # $pid == 0 means we're the child - - $client = new Net::SMTP::Server::Client($conn) || - dienice ("Unable to start SMTP client connection!"); - - # Capture the IP address of our client. - $IPaddr = $client->{SOCK}->peerhost(); - - syslog('info',"Incoming connection from [$IPaddr]") if ($daemon >= 1); - printf("\nConnection from [$IPaddr]\n") if ($verbose >= 1); - - # Do we allow this IP to relay through us? - if (AllowRelay($IPaddr) == 0) { - warnnice("Connection refused to [$IPaddr]"); - } - - if ($client->process) { - if ($verbose >= 1 ) { - printf("MAIL FROM: $client->{FROM}\n"); - for ($i=0; $i <= $#client->{TO}; $i++) { - printf("RCPT TO: $client->{TO}[i]\n"); - } - printf("DATA:\n\n$client->{MSG}\n"); - } - # Now relay the msg on. - $from = $client->{FROM}; - for ($i=0; $i <= $#client->{TO}; $i++) - { $to[$i] = $client->{TO}[$i];} - $msgsrc = $client->{MSG}; - - if ($daemon >= 1) { - $size = length($msgsrc); - $nrcpt = $#to + 1; - syslog('info',"from=$from, size=$size, nrcpt=$nrcpt"); - for ($i=0; $i <= $#to; $i++) - { syslog('info',"to=$to[$i]"); } - } - - printf("Relay via GMail account $gmailusername...\n") if ($verbose >= 1); - if ($daemon >= 1) - { syslog('info',"relay via GMail account $gmailusername"); } - - &RelayOurMSG(); - #$client->shutdown; - exit 1; - } - } - undef $client; - } -} - -sub RelayOurMSG -{ -###nieuw vanaf hier -if ($verbose >= 1) - {printf("Connecting to GMail...\n");} - my ( $gmail ) = Mail::Webmail::Gmail->new( - username => $gmailusername, password => $gmailpassword, proxy_name=> $proxy_name, ); - -if ($verbose >= 1) - {printf("Connection to Gmail established.\n");} - -if ($verbose >= 1) - {printf("Attempting to send message.\n");} - - my $msgid = $gmail->send_message - ( to => $to[0], - subject => time(), - msgbody => $msgsrc ); - print "Msgid: $msgid\n"; - if ( $msgid ) { - if ( $gmail->error() ) { - if ($verbose >= 1) - {printf("We ran into a problem. Attempting to display the problem...\n");} - print $gmail->error_msg(); - } else { - ### Create new label ### - if ($verbose >= 1) - {printf("Creating new label\n");} - my $test_label = "tl_" . time(); - $gmail->edit_labels( label => $test_label, action => 'create' ); - if ( $gmail->error() ) { - print $gmail->error_msg(); - } else { - ### Add this label to our new message ### - $gmail->edit_labels( label => $test_label, action => 'add', 'msgid' => $msgid ); - if ( $gmail->error() ) { - print $gmail->error_msg(); - } else { - print "Added label: $test_label to message $msgid\n"; - } - } - } - } -###tot hier - - # Good bye... - if ($verbose >= 1) - {printf("Message sent succesfully.\n");} - if ($daemon >= 1) { - syslog('info',"Message relay successful"); - } -} - -# This is the main SMTP "engine". -sub run_smtp -{ - - - # We can do a relay-test now if a recipient was set. - if ($#to >= 0) { - if (!defined ($from)) { - $from = "<$gmailusername>"; - if ($verbose >= 1) - {printf("From: address not set. Using $gmailusername.\n");} - if ($daemon >= 1) - {syslog('info',"From: address not set. Using $gmailusername.");} - } - &send_line ($sock, "MAIL FROM: %s\n", $from); - ($code, $text, $more) = &get_line ($sock); - if ($code != 250) { warnnice ("MAIL FROM failed: '$code $text'\n"); } - - my $i; - for ($i=0; $i <= $#to; $i++) { - &send_line ($sock, "RCPT TO: %s\n", $to[$i]); - ($code, $text, $more) = &get_line ($sock); - if ($code != 250) { - warnnice ("RCPT TO ".$to[$i]." "."failed: '$code $text'\n"); - } - } - } - - # Wow, we should even send something! - if (defined ($msgsrc)) - { - &send_line ($sock, "DATA\n"); - ($code, $text, $more) = &get_line ($sock); - if ($code != 354) { warnnice ("DATA failed: '$code $text'\n"); } - - if ($verbose >= 1) { - printf("Sending the following.\n\n"); - printf("$msgsrc\n"); - } - - $sock->printf ("$msgsrc\r\n.\r\n"); - - ($code, $text, $more) = &get_line ($sock); - if ($code != 250) { warnnice ("DATA not sent: '$code $text'\n"); } - } - - # Perfect. Everything succeeded! - return 1; -} - -# Get one line of response from the server. -sub get_line ($) -{ - my $sock = shift; - my ($code, $sep, $text) = ($sock->getline() =~ /(\d+)(.)([^\r]*)/); - my $more; - if ($sep eq "-") { $more = 1; } else { $more = 0; } - printf ("[%d] '%s'\n", $code, $text) if ($verbose >= 1); - return ($code, $text, $more); -} - -# Send one line back to the server -sub send_line ($@) -{ - my $socket = shift; - my @args = @_; - - printf ("> ") if ($verbose >= 1); - printf (@args) if ($verbose >= 1); - $socket->printf (@args); -} - -# Helper function to encode CRAM-MD5 challenge -sub encode_cram_md5 ($$$) -{ - my ($ticket64, $username, $password) = @_; - my $ticket = decode_base64($ticket64) or - dienice ("Unable to decode Base64 encoded string '$ticket64'"); - - my $password_md5 = hmac_md5_hex($ticket, $password); - return encode_base64 ("$username $password_md5", ""); -} - -# Store all server's ESMTP features to a hash. -sub say_hello ($$$$) -{ - my ($sock, $ehlo_ok, $gmailhello, $featref) = @_; - my ($feat, $param); - my $hello_cmd = $ehlo_ok ? "EHLO" : "HELO"; - - &send_line ($sock, "$hello_cmd $gmailhello\n"); - my ($code, $text, $more) = &get_line ($sock); - - if ($code != 250) { warnnice ("$hello_cmd failed: '$code $text'\n"); } - - # Empty the hash - %{$featref} = (); - - ($feat, $param) = ($text =~ /^(\w+)[= ]*(.*)$/); - $featref->{$feat} = $param; - - # Load all features presented by the server into the hash - while ($more == 1) { - ($code, $text, $more) = &get_line ($sock); - ($feat, $param) = ($text =~ /^(\w+)[= ]*(.*)$/); - $featref->{$feat} = $param; - } - - return 1; -} - -sub warnnice { - my ($txt) = @_; - - if ( $daemon >= 1 ) { - syslog('info', $txt); - syslog('info', 'Connection terminated!'); - } - else { - printf("\n$txt\n"); - printf("Connection terminated!\n"); - } - if ($sock) { - printf("Shutdown!!!!!\n"); - &send_line ($sock, "QUIT\n"); - } - if ($client) { $client->shutdown;} - exit 1; -} - -sub dienice { - my ($txt) = @_; - - if ( $daemon >= 1 ) { - syslog('info', $txt); - syslog('info',"Aborting"); - } - else { - printf("\n$txt\n"); - printf("Aborting\n\n"); - } - if ($client) {$client->shutdown;} - exit 1; -} - -sub AllowRelay($) { - - my $IP = shift; - my $i; - - for ($i=0; $i <= $#relayIP; $i++) { - if ($IP =~ /^$relayIP[$i]/) { return "1";} - } - - # Did not find a match. - return "0"; -} - -sub BuildRelayIPTable { - - my ($i); - - $i=0; - - if ($verbose >= 1) { printf("Loading relay table from $relayfile\n");} - if ($daemon >= 1) { syslog('info',"Loading relay table from $relayfile");} - - open(INFILE, "$relayfile") || dienice("Cannot open relay file $relayfile!"); - while($line = ) { - $line =~ s/#.*//; # ignore comments by erasing them - next if $line =~ /^(\s)*$/; # skip blank lines - chomp($line); - if ($verbose >= 1) { printf("Adding [$line] to relay table\n");} - if ($daemon >= 1) {syslog('info',"Adding [$line] to relay table");} - - $relayIP[$i++] = $line; - } - close(INFILE); -} - -sub usage () -{ - printf ("\nA simple SMTP server that relays local email through a gmail account via HTTPS. - -Author: Frederik Vanrenterghem - http://vanrenterghem.biz/ - -Version: $version - -Usage: gmailsmtp.pl [--options] - - --config-file= The location of the gmailsmtp.conf file. - (default: /usr/local/etc/gmailsmtp.conf) - --relay-file= The location of the gmailsmtp.relay file. - (default: /usr/local/etc/gmailsmtp.relay) - --verbose Be verbose instead of silent. - --daemon Start as daemon process. - --help Shows you this output. - -Current Options: - - \$gmailserver = [$gmailserver] - \$gmailport = [$gmailport] - \$gmailusername = [$gmailusername]\n"); - - if ($gmailpassword ne "") { - printf (" \$gmailpassword = [is set]\n"); - } else { - printf (" \$gmailpassword = [is NOT set]\n"); - } - - printf (" \$gmailhello = [$gmailhello] - \$localserver = [$localserver] - \$localport = [$localport] -"); - exit (0); -} - - \ No newline at end of file