 
 
 
 
 
 
 
  
 Next: Receiving Mail (POP)
 Up: Sending Mail (SMTP)
 Previous: Reporting Undeliverable Mail
Enough theory let's 
see some actual Perl code.
The sendmail.pl program below does just this. It' basic operation is as follows:
(Some comments have been added to indicate changes that are needed for porting to
some machines)
-  Turn on the warning compiler option.
-  Load the Socket.
-  Turn on the strict pragma.
-  Initialize $mail To  which holds the
recipient's mail address.
-  Initialize $mailServer
which holds the symbolic name of your mail server.
-  Initialize $mailFrom
which holds the originator's mail address.
-  Initialize $realName  which
holds the text that appears in the From header field.
-  Initialize $subject
which holds the text that appears in the Subject header field.
-  Initialize $body
which holds the text of the letter.
-  Declare a signal handler for the Interrupt signal. This handler
will trap users hitting Ctrl+c or Ctrl+break.
-  Get the protocol number for the tcp protocol and the port number
for the smtp service. Recall: Windows 95 and NT do not implement the 
getprotobyname()or getservbyname()
functions so default values are supplied.
-  Initialize $serverAddr 
with the mail server's Internet address.
-  The $length
variable is tested to see if it is defined, if not, then the
gethostbyname()  function failed.
-  Create a socket called SMTP 
using standard parameters.
-  Initialize $packedFormat
with format specifiers.
-  Connect the socket to the port on the mail server.
-  Change the socket to use unbuffer input/output. Normally, sends
and receives are stomiles in an internal buffer before being sent
to your script. This line of code eliminates the buffering steps.
-  Create a temporary buffer. The buffer is temporary because it
is local to the block surrounded by the curly brackets.
-  Read two responses from the server. Some servers send two reponses
when the connection is made. Your server may only send one response -- If so, delete one
of the recv()  calls.
-  Send the HELO
command. The sendSMTP() 
function will take care of reading the response.
-  Send the MAIL
command indicating where messages that the mail server sends back
(like undeliverable mail messages) should be sent.
-  Send the RCPT 
command to specify the recipient.
-  Send the DATA
command.
-  Send the body of the letter. Note that no reponses are received
from the mail server while the letter is sent.
-  Send a line containing a single period indicating that you are
finished sending the body of the letter.
-  Send the QUIT
command to end the conversation.
-  Close the socket.
-  Define the closeSocket()
function which will act as a signal handler.
-  Close the socket.
-  Call die()
to display a message and end the script.
-  Define the send SMTP()
function.
-  Get the debug parameter.
-  Get the smtp 
command from the parameter array.
-  Send the smtp 
command to STDERR 
if the debug parameters were true.
-  Send the smtp
command to the mail server.
-  Get the mail server's response.
Send the response to STDERR
if the debug parameter were true.
-  Split the response into reply code and message, and return just
the reply code.
The Perl code for sendmail.pl is as follows:
#!/usr/bin/perl -w
use Socket;
use strict;
my($mailTo)     = 'dave@cs.cf.ac.uk';
my($mailServer) = 'mailhost2.cs.cf.ac.uk';
my($mailFrom)   = 'dave@cs.cf.ac.uk';
my($realName)   = "Ralph Martin";
my($subject)    = 'Test';
my($body)       = "Test Line One.\nTest Line Two.\n";
$main::SIG{'INT'} = 'closeSocket';
my($proto)      = getprotobyname("tcp")        || 6;
my($port)       = getservbyname("SMTP", "tcp") || 25;
my($serverAddr) = (gethostbyname($mailServer))[4];
if (! defined($length)) {
    die('gethostbyname failed.');
}
socket(SMTP, AF_INET(), SOCK_STREAM(), $proto)
    or die("socket: $!");
$packFormat = 'S n a4 x8';   # Windows 95, SunOs 4.1+
#$packFormat = 'S n c4 x8';   # SunOs 5.4+ (Solaris 2)
connect(SMTP, pack($packFormat, AF_INET(), $port, $serverAddr))
    or die("connect: $!");
select(SMTP); $| = 1; select(STDOUT);    # use unbuffemiles i/o.
{
    my($inpBuf) = '';
    recv(SMTP, $inpBuf, 200, 0);
    recv(SMTP, $inpBuf, 200, 0);
}
sendSMTP(1, "HELO\n");
sendSMTP(1, "MAIL From: <$mailFrom>\n");
sendSMTP(1, "RCPT To: <$mailTo>\n");
sendSMTP(1, "DATA\n");
send(SMTP, "From: $realName\n", 0);
send(SMTP, "Subject: $subject\n", 0);
send(SMTP, $body, 0);
sendSMTP(1, "\r\n.\r\n");
sendSMTP(1, "QUIT\n");
close(SMTP);
sub closeSocket {     # close smtp socket on error
    close(SMTP);
    die("SMTP socket closed due to SIGINT\n");
}
sub sendSMTP {
    my($debug)  = shift;
    my($buffer) = @_;
    print STDERR ("> $buffer") if $debug;
    send(SMTP, $buffer, 0);
    recv(SMTP, $buffer, 200, 0);
    print STDERR ("< $buffer") if $debug;
    return( (split(/ /, $buffer))[0] );
}
This program displays:
> HELO
< 250 sentinel.cs.cf.ac.uk Hello dave@miles.cs.cf.ac.uk
    [207.3.100.120], pleased to meet you
> MAIL From: <dave@cs.cf.ac.uk>
< 250 <dave@cs.cf.ac.uk>... Sender ok
> RCPT To: <mail@net.cf.ac.uk>
< 250 <mail@net.cf.ac.uk>... Recipient ok
> DATA
< 354 Enter mail, end with "." on a line by itself
>
.
< 250 TAA12656 Message accepted for delivery
> QUIT
< 221 sentinel.cs.cf.ac.uk closing connection
The lines in bold are the commands that were sent to the server.
The body of the letter is not shown in the output.
 
 
 
 
 
 
 
  
 Next: Receiving Mail (POP)
 Up: Sending Mail (SMTP)
 Previous: Reporting Undeliverable Mail
dave@cs.cf.ac.uk