/* ============================================================================ . 25 Jan 1999 . . MAILIT: An OS/2 REXX procedure to mail a note to several recipients. . . Called as: . status=mailit(address_list,message_string,smtp_gateway,sender_address,verbose) . where: . address_list: A space delimited list of addresses . message_string: A message string, that may contain CRLFs (and may be rather long) . smtp_gateway: The address of your SMTP server . optional_senders_address: The sender's address (optional) . If sender's address is not given, it will be generated using the HOSTNAME command. . verbose: if 1, then report status messages . and . status : 0 if failure detected, 1 if success . . . Example: . status=mailit("BOB@HIS.NET" , "This is my message ", "MAIL.MY.ORG" ) . or . status= mailit("BOB@HIS.NET JILL@HER.COM " , "This is my message ", , . "MAIL.HAPPYFACE.ORG", "HARRY@MY.ORG") . .NOTES: . SMTP gateway addresses. . If you are using an INTERNET provider, try using their SMTP gateway address. . . If no such address is available, you can try running the OS/2 SENDMAIL program, and . use your hostname as the SMTP gateway address. . For example, assuming that SENDMAIL.UML is in c:\mptn\etc, . before starting GoServe you should start sendmail with: . [C:]START SENDMAIL -bd -q30m -Cc:\mptn\etc\sendmail.uml . Alternatively, you can use AUTOSTART sendmail using the TCPCFG program. . . Note on recipient addresses: . The message will be sent to each address. Since the addresses are . sent and then the message, this allows for fairly rapid mailing to multiple . individuals. . . Acknowledgment: . This is a modification of a routine written by Dave Briccetti (see acknowledgment at . bottom of file) . It was first modified by Daniel Hellerstein for use in SRE-http in 1996. . . ============================================================================ */ mailit: parse arg whotos , themessage , smtpaddress , sender_address,verbose smtpaddress=strip(smtpaddress) sender_address=strip(sender_address) /* set some constants */ CRLF = '0d0a'x TRUE = 1 FALSE = 0 REPLYTYPE_OK = '2' /* SMTP reply code first byte */ REPLY_START_MAIL_INPUT = '354' /* SMTP reply code */ if sender_address="" then do do queued(); pull .; end address cmd '@hostname | rxqueue' parse pull sendinghost sendinguser="WebServer" sender_address=sendinguser||'@'||sendinghost end MailServer = smtpaddress /* Mail server, leave blank if you are connected through a LAN */ if \RxFuncQuery("SockLoadFuncs") then nop else do call RxFuncAdd "SockLoadFuncs","rxSock","SockLoadFuncs" call SockLoadFuncs end if EstablishProtocol() = FALSE then return 0 /* The protocol initiated, we'll now send the message to each recipient */ call SendMsgToEachRecipient /* QUIT ends the protocol */ CmdReply = TransactSmtpCommand(socket, 'QUIT', 1) /* Close the socket */ call SockSoClose socket return 1 /* ========================================================================= */ SetConstants: /* ========================================================================= */ return /* ========================================================================= */ EstablishProtocol: /* ========================================================================= */ socket = ConnectToMailServer(MailServer) if socket <= 0 then do if verbose>0 then say 'Could not connect to mail server' return FALSE end CmdReply = GetCmdReply(socket) if left(CmdReply, 1) \= REPLYTYPE_OK then do if verbose>0 then say 'Could not establish protocol' return FALSE end /* Send the extended hello, in case this SMTP server supports SMTP extensions */ CmdReply = TransactSmtpCommand(socket, 'EHLO', 1) SizeExtensionSupported = 0 if left(CmdReply, 1) = REPLYTYPE_OK then do /* That worked, so enable extended SMTP processing. If the response to the EHLO indicates support for SIZE, enable our use of that feature */ SmtpExtensionsSupported = TRUE if pos('250 SIZE', CmdReply) > 0 | pos('250-SIZE', CmdReply) > 0 then SizeExtensionSupported = 1 end else do /* The server didn't recognize the EHLO so we'll go with the regular HELO */ SmtpExtensionsSupported = FALSE SizeExtensionSupported = FALSE CmdReply = TransactSmtpCommand(socket, 'HELO', 1) end if left(CmdReply, 1) = REPLYTYPE_OK then return TRUE else return FALSE /* ========================================================================= */ SendMsgBody: /* ========================================================================= */ /* DATA tells the server that the body of the message is coming. It should reply with a code meaning "go ahead." */ CmdReply = TransactSmtpCommand(socket, 'DATA', 1) if substr(CmdReply, 1, 3) = REPLY_START_MAIL_INPUT then do /* Send the data, followed by a '.' on a line by itself to indicate the end of the message */ CmdReply = TransactSmtpCommand(socket, MsgFileContents || CRLF || '.', 0) end return /* ========================================================================= */ SendMsgToEachRecipient: /* ========================================================================= */ /* MsgFileContents = charin(MessageFile, 1, chars(MessageFile)) call stream MessageFile, 'c', 'close' */ msgfilecontents=themessage MsgFileContents = strip(MsgFileContents, 't', '1a'x) /* Strip EOF */ /* MAIL FROM identifies the sender. The SIZE= extension provides the size of the message, to allow the server to quickly refuse messages bigger than it wants. */ MailFromCmd = 'MAIL FROM:' ||sender_address if SizeExtensionSupported then MailFromCmd = MailFromCmd 'SIZE=' || length(MsgFileContents) CmdReply = TransactSmtpCommand(socket, MailFromCmd, 1) if left(CmdReply, 1) = REPLYTYPE_OK then whotos=translate(whotos,' ','000d0a1a09'x) do while whotos<> "" parse var whotos whoto whotos RecipientEmailAddress = strip(whoto) if RecipientEmailAddress \= '' then /* RCPT identifies the intended recipient of the message */ CmdReply = TransactSmtpCommand(socket,, "RCPT TO:" || RecipientEmailAddress, 1) /*say " cmdreply " cmdreply*/ end /* do */ call SendMsgBody return /* ========================================================================= */ ConnectToMailServer: procedure expose verbose /* ========================================================================= */ parse arg MailServer socket = 0 /* Open a socket to the mail server. (The Sock* functions are documented in the REXX Socket book in the Information folder in the OS/2 System folder */ call SockInit if SockGetHostByName(MailServer, 'host.!') = 0 then do if verbose>0 then say 'Could not get host by name' errno h_errno end else do socket = SockSocket('AF_INET','SOCK_STREAM',0) address.!family = 'AF_INET' address.!port = 25 /* the standard SMTP port */ address.!addr = host.!addr if SockConnect(socket, 'address.!') = -1 then do if verbose>0 then say 'Could not connect socket' errno h_errno end end return socket /* ========================================================================= */ GetCmdReply: procedure expose verbose /* ========================================================================= */ parse arg socket CRLF = '0d0a'x /* Receive the response to the SMTP command into a variable. Use more than one socket read if necessary to collect the whole response. */ if SockRecv(socket, 'CmdReply', 200) < 0 then do if verbose>0 then say 'Error reading from socket' errno h_errno exit 0 end ReadCount = 1 MaxParts = 10 do while ReadCount < MaxParts & right(CmdReply, 2) \= CRLF if SockRecv(socket, 'CmdReplyExtra', 200) < 0 then do if verbose>0 then say 'Error reading from socket' exit 0 end CmdReply = CmdReply || CmdReplyExtra ReadCount = ReadCount + 1 end return CmdReply /* ========================================================================= */ TransactSmtpCommand: /* ========================================================================= */ parse arg socket, Cmd, SayCmd /* Send a command to the SMTP server, echoing it to the display if requested */ if SayCmd then if verbose>0 then say " Command is " Cmd rc = SockSend(socket, Cmd || CRLF) return GetCmdReply(socket) /* ------------- Original Acknowledgement ------------------------------ Most of this e-mail routine was obtained from: Send Email Message to a Mailing List Via SMTP, Using the REXX Socket Interface Written by a novice REXX programmer Dave Briccetti, November 1995 daveb@davebsoft.com, http://www.davebsoft.com May be used for any purpose Thanks to REXX expert Charles Daney and internet expert David Singer for looking over the code ---------------------------------------------------------- */