email.pwp


//-------------------------------------------------------------------------
// 
//                PicoWeb "email" Project File
//                ----------------------------
// 
// This sample PicoWeb project demonstrates the use of the PicoWeb''s short
// outgoing TCP/IP connection API (i.e., tcp_connect) by sending a short
// e-mail message to an SMTP server.  This project was tested using a Linux
// "sendmail" server running on TCP port 25.  The IP address of the SMTP
// server is set using #define SMTP_IP below.
// 
// The outgoing TCP session with the "sendmail" program is initiated by
// calling the project''s pcode routine "make_connection".  This routine is
// automatically triggered by retrieving the project''s "home page", namely
// the file "email.htm".  This HTML file has a PicoWeb tag that causes
// "make_connection" to be called whenever the Web page is retrieved from
// the PicoWeb server.  Here is what the returned Web page looks like:
// 
//   --------------------------------------------------
// 
//             Send Email from PicoWeb
// 
//      You just send email from this PicoWeb server! 
// 
//       Powered by PicoWeb v2.03 (www.picoweb.net) 
// 
//   ---------------------------------------------------
// 
// This project logs the progress of it''s dialog with the SMTP server to the
// PicoWeb''s serial port.  Here is what apears on the PicoWeb''s serial port:
// 
//   PicoWeb Sendmail!
//   ea = 00 01 02 03 04 0E
// 
//   Establishing connection
//   Connection open220 mail.lightner.net ESMTP Sendmail 8.8.7/8.8.6;
//                      Mon, 3 Jul 2000 11:56:09 -0700
//   250 mail.lightner.net Hello neptune [192.245.227.15], pleased to meet you
//   250 <picoweb@lightner.net>... Sender ok
//   250 <bruce@lightner.net>... Recipient ok
//   354 Enter mail, end with "." on a line by itself
//   250 LAA11334 Message accepted for delivery
//   503 Need MAIL before RCPT
//   503 Need MAIL command
//   500 Command unrecognized: "Subject: Re: PicoWeb"
//   500 Command unrecognized: "Hello, I am a PicoWeb!"
//   500 Command unrecognized: "Look out!! I know how to talk to sendmail now."
//   500 Command unrecognized: "."
//   221 mail.lightner.net closing connection
// 
//   Connection closed.
// 
// Note that the SMTP server (i.e., "sendmail") complains about the fact
// that the PicoWeb has sent it multiple text lines without waiting for
// prompting.  Nevertheless, "sendmail" does send out the email message
// exactly as requested.
// 
// Here is a copy of the email after receipt by the addressee:
// 
//   From picoweb@lightner.net  Mon Jul  3 11:56:09 2000
//   Return-Path: <picoweb@lightner.net>
//   Received: from snert.lightner.net (neptune [192.245.227.15])
//           by mail.lightner.net (8.8.7/8.8.6) with SMTP id LAA11334
//           for <bruce@lightner.net>; Mon, 3 Jul 2000 11:56:09 -0700
//   Date: Mon, 3 Jul 2000 11:56:09 -0700
//   From: picoweb@lightner.net
//   Message-Id: <200007031856.LAA11334@mail.lightner.net>
//   Subject: Re: PicoWeb
//   Status: RO
//   X-Status:
//   X-Keywords:
//   X-UID: 194
// 
//   Hello, I am a PicoWeb!
//   Look out!! I know how to talk to sendmail now.
// 
// --------------------------------------------------------------------
// 
//                Program Logic Description
//                -------------------------
// 
// The routine "make_connection" sets up the IP address of the SMTP host
// computer in the 32-bit global SRAM location "conn_ip", in "network" byte
// order.  It also sets up the TCP port of the SMTP server (i.e., port 25)
// in the 16-bit global SRAM location "conn_dp", in "native" byte order.
// Finally, the routine places the address of a 4-entry "state table"
// in SRAM location "conn_user", then calls "tcp_connect".
// 
// The "state table" is used by "tcp_connect" to signal the user when
// certain events have taken place.  Here is a copy of this table:
// 
//  ob_table:
//     pjump   conn_fail   ; go here if connections fails or times out
//     pjump   send_mail   ; go here to supply outgoing data packet
//     pjump   read_data   ; go here to read any response packets
//     pjump   conn_closed ; go here when connection successfully closed
// 
// The short, out-going TCP/IP session initiated by "tcp_connect" is
// asynchronous in the sense that "tcp_connect" returns to the caller
// immediately.  The "state table" is used to specify "call back" routines
// which will be called at a later time by the PicoWeb "kernel".
// 
// Note that "tcp_connect" has restrictions on the amount of data that can be
// sent to and/or from the remote host computer.  Both outgoing and incoming
// data is limited to one Ethernet packet.  In practical terms, this means
// that no more than about 1400 bytes should be sent in either direction.
// 
// Once "tcp_connect" has been called, it should not be called again
// until either the "conn_fail" or "conn_closed" events have occurred.
// In the example, "conn_fail" will be called only if the TCP/IP connection
// failed for some reason, for example, it the remote host computer failed
// to responsed, or no ARP reply was received.  The routine "conn_closed"
// is called when the outgoing TCP/IP session is complete.
// 
// In our example, the routine "send_mail" is called after "tcp_connect"
// has ARPed for the remote host IP address and has made a connection
// to the SMTP TCP port.  At this point, "tcp_connect" needs a (single)
// packet of data to send to the remote host.  The routine "send_mail"
// supplies this data by writing strings to the PicoWeb standard output
// stream, with the stream directed at "the network".
// 
// After the "sendmail" program has received our packet of data, it responds
// with it''s own data.  When this data packet is received by the PicoWeb
// server, our routine "read_data" will be called.  We have chosen to echo
// this data to the PicoWeb serial port.
// 
// ------------------------------------------------------------------------
//
// application-specific preprocessor definitions
//
#define BANNER "\r\nPicoWeb Sendmail!\r\n"
#define EEPROM_IP
#define NET_CONFIG_IP     /* allow IP address reconfiguration via net */
#define ENABLE_WATCHDOG   /* use Atmel watchdog timer hardware */
#define DEBUGGER          /* include debugger firmware */
//#undef DEBUGGER

//#define CLOCK 8000000     /* processor clock rate */
#define CLOCK 7372000     /* processor clock rate */
#define BAUD_RATE 19200   /* serial port baud rate */

#define SMTP_IP   209,75,29,2  /* SMTP server IP: 209.75.29.2 */
#define SMTP_PORT 25           /* SMTP TCP port */

#define MY_HOST_NAME "snert.lightner.net"
#define FROM_ADDRESS "picoweb@lightner.net"
#define TO_ADDRESS "bruce@lightner.net"
#define SUBJECT "Re: PicoWeb"
#define MESSAGE "Hello, I am a PicoWeb!\r\nLook out!! I know how to talk to sendmail now.\r\n"

//
// application-specific HTML and image file names
//

email.htm                  // home page

make_connection.cgi        // public CGI routine

//
// included application-specific pcode and/or AVR assembly language follows
//
#avr_reset
;--------------------------------------------------------------------------
; this code is executed each time microcontroller is reset
;--------------------------------------------------------------------------
;

#avr_slow
;--------------------------------------------------------------------------
; this code is executed each trip through "slow idle" loop (~1 sec period)
;--------------------------------------------------------------------------
;

#avr_fast
;--------------------------------------------------------------------------
; this code is executed each trip through "fast idle" loop
;--------------------------------------------------------------------------
;

#avr_asm

#define putchar_serial pclrw putc_b
#define putchar_net    pmovbi putc_b,1
#define serial_binary  pser_mode 1
#define serial_normal  pser_mode 0

.section seeprom
smtp_ip: .byte SMTP_IP           ; IP address of SMTP server goes here
.align 1

.eseg

;
; make outbound TCP/IP connection to SMTP mail server
;
    .global make_connection
make_connection:
    putchar_serial
    pprint "\r\nEstablishing connection"
    putchar_net
    psee2s conn_ip,smtp_ip,4
    pmovwi conn_dp,SMTP_PORT                              ; set SMTP TCP port
    pmovwi conn_user,ob_table                             ; set state table
    pcall tcp_connect                                     ; make connection
    pret
;
; PicoWeb outbound TCP/IP state table
;
ob_table:
    pjump   conn_fail     ; go here if connections fails or times out
    pjump   send_mail     ; go here to supply outgoing data packet
    pjump   read_data     ; go here to read any response packets
    pjump   conn_closed   ; go here when connection successfully closed

;
; outbound TCP/IP connection failed
;
conn_fail:
    putchar_serial
    pprint "\r\nConnection failed\r\n"
    pret

;
; outbound TCP/IP connection closed
;
conn_closed:
    putchar_serial
    pprint "\r\nConnection closed.\r\n"
    pret

;
; outbound TCP/IP connection needs outgoing Ethernet packet
;
; Note: No more than one packet of data (~1400 bytes) may be sent!!!
;
send_mail:
    putchar_serial
    pprint "\r\nConnection open"

    putchar_net                   ; direct output to network
    pprint "helo "                ; get attention of sendmail daemon
    pprint MY_HOST_NAME
    pprint "\r\n"
    pprint "mail from: <"         ; send FROM email address
    pprint FROM_ADDRESS
    pprint ">\r\n"
    pprint "rcpt to: <"           ; send TO email address
    pprint TO_ADDRESS
    pprint ">\r\n"
    pprint "data\r\n"
    pprint "Subject: "            ; send SUBJECT line
    pprint SUBJECT
    pprint "\r\n"
    pprint MESSAGE                ; send email message body
    pprint ".\r\n"                ; end email message
    pprint "quit\r\n"             ; disconnect from server
    pret

;
; outbound TCP/IP connection has sent a response packet
;
; Note: We copy received packet data to the serial port.
;
#define ADDR buf+10
#define LEN  ADDR+2
#define CHAR LEN+2

read_data:
    putchar_serial
    pmovwi ADDR,[data_addr]      ; point to start of data in packet
    pmovwi LEN,[data_len]        ; do all of the packets data
2:
    pwdr                         ; reset the watchdog timer
    pr2s CHAR,[ADDR],1           ; get next byte from packet
    pcmpbi CHAR,'\n'             ; check for newline character
    pjumpne 1f                   ; skip if not
    pputc '\r'                   ; newline...output a CR as welfl
1:
    pputcb CHAR                  ; output character from packet
    pincw ADDR                   ; bump receive packet data pointer
    pdecw LEN                    ; decrement character counter
    pjumpne 2b                   ; back for more if not done
    pret


Back