rem Email320.bas rem rem last revision 2005 May 13 rem rem send an Email from a Tiger 320 with Ethernet module rem when capture pin is connected to common; rem LED6 indicates that a message is being sent rem the macro makes use of the XPorts modem mode to rem establish a connection - once established it is plain SMTP rem rem see RFC 821 for more details on SMTP rem rem XPort modem mode set to 'Without Echo' so we get only SMTP replies rem rem the IP and Gateway address of the Tiger have rem to be setup correctly in the Ethernet module DIM MSG[] = [ "", \ "Email rejected", \ "Email permanently disabled !!!", \ "Communication timed out", \ "Done", \ " " ] // MSG[] index, also used as #msg value CONST mNONE = 0 CONST mREJECTED = 1 CONST mMAIL_DISABLED = 2 CONST mTIMEOUT = 3 CONST mDONE = 4 CONST mSPACE = 5 // other #msg values CONST mRESTART = 7 CONST mRESET_MODEM = 8 CONST mDISCONNECT = 9 CONST mCONNECT = 10 CONST mHELO = 11 CONST mFROM = 12 CONST mTO = 13 CONST mDATA = 14 CONST mdFROM = 15 // not mandatory CONST mdTO = 16 // not mandatory CONST mdSUBJECT = 17 // not mandatory CONST mdPRIORITY = 18 // not mandatory CONST mdLINE1 = 19 // the actual mail body CONST mEND_MESSAGE = 20 // #state values CONST sIDLE = 0 CONST sSEND = 1 CONST sWAIT_FOR_REPLY = 2 // wait for SMTP replies CONST sWAIT = 3 // pauses for modem commands CONST sERROR = 4 CONST sRESET = 5 // serial setup CONST SLAVE_MODE = 0000 CONST MASTER_MODE = 0002 MEM &CODE3 = SLAVE_MODE MEM &STRING_LENGTH = 0 // replies have variable length MEM &STRING_CHARACTER = CR // all SMTP replies should end with CR/LF // don't wait forever for replies CONST TIMEOUT = 300 // 30.0 secs (only the CONNECT should take that long) // there has to be a pause >1sec before and after the '+++' for disconnect CONST MODEM_TIMEOUT = 12 // don't send messages when a permanent messaging failure has occured BITREG &USER_MEMORY_1 = [ |SEND_MESSAGE ] MEM &USER_MEMORY_1 = 0x0001 // send messages // mail priority CONST PRIORITY_HIGHEST = 1 CONST PRIORITY_HIGH = 2 CONST PRIORITY_NORMAL = 3 //////////////////////////////////////////////////////////////////////////////// CUSTOMER_ID_MACRO: //////////////////////////////////////////////////////////////////////////////// write " Email 320 " END //////////////////////////////////////////////////////////////////////////////// RESET_MACRO: //////////////////////////////////////////////////////////////////////////////// #state = sIDLE #msg = mNONE #errmsg = mNONE |message_sent = false &TIMER1 = 0 &CODE3 = SLAVE_MODE // so we can talk to the meter in ASCII mode END //////////////////////////////////////////////////////////////////////////////// MAIN_MACRO: //////////////////////////////////////////////////////////////////////////////// select #state case sIDLE: |LED6 = off // send email when capture pin is connected to common if |CAPTURE_PIN = on and |SEND_MESSAGE = true then &CODE3 = MASTER_MODE // terminate any connections before we start with a new one #msg = mRESTART #state = sSEND |message_sent = false &TIMER1 = 0 endif case sSEND: if &CODE2 >= 0200 then // in fast mode we have to wait a little for the print command to finish #state = sWAIT endif |LED6 = on &TIMER1 = 0 print "" // reset serial buffer select #msg // modem commands case mRESTART: // timer is already reset so we just wait before we send '+++' #state = sWAIT case mRESET_MODEM: // wait agagin after the '+++' #state = sWAIT print "+++" case mDISCONNECT: // wait again before we start a new connection #state = sWAIT print "ATH" + CHR(CR) // hang up connection case mCONNECT: #state = sWAIT_FOR_REPLY // dial to IP address and SMTP port print "ATDT192.168.10.1/0025" + CHR(CR) // SMTP commands case mHELO: #state = sWAIT_FOR_REPLY print "HELO mycompany.com" // "Hello, I am from " case mFROM: #state = sWAIT_FOR_REPLY print "MAIL FROM: " case mTO: #state = sWAIT_FOR_REPLY print "RCPT TO: " // actual email text case mDATA: print "DATA" case mdFROM: print "From: tiger320@mycompany.com" case mdTO: print "To: technician@mycompany.com" case mdSUBJECT: print "Subject: Alarm" case mdPRIORITY: print "X-Priority: " + PRIORITY_HIGHEST case mdLINE1: // add an empty line to separate the mail body from the mail header print CHR(CR) + CHR(LF) + "CH1: " + &CH1 + CHR(TAB) + "CH2: " + &CH2 case mEND_MESSAGE: #state = sWAIT_FOR_REPLY |message_sent = true print "." endsel // only SMTP commands send CR/LF if #msg > mCONNECT then print CHR(CR)+CHR(LF) if #msg > mTO then // keep on sending the email text line by line without WAIT_FOR_REPLY #msg = #msg + 1 endif endif case sWAIT_FOR_REPLY: if |RECEIVE_READY = true then // let's first assume that the reply is OK and we can continue... #state = sSEND // ...then check for errors if #msg = mCONNECT then // got service ready reply on connect if SERIAL_INPUT = "220" then #msg = mHELO else // wrong answer #state = sERROR #errmsg = mREJECTED endif else if &RECEIVE_BUFFER[0] = ASC("4") or SERIAL_INPUT = "552" then // couldn't get through or mailbox is full #state = sERROR #errmsg = mREJECTED elsif &RECEIVE_BUFFER[0] = ASC("5") then // permanent failure, see RFC 821 for more details on error codes |SEND_MESSAGE = false #state = sERROR #errmsg = mMAIL_DISABLED elsif #msg >= mEND_MESSAGE then // terminate current connection #msg = mRESTART else #msg = #msg + 1 endif endif elsif &TIMER1 > TIMEOUT then // don't wait forever #state = sERROR #errmsg = mTIMEOUT endif case sWAIT: if #msg >= mDATA and &TIMER1 > 0 then // delay new output to avoid aborting old message (only in fast mode) #state = sSEND elsif &TIMER1 > MODEM_TIMEOUT then // wait before and after the '+++' to terminate the connection if #msg = mDISCONNECT and |message_sent = true then #state = sRESET else #msg = #msg + 1 #state = sSEND endif endif case sERROR: // terminate current connection #msg = mRESTART #state = sSEND |message_sent = true write MSG[mSPACE] append MSG[#errmsg] append MSG[mSPACE] case sRESET: print "" // reset serial buffer &CODE3 = SLAVE_MODE #msg = mNONE #errmsg = mNONE #state = sIDLE write MSG[mSPACE] append MSG[mDONE] append MSG[mSPACE] endsel END