88 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Factor
		
	
	
| ! Copyright (C) 2007 Elie CHAFTARI
 | |
| ! See http://factorcode.org/license.txt for BSD license.
 | |
| USING: combinators kernel prettyprint io io.timeouts sequences
 | |
| namespaces io.sockets io.sockets.secure continuations calendar
 | |
| io.encodings.ascii io.streams.duplex destructors locals
 | |
| concurrency.promises threads accessors smtp.private
 | |
| io.sockets.secure.debug io.crlf ;
 | |
| IN: smtp.server
 | |
| 
 | |
| ! Mock SMTP server for testing purposes.
 | |
| 
 | |
| ! $ telnet 127.0.0.1 4321
 | |
| ! Trying 127.0.0.1...
 | |
| ! Connected to localhost.
 | |
| ! Escape character is '^]'.
 | |
| ! 220 hello
 | |
| ! EHLO
 | |
| ! 220 and..?
 | |
| ! MAIL FROM: <here@mail.com>
 | |
| ! 220 OK
 | |
| ! RCPT TO: <there@mail.com>
 | |
| ! 220 OK
 | |
| ! Hi
 | |
| ! 500 ERROR
 | |
| ! DATA
 | |
| ! 354 Enter message, ending with "." on a line by itself
 | |
| ! Hello I am still waiting for your call
 | |
| ! Thanks
 | |
| ! .
 | |
| ! 220 OK
 | |
| ! QUIT
 | |
| ! bye
 | |
| ! Connection closed by foreign host.
 | |
| 
 | |
| SYMBOL: data-mode
 | |
| 
 | |
| : process ( -- )
 | |
|     read-crlf {
 | |
|         { [ dup not ] [ f ] }
 | |
|         {
 | |
|             [ dup [ "HELO" head? ] [ "EHLO" head? ] bi or ]
 | |
|             [ "220 and..?\r\n" write flush t ]
 | |
|         }
 | |
|         {
 | |
|             [ dup "STARTTLS" = ]
 | |
|             [
 | |
|                 "220 2.0.0 Ready to start TLS\r\n" write flush
 | |
|                 accept-secure-handshake t
 | |
|             ]
 | |
|         }
 | |
|         { [ dup "QUIT" = ] [ "220 bye\r\n" write flush f ] }
 | |
|         { [ dup "MAIL FROM:" head? ] [ "220 OK\r\n" write flush t ] }
 | |
|         { [ dup "RCPT TO:" head? ] [ "220 OK\r\n" write flush t ] }
 | |
|         {
 | |
|             [ dup "DATA" = ]
 | |
|             [
 | |
|                 data-mode on
 | |
|                 "354 Enter message, ending with \".\" on a line by itself\r\n"
 | |
|                 write flush t
 | |
|             ]
 | |
|         }
 | |
|         {
 | |
|             [ dup "." = data-mode get and ]
 | |
|             [
 | |
|                 data-mode off
 | |
|                 "220 OK\r\n" write flush t
 | |
|             ]
 | |
|         }
 | |
|         { [ data-mode get ] [ dup [ print ] with-global t ] }
 | |
|         [ "500 ERROR\r\n" write flush t ]
 | |
|     } cond nip [ process ] when ;
 | |
| 
 | |
| :: mock-smtp-server ( promise -- )
 | |
|     ! Store the port we are running on in the promise.
 | |
|     [
 | |
|         [
 | |
|             "127.0.0.1" 0 <inet4> ascii <server> [
 | |
|             dup addr>> port>> promise fulfill
 | |
|                 accept drop [
 | |
|                     1 minutes timeouts
 | |
|                     "220 hello\r\n" write flush
 | |
|                     process
 | |
|                     [ flush ] with-global
 | |
|                 ] with-stream
 | |
|             ] with-disposal
 | |
|         ] with-test-context
 | |
|     ] in-thread ;
 |