############################################################ # SMTPMAIL_LIB.PL # # This script was written by Gunther Birznieks. # Date Created: 2-22-96 # Date Last Modified: 5-5-96 #-------------------------------------------------------------- # Note: save this script as mail-lib.pl in Perl/Lib in NT # added by Al Bento - 06/07/1997 #-------------------------------------------------------------- # You may copy this under the terms of the GNU General Public # License or the Artistic License which is distributed with # copies of Perl v5.x for UNIX. # # Purpose: Provides a set of library routines to send email # over the internet. It communicates using TCP/IP Sockets directly # to SMTP (Simple Mail Transfer Protocol) # # Modified by Gunther Birznieks 3-19-96 to run on PERL 5 for Windows NT # as well as the Solaris system it was originally written under # # Main Procedures: # real_send_mail - flexible way to send email # send_mail - easier to use version of real_send_mail # # Special Notes: Script is UNIX Specific and ties into the # Sendmail Program which is usually located in /usr/lib or # /usr/bin. # # Also, remember to escape @ signs with a backslash (\@) # for compatibility with PERL 5. # # Change the $mail_program variable to change location of your # sendmail program # # Set the $mail_os variable equal to NT if you are on Windows NT perl # Set it to UNIX for normal UNIX operations. # # If you do not have a version of PERL with the Socket.pm, you # can manually define $AF_INET and $SOCK_STREAM to 2 and 1 respectively. # On some systems, SOCK_STREAM may be 2. # # NOTE: This program does not support MX DNS records which is # an important part of the internet mail standard. Use sendmail_lib.pl # if you can since the sendmail daemon on unix supports MX records. ############################################################ # Use the Sockets library for TCP/IP Communications use Socket; $mail_os = "NT"; ############################################################ # # subroutine: real_send_mail # Usage: # &send_mail("me@myhouse.com","myhouse.com","you@yourhouse.com", # "yourhouse.com", "Mysubject", "My message"); # # Parameters: # $fromuser = Full Email address of sender # $fromsmtp = Full Internet Address of sender's SMTP Server # $touser = Full Email address of receiver # $tosmtp = Full Internet Address of receiver's SMTP Server # $subject = Subject of message # $messagebody = Body of message including newlines. # # Output: # None ############################################################ sub real_send_mail { local($fromuser, $fromsmtp, $touser, $tosmtp, $subject, $messagebody) = @_; local($ipaddress, $fullipaddress, $packconnectip); local($packthishostip); local($AF_INET, $SOCK_STREAM, $SOCK_ADDR); local($PROTOCOL, $SMTP_PORT); local($buf); # We start off by making the message that will be sent # By combining the subject with the message body text # $messagebody = "Subject: $subject\n\n" . $messagebody; # The following variables are set using values defined in # The sockets.pm library. If your version of perl (v4) does # not have the sockets library, you can substitute some # default values such as 2 for AF_INIT, and 1 for SOCK_STREAM. # if 1 does not work for SOCK_STREAM, try using 2. # # AF_INET defines the internet class of addressing # # SOCK_STREAM is a variable telling the program to use # a socket connection. This varies from using SOCK_DGRAM # which would send UDP datagrams using a connectionless paradigm # instead. # # PROTOCOL is TCPIP (6). # # PORT is 25 for SMTP service. # # SOCK_ADDR is the packeted format of the full socket address # including the AF_INIT value, SMTP_PORT, and IP ADDRESS in that order # $AF_INET = AF_INET; $SOCK_STREAM = SOCK_STREAM; $SOCK_ADDR = "S n a4 x8"; # The following routines get the protocol information # $PROTOCOL = (getprotobyname('tcp'))[2]; $SMTP_PORT = (getservbyname('smtp','tcp'))[2]; $SMTP_PORT = 25 unless ($SMTP_PORT =~ /^\d+$/); $PROTOCOL = 6 unless ($PROTOCOL =~ /^\d+$/); # Ip address is the Address of the host that we need to connect # to $ipaddress = (gethostbyname($tosmtp))[4]; $fullipaddress = join (".", unpack("C4", $ipaddress)); $packconnectip = pack($SOCK_ADDR, $AF_INET, $SMTP_PORT, $ipaddress); $packthishostip = pack($SOCK_ADDR, $AF_INET, 0, "\0\0\0\0"); # First we allocate the socket socket (S, $AF_INET, $SOCK_STREAM, $PROTOCOL) || &web_error( "Can't make socket:$!\n"); # Then we bind the socket to the local host bind (S,$packthishostip) || &web_error( "Can't bind:$!\n"); # Then we connect the socket to the remote host connect(S, $packconnectip) || &web_error( "Can't connect socket:$!\n"); # The following selects the socket handle and turns off # output buffering # select(S); $| = 1; select (STDOUT); # The following sends the information to the SMTP Server. # The first connect should give us information about the SMTP # server $buf = read_sock(S, 6); print S "HELO $fromsmtp\n"; $buf = read_sock(S, 6); print S "MAIL From:<$fromuser>\n"; $buf = read_sock(S, 6); print S "RCPT To:<$touser>\n"; $buf = read_sock(S, 6); print S "DATA\n"; $buf = read_sock(S, 6); print S $messagebody . "\n"; print S ".\n"; $buf = read_sock(S, 6); print S "QUIT\n"; close S; } #end of real_send_mail ############################################################ # # subroutine: send_mail # Usage: # &send_mail("me@myhouse.com","you@yourhouse.com", # "Mysubject", "My message"); # # Parameters: # $fromuser = Full Email address of sender # $touser = Full Email address of receiver # $subject = Subject of message # $messagebody = Body of message including newlines. # # Output: # None # ############################################################ sub send_mail { local($from, $to, $subject, $messagebody) = @_; local($fromuser, $fromsmtp, $touser, $tosmtp); # This routine takes the simpler parameters of # send_mail and breaks them up into the parameters # to be sent to real_send_mail. # $fromuser = $from; $touser = $to; # # Split is used to break the address up into # user and hostname pairs. The hostname is the # 2nd element of the split array, so we reference # it with a 1 (since arrays start at 0). # $fromsmtp = (split(/\@/,$from))[1]; $tosmtp = (split(/\@/,$to))[1]; # Actually call the sendmail routine with the # newly generated parameters # &real_send_mail($fromuser, $fromsmtp, $touser, $tosmtp, $subject, $messagebody); } # End of send_mail ############################################################ # # subroutine: read_sock # Usage: # &read_socket(SOCKET_HANDLE, $timeout); # # Parameters: # SOCKET_HANDLE = Handle to an allocated Socket # $timeout = amount of time read_sock is allowed to # wait for input before timing out # (measured in seconds) # # Output: # Buffer containing what was read from the socket # ############################################################ sub read_sock { local($handle, $endtime) = @_; local($localbuf,$buf); local($rin,$rout,$nfound); # Set endtime to be time + endtime. $endtime += time; # Clear buffer $buf = ""; # Clear $rin (Read Input variable) $rin = ''; # Set $rin to be a vector of the socket file handle vec($rin, fileno($handle), 1) = 1; # nfound is 0 since we have not read anything yet $nfound = 0; # Loop until we time out or something was read read_socket: while (($endtime > time) && ($nfound <= 0)) { # Read 1024 bytes at a time $length = 1024; # Preallocate buffer $localbuf = " " x 1025; # NT does not support select for polling to see if # There are characters to be received. This is important # Because we dont want to block if there is nothing # being received. $nfound = 1; if ($mail_os ne "NT") { # The following polls to see if there is anything in the input # buffer to read. If there is, we will later call the sysread routine $nfound = select($rout=$rin, undef, undef,.2); } } # If we found something in the read socket, we should # get it using sysread. if ($nfound > 0) { $length = sysread($handle, $localbuf, 1024); if ($length > 0) { $buf .= $localbuf; } } # Return the contents of the buffer $buf; } ############################################################ # # subroutine: web_error # Usage: # &web_error("File xxx could not be opened"); # # Parameters: # $error = Description of Web Error # # Output: # None # ############################################################ sub web_error { local ($error) = @_; $error = "Error Occured: $error"; print "$error

\n"; # Die exits the program prematurely and prints an error to # stderr die $error; } # end of web_error 1;