home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / defdata / smtp.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  67.0 KB  |  2,370 lines

  1. --::::::::::::::
  2. --slog.ada
  3. --::::::::::::::
  4. -----------------------------------------------------------------------
  5. --
  6. --         DoD Protocols    NA-00006-200       80-01133-100(-)
  7. --         E-Systems, Inc.  August 07, 1985
  8. --
  9. --         slog.ada       Author : Paul Higgins
  10. --
  11. -----------------------------------------------------------------------
  12. package ssmtp_logger is
  13.  
  14. procedure error_log (msg : string) ;
  15.  
  16. end ssmtp_logger ;
  17.  
  18.  
  19. -- debug version
  20. with text_io ; use text_io ;
  21. package body ssmtp_logger is
  22.  
  23. procedure error_log (msg : string) is
  24. begin
  25. --- may also record connection info, such as usmtp host, usmtp name, etc
  26. put_line(msg) ;
  27. end error_log ;
  28.  
  29. end ssmtp_logger ;
  30. --::::::::::::::
  31. --sglobs.ada
  32. --::::::::::::::
  33. -----------------------------------------------------------------------
  34. --
  35. --         DoD Protocols    NA-00006-200       80-01132-100(-)
  36. --         E-Systems, Inc.  August 07, 1985
  37. --
  38. --         sglobs.ada       Author : Paul Higgins
  39. --
  40. -----------------------------------------------------------------------
  41. package ssmtp_globals is
  42.  
  43. -- here are the conditions which interrupt 
  44. --  normal flow of control:
  45.  
  46. sudden_connection_close : exception ;
  47.  -- connection closed or connection aborted
  48. transport_error         : exception ;
  49.  -- unexpected message from transport 
  50. ssmtp_reset             : exception ;
  51.  -- reset command received
  52. ssmtp_quit              : exception ;
  53.  -- quit command received 
  54.  
  55.  
  56. --&KJW 21-jul-85 transport_connection_open : boolean ;
  57. transport_connection_open : boolean := false;    --&KJW 21-jul-85 
  58.  -- state of the transport connection
  59.  
  60.  
  61. --
  62. -- this is to support the list of local receivers
  63. -- smtp_rcpt creates this list
  64. -- smtp_deliver uses it 
  65. --
  66. subtype user_name_type is string (1..80) ;
  67. subtype host_name_type is string (1..80) ;
  68. max_rcpt           : constant integer := 80 ;
  69. rcpt_list          : array (1..max_rcpt) of user_name_type ;
  70. number_of_rcpt     : integer range 0..max_rcpt ;
  71.  
  72. source_host        : host_name_type ;
  73. source_host_length : integer range 0..80 ;
  74. source_name        : user_name_type ;
  75. source_name_length : integer range 0..80 ;
  76.  
  77. --
  78. -- used to parse the smtp commands
  79. --
  80. max_command_length : constant integer := 80 ;
  81. command            : string (1..4) ;
  82.   -- 4 letter smtp command, lower case
  83. command_parms      : string (1..max_command_length) ;
  84.   -- the rest of the received command
  85. parm_length        : integer range 0..max_command_length ;
  86.  
  87. --
  88. -- where the mail message is saved 
  89. --
  90. type lines is record
  91.   message_line : string(1..512) ;
  92.   line_length  : integer ;
  93.   end record ;
  94. max_message_length : constant integer := 2048 ;
  95. message            : array (1..max_message_length) of lines ;
  96. message_length     : integer ;
  97.  
  98. procedure reset_receive_buffers ;
  99.   -- prepare to receive a new message
  100.  
  101. end ssmtp_globals ;
  102.  
  103. package body ssmtp_globals is
  104.  
  105. procedure reset_receive_buffers is
  106.   begin
  107.   number_of_rcpt := 0 ;
  108.   message_length := 0 ;
  109. end reset_receive_buffers ;
  110.  
  111.  
  112. end ssmtp_globals ;
  113.  
  114. --::::::::::::::
  115. --strans_.ada
  116. --::::::::::::::
  117. -----------------------------------------------------------------------
  118. --
  119. --         DoD Protocols    NA-00006-200       80-01141-100(-)
  120. --         E-Systems, Inc.  August 07, 1985
  121. --
  122. --         strans_.ada       Author : Paul Higgins
  123. --
  124. -----------------------------------------------------------------------
  125. package ssmtp_transport is
  126. --
  127. -- all the procedures required to interface to the transport service
  128. --
  129.  
  130. procedure send_passive_open ;
  131. -- send a listen on the well-known smtp socket
  132.  
  133. procedure wait_for_open  ;
  134. -- wait for the open ok message
  135.  
  136. procedure close_connection ;
  137. -- send a close to transport layer, wait for close ok message
  138.  
  139. procedure send_string (str : in string) ;
  140. -- send a character string via the transport protocol
  141.  
  142. procedure get_command ;
  143. -- this procedure gets an entire command from the transport layer
  144. -- puts the first four letters, in lower case, in ssmtp_globals.command
  145. -- and leaves the rest in ssmtp_globals.command_line 
  146. -- may raise the following exceptions:
  147. --   sudden_connection_close
  148. --   transport_error
  149.  
  150. procedure get_a_line( str : out string;
  151.                       len : out integer ) ;
  152. -- this procedure gets an entire line from the transport layer
  153. -- may raise the following exceptions:
  154. --   sudden_connection_close
  155. --   transport_error
  156.  
  157.  
  158. end ssmtp_transport ;
  159. --::::::::::::::
  160. --strans.ada
  161. --::::::::::::::
  162. -----------------------------------------------------------------------
  163. --
  164. --         DoD Protocols    NA-00006-200       80-01142-100(-)
  165. --         E-Systems, Inc.  August 07, 1985
  166. --
  167. --         strans.ada       Author : Paul Higgins
  168. --
  169. -----------------------------------------------------------------------
  170. with ssmtp_globals ;         use ssmtp_globals ;
  171. with text_io ;               use text_io ;
  172. with ssmtp_logger ;          use ssmtp_logger ;
  173. with with_ulp_communicate ;  use with_ulp_communicate ;
  174. with buffer_data;            use buffer_data ;
  175.  
  176. package body ssmtp_transport is
  177.  
  178. package int_io_16 is new integer_io(sixteen_bits) ;
  179.  
  180. --------------------------------------------------------------------------------
  181.  
  182. current_lcn : lcn_ptr_type ;
  183.  
  184. --------------------------------------------------------------------------------
  185.  
  186.  
  187. --
  188. -- This is a local procedure to send a receive request to tcp
  189. -- We should always have a few outstanding receives for tcp to put data into
  190. --
  191. procedure send_a_receive is
  192. request_ok : boolean ;
  193. tcp_params : with_ulp_communicate.message(receive) ;
  194. a_buf      : packed_buffer_ptr ;
  195. begin
  196. buffget(a_buf,1) ;
  197. if a_buf = null then
  198.     error_log("Could not get a buffer") ;
  199.     raise constraint_error ;   -- crash the connection
  200. end if ;
  201. tcp_params.receive_parameters.local_connection_name := current_lcn ;
  202. tcp_params.receive_parameters.bufptr := a_buf ;
  203. tcp_params.receive_parameters.byte_count := 190 ;
  204. message_for_tcp(tcp_params,request_ok) ;
  205. if not request_ok then
  206.    raise transport_error ;
  207. end if ;
  208. exception
  209.   when others => 
  210.     error_log("Exception in send_a_receive") ;
  211.     raise ;
  212. end send_a_receive ;
  213.  
  214.  
  215.  
  216. procedure send_passive_open is
  217. request_ok : boolean ;
  218. tcp_params : with_ulp_communicate.message(open) ;
  219. begin
  220. -- do a listen on the tcp port for smtp mail service.
  221. tcp_params.open_parameters.local_connection_name := current_lcn ;
  222. tcp_params.open_parameters.local_port := 25 ;
  223. tcp_params.open_parameters.foreign_port := 0 ;
  224. tcp_params.open_parameters.foreign_net_host := 0 ;
  225. tcp_params.open_parameters.active_passive := passive ;
  226. tcp_params.open_parameters.buffer_size := 0 ;
  227. tcp_params.open_parameters.timeout := 2000 ;
  228. tcp_params.open_parameters.security := 0 ;
  229. tcp_params.open_parameters.precedence := 0 ;
  230. tcp_params.open_parameters.options := (others => 0) ;
  231. message_for_tcp(tcp_params,request_ok) ;
  232. current_lcn := tcp_params.open_parameters.local_connection_name ;
  233. if not request_ok then
  234.    raise transport_error ;
  235. end if ;
  236. exception
  237.   when others => 
  238.     error_log("Exception in send_passive_open") ;
  239.     raise ;
  240. end ;
  241.  
  242.  
  243.  
  244.  
  245. --------------------------------------------------------------------------------
  246. --------------------------------------------------------------------------------
  247.  
  248.  
  249.  
  250.  
  251. procedure wait_for_open is
  252. reply : user_message ;
  253. begin
  254. loop 
  255.   reply.local_connection_name := current_lcn ;
  256.   wait_for_tcp_message (reply) ;
  257.   case reply.message_number is
  258.     when 23 =>
  259.       send_a_receive ; -- leave a receive pending
  260.       transport_connection_open := true;    --&KJW 21-jul-85 
  261.       exit ;
  262.     when 14 =>
  263.       current_lcn.lcn_ptr := reply.local_connection_name.lcn_ptr ;
  264.     when 2 | 5 | 9 | 11 | 20 =>
  265.       put("could not open, reason code = ") ;
  266.       int_io_16.put(reply.message_number) ;
  267.       put_line (" ." ) ;
  268.     when 8 | 16 =>
  269.       put_line("connection aborted") ;
  270.       raise transport_error ;
  271.     when others =>
  272.       put("connection message") ;
  273.       int_io_16.put(reply.message_number) ;
  274.       new_line ;
  275.     end case ;
  276. end loop ;
  277. exception
  278.   when others => 
  279.     error_log("Exception in wait_for_open") ;
  280.     raise ;
  281. end wait_for_open ;
  282.  
  283.  
  284.  
  285.  
  286. --------------------------------------------------------------------------------
  287. --------------------------------------------------------------------------------
  288.  
  289.  
  290.  
  291. procedure close_connection is
  292. --
  293. -- Send a close command to tcp and wait for a connection_closed response.
  294. --
  295. tcp_params : with_ulp_communicate.message(close) ;
  296. reply : user_message ;
  297. request_ok : boolean ;
  298. begin
  299. --&KJW 11-jul-85 put_line("closing transport connection") ;
  300. --&KJW 11-jul-85 tcp_params.abort_close_parameters.local_connection_name := current_lcn ;
  301. --&KJW 11-jul-85 message_for_tcp(tcp_params,request_ok) ;  
  302. --&KJW 11-jul-85 if not request_ok then
  303. --&KJW 11-jul-85   raise transport_error ;
  304. --&KJW 11-jul-85 end if ;
  305. --&KJW 11-jul-85 reply.local_connection_name := current_lcn ;
  306. loop 
  307. reply.local_connection_name := current_lcn ;
  308. wait_for_tcp_message (reply) ;
  309. case reply.message_number is
  310.   when 8 | 16 =>
  311.     put_line("connection aborted") ;
  312.     transport_connection_open := false;        --&KJW 21-jul-85 
  313.     exit ;
  314.   when 6 =>
  315.     tcp_params.abort_close_parameters.local_connection_name := current_lcn ;
  316.     message_for_tcp(tcp_params,request_ok) ;      --&KJW 11-jul-85
  317.     if not request_ok then            --&KJW 11-jul-85
  318.       raise transport_error ;            --&KJW 11-jul-85
  319.     end if ;                    --&KJW 11-jul-85
  320.     reply.local_connection_name := current_lcn ;--&KJW 11-jul-85
  321.     wait_for_tcp_message (reply) ;        --&KJW 11-jul-85
  322.     case reply.message_number is        --&KJW 11-jul-85
  323.       when 8 | 16 =>                --&KJW 11-jul-85
  324.         put_line("connection aborted") ;    --&KJW 11-jul-85
  325.         transport_connection_open := false;    --&KJW 21-jul-85 
  326.         exit ;                    --&KJW 11-jul-85
  327.       when 18 =>                --&KJW 11-jul-85
  328.         put_line("connection closed") ;
  329.         transport_connection_open := false;    --&KJW 21-jul-85 
  330.         exit ;
  331.       when others =>                --&KJW 11-jul-85
  332.         put("connection message ") ;        --&KJW 11-jul-85
  333.         int_io_16.put(reply.message_number) ;   --&KJW 11-jul-85
  334.         new_line ;                --&KJW 11-jul-85
  335.     end case;                    --&KJW 11-jul-85
  336.   when others =>
  337.     put("connection message") ;
  338.     int_io_16.put(reply.message_number) ;
  339.     new_line ;
  340.   end case ;
  341. end loop ;
  342. exception
  343.   when others => 
  344.     error_log("Exception in close_connection") ;
  345.     raise ;
  346. end close_connection ;
  347.  
  348.  
  349.  
  350. --------------------------------------------------------------------------------
  351. --------------------------------------------------------------------------------
  352.  
  353.  
  354.  
  355. procedure send_string (str : in string) is
  356. a_buffer : packed_buffer_ptr ;
  357. send_block : send_params ;
  358. tcp_params : with_ulp_communicate.message(send) ;
  359. request_ok : boolean ;
  360. begin
  361. put("S: ") ;
  362. put_line(str) ;
  363. buffget(a_buffer,1) ;
  364. if a_buffer = null then
  365.     error_log("Could not get a buffer") ;
  366.     raise constraint_error ;   -- crash the connection
  367. end if ;
  368. ---a_buffer.tcp_ptr := maximum_datagram_size - sixteen_bits(str'length) ;
  369. -- patch for incorrect buffer spec
  370. a_buffer.tcp_ptr := 254 - sixteen_bits(str'length) ;
  371. --- a_buffer.size := str'length ;  --- patch for tcp error
  372. a_buffer.size := str'length + 1 ;  --- patch for tcp error
  373. -- put the string bytes into the end of the buffer
  374. for i in 1..str'length loop
  375.   a_buffer.byte(a_buffer.tcp_ptr + sixteen_bits(i))
  376.       := character'pos(str(i)) ;
  377. end loop ;
  378. send_block.local_connection_name := current_lcn ;
  379. send_block.bufptr := a_buffer ;
  380. send_block.byte_count := a_buffer.size ;
  381. send_block.push_flag  := 0 ;
  382. send_block.urg_flag := 0 ;
  383. send_block.timeout  := 2000 ;
  384. tcp_params.send_parameters := send_block ;
  385. message_for_tcp(tcp_params,request_ok) ;  
  386. if not request_ok then
  387.   raise transport_error ;
  388. end if ;
  389. exception
  390.   when others => 
  391.     error_log("Exception in send_string") ;
  392.     raise ;
  393.   end ;
  394.  
  395.  
  396.  
  397. --------------------------------------------------------------------------------
  398. --------------------------------------------------------------------------------
  399.  
  400.  
  401.  
  402.  
  403.  
  404. procedure process_data ( buf : packed_buffer_ptr;
  405.                          done : out boolean) is
  406. data_byte : integer ;
  407. len       : integer ;
  408. begin
  409. len := integer(buf.telnet_ptr - buf.tcp_ptr);
  410. if len < 4 then
  411.   command := "    " ;       --- blank it out
  412.   put_line (" Bad command...incomplete") ;
  413. else
  414.   for i in 1..4 loop
  415.     data_byte := integer(buf.byte(buf.tcp_ptr + sixteen_bits(i)-1)) ;
  416.     if ((data_byte >= character'pos('A')) 
  417.           and (data_byte <= character'pos('Z'))) then
  418.        command(i) := character'val( data_byte - character'pos('A') 
  419.                                 + character'pos('a')) ; -- make it lower case
  420.     else
  421.       command(i) := character'val(data_byte) ;
  422.     end if ;
  423.   end loop ;
  424. end if ;
  425. command_parms := (others => ' ') ;    --&KJW 21-jul-85 
  426. if len <= 4 then
  427.   --&KJW 21-jul-85 command_parms := (others => ' ') ;
  428.   parm_length   := 0 ;
  429. else
  430.   parm_length := len - 4 ;
  431.   for i in 1..parm_length loop
  432.     data_byte := integer(buf.byte(sixteen_bits(i)+buf.tcp_ptr+3))  ;
  433.     --&KJW 21-jul-85 if ((data_byte >= character'pos('A')) and (data_byte <= character'pos('Z'))) then
  434.     --&KJW 21-jul-85    command_parms(i) := character'val(data_byte - character'pos('A') 
  435.     --&KJW 21-jul-85                                + character'pos('a')) ; -- make it lower case
  436.     --&KJW 21-jul-85 else
  437.     --&KJW 21-jul-85   command_parms(i) := character'val(data_byte) ;
  438.     --&KJW 21-jul-85 end if ;
  439.     command_parms(i) := character'val(data_byte) ;
  440.   end loop ;
  441. end if ;
  442. put("R: ") ;
  443. put(command) ;
  444. put_line(command_parms) ;
  445. done := true ;      -- single segment replies only for test
  446. exception
  447.   when others => 
  448.     error_log("Exception in process_data") ;
  449.     raise ;
  450.  
  451. end process_data ;
  452.  
  453.  
  454. -------------------------------------------------------------------------------
  455.  
  456.  
  457. procedure get_command is
  458.   len : integer ;          -- test
  459.   cmd : string (1..256) ;  -- test
  460.   reply_done : boolean := false ;
  461.   tcp_reply : with_ulp_communicate.user_message ;
  462. begin
  463. command := "    " ;
  464. while not reply_done loop 
  465.   tcp_reply.local_connection_name := current_lcn ;
  466.   wait_for_tcp_message (tcp_reply) ;
  467.   case tcp_reply.message_number is
  468.   when 16 =>
  469.     put_line("connection aborted") ;
  470.      raise sudden_connection_close ;
  471.   when 10 =>
  472.     process_data (tcp_reply.data_buffer, reply_done) ;
  473.     send_a_receive ;  -- replace the receive
  474.   when others =>
  475.     put("connection message") ;
  476.     int_io_16.put(tcp_reply.message_number) ;
  477.     new_line ;
  478.   end case ;
  479. end loop ;
  480. exception
  481.   when others =>
  482.     error_log("exception in get_command") ;
  483.     raise ;
  484. end get_command ;
  485.  
  486.  
  487.  
  488. -------------------------------------------------------------------------------
  489. -------------------------------------------------------------------------------
  490.  
  491.  
  492. procedure process_str  ( buf  : packed_buffer_ptr;
  493.                          done : out boolean;
  494.                          str  : out string ;
  495.                          len  : out integer ) is
  496. str1      : string(1..255)  ;
  497. len1      : integer ;
  498. data_byte : integer ;
  499. begin
  500. len1 := integer(buf.telnet_ptr - buf.tcp_ptr);
  501. for i in 1..len1 loop
  502.   str1(i) := character'val(buf.byte(buf.tcp_ptr + sixteen_bits(i)-1)) ;
  503.   end loop ;
  504. put("R: ") ;
  505. put_line(str1(1..len1)) ;
  506. str(1..len1) := str1(1..len1) ;
  507. len := len1 ;
  508. done := true ;      -- single segment replies only for test
  509. exception
  510.   when others => 
  511.     error_log("Exception in process_str") ;
  512.     raise ;
  513.  
  514. end process_str ;
  515.  
  516.  
  517. -------------------------------------------------------------------------------
  518.  
  519.  
  520.  
  521. procedure get_a_line( str : out string ;
  522.                       len : out integer ) is
  523. str_done : boolean := false ;
  524. tcp_reply : with_ulp_communicate.user_message ;
  525. begin
  526. while not str_done loop 
  527.   tcp_reply.local_connection_name := current_lcn ;
  528.   wait_for_tcp_message (tcp_reply) ;
  529.   case tcp_reply.message_number is
  530.   when 16 =>
  531.     put_line("connection aborted") ;
  532.      raise sudden_connection_close ;
  533.   when 10 =>
  534.     process_str (tcp_reply.data_buffer, str_done, str, len) ;
  535.     send_a_receive ;  -- replace the receive
  536.   when others =>
  537.     put("connection message") ;
  538.     int_io_16.put(tcp_reply.message_number) ;
  539.     new_line ;
  540.   end case ;
  541. end loop ;
  542. exception
  543.   when others =>
  544.     error_log("exception in get_a_line") ;
  545.     raise ;
  546. end get_a_line ;
  547.  
  548.  
  549.  
  550.  
  551.  
  552. end ssmtp_transport ;
  553. --::::::::::::::
  554. --sreps_.ada
  555. --::::::::::::::
  556. -----------------------------------------------------------------------
  557. --
  558. --         DoD Protocols    NA-00006-200       80-01136-100(-)
  559. --         E-Systems, Inc.  August 07, 1985
  560. --
  561. --         sreps_.ada       Author : Paul Higgins
  562. --
  563. -----------------------------------------------------------------------
  564. package ssmtp_replies is
  565.  
  566. procedure send_ready_message ;
  567.  
  568. procedure send_helo_ok ;
  569.  
  570. procedure send_mail_ok ;
  571.  
  572. procedure send_rcpt_ok ;
  573.  
  574. procedure send_rcpt_not_ok ;
  575.  
  576. procedure send_no_room ;
  577.  
  578. procedure send_data_ok ;
  579.  
  580. procedure send_completed_ok ;
  581.  
  582. procedure send_completed_not_ok ;
  583.  
  584. procedure send_quit_ok ;
  585.  
  586. procedure bad_command ;
  587.  
  588. end ssmtp_replies ;
  589.  
  590. --::::::::::::::
  591. --sreps.ada
  592. --::::::::::::::
  593. -----------------------------------------------------------------------
  594. --
  595. --         DoD Protocols    NA-00006-200       80-01137-100(-)
  596. --         E-Systems, Inc.  August 07, 1985
  597. --
  598. --         sreps.ada       Author : Paul Higgins
  599. --
  600. -----------------------------------------------------------------------
  601.  
  602. with ssmtp_transport ; use ssmtp_transport ;
  603. with text_io ;         use text_io ;
  604. with ssmtp_logger ;    use ssmtp_logger ;
  605. with ssmtp_globals ;   use ssmtp_globals ;
  606.  
  607. package body ssmtp_replies is
  608.  
  609. procedure send_ready_message is
  610.   begin
  611.   send_string("220  SMTP mail service ready") ;
  612.   exception
  613.     when others =>
  614.       error_log ("Exception in send_helo_ok") ;
  615.   end send_ready_message ;
  616.  
  617. procedure send_helo_ok is
  618.   begin
  619.   send_string("250 Helo ok") ;
  620.   exception
  621.     when others =>
  622.     error_log  ("Exception in send_helo_ok") ;
  623.   end send_helo_ok ;
  624.  
  625. procedure send_mail_ok is
  626.   begin
  627.   send_string("250 mail ok") ;
  628.   exception
  629.     when others =>
  630.     error_log  ("Exception in send_mail_ok") ;
  631.   end send_mail_ok ;
  632.  
  633. procedure send_rcpt_ok is
  634.   begin
  635.   send_string("250 rcpt ok") ;
  636.   exception
  637.     when others =>
  638.       error_log  ("Exception in send_rcpt_ok") ;
  639.   end send_rcpt_ok ;
  640.  
  641. procedure send_rcpt_not_ok is
  642.   begin
  643.   send_string("550 User not local, cannot forward") ;
  644.   exception
  645.     when others =>
  646.       error_log  ("Exception in send_rcpt_not_ok") ;
  647.   end send_rcpt_not_ok ;
  648.  
  649. procedure send_no_room is
  650.   begin
  651.   send_string("501 out of resources") ;
  652.   error_log("Ran out of resources") ;
  653.   exception
  654.     when others =>
  655.       error_log  ("Exception in send_no_room ") ;
  656.   end send_no_room ;
  657.  
  658. procedure send_data_ok is
  659.   begin
  660.   send_string("354 begin data... ") ;
  661.   exception
  662.     when others =>
  663.       error_log  ("Exception in send_data_ok") ;
  664.   end send_data_ok ;
  665.  
  666. procedure send_completed_ok is
  667.   begin
  668.   send_string("250 mail sent") ;
  669.   exception
  670.     when others =>
  671.       error_log  ("Exception in send_completed_ok") ;
  672.   end send_completed_ok ;
  673.  
  674. procedure send_completed_not_ok is
  675.   begin
  676.   send_string("250 mail not sent to some recipients ") ;
  677.   exception
  678.     when others =>
  679.       error_log  ("Exception in send_completed_not_ok") ;
  680.   end send_completed_not_ok ;
  681.  
  682.  
  683. procedure send_quit_ok is
  684.   begin
  685.   send_string("221 SMTP closing connection") ;
  686.   exception
  687.     when others =>
  688.       error_log  ("Exception in send_quit_ok") ;
  689.   end send_quit_ok ;
  690.  
  691.  
  692. procedure bad_command is
  693.   begin
  694.   if command = "rset" then
  695.     raise ssmtp_reset ;
  696.   elsif command = "quit" then
  697.     raise ssmtp_quit ;
  698.   else
  699.     send_string("451 Unexpected or unimplemented command") ;
  700.   end if ;
  701.   exception
  702.     when ssmtp_reset | ssmtp_quit =>
  703.       raise ;
  704.     when others =>
  705.       error_log ("Exception in bad_command") ;
  706.       raise ;
  707.   end bad_command ;
  708.   
  709.  
  710.  
  711. end ssmtp_replies ;
  712.  
  713. --::::::::::::::
  714. --sdel_.ada
  715. --::::::::::::::
  716. -----------------------------------------------------------------------
  717. --
  718. --         DoD Protocols    NA-00006-200       80-01130-100(-)
  719. --         E-Systems, Inc.  August 07, 1985
  720. --
  721. --         sdel_.ada       Author : Paul Higgins
  722. --
  723. -----------------------------------------------------------------------
  724. package ssmtp_deliver is
  725.  
  726. procedure deliver_mail ;
  727.  
  728. end ssmtp_deliver ;
  729.  
  730.  
  731. --::::::::::::::
  732. --sdel.ada
  733. --::::::::::::::
  734. -----------------------------------------------------------------------
  735. --
  736. --         DoD Protocols    NA-00006-200       80-01131-100(-)
  737. --         E-Systems, Inc.  August 07, 1985
  738. --
  739. --         sdel.ada       Author : Paul Higgins
  740. --
  741. -----------------------------------------------------------------------
  742. with ssmtp_globals ;   use ssmtp_globals ;
  743. with ssmtp_logger ;    use ssmtp_logger ;
  744. with ssmtp_replies ;   use ssmtp_replies ;
  745. with text_io ;         use text_io ;
  746. with system;           use system ;
  747.  
  748. package body ssmtp_deliver is
  749.  
  750. procedure copy_mail(user_name : user_name_type; ok : out boolean ) is
  751. smtp_mail : file_type ;
  752. begin
  753.   ok := true ;
  754.   create(smtp_mail,out_file,"smtp_mail.txt") ;
  755.   for i in 1..message_length loop
  756.     put_line(smtp_mail,message(i).message_line(1..message(i).line_length)) ;
  757.   end loop ;
  758.   close(smtp_mail) ;
  759.   exception
  760.     when others => 
  761.       error_log("Exception in copy_mail");
  762.   end ;
  763.  
  764.  
  765. procedure deliver_mail is
  766. all_ok, delivered_ok : boolean := true ;
  767. rcpt_file : file_type ;
  768. begin
  769.   create(rcpt_file,out_file,"rcpt_list.txt") ;
  770.   for i in 1..number_of_rcpt loop
  771.     put_line(rcpt_file,rcpt_list(i)) ;
  772.     copy_mail(rcpt_list(i),delivered_ok);
  773.     all_ok := delivered_ok and all_ok ;
  774.   end loop ;
  775.   close(rcpt_file);
  776.   if all_ok then
  777.     send_completed_ok ;
  778.   else
  779.     send_completed_not_ok ;
  780.   end if ;
  781.   exception
  782.     when others => 
  783.       error_log("Exception in deliver_mail");
  784. end ;
  785.  
  786. end ssmtp_deliver ;
  787. --::::::::::::::
  788. --sconn_.ada
  789. --::::::::::::::
  790. -----------------------------------------------------------------------
  791. --
  792. --         DoD Protocols    NA-00006-200       80-01128-100(-)
  793. --         E-Systems, Inc.  August 07, 1985
  794. --
  795. --         sconn_.ada       Author : Paul Higgins
  796. --
  797. -----------------------------------------------------------------------
  798. package ssmtp_connections is
  799. --
  800. -- This package contains support for establishing the connection
  801. --  between the ssmtp and a usmtp.
  802. --
  803. procedure establish_transport_connection ;
  804. --
  805. -- This procedure sets up the transport connection between the
  806. -- ssmtp and a usmtp. It waits for a usmtp to call it, performs
  807. -- any handshaking required, and sends the ssmtp greeting reply.
  808. --
  809. procedure establish_sender ;
  810. --
  811. -- this procedure gets the helo command from the usmtp and saves the
  812. -- usmtp host string. Currently does not verify the host name string.
  813. --
  814. end ssmtp_connections ;
  815.  
  816.  
  817. --::::::::::::::
  818. --sconn.ada
  819. --::::::::::::::
  820. -----------------------------------------------------------------------
  821. --
  822. --         DoD Protocols    NA-00006-200       80-01129-100(-)
  823. --         E-Systems, Inc.  August 07, 1985
  824. --
  825. --         sconn.ada       Author : Paul Higgins
  826. --
  827. -----------------------------------------------------------------------
  828.  
  829.  
  830. with ssmtp_transport ;    use ssmtp_transport ;
  831. with ssmtp_globals ;      use ssmtp_globals ;
  832. with ssmtp_replies ;      use ssmtp_replies ;
  833. with text_io ;            use text_io ;
  834. with ssmtp_logger ;       use ssmtp_logger ;
  835.  
  836. package body ssmtp_connections is
  837.  
  838. --
  839. --   Implementation for :  vax 11/780
  840. --                         dec ada
  841. --                         tcp transport service
  842. --
  843.  
  844.  
  845. procedure establish_transport_connection is
  846. begin
  847. if not transport_connection_open then
  848.   send_passive_open ;
  849.   wait_for_open ;
  850.   end if ;
  851. loop
  852.   begin
  853.     send_ready_message ;
  854.     reset_receive_buffers ;
  855.     get_command ;
  856.     if command = "helo" then
  857.       source_host := command_parms ; -- save the "from" address as is
  858.       send_helo_ok ;
  859.       exit ;
  860.     else
  861.         bad_command ;
  862.     end if ;
  863.   exception
  864.     when ssmtp_reset =>
  865.       put_line("RSET received") ;
  866.     when others =>
  867.       error_log ("Exception in establish_transport_connection") ;
  868.       raise ;
  869.   end ;
  870. end loop ;
  871.  
  872. end ;
  873.  
  874.  
  875.  
  876.  
  877. procedure establish_sender is
  878. begin
  879.   get_command ;
  880.   if command = "mail" then
  881.     source_name := command_parms ;
  882.     send_mail_ok ;
  883.   else
  884.     bad_command ;
  885.   end if ;
  886.   exception
  887.     when ssmtp_reset =>
  888.       put_line("RSET received") ;
  889.     when others =>
  890.       error_log ("Exception in establish sender") ;
  891.       raise ;
  892.   end establish_sender ;
  893.  
  894.  
  895. end ssmtp_connections ;
  896.  
  897.  
  898. --::::::::::::::
  899. --stext_.ada
  900. --::::::::::::::
  901. -----------------------------------------------------------------------
  902. --
  903. --         DoD Protocols    NA-00006-200       80-01139-100(-)
  904. --         E-Systems, Inc.  August 07, 1985
  905. --
  906. --         stext_.ada       Author : Paul Higgins
  907. --
  908. -----------------------------------------------------------------------
  909. package ssmtp_text is
  910. procedure expect_text ;
  911. -- this program reads in mail from the transport layer and stores them
  912. --  into ssmtp_globals.text as characters
  913. --  exits upon end-of-mail indicator (i.e.  <crlf>.<crlf>)
  914. --  may also exit with a raised exception:
  915. --    ssmtp_quit :
  916. --       if a quit command is received
  917. --    ssmtp_reset :
  918. --       if a reset is received
  919. --    transport_close: 
  920. --       if a transport connection_aborted or connection_closed is found
  921. --    transport_error :
  922. --       if an unknown transport condition is found
  923. --
  924. end ssmtp_text ;
  925.  
  926.  
  927. --::::::::::::::
  928. --stext.ada
  929. --::::::::::::::
  930. -----------------------------------------------------------------------
  931. --
  932. --         DoD Protocols    NA-00006-200       80-01140-100(-)
  933. --         E-Systems, Inc.  August 07, 1985
  934. --
  935. --         stext.ada       Author : Paul Higgins
  936. --
  937. -----------------------------------------------------------------------
  938.  
  939.  
  940. with text_io;            use text_io ;
  941. with ssmtp_transport ;   use ssmtp_transport ;
  942. with ssmtp_logger ;      use ssmtp_logger ;
  943. with ssmtp_globals ;     use ssmtp_globals;
  944.  
  945. package body ssmtp_text is
  946.  
  947. procedure expect_text is
  948. line : string (1..256) ;
  949. len : integer ;
  950. begin
  951.   send_string ("354 Start Mail Input") ;
  952.   loop
  953.     get_a_line(line,len) ;
  954.     if line(1) = '.' then    --&KJW 21-jul-85 
  955.       exit when len = 1 ;
  956.       message_length := message_length + 1 ;
  957.       message(message_length).message_line(1..len-1) := line(2..len) ;
  958.       message(message_length).line_length := len-1 ;
  959.     else
  960.       message_length := message_length + 1 ;
  961.       message(message_length).message_line(1..len) := line(1..len) ;
  962.       message(message_length).line_length := len ;
  963.     end if ;            --&KJW 21-jul-85 
  964.     --&KJW 21-jul-85 message_length := message_length + 1 ;
  965.     --&KJW 21-jul-85 message(message_length).message_line(1..len) := line(1..len) ;
  966.     --&KJW 21-jul-85 message(message_length).line_length := len ;
  967.     --&KJW 21-jul-85 exit when line(1) = '.' ;
  968.   end loop ;
  969. exception
  970.   when others =>
  971.     error_log ("Exception in ssmtp.expect_text") ;
  972. end expect_text ;
  973.  
  974. end ssmtp_text ;
  975.  
  976.  
  977. --::::::::::::::
  978. --srcpt_.ada
  979. --::::::::::::::
  980. -----------------------------------------------------------------------
  981. --
  982. --         DoD Protocols    NA-00006-200       80-01134-100(-)
  983. --         E-Systems, Inc.  August 07, 1985
  984. --
  985. --         srcpt_.ada       Author : Paul Higgins
  986. --
  987. -----------------------------------------------------------------------
  988. package ssmtp_rcpt is
  989.  
  990.   procedure expect_rcpt_list ;
  991.  
  992. end ssmtp_rcpt ;
  993.  
  994.  
  995. --::::::::::::::
  996. --srcpt.ada
  997. --::::::::::::::
  998. -----------------------------------------------------------------------
  999. --
  1000. --         DoD Protocols    NA-00006-200       80-01135-100(-)
  1001. --         E-Systems, Inc.  August 07, 1985
  1002. --
  1003. --         srcpt.ada       Author : Paul Higgins
  1004. --
  1005. -----------------------------------------------------------------------
  1006.  
  1007. with ssmtp_transport ;    use ssmtp_transport ;
  1008. with ssmtp_globals ;      use ssmtp_globals ;
  1009. with ssmtp_replies ;      use ssmtp_replies ;
  1010. with text_io ;            use text_io ;
  1011. with ssmtp_logger ;       use ssmtp_logger ;
  1012.  
  1013. package body ssmtp_rcpt is
  1014.  
  1015. -- this table is system dependent, not really the best method
  1016.  
  1017. max_users : integer := 100 ;
  1018. user_name_table : array (1..max_users) of user_name_type ;
  1019. number_of_users : integer ;
  1020.  
  1021. procedure lookup_user_name(name       : in  user_name_type ;
  1022.                            user_local : out boolean) is
  1023. --- look up user in list 
  1024. --- could make system call if available
  1025. begin
  1026. user_local := false ;
  1027. for i in 1..number_of_users loop
  1028.   if user_name_table(i) = name then
  1029.     user_local := true ;
  1030.     exit ;
  1031.   end if ;
  1032. end loop ;
  1033. exception 
  1034. when others =>
  1035.   error_log("exception in lookup_user_name") ;
  1036.   raise ;
  1037. end lookup_user_name ;
  1038.  
  1039.  
  1040. procedure parse_user_name(user_local : out boolean;
  1041.                           user_name  : out user_name_type) is
  1042. ptr : integer := 0 ;
  1043. name : user_name_type := (others => ' ') ;
  1044. begin
  1045. user_name := (others => ' ') ;
  1046. user_local := false ;
  1047. for i in 1..parm_length loop
  1048.   if command_parms(i) /= ' ' then
  1049.     ptr := i ;
  1050.     exit ;
  1051.   end if ;
  1052. end loop ;
  1053. if ((ptr /= 0) and (ptr <= parm_length+3)) and then
  1054.     command_parms(ptr..ptr+2) = "to:" then
  1055.   for i in 1..(parm_length-(ptr+3)) loop 
  1056.     name(i) := command_parms(i+ptr+3) ;
  1057.   end loop ;
  1058.   lookup_user_name(name,user_local) ; 
  1059.   user_name := name ;
  1060. else 
  1061.   put("bad format rcpt: ") ;
  1062.   put_line(command_parms) ;
  1063. end if ;
  1064. exception 
  1065. when others =>
  1066.   error_log("exception in parse_user_name") ;
  1067.   raise ;
  1068. end parse_user_name ;
  1069.  
  1070. procedure expect_rcpt_list is
  1071.   user_local : boolean ;
  1072.   user_name  : user_name_type ;
  1073.   begin
  1074.   loop
  1075.     get_command ;
  1076.     if command = "rcpt" then
  1077.       parse_user_name(user_local,user_name) ;
  1078.       if not user_local then
  1079.         send_rcpt_not_ok  ;
  1080.       else
  1081.         if number_of_rcpt < max_rcpt then
  1082.           number_of_rcpt := number_of_rcpt + 1 ;
  1083.           rcpt_list(number_of_rcpt) := (others => ' ') ;
  1084.           rcpt_list(number_of_rcpt) := user_name ;
  1085.           send_rcpt_ok ;
  1086.         else
  1087.           send_no_room ;
  1088.         end if ;
  1089.       end if ;
  1090.     elsif command = "data" then
  1091.       exit ;
  1092.     else
  1093.       bad_command ;
  1094.     end if ;
  1095.     end loop ;
  1096.   exception
  1097.     when ssmtp_reset =>
  1098.       put_line("Reset in expect_rcpt_list");
  1099.       raise ssmtp_reset ;
  1100.     when ssmtp_quit =>
  1101.       put_line("Quit in expect_rcpt_list");
  1102.       raise ssmtp_quit ;
  1103.     when others =>
  1104.       error_log("exception in expect_rcpt_list");
  1105.       raise ;
  1106. end expect_rcpt_list ;
  1107.  
  1108.  
  1109. begin
  1110. --&KJW 11-jul-85 user_name_table(1)       := (others => ' ') ;
  1111. --&KJW 11-jul-85 user_name_table(1)(1..7) := "higgins" ;
  1112. --&KJW 11-jul-85 user_name_table(2)       := (others => ' ') ;
  1113. --&KJW 11-jul-85 user_name_table(2)(1..6) := "thomas" ;
  1114. --&KJW 11-jul-85 user_name_table(3)       := (others => ' ') ;
  1115. --&KJW 11-jul-85 user_name_table(3)(1..5) := "baldo" ;
  1116. --&KJW 11-jul-85 user_name_table(3)       := (others => ' ') ;
  1117. --&KJW 11-jul-85 user_name_table(3)(1..7) := "noscada" ;
  1118. --&KJW 11-jul-85 number_of_users := 4 ;
  1119.  
  1120. -- Read user names into user_name_table from file "usernames.lcl".
  1121. -- Each installation can configure allowable user identifiers via this file.
  1122. -- If the open for the file fails, then it is either in use (i.e. being editted)
  1123. -- or does not exist.  This version of the SMTP server cannot continue if there 
  1124. -- are no local users since it does not forward mail to another node.
  1125.  
  1126. loop
  1127.   declare
  1128.     name_file : file_type ;
  1129.     last,index : natural ;
  1130.   begin
  1131.     open(name_file,in_file,"usernames.lcl") ;
  1132.     number_of_users := 0 ;
  1133.     while not end_of_file(name_file) loop
  1134.       index := number_of_users + 1;
  1135.       get_line (name_file, user_name_table(index), last) ;
  1136.       -- user names can be in any form; but they must NOT be preceeded by any
  1137.       -- "white space" (this implementation won't look for it or discard it).
  1138.       -- the length of a user name must NOT exceed the space reserved for it in
  1139.       -- the user_name_table (regardless of the unused space in other names).
  1140.       -- comments in the name table are introduced as Ada-style comments; how-
  1141.       -- ever, the two hyphens must be the first two characters in the line.
  1142.       if user_name_table(index)(1..2) /= "--" then
  1143.         user_name_table(index)(last+1 .. user_name_table(index)'Last) 
  1144.              := (others => ' ') ;
  1145.         number_of_users := index ;
  1146.       end if ;
  1147.       exit when number_of_users >= max_users ;
  1148.     end loop ;
  1149.     close(name_file) ;
  1150.     exit ;
  1151.   exception
  1152.     when status_error =>    -- file is open; try again later
  1153.       delay 30.0;
  1154.     when name_error =>        -- file does not exist
  1155.       put_line("could not find file 'usernames.lcl'" & 
  1156.                " in package body ssmtp_rcpt") ;
  1157.       raise ;
  1158.     when others =>        -- ???
  1159.       put_line("unknown exception in package body ssmtp_rcpt elaboration.") ;
  1160.       close(name_file) ;    -- just in case it was open
  1161.       raise;
  1162.   end ;
  1163. end loop ;
  1164.  
  1165. end ssmtp_rcpt;
  1166. --::::::::::::::
  1167. --ssmtp.ada
  1168. --::::::::::::::
  1169. -----------------------------------------------------------------------
  1170. --
  1171. --         DoD Protocols    NA-00006-200       80-01138-100(-)
  1172. --         E-Systems, Inc.  August 07, 1985
  1173. --
  1174. --         ssmtp.ada       Author : Paul Higgins
  1175. --
  1176. -----------------------------------------------------------------------
  1177. with text_io;            use text_io ;
  1178. with ssmtp_globals ;     use ssmtp_globals ;
  1179. with ssmtp_replies ;     use ssmtp_replies ;
  1180. with ssmtp_connections ; use ssmtp_connections ;
  1181. with ssmtp_transport ;   use ssmtp_transport ;
  1182. with ssmtp_rcpt ;        use ssmtp_rcpt ;
  1183. with ssmtp_text ;        use ssmtp_text ;
  1184. with ssmtp_deliver ;     use ssmtp_deliver ;
  1185. with ssmtp_logger ;      use ssmtp_logger ;
  1186. with buffer_data ;       use buffer_data ;
  1187.  
  1188. procedure ssmtp is
  1189. begin
  1190.   buffer_data.init ;
  1191.   loop
  1192.     begin
  1193.     establish_transport_connection ;
  1194.     establish_sender ;
  1195.     loop
  1196.       begin
  1197.       reset_receive_buffers ;
  1198.       expect_rcpt_list ;
  1199.       expect_text ;
  1200.       deliver_mail ;
  1201.       exception
  1202.         when ssmtp_reset =>
  1203.           put_line("reset received") ;
  1204.           --send_reset_ok ;
  1205.       end ;
  1206.       end loop ;
  1207.   exception
  1208.     when ssmtp_quit =>
  1209.       put_line("quit received") ;
  1210.       send_quit_ok ;
  1211.       close_connection ;
  1212.       EXIT ;    -- for VAX/VMS  O N L Y !!! (let command file distribute mail)
  1213.     when ssmtp_reset =>
  1214.       put_line("reset received") ;
  1215.       --send_reset_ok ;
  1216.     when sudden_connection_close =>
  1217.       put_line("Transport connection closed") ;
  1218.     when transport_error =>
  1219.       put_line("Transport error ") ;
  1220.     when others =>
  1221.       error_log ("Unknown exception in server smtp... exiting") ;
  1222.       raise ;
  1223.    end ;
  1224.   end loop ;
  1225. end ssmtp ;
  1226.  
  1227. --::::::::::::::
  1228. --uutils_.ada
  1229. --::::::::::::::
  1230. -----------------------------------------------------------------------
  1231. --
  1232. --         DoD Protocols    NA-00006-200       80-01154-100(-)
  1233. --         E-Systems, Inc.  August 07, 1985
  1234. --
  1235. --         uutils.ada       Author : Paul Higgins
  1236. --
  1237. -----------------------------------------------------------------------
  1238.  
  1239. -------------------------------------------------------------------------------
  1240. --
  1241. -- USMTP globals
  1242. --
  1243. package usmtp_utils is
  1244.  
  1245.   -- abnormal conditions:
  1246.   abort_usmtp : exception ;       -- user requests exit
  1247.   smtp_error  : exception ;       -- server sends error code (4xx or 5xx)
  1248.   unexpected_reply : exception ;  -- server sends insane reply
  1249.   tcp_reset   : exception ;       -- tcp resets connection
  1250.  
  1251.   -- implementation constraints
  1252.   max_line_len : constant integer := 80 ;
  1253.  
  1254.  
  1255. -- the following are the known replies to usmtp
  1256.  
  1257. open_ok      : constant string(1..3) := "220" ;
  1258. data_ok      : constant string(1..3) := "250" ;
  1259. send_data_ok : constant string(1..3) := "354" ;
  1260. rcpt_ok      : constant string(1..3) := "250" ;
  1261. will_forward : constant string(1..3) := "251" ;
  1262. helo_ok      : constant string(1..3) := "250" ;
  1263. quit_ok      : constant string(1..3) := "221" ;
  1264.  
  1265.  
  1266. end usmtp_utils ;
  1267.  
  1268. --::::::::::::::
  1269. --xhost_.ada
  1270. --::::::::::::::
  1271. -----------------------------------------------------------------------
  1272. --
  1273. --         DoD Protocols    NA-00006-200       80-01155-100(-)
  1274. --         E-Systems, Inc.  August 07, 1985
  1275. --
  1276. --         xhost_.ada       Author : Paul Higgins
  1277. --
  1278. -----------------------------------------------------------------------
  1279. with buffer_data ;      -- to import address type 
  1280.  
  1281. package xhost is
  1282. --
  1283. -- Utilities to translate host names to host addresses
  1284. -- Only TCP format addresses supported
  1285. -- could add some table maintainence procedures here if desired
  1286. --
  1287. procedure translate_host_name_to_address
  1288. --
  1289. -- Look up the host name in the table and return the address.
  1290. --
  1291.    (host_name    :  in string ;
  1292.     host_id      : out buffer_data.thirtytwo_bits ;  -- an internet address
  1293.     host_name_ok : out boolean ) ;
  1294.  
  1295. end ;
  1296.  
  1297. --::::::::::::::
  1298. --xhost.ada
  1299. --::::::::::::::
  1300. -----------------------------------------------------------------------
  1301. --
  1302. --         DoD Protocols    NA-00006-200       80-01156-100(-)
  1303. --         E-Systems, Inc.  August 07, 1985
  1304. --
  1305. --         xhost.ada       Author : Paul Higgins
  1306. --
  1307. -----------------------------------------------------------------------
  1308. with text_io ;       use text_io ;
  1309. with usmtp_utils ;   use usmtp_utils ;
  1310. with buffer_data ;   use buffer_data ;  -- for type thirtytwo_bits
  1311.  
  1312. package body xhost is
  1313.  
  1314. type name_id_pair is record 
  1315.   name : string (1..80) ;
  1316.   id   : buffer_data.thirtytwo_bits ;
  1317. end record ;
  1318.  
  1319. a_blank_line : string (1..80) := (others => ' ') ;
  1320. a_name : string (1..80) ;
  1321. an_id  : thirtytwo_bits ;
  1322.  
  1323. host_name_table : array (1..10) of name_id_pair :=
  1324.     ( others => (a_blank_line, 0) ) ;
  1325.  
  1326. number_of_hosts : integer range 1..10 ;
  1327.  
  1328. procedure translate_host_name_to_address
  1329. --
  1330. -- Look up the host name in the table and return the address.
  1331. --
  1332.    (host_name    :  in string ;
  1333.     host_id      : out thirtytwo_bits ;
  1334.     host_name_ok : out boolean ) is
  1335. begin
  1336. host_name_ok := false ;
  1337. a_name := a_blank_line ;
  1338. a_name(1..host_name'length) := host_name ;
  1339. for i in 1..number_of_hosts loop
  1340.   if a_name = host_name_table(i).name then
  1341.     host_id := host_name_table(i).id ;
  1342.     host_name_ok := true ;
  1343.     exit ;
  1344.     end if ;
  1345. end loop ;
  1346. exception
  1347.   when others =>
  1348.     put_line("EXCEPTION IN TRANSLATE_HOST_NAME") ;
  1349.     raise ;
  1350. end ;
  1351.  
  1352.  
  1353. begin
  1354.  
  1355. a_name := a_blank_line ;    
  1356. a_name(1..6) := "saturn" ;
  1357. an_id :=  1 ;
  1358. host_name_table (1) := (a_name, an_id) ;
  1359.  
  1360. a_name := a_blank_line ;    
  1361. a_name(1..4) := "mars" ;
  1362. an_id := 2 ;
  1363. host_name_table (2) := (a_name, an_id) ;
  1364.  
  1365. a_name := a_blank_line ;    
  1366. a_name(1..5) := "wicat" ;
  1367. an_id := 3 ;
  1368. host_name_table (3) := (a_name, an_id) ;
  1369.  
  1370. number_of_hosts := 3 ;
  1371.  
  1372. end xhost ;
  1373. --::::::::::::::
  1374. --unet_.ada
  1375. --::::::::::::::
  1376. -----------------------------------------------------------------------
  1377. --
  1378. --         DoD Protocols    NA-00006-200       80-01147-100(-)
  1379. --         E-Systems, Inc.  August 07, 1985
  1380. --
  1381. --         unet_.ada       Author : Paul Higgins
  1382. --
  1383. -----------------------------------------------------------------------
  1384. package usmtp_network is
  1385. --
  1386. -- This package contains the usmtp interfaecs to the network transport
  1387. --   protocol process and other network-related functions.
  1388. --
  1389. --
  1390. procedure send_open_to_transport_layer(host_id : string) ;
  1391. --
  1392. -- Sends an open connection request to the transport layer.
  1393. --
  1394. --
  1395. procedure send_abort_to_transport ;
  1396. --
  1397. -- Sends an abort command to the transport layer to force termination
  1398. --  of a connection.
  1399. --  
  1400. --
  1401. procedure send_string (str : in string) ;
  1402. --
  1403. -- formats an ascii string into the desired transport form and sends it
  1404. --   to the ssmtp
  1405. --
  1406. procedure send_close_to_transport_layer ;
  1407. --
  1408. -- Sends a close command to the transport layer to force a normal connection
  1409. --   close.
  1410. --
  1411. --
  1412.  
  1413. procedure get_reply (reply  : out string) ;
  1414. --
  1415. -- This procedure gets a reply string from the transport layer.
  1416. --  Converts transport layer format to string. Performs as many
  1417. --  transport layer reads as necessary until a complete response is found
  1418. --  (in case of multiline responses, etc.)
  1419. --
  1420.  
  1421. end usmtp_network ;
  1422.  
  1423.  
  1424. --::::::::::::::
  1425. --unet.ada
  1426. --::::::::::::::
  1427. -----------------------------------------------------------------------
  1428. --
  1429. --         DoD Protocols    NA-00006-200       80-01148-100(-)
  1430. --         E-Systems, Inc.  August 07, 1985
  1431. --
  1432. --         unet.ada       Author : Paul Higgins
  1433. --
  1434. -----------------------------------------------------------------------
  1435.  
  1436. with buffer_data ;           use buffer_data ;
  1437. with with_ulp_communicate ;  use with_ulp_communicate ;
  1438. with text_io;                use text_io ;
  1439. with usmtp_utils ;           use usmtp_utils ;
  1440. with xhost ;                 use xhost ;
  1441. with system ;                use system ;
  1442. --
  1443. package body usmtp_network is
  1444. --
  1445. -- Implementation for:    Vax 11/780
  1446. --                        tcp transport layer (esystesm version)
  1447. --                        dec ada
  1448. --
  1449. --
  1450. package int_io_32 is new integer_io(thirtytwo_bits) ;
  1451. package int_io_16 is new integer_io(sixteen_bits) ;
  1452. --
  1453. --
  1454. current_lcn : lcn_ptr_type ;  -- the lcn for the current open connection
  1455. --
  1456. --
  1457. --------------------------------------------------------------------------------
  1458. --------------------------------------------------------------------------------
  1459. --
  1460. ----
  1461. -- This is a local procedure to send a receive request to tcp
  1462. -- We should always have a few outstanding receives for tcp to put data into
  1463. --
  1464. procedure send_a_receive is
  1465. request_ok : boolean ;
  1466. tcp_params : with_ulp_communicate.message(receive) ;
  1467. a_buf      : packed_buffer_ptr ;
  1468. begin
  1469. buffget(a_buf,1) ;
  1470. if a_buf = null then
  1471.     put_line("Could not get a buffer") ;
  1472.     raise constraint_error ;   -- crash the connection
  1473. end if ;
  1474. tcp_params.receive_parameters.local_connection_name := current_lcn ;
  1475. tcp_params.receive_parameters.bufptr := a_buf ;
  1476. tcp_params.receive_parameters.byte_count := 190 ;
  1477. message_for_tcp(tcp_params,request_ok) ;
  1478. if not request_ok then
  1479.    raise constraint_error ;  -- crash the connection
  1480. end if ;
  1481. exception
  1482.   when others => 
  1483.     put_line("Exception in send_a_receive") ;
  1484.     raise ;
  1485. end send_a_receive ;
  1486.  
  1487. --
  1488. procedure send_string(str : in string) is
  1489. --
  1490. -- Given an ascii string, this procedure converts it to the
  1491. --  tcp format (byte array), formats a tcp send call, and calls the
  1492. --  tcp interface.
  1493. --
  1494. a_buffer   : packed_buffer_ptr ;
  1495. tcp_params : message(send) ;
  1496. send_block : send_params ;
  1497. request_ok : boolean ;
  1498.  
  1499. begin
  1500.   put("S: ") ;
  1501.   put_line(str) ;
  1502.   buffget(a_buffer, 0) ;
  1503.   -- patch for incorrect buffer spec
  1504.   --a_buffer.tcp_ptr := maximum_datagram_size - sixteen_bits(str'length) ;
  1505.   a_buffer.tcp_ptr := 254 - sixteen_bits(str'length) ;
  1506.   --- a_buffer.size := str'length ;  --- patch for tcp error :
  1507.   a_buffer.size := str'length + 1 ;  --- patch for tcp
  1508.   -- put the string bytes into the end of the buffer
  1509.   for i in 1..str'length loop
  1510.     a_buffer.byte(a_buffer.tcp_ptr + sixteen_bits(i))
  1511.         := character'pos(str(i)) ;
  1512.   end loop ;
  1513.   send_block.local_connection_name := current_lcn ;
  1514.   send_block.bufptr := a_buffer ;
  1515.   send_block.byte_count := a_buffer.size ;
  1516.   send_block.push_flag  := 0 ;
  1517.   send_block.urg_flag := 0 ;
  1518.   send_block.timeout  := 2000 ;
  1519.   tcp_params.send_parameters := send_block ;
  1520.   message_for_tcp(tcp_params,request_ok ) ;  
  1521.   if not request_ok then
  1522.     raise tcp_reset ;
  1523.   end if ;
  1524. exception
  1525.   when tcp_reset => 
  1526.     put_line("TCP error in send_string") ;
  1527.     raise ;
  1528.   when others =>
  1529.     put_line("exception in send_string") ;
  1530.     raise ;
  1531.   end ;
  1532.  
  1533.  
  1534. --------------------------------------------------------------------------------
  1535. --------------------------------------------------------------------------------
  1536.  
  1537.  
  1538. procedure  send_abort_to_transport is
  1539. --
  1540. -- Format and send a tcp abort command to reset the connection.
  1541. -- May wait for connection_closed message from tcp.
  1542. --
  1543. tcp_params : message(abor_t) ;
  1544. reply : user_message ;
  1545. request_ok : boolean ;
  1546. begin
  1547. tcp_params.abort_close_parameters.local_connection_name := current_lcn ;
  1548. message_for_tcp(tcp_params,request_ok ) ;  
  1549. if not request_ok then
  1550.   raise tcp_reset ;
  1551. end if ;
  1552. loop 
  1553. reply.local_connection_name := current_lcn ;
  1554. wait_for_tcp_message (reply) ;
  1555. case reply.message_number is
  1556.   when 8 | 16 =>
  1557.     put_line("connection aborted") ;
  1558.     exit ;
  1559.   when others =>
  1560.     put("connection message") ;
  1561.     int_io_16.put(reply.message_number) ;
  1562.     new_line ;
  1563.   end case ;
  1564. end loop ;
  1565.  
  1566. exception
  1567.   when tcp_reset => 
  1568.     put_line("TCP error in send_abort_to_transport") ;
  1569.     raise ;
  1570.   when others =>
  1571.     put_line("exception in send_abort_to_transport ") ;
  1572.     raise ;
  1573. end ;
  1574.  
  1575.  
  1576.  
  1577. --------------------------------------------------------------------------------
  1578. --------------------------------------------------------------------------------
  1579.  
  1580.  
  1581. procedure send_to_transport(data_line : in string ) is
  1582. --
  1583. -- Call send_string to send a string.
  1584. --
  1585. begin
  1586. send_string(data_line) ;
  1587. exception
  1588.   when others =>
  1589.     put_line("exception in send_to_transport") ;
  1590.     raise ;
  1591. end ;
  1592.  
  1593.  
  1594. --------------------------------------------------------------------------------
  1595. --------------------------------------------------------------------------------
  1596.  
  1597. procedure convert_to_lower_case (str : in out string) is
  1598. begin
  1599.  for i in 1..str'length loop
  1600.    if ( str(i) IN 'A'..'Z' ) then
  1601.      str(i) := character'val(character'pos(str(i)) + 32) ;
  1602.    end if ;
  1603.   end loop ;
  1604. end convert_to_lower_case ;
  1605.  
  1606.  
  1607. procedure send_open_to_transport_layer(host_id : string) is
  1608. --
  1609. -- Format a tcp_open and wait for connection_opened tcp response.
  1610. --
  1611. host_name_ok : boolean ;
  1612. host_addr    : buffer_data.thirtytwo_bits ;
  1613. tcp_params   : message(open) ;
  1614. reply        : user_message ;
  1615. request_ok   : boolean ;
  1616. id           : string (1..host_id'length) ;
  1617. begin
  1618.   id := host_id ;
  1619.   convert_to_lower_case(id) ;
  1620.   translate_host_name_to_address(id, host_addr, host_name_ok) ;
  1621.   if not host_name_ok then
  1622.     put_line("Bad host name") ;
  1623.     raise tcp_reset ;
  1624.   end if ;
  1625.   tcp_params.open_parameters.local_connection_name := current_lcn ;
  1626.   tcp_params.open_parameters.local_port := 26 ;
  1627.   tcp_params.open_parameters.foreign_net_host := host_addr ;
  1628.   tcp_params.open_parameters.foreign_port := 25 ;
  1629.   tcp_params.open_parameters.active_passive := active ;
  1630.   tcp_params.open_parameters.buffer_size := 0 ;
  1631.   tcp_params.open_parameters.timeout := 2000 ;
  1632.   tcp_params.open_parameters.security := 0 ;
  1633.   tcp_params.open_parameters.precedence := 0 ;
  1634.   tcp_params.open_parameters.options := (others => 0) ;
  1635.   message_for_tcp(tcp_params,request_ok ) ;
  1636.   current_lcn := tcp_params.open_parameters.local_connection_name ;
  1637.   if not request_ok then
  1638.     raise tcp_reset ;
  1639.   end if ;
  1640.   loop 
  1641.     reply.local_connection_name := current_lcn ;
  1642.     wait_for_tcp_message (reply) ;
  1643.     case reply.message_number is
  1644.       when 23 =>
  1645.         exit ;
  1646.       when 14 =>
  1647.         current_lcn.lcn_ptr := reply.local_connection_name.lcn_ptr ;
  1648.       when 2 | 5 | 9 | 11 | 20 =>
  1649.         put("could not open, reason code = ") ;
  1650.         int_io_16.put(reply.message_number) ;
  1651.         put_line (" ." ) ;
  1652.         raise tcp_reset ;
  1653.       when 8 | 16 =>
  1654.         put_line("connection aborted") ;
  1655.         raise tcp_reset ;
  1656.       when others =>
  1657.         put("connection message") ;
  1658.         int_io_16.put(reply.message_number) ;
  1659.         new_line ;
  1660.       end case ;
  1661.   end loop ;
  1662.   send_a_receive ; -- leave an outstanding receive
  1663.  
  1664. exception
  1665.   when tcp_reset =>
  1666.     raise ;
  1667.   when others =>
  1668.     put_line("exception in send_open_to_transport ") ;
  1669.     raise ;
  1670. end send_open_to_transport_layer ;
  1671.  
  1672.  
  1673.  
  1674. --------------------------------------------------------------------------------
  1675. --------------------------------------------------------------------------------
  1676.  
  1677.  
  1678. procedure send_close_to_transport_layer is
  1679. --
  1680. -- Send a close command to tcp and wait for a connection_closed response.
  1681. --
  1682. tcp_params : message(close) ;
  1683. reply : user_message ;
  1684. request_ok : boolean ;
  1685. begin
  1686. tcp_params.abort_close_parameters.local_connection_name := current_lcn ;
  1687. message_for_tcp(tcp_params,request_ok ) ;  
  1688. if not request_ok then
  1689.   raise tcp_reset ;
  1690. end if ;
  1691. loop 
  1692. reply.local_connection_name := current_lcn ;
  1693. wait_for_tcp_message (reply) ;
  1694. case reply.message_number is
  1695.   when 8 | 16 =>
  1696.     put_line("connection aborted") ;
  1697.     exit ;
  1698.   when 6 | 18 =>    --&KJW 11-jul-85
  1699.     put_line("connection closed") ;
  1700.     exit ;
  1701.   when others =>
  1702.     put("connection message") ;
  1703.     int_io_16.put(reply.message_number) ;
  1704.     new_line ;
  1705.   end case ;
  1706. end loop ;
  1707. exception
  1708.   when tcp_reset => 
  1709.     put_line("TCP error in send_close") ;
  1710.     raise ;
  1711.   when others =>
  1712.     put_line("exception in send_close ") ;
  1713.     raise ;
  1714. end ;
  1715.  
  1716.  
  1717. --------------------------------------------------------------------------------
  1718. --------------------------------------------------------------------------------
  1719.  
  1720. --
  1721. -- this procedure gets tcp data buffers until a reply  terminator is found
  1722. --
  1723. -- converts system.byte into ascii chars
  1724. -- keeps gathering characters until an end-of-reply (eor) is found.
  1725. -- an eor is indicated by a <crlf> if a single line reply or a
  1726. --  <crlf>.<crlf> if a multiline reply. 
  1727. -- also separates the received data into the reply and any excess found in the
  1728. --  segment after the <crlf>. Note that there should not be anything
  1729. --  after the <crlf> if the server_smtp is ok.
  1730. --
  1731. -- all this is necessary because we cannot rely on the entire
  1732. --  reply being in a single tcp segment.
  1733. --
  1734. --    <reply_format>        = NNN<multiline_indicator>reply_text<eor>
  1735. --    <multiline_indicator> = <space> | -
  1736. --    <eor>                 = <crlf> | <crlf>.<crlf>
  1737. --
  1738. -- accepts all tcp messages
  1739. --  if tcp resets or closes  it will raise tcp_reset
  1740. --  tosses all others away
  1741. --
  1742.  
  1743. procedure process_data ( buf : packed_buffer_ptr;
  1744.                          str : out string ) is
  1745. str1 : string (1..str'length) := ( others =>  ' ') ;
  1746. len : integer ;
  1747. begin
  1748. len := integer(buf.telnet_ptr-buf.tcp_ptr);
  1749. for i in 1..len loop
  1750.   str1(i) := character'val(buf.byte(buf.tcp_ptr+sixteen_bits(i)-1) ) ;
  1751. end loop ;
  1752. put("R: ") ;                        
  1753. put_line(str1(1..len)) ;
  1754. str(1..3) := str1(1..3) ;
  1755. str(4..str'length) := (others => ' ') ;
  1756. end process_data ;
  1757.  
  1758. procedure get_reply (reply  : out string) is
  1759.   eor_found : boolean := false ;
  1760.   rep : string (1..80) ;           -- for debug
  1761.   erep : integer ;                 -- for debug
  1762.   reply_done : boolean := false ;
  1763.   tcp_reply : user_message ;
  1764. begin
  1765. reply(1..3) := "   " ;
  1766. while not reply_done loop 
  1767.   tcp_reply.local_connection_name := current_lcn ;
  1768.   wait_for_tcp_message (tcp_reply) ;
  1769.   case tcp_reply.message_number is
  1770.   when 16 =>
  1771.     put_line("connection aborted") ;
  1772.     raise tcp_reset ;
  1773.   when 10 =>
  1774.     process_data (tcp_reply.data_buffer, reply) ;
  1775.     send_a_receive ;
  1776.     reply_done := true ;  -- single segment replies only!
  1777.   when others =>
  1778.     put("connection message") ;
  1779.     int_io_16.put(tcp_reply.message_number) ;
  1780.     new_line ;
  1781.   end case ;
  1782. end loop ;
  1783. exception
  1784.   when others =>
  1785.     put_line("exception in get_reply") ;
  1786.     raise ;
  1787. end get_reply ;
  1788.  
  1789.  
  1790. end usmtp_network ;
  1791. --::::::::::::::
  1792. --ucomm_.ada
  1793. --::::::::::::::
  1794. -----------------------------------------------------------------------
  1795. --
  1796. --         DoD Protocols    NA-00006-200       80-01143-100(-)
  1797. --         E-Systems, Inc.  August 07, 1985
  1798. --
  1799. --         ucomm_.ada       Author : Paul Higgins
  1800. --
  1801. -----------------------------------------------------------------------
  1802. package usmtp_commands is
  1803. --
  1804. -- This package contains all the commands sent by the usmtp.
  1805. --
  1806. --
  1807. --
  1808. procedure send_data_to_server ;
  1809. --
  1810. -- Sends a DATA command to the ssmtp.
  1811. --
  1812. --
  1813. procedure send_rcpt_to_server(name : string) ;
  1814. --
  1815. -- Sends a RCPT command to the ssmtp.
  1816. --
  1817. --
  1818. procedure send_helo ;
  1819. --
  1820. -- Sends a HELO command to the ssmtp.
  1821. --
  1822. --  
  1823. procedure send_mail (name : string) ;
  1824. --
  1825. -- Sends a MAIL command to the ssmtp.
  1826. --
  1827. --
  1828. procedure send_quit ;
  1829. --
  1830. -- Sends a QUIT command to the ssmtp.
  1831. --
  1832. --
  1833. procedure send_reset ;
  1834. --
  1835. -- Sends a RSET command to the ssmtp.
  1836. --
  1837. --
  1838. end usmtp_commands ;
  1839.  
  1840.  
  1841. --::::::::::::::
  1842. --ucomm.ada
  1843. --::::::::::::::
  1844. -----------------------------------------------------------------------
  1845. --
  1846. --         DoD Protocols    NA-00006-200       80-01144-100(-)
  1847. --         E-Systems, Inc.  August 07, 1985
  1848. --
  1849. --         ucomm.ada       Author : Paul Higgins
  1850. --
  1851. -----------------------------------------------------------------------
  1852. with usmtp_utils ;       use usmtp_utils ; 
  1853. with usmtp_network ;     use usmtp_network ;
  1854. with text_io ;           use text_io ;
  1855.  
  1856. package body usmtp_commands is
  1857. --
  1858. -- This package contains all the commands sent by the usmtp.
  1859. --
  1860. --
  1861. --
  1862. --
  1863. procedure send_data_to_server is
  1864. --
  1865. -- Send the DATA command to tcp.
  1866. --
  1867. begin
  1868. send_string("DATA") ;
  1869. exception
  1870.   when others =>
  1871.     put_line("exception in send_data_to_server") ;
  1872.     raise ;
  1873. end ;
  1874. --
  1875. --
  1876. --
  1877. procedure send_rcpt_to_server(name : string) is
  1878. --
  1879. -- Send the RCPT command to tcp. Formats the name into a proper command line
  1880. --  and calls send_string.
  1881. --
  1882. line : string (1..256) ;
  1883. len : integer ;
  1884. prep : string (1..9) := "RCPT to: " ;
  1885. begin
  1886.   len := name'length + prep'length ;
  1887.   line(1..len) := prep & name ;
  1888.   send_string(line (1..len));
  1889. exception
  1890.   when others =>
  1891.     put_line("exception in send_rcpt_to_server") ;
  1892.     raise ;
  1893. end send_rcpt_to_server ;
  1894.  
  1895.  
  1896.  
  1897. procedure  send_helo is
  1898. --
  1899. -- Send the HELO command to tcp. Formats the host name into a proper command 
  1900. --  line and calls send_string.
  1901. -- To rehost, change my_host_name and recompile.
  1902. --
  1903. line : string (1..256) ;
  1904. len : integer ;
  1905. my_host_name : constant string(1..10)  := "ECI.SATURN" ;
  1906. begin
  1907. len := 5 + my_host_name'length ;
  1908. line(1..len) := "HELO " & my_host_name ;
  1909. send_string(line(1..len)) ;
  1910. exception
  1911.   when others =>
  1912.     put_line("exception in send_helo") ;
  1913.     raise ;
  1914. end send_helo ;
  1915. --
  1916. --
  1917. --  
  1918. procedure send_mail (name : string) is
  1919. line : string (1..256) ;
  1920. len : integer ;
  1921. begin
  1922. len := 11 + name'length ;
  1923. line(1..len) := "MAIL from: " & name ;
  1924. send_string(line(1..len)) ;
  1925. exception
  1926.   when others =>
  1927.     put_line("exception in send_mail") ;
  1928.     raise ;
  1929. end send_mail ;
  1930. --
  1931. --
  1932. --
  1933. procedure send_quit is
  1934. begin
  1935. send_string("QUIT") ;
  1936. exception
  1937.   when others =>
  1938.     put_line("exception in send_quit") ;
  1939.     raise ;
  1940. end ;
  1941. --
  1942. --
  1943. --
  1944. procedure send_reset is
  1945. begin
  1946. send_string("RSET") ;
  1947. exception
  1948.   when others =>
  1949.     put_line("exception in send_reset ") ;
  1950.     raise ;
  1951. end ;
  1952. --
  1953. --
  1954. --
  1955. end usmtp_commands ;
  1956.  
  1957.  
  1958. --::::::::::::::
  1959. --uconn_.ada
  1960. --::::::::::::::
  1961. -----------------------------------------------------------------------
  1962. --
  1963. --         DoD Protocols    NA-00006-200       80-01145-100(-)
  1964. --         E-Systems, Inc.  August 07, 1985
  1965. --
  1966. --         uconn_.ada       Author : Paul Higgins
  1967. --
  1968. -----------------------------------------------------------------------
  1969. package usmtp_connections is
  1970. --
  1971. -- This pacakge contains the connection related functions for the 
  1972. --   communications with the ssmtp.
  1973. -- Allows opening connections, sending data, closing connections,
  1974. --    and forcing resets on connections.
  1975. --
  1976. --
  1977. --
  1978. procedure establish_connection_and_send_helo ;
  1979. --
  1980. -- This procedure performs the follwing functions:
  1981. --   1. request a transport connection to the well-known ssmtp network address
  1982. --   2. wait for the connection to be successfully opened
  1983. --   3. wait for a greeting reply from the ssmtp and print it
  1984. --   4. send a helo to the ssmtp
  1985. --   5. wait for a helo_ok reply from the ssmtp
  1986. --
  1987. -- If proper handshaking fails (connection not opened, incorrect reply 
  1988. --   from ssmtp, etc.; this procedure queries the user for retries and loops
  1989. --   if requested. Exits with an excetpion if unsuccessful and no retry 
  1990. --   requested.
  1991. --
  1992. -- raises the following exceptions:
  1993. --   abort_ssmtp if connection fails and user does not request retry
  1994. --
  1995. --
  1996. --
  1997. procedure close_smtp_connection ;
  1998. --
  1999. -- Sends a QUIT command to the ssmtp, waits for a proper reply, and
  2000. --  sends a close command to the transport layer for a normal connection
  2001. --  close.
  2002. --
  2003. --
  2004. --
  2005. end usmtp_connections ;
  2006.  
  2007. --::::::::::::::
  2008. --uconn.ada
  2009. --::::::::::::::
  2010. -----------------------------------------------------------------------
  2011. --
  2012. --         DoD Protocols    NA-00006-200       80-01146-100(-)
  2013. --         E-Systems, Inc.  August 07, 1985
  2014. --
  2015. --         uconn.ada       Author : Paul Higgins
  2016. --
  2017. -----------------------------------------------------------------------
  2018.  
  2019. with text_io;        use text_io ;
  2020. with usmtp_utils ;   use usmtp_utils ;
  2021. with usmtp_network;  use usmtp_network ;
  2022. with usmtp_commands; use usmtp_commands;
  2023.  
  2024. package body usmtp_connections is
  2025. --
  2026. -- Package implementation for :  Vax 11/780
  2027. --                               tcp transport service (esystems version)
  2028. --                               dec ada
  2029.  
  2030. procedure establish_connection_and_send_helo is
  2031. --
  2032. -- This procedure performs the follwing functions:
  2033. --   1. request a tcp connection to the well-known ssmtp socket
  2034. --   2. wait for a greeting reply (220) from the ssmtp and print it
  2035. --   3. send a helo to the ssmtp
  2036. --   4. wait for a helo_ok reply from the ssmtp
  2037. --
  2038. -- If proper handshaking fails (connection not opened, incorrect reply 
  2039. --   from ssmtp, etc.; This procedure exits with an exception 
  2040. --   if unsuccessful. Connection is closed if this occurs.
  2041. --
  2042. -- raises or propagates the following exceptions:
  2043. --   unexpected_reply if bad reply from ssmtp
  2044. --   smtp_error       if 4xx or 5xx from ssmtp
  2045. --   tcp reset        if connection lost or could not open
  2046. --   
  2047. --
  2048.  
  2049.   host_name    : string (1..80) ;
  2050.   eol          : integer := 0 ;
  2051.   reply        : string (1..80) ;
  2052. begin
  2053.   put_line("Establish Connection to Remote Host ") ;
  2054.   put("enter remote host name -> ") ;
  2055.   get_line(host_name, eol) ;
  2056.   send_open_to_transport_layer(host_name(1..eol)) ;
  2057.   get_reply(reply) ;
  2058.   if reply(1..3) /= open_ok then
  2059.     put_line("Could not open...bad reply") ;
  2060.     put_line("Aborting connection") ;
  2061.     send_abort_to_transport ;
  2062.     raise tcp_reset ;
  2063.   else
  2064.     send_helo ;
  2065.     get_reply(reply) ;
  2066.     if reply(1..3) /= helo_ok then 
  2067.       put_line("server not responding");
  2068.       put_line("Aborting connection") ;
  2069.       send_aborT_to_transport ;
  2070.       raise smtp_error ;
  2071.     end if ;
  2072.   end if ;
  2073. exception
  2074.   when smtp_error | tcp_reset =>
  2075.     raise ;
  2076.   when others =>
  2077.     put_line("unexpected exception in establish_connection_and_send_helo") ;
  2078.     raise ;
  2079. end establish_connection_and_send_helo;
  2080.  
  2081.  
  2082.  
  2083.  
  2084. procedure close_smtp_connection is
  2085.   reply : string(1..80) ;        --&KJW 11-jul-85;
  2086. begin
  2087. send_quit ;
  2088. get_reply(reply) ;            --&KJW 11-jul-85;
  2089. if reply(1..3) /= quit_ok then        --&KJW 11-jul-85;
  2090.   put_line("Quit reply not received") ;    --&KJW 11-jul-85;
  2091.   raise unexpected_reply ;        --&KJW 11-jul-85;
  2092. end if ;                --&KJW 11-jul-85;
  2093. send_close_to_transport_layer ;
  2094. exception
  2095.   when others =>
  2096.     put_line("exception in close_smtp_connection") ;
  2097.     raise ;
  2098. end close_smtp_connection ;
  2099.  
  2100.  
  2101.  
  2102. end usmtp_connections ;
  2103.  
  2104.  
  2105.  
  2106. --::::::::::::::
  2107. --utext_.ada
  2108. --::::::::::::::
  2109. -----------------------------------------------------------------------
  2110. --
  2111. --         DoD Protocols    NA-00006-200       80-01152-100(-)
  2112. --         E-Systems, Inc.  August 07, 1985
  2113. --
  2114. --         utext_.ada       Author : Paul Higgins
  2115. --
  2116. -----------------------------------------------------------------------
  2117. package usmtp_text is
  2118. --
  2119. -- This package supports the mail data entry mode of usmtp.
  2120. --
  2121. procedure send_text ;
  2122. --
  2123. -- Continually get lines from the user and send them to the transport
  2124. --   layer until end-of-message is found. 
  2125. --
  2126. end usmtp_text ;
  2127.  
  2128. --::::::::::::::
  2129. --utext.ada
  2130. --::::::::::::::
  2131. -----------------------------------------------------------------------
  2132. --
  2133. --         DoD Protocols    NA-00006-200       80-01153-100(-)
  2134. --         E-Systems, Inc.  August 07, 1985
  2135. --
  2136. --         utext.ada       Author : Paul Higgins
  2137. --
  2138. -----------------------------------------------------------------------
  2139. with text_io;           use text_io ;
  2140. with usmtp_utils ;      use usmtp_utils ;
  2141. with usmtp_connections; use usmtp_connections ;
  2142. with usmtp_network ;    use usmtp_network ;
  2143. with usmtp_commands ;   use usmtp_commands ;
  2144. with usmtp_network ;    use usmtp_network ;
  2145.  
  2146.  
  2147. package body usmtp_text is
  2148.  
  2149.  
  2150. procedure send_text is
  2151. --
  2152. -- keep getting lines of data from the user and sending them to the transport
  2153. --   layer until an end-of-message is found.
  2154. --
  2155. -- Limitations:
  2156. --  Current end of message :  <CRLF>.<CRLF>
  2157. --  does not support mailing files.
  2158. --
  2159.   data_line : string(1..max_line_len) ;
  2160.   eol : natural ;
  2161.   reply : string(1..80) ;
  2162.   eof : boolean := false ;
  2163.   --&KJW 21-jul-85 end_mark : string (1..1) ;  -- could be a character if TS allowed it
  2164. begin
  2165. --&KJW 21-jul-85 end_mark(1) := '.' ;
  2166. send_data_to_server ;
  2167. get_reply(reply) ;
  2168. if reply(1..3) /= send_data_ok then
  2169.   put_line("server not responding") ;
  2170.   send_abort_to_transport ;
  2171. else
  2172.   put_line("Enter data. Terminate message with <CRLF>.<CRLF> ") ;
  2173.   while not eof loop
  2174.     get_line(data_line,eol) ;
  2175.     --&KJW 21-jul-85 if data_line(1..eol) = end_mark then
  2176.     --&KJW 21-jul-85   put_line("End of file found") ;
  2177.     --&KJW 21-jul-85   eof := true ;
  2178.     --&KJW 21-jul-85 elsif data_line(1..1) = "."  then 
  2179.     --&KJW 21-jul-85   data_line := " " & data_line(1..79) ;
  2180.     --&KJW 21-jul-85   eol := eol + 1 ;
  2181.     --&KJW 21-jul-85 end if ;
  2182.     --&KJW 21-jul-85 send_string(data_line(1..eol)) ;
  2183.     if data_line(1) = '.' then            --&KJW 21-jul-85 
  2184.       eof := eol = 1 ;                --&KJW 21-jul-85 
  2185.       if eof then                --&KJW 21-jul-85 
  2186.         send_string(".") ;            --&KJW 21-jul-85 
  2187.       else                    --&KJW 21-jul-85 
  2188.         send_string("." & data_line(1..eol)) ;    --&KJW 21-jul-85 
  2189.       end if ;                    --&KJW 21-jul-85 
  2190.     else                    --&KJW 21-jul-85 
  2191.       send_string(data_line(1..eol)) ;        --&KJW 21-jul-85 
  2192.     end if ;                    --&KJW 21-jul-85 
  2193.   end loop ;
  2194.   get_reply(reply) ;
  2195.   if reply(1..3) /= data_ok then 
  2196.     put_line ("server could not deliver") ;
  2197.   end if ;
  2198. end if ;
  2199. exception
  2200.   when others =>
  2201.     put_line("exception in send_text") ;
  2202.     raise ;
  2203. end  send_text ;
  2204.  
  2205. end usmtp_text ;
  2206. --::::::::::::::
  2207. --urcpt_.ada
  2208. --::::::::::::::
  2209. -----------------------------------------------------------------------
  2210. --
  2211. --         DoD Protocols    NA-00006-200       80-01149-100(-)
  2212. --         E-Systems, Inc.  August 07, 1985
  2213. --
  2214. --         urcpt_.ada       Author : Paul Higgins
  2215. --
  2216. -----------------------------------------------------------------------
  2217. package usmtp_rcpt is
  2218. --
  2219. -- This package handles the recipient list mode.
  2220. --
  2221. procedure send_rcpt_list ;
  2222. --
  2223. -- Query the user for each recipient name in the list, send
  2224. --  the RCPT command, and wait for a response. Must receive
  2225. --  at least one rcpt_ok respone from the ssmtp before proceeding.
  2226. --
  2227. end usmtp_rcpt ;
  2228.  
  2229. --::::::::::::::
  2230. --urcpt.ada
  2231. --::::::::::::::
  2232. -----------------------------------------------------------------------
  2233. --
  2234. --         DoD Protocols    NA-00006-200       80-01150-100(-)
  2235. --         E-Systems, Inc.  August 07, 1985
  2236. --
  2237. --         urcpt.ada       Author : Paul Higgins
  2238. --
  2239. -----------------------------------------------------------------------
  2240.  
  2241. with text_io;           use text_io ;
  2242. with usmtp_utils ;      use usmtp_utils ;
  2243. with usmtp_connections; use usmtp_connections ;
  2244. with usmtp_commands;    use usmtp_commands;    
  2245. with usmtp_network ;    use usmtp_network ;
  2246.  
  2247. package body usmtp_rcpt is
  2248.  
  2249. procedure send_rcpt_list is
  2250. --
  2251. -- For each recipient, query the user for the name and send it using
  2252. --   the send_rcpt procedure in usmtp_network.
  2253. -- Current limitations:
  2254. --   does not do any processing on user name strings
  2255. --   does not support local lists
  2256. --
  2257. --&KJW 21-jul-85 a_rcpt : boolean := false ;
  2258. rcpt_count : natural := 0 ;        --&KJW 21-jul-85 
  2259. user_name : string (1..80) ;
  2260. eol : integer := 0 ;
  2261. reply : string (1..80) ;
  2262. begin
  2263.   put_line("Enter rcpt list 1 at a time ... nul line to terminate list") ;
  2264.   loop
  2265.     put ("To: ") ;
  2266.     get_line(user_name,eol);
  2267.     if eol /= 0 then
  2268.       send_rcpt_to_server(user_name(1..eol)) ;
  2269.       get_reply(reply) ;
  2270.       --&KJW 18-jul-85 if reply(1..3) = rcpt_ok then
  2271.       --&KJW 18-jul-85   put_line ("rcpt ok") ;
  2272.       --&KJW 18-jul-85   a_rcpt := true ;
  2273.       --&KJW 18-jul-85 else
  2274.       --&KJW 18-jul-85   put_line("rcpt not ok") ;
  2275.       --&KJW 18-jul-85 end if ;
  2276.       --&KJW 21-jul-85 a_rcpt := reply(1..3) = rcpt_ok ;--&KJW 18-jul-85 
  2277.       if reply(1..3) = rcpt_ok then    --&KJW 21-jul-85 
  2278.         rcpt_count := rcpt_count + 1 ;    --&KJW 21-jul-85 
  2279.       end if ;                --&KJW 21-jul-85 
  2280.     else
  2281.       --&KJW 21-jul-85 if not a_rcpt then
  2282.       if rcpt_count < 1 then        --&KJW 21-jul-85 
  2283.         put_line ("Must enter at least one rcpt") ;
  2284.       else
  2285.         exit ;
  2286.       end if ;
  2287.     end if ;
  2288.   end loop ;
  2289. exception
  2290.   when others =>
  2291.     put_line("exception in send_rcpt_list") ;
  2292.     raise ;
  2293. end send_rcpt_list ;
  2294.  
  2295.  
  2296. end usmtp_rcpt ;
  2297. --::::::::::::::
  2298. --usmtp.ada
  2299. --::::::::::::::
  2300. -----------------------------------------------------------------------
  2301. --
  2302. --         DoD Protocols    NA-00006-200       80-01151-100(-)
  2303. --         E-Systems, Inc.  August 07, 1985
  2304. --
  2305. --         usmtp.ada       Author : Paul Higgins
  2306. --
  2307. -----------------------------------------------------------------------
  2308. with text_io;             use text_io ;
  2309. with usmtp_utils ;        use usmtp_utils ;
  2310. with usmtp_connections;   use usmtp_connections ;
  2311. with usmtp_network ;      use usmtp_network ;
  2312. with usmtp_rcpt ;         use usmtp_rcpt ;
  2313. with usmtp_text ;         use usmtp_text ;
  2314. with usmtp_commands ;     use usmtp_commands ;
  2315. with buffer_data ;        use buffer_data ;
  2316.  
  2317. procedure usmtp is
  2318.  
  2319. name        : string (1..255) ;
  2320. name_length : integer ;
  2321. continue    : string (1..255) := ('y', others => ' ') ;
  2322. len         : integer ;
  2323. reply       : string(1..80) ;
  2324.  
  2325. begin
  2326. put_line ("SMTP ver 1.0") ;
  2327. buffer_data.init ;
  2328. while continue(1) = 'y' loop
  2329.   begin
  2330.   establish_connection_and_send_helo ;
  2331.   put("Enter sender's name -> ");
  2332.   get_line(name,name_length) ;
  2333.   send_mail(name(1..name_length));
  2334.   get_reply(reply) ;
  2335.   if reply(1..3) /= helo_ok then
  2336.     put_line("Mail reply not received") ;
  2337.     raise unexpected_reply ;
  2338.   end if ;
  2339.   while continue(1) = 'y' loop
  2340.     send_rcpt_list ;
  2341.     send_text ;
  2342.     put_line("Any more mail for this host (y for yes)? " ) ;
  2343.     get_line(continue,len) ;
  2344.   end loop ;
  2345. --&KJW 11-jul-85 send_quit ;
  2346. --&KJW 11-jul-85 send_close_to_transport_layer ;
  2347. close_smtp_connection ;    --&KJW 11-jul-85 
  2348. exception
  2349.   when abort_usmtp =>
  2350.     put_line(" Exit SMTP ") ;
  2351.     raise ;
  2352.   when smtp_error =>
  2353.     put_line(" server replies error in transmission... connection aborted ") ;
  2354.   when unexpected_reply =>
  2355.     put_line(" error in server - unexpected reply... connection aborted ") ;
  2356.   when tcp_reset =>
  2357.     put_line(" error in tcp transmission... connection aborted ") ;
  2358.   when others =>
  2359.     put_line ("unknown exception in smtp... exiting") ;
  2360.     raise ;
  2361.   end ;
  2362. put_line("Any more mail to send  (y for yes)? " ) ;
  2363. get_line(continue,len) ;
  2364. end loop ;
  2365. put_line(" Exit SMTP ") ;
  2366. exception
  2367.   when others =>
  2368.     put_line("enter ctrl-c to terminate all tasks...") ;
  2369. end usmtp ;
  2370.