home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 35 Internet
/
35-Internet.zip
/
wrpdis20.zip
/
SENDIT.CMD
< prev
next >
Wrap
OS/2 REXX Batch file
|
1996-04-21
|
16KB
|
468 lines
/****************************************************************************/
/* SENDIT.CMD - an ka9q compatible OS/2 smtp client */
/* Copyright (C) 1995,1996 Alex Chapman <alex@budgetweb.com> */
/* */
/* 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* */
/* Requires rxsock.zip from IBM Employee Written Software */
/* <ftp://src.doc.ic.ac.uk/packages/os2/ibm/ews/rxsock.zip> */
/* */
/* Last Modified: 21st April, 1996 */
Version = 1.25
/****************************************************************************/
/************************************************************/
/* Change History */
/************************************************************/
/* 0.1 950117 First version */
/* 0.11 950118 Fixed . --> .. conversion */
/* 0.12 950119 Added progress indicator for long notes */
/* 0.14 950127 Issue QUIT before closing socket */
/* 0.15 950129 Fixed dot transparency rfc821 4.5.2 */
/* 0.16 950131 Removed GNU license for purposes of testing */
/* 0.17 950204 Implement a control queue for a control prog*/
/* 0.50 950205 Final Beta Release */
/* 1.00 950211 First Release */
/* 1.01 950416 added logfile parameter */
/* 1.02 950418 added code to read KA9Q variable */
/* 1.03 950505 removed setting of send buffer */
/* 1.04 950505 correct logfile parameter to sendit.log */
/* 1.20 950510 read settings from sendit.ini */
/* 1.21 950521 moved call to readinifile */
/* 1.22 950621 use WARPDIS as rexx queue */
/* 1.23 950718 move queue settings into ini file */
/* 1.24 960421 handle multiple recipients in wrk file */
/* 1.25 960421 handle multi line responses from smtp daemon*/
/************************************************************/
arg gnu rest
port = 25 /* SMTP port */
crlf = d2c(13)||d2c(10) /* CR + LF */
ControlQ = '' /* Control Queue */
CurrentQ = '' /* Current Queue */
Say 'SENDIT.CMD - OS/2 SMTP client (version' version')'
Say 'Copyright (C) 1995 Alex Chapman'
Say "SENDIT comes with ABSOLUTELY NO WARRANTY; for details type 'SENDIT w'."
Say 'This is free software, and you are welcome to redistribute it under certain'
Say "conditions; type `SENDIT c' for details."
Say
call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
call SysLoadFuncs
Call ReadINIFile 'SENDIT.INI', 'SENDIT'
Select
When gnu = 'C' Then Do
Call ShowConditions
Exit 0
End
When gnu = 'W' Then Do
Call ShowWarranty
Exit 0
End
When gnu = 'H' | gnu = '?' Then Do
Exit 0
End
When gnu = 'Q' Then Do
Say 'The Q parameter is now obsolete, and has been superceded by the use of'
Say 'the ini settings queue_messages and queue_name'
Exit 0
End
When gnu<>'' Then Do
Say 'Invalid parameter. Process terminated.'
Exit 0
End
Otherwise
End
If queue_messages = 'YES' Then Do
ControlQ = queue_name
CurrentQ = RXQUEUE('Create', ControlQ)
If CurrentQ<>ControlQ Then Do
Call RXQUEUE 'Delete', CurrentQ
End
CurrentQ = RXQUEUE('Set', ControlQ)
Call SendMsg '<SENDIT> START'
End
Call RxFuncAdd 'SockLoadFuncs', 'RxSock', 'SockLoadFuncs'
Call SockLoadFuncs('QUIET')
if Right(mqueue, 1)<>'\' Then mqueue = mqueue || '\'
Call SysFileTree mqueue||'*.wrk', 'file', 'FO'
If file.0 = 0 Then Do
Say 'No mail queued'
Call SendMsg '<SENDIT> STOP SENDIT 0'
Exit 0
End
If file.0 = 1 Then Do
Say 'One mail item to deliver'
End
Else Do
Say file.0 'mail items to deliver'
End
retcode = SockGetHostByName(server, 'host.!')
If retcode = 0 Then Do
Say 'SockGetHostByName()' errno
Call SendMsg '<SENDIT> FAIL SOCK' errno
Exit errno
End
server = host.!addr;
Say 'SMTPSERVER' server
heloplace = SockGetHostID()
retcode = SockGetHostByAddr(heloplace, 'host.!')
If retcode = 0 Then Do
Say 'SockGetHostByName()' errno
Call SendMsg '<SENDIT> FAIL SOCK' errno
Exit errno
End
heloplace = host.!name
Say 'local host' heloplace
/* Open Socket */
socket = SockSocket('AF_INET', 'SOCK_STREAM', 0)
If socket < 0 Then Do
Say 'SockSocket()' errno
Call SendMsg '<SENDIT> FAIL SOCK' errno
Exit errno
End
/* I'm not sure why I need to do this, but it seems to be the only
thing that will allow me to deliver large notes. Without this,
SockSend() reports good return codes, even when post hasn't received
anything. Consequently, I go ploughing on sending stuff, and post
never seems to catch up. Anyway, setting SO_SNDBUF to 0 is a workaround */
/* Since applying the PPP upgrade (950501) attempting to set the send buffer
to zero has caused the program to hang. Upon commenting out this line
everything appears to work fine. If you have problems with this program
try changing the value of sendbuffer_patch from 0 to 1 near the top */
If sendbuffer_patch = 1 Then Do
retcode = SockSetSockOpt(socket, "SOL_SOCKET", "SO_SNDBUF", "0")
If retcode < 0 Then Do
Say 'SockSetSockOpt()' errno
Call SendMsg '<SENDIT> FAIL SOCK' errno
Exit errno
End
End
signal on halt
Call Log '-------------------------------------------------------------'
Call Log 'SENDIT version' version 'started' date() time()
Call Log 'local host' heloplace
/* Connect Socket */
server.!family = 'AF_INET'
server.!port = port
server.!addr = server
retcode = SockConnect(socket,'server.!')
If retcode < 0 Then Do
Say 'SockConnect()' errno
Call SendMsg '<SENDIT> FAIL SOCK' errno
Exit errno
End
/* Get response from connect */
reply = GetResponse(socket)
If reply<>220 Then Do
Say reply 'from server after connect. Expected 220.'
Call SendMsg '<SENDIT> FAIL NNTP' reply
Call halt
End
data = 'HELO' heloplace || crlf
Call MySockSend socket, data
reply = GetResponse(socket)
If reply<>250 Then Do
Say reply 'from server after HELO' heloplace' - Expected 250.'
Call SendMsg '<SENDIT> FAIL NNTP' reply
Call halt
End
Do i = 1 to file.0
Parse upper var file.i stem'.WRK'
lock = stem || '.LCK'
note = stem || '.TXT'
work = stem || '.WRK'
number = FileSpec("name", stem)
If chars(lock)=0 Then Do /* The mail item isn't locked */
retcode = stream(lock, 'c', 'open write')
retcode = Stream(work, 'c', 'open read')
Parse value linein(work) with domain
Parse value linein(work) with from
numto = 0
Do While Lines(work) <> 0
numto = numto + 1
Parse value linein(work) with to.numto
End
retcode = Stream(work, 'c', 'close')
doneto = 0
Do j = 1 to numto
retcode = SendMail(socket, to.j, from, note)
If retcode=0 Then Do /* mail was transmitted successfully */
Say 'Mail ('i'/'file.0') posted ('number')' from 'to' to.j
Call Log 'Mail ('i'/'file.0') posted ('number')' from 'to' to.j
doneto = doneto + 1
End
Else Do
Say 'Mail ('i'/'file.0') failed ('number') return 'RC from 'to' to
Call Log 'Mail ('i'/'file.0') failed ('number') return 'RC from 'to' to
End
End
If doneto = numto Then Do
Call SysFileDelete work
Call SysFileDelete note
End
retcode = Stream(lock, 'c', 'close')
Call SysFileDelete lock
End
Else Do
Say 'Mail ('i'/'file.0') locked ('number')' from 'to' to
Call Log 'Mail ('i'/'file.0') locked ('number')' from 'to' to
End
End
Call SendMsg '<SENDIT> STOP SENDIT' file.0
Call Log 'process complete'
/* Close socket */
halt:
If CurrentQ <> '' Then Do
Call RXQUEUE 'Set', CurrentQ
End
Say 'Quitting...'
Call MySockSend socket, 'QUIT'crlf
Say 'Closing socket...'
retcode = SockSoClose(socket)
If retcode < 0 Then Do
Say 'SockSoClose()' errno
Exit errno
End
Exit 0
SendMail: Procedure expose ControlQ CurrentQ crlf
Parse arg socket, to, from, note
retcode = Stream(note, 'c', 'open read')
If retcode <> 'READY:' Then Do
Say 'note' note 'missing'
Return 1
End
Else Do
data = 'MAIL FROM:<'from'>'crlf
Call MySockSend socket, data
reply = GetResponse(socket)
If reply<>250 Then Do
Say reply 'from server after MAIL FROM:<'from'> - Expected 250.'
Call halt
End
data = 'RCPT TO:<'to'>'crlf
Call MySockSend socket, data
reply = GetResponse(socket)
If reply<>250 Then Do
Say reply 'from server after RCPT TO:<'to'> - Expected 250.'
Call halt
End
data = 'DATA'crlf
Call MySockSend socket, data
reply = GetResponse(socket)
If reply<>354 Then Do
Say reply 'from server after DATA - Expected 354.'
Call halt
End
line = 0
Do While Lines(note)<>0
line = line + 1
data.line = LINEIN(note)
End
Parse value ProgressIndicator(0, line, row, col) with row, col
Do i = 1 to line
If Left(data.i, 1) = '.' Then data.i = '.' || data.i
data = data.i || crlf
Call MySockSend socket, data
Parse value ProgressIndicator(i, line, row, col) with row, col
End
data = crlf||'.'||crlf
Call MySockSend socket, data
reply = GetResponse(socket)
If reply<>250 Then Do
Say reply 'from server after .CRLF - Expected 250.'
Call halt
End
retcode = Stream(note, 'c', 'close')
Return 0
End
/* Shouldn't really get here */
Return 99
MySockSend: Procedure
Parse arg socket, data
retcode = 0
Do While retcode < Length(data)
retcode = SockSend(socket, data)
If retcode < 0 Then Do
Say 'SockSend()' errno
Call SendMsg '<SENDIT> FAIL SOCK' errno
Exit errno
End
If retcode < Length(data) Then Do
data = Substr(data, retcode + 1)
retcode = 0
End
End
Return
ProgressIndicator: Procedure
arg current, total, row','col
If current = 0 Then Do /* Initialise */
Say
Say
Parse value SysCurPos() with row col
row = row - 2
Call SysCurState('OFF')
End
If current = total Then Do
Call SysCurState('ON')
End
Call SysCurPos row,col
progress = Trunc( current / total * 20)
Say Copies(d2c(219), progress)||Copies(d2c(254), 20-progress)||,
'['Trunc(current / total*100)'%]'
Return row','col
/* smtp should only ever send single line replies, and we're
only really interested in the first reply code bit */
GetResponse: Procedure expose ControlQ CurrentQ crlf
Parse arg socket .
buffer = ''
Do Until Datatype(reply)='NUM'
Do While Pos(crlf, buffer) = 0
retcode = SockRecv(socket, 'data', 10000)
If retcode < 0 Then Do
Say 'SockRecv()' errno
Call SendMsg '<SENDIT> FAIL SOCK' errno
Exit errno
End
buffer = buffer || data
End
Parse value Left(buffer, Pos(crlf, buffer) - 1) with reply .
buffer = Substr(buffer, Pos(crlf, buffer) + 2)
End
Return reply
Log: Procedure expose logfile crlf ControlQ CurrentQ
Parse arg line
retcode = Stream(logfile, 'c', 'open write')
retcode = LINEOUT(logfile, line)
retcode = Stream(logfile, 'c', 'close')
Return
SendMsg: Procedure expose ControlQ CurrentQ
Parse arg message
If ControlQ <> '' & ControlQ <> 'CONTROLQ' Then Do
Queue message
End
Return
ReadINIFile:
arg inifile, application
file = SysSearchPath('PATH',inifile)
If file = '' Then Do
Say 'Unable to find' inifile
Exit 1
End
app = ''
ini. = 0
retcode = Stream(file, 'c', 'open read')
If retcode <> 'READY:' Then Do
Say 'Unable to open' file
Exit 2
End
Do While Lines(file) <> 0
line = LINEIN(file)
If Left(line, 1) = '[' Then Do
Parse Upper var line '[' app ']' .
End
Else Do
If line <> '' & Left(line, 1) <> '#' Then Do
If app = '' Then Do
Say 'Invalid line in' file 'expected [application_name]'
Exit 1
End
If app = application | app = 'DEFAULT' Then Do
Parse var line varname '=' varvalue
Parse Upper var varname varname
varname = Strip(varname)
varvalue = Strip(varvalue)
If ini.varname = 0 | app = application Then Do
retcode = Value(varname, varvalue)
ini.varname = 1
End
End
End
End
End
retcode = Stream(file, 'c', 'close')
Return
ShowWarranty:
Say 'Because the program is licensed free of charge, there is no warranty'
Say 'for the program, to the extent permitted by applicable law. Except when'
Say 'otherwise stated in writing the copyright holders and/or other parties'
Say 'provide the program "as is" without warranty of any kind, either expressed'
Say 'or implied, including, but not limited to, the implied warranties of'
Say 'merchantability and fitness for a particular purpose. The entire risk as'
Say 'to the quality and performance of the program is with you. Should the'
Say 'program prove defective, you assume the cost of all necessary servicing,'
Say 'repair or correction.'
Say
Say 'Read the GNU PUBLIC LICENSE for full details'
Return
ShowConditions:
Say 'You may copy and distribute verbatim copies of the Program''s'
Say 'source code as you receive it, in any medium, provided that you'
Say 'conspicuously and appropriately publish on each copy an appropriate'
Say 'copyright notice and disclaimer of warranty; keep intact all the'
Say 'notices that refer to this License and to the absence of any warranty;'
Say 'and give any other recipients of the Program a copy of this License'
Say 'along with the Program.'
Say
Say 'Read the GNU PUBLIC LICENSE for full details'
Return