Setting Up an Embedded Email Server
The EtherSmart/WiFi Wildcard enables your application program to send emails to other computers on the network when significant events occur. The driver software implements SMTP (Simple Mail Transfer Protocol) to send outgoing email to a mail server on the LAN (Local Area Network). Outgoing emails can be used by your instrument to send alerts or status updates.
The Ether_Send_Email function handles all of the details for you. You pass to the function the gateway IP address on your LAN, and strings that specify the sender email address, recipient email address, and the email body including an optional subject line. The EtherSmart/WiFi driver software and the mail server running on the gateway computer cooperate to process the email.
Note that the Lantronix device can connect only to destinations on the local network. If you need to send an email to a WAN (Wide Area Network) destination that is not on the LAN or WLAN (Wireless LAN), address the email to the gateway (router) computer’s IP address, and ask your system administrator to configure the gateway to "relay" (forward) the email to the desired destination. Also, note that the EtherSmart/WiFi Wildcard can send emails, but cannot receive them. To send a message to the Wildcard, use a serial tunneling connection or a forms-based web connection as described in other sections of this document.
A demonstration email function
Listing 1-7 illustrates the Email_Test
function from the demo program. Let’s take a look at how this function works. If you have not already done so, initialize the Wildcard by invoking an initialization function. If you have an EtherSmart Wildcard, you can type one of the following at the terminal prompt:
Ether_Task_Setup_Default( )
or:
Ether_Web_Demo( )
or any other function that invokes Ether_Task_Setup_Default
.
If you have a WiFi Wildcard, you can initialize it by typing one of the following at the terminal prompt:
WiFi_Task_Setup_Default( )
or:
WiFi_Web_Demo( )
or any other function that invokes WiFi_Task_Setup_Default
. Now to run the email demonstration type at your terminal:
Email_Test( )
As usual, there must be no space before the (
and at least one space before the )
character. An examination of Listing 1 7 reveals how easy it is to send an email. Note that the hostname, sender, recipient, and IP address must be edited and the demo program compiled and downloaded for this function to work on your local network.
The four string definitions at the top of Listing 1 7 specify the hostname, email sender, email recipient, and the email body, respectively. Edit these to represent values that make sense on your LAN. Note that the first line of the email_body_str
is:
Subject: EtherSmart Email Test\r\n\
This is the optional subject line. As shown, the word Subject:
should be the first word on the line. The Ether_Send_Email routine automatically prepends a To:
line to the email body, emplacing the recipient name string that is passed as an input parameter. You can include other "email header" items in the body of your email, such as:
Date: Cc: From:
Each of these lines should be terminated with a carriage return/linefeed (\r\n
) which is the standard end of line sequence for the SMTP protocol.
An interactive email test function
// ********************* EMAIL TEST *************************** // NOTE: Edit these to specify valid host, sender, and recipient: char* hostname_str = “wildcard.yourdomain.com”; // hostname string char* sender_str = “niceguy@yourdomain.com”; // email sender string char* recipient_str = “notso_niceguy@yourdomain.com”; // email recipient string char* email_body_str = // email_body string “Subject: EtherSmart/WiFi Email Test\r\n\ This is a test email from the EtherSmart/WiFi Wildcard.\r\n\ Emails can of course have multiple lines...”; #define SMTP_PORT 25 // email Simple Mail Transfer Protocol destination port _Q int Email_Test( void ) // works for xport or wiport (ethernet/wifi) instrumentation // call after doing Ether_Task_Setup_Default or WiFi_Task_Setup_Default // smtp email test routine. // Note: YOU MUST EDIT THIS FUNCTION’s HARD-CODED IP ADDRESS // AND the hostname_str, sender_str, and recipient_str BEFORE CALLING! // Otherwise, it will not work on your system. // error= 0 on success, or error_no_response = 0x10, or smtp 3-digit error code { xaddr scratchbuf = Ether_Inbuf( E_MODULENUM ); // scratchpad xbuffer Ether_Send_Email( STRING_XADDR(email_body_str), strlen(email_body_str), // subject plus email STRING_XADDR(hostname_str), strlen(hostname_str), STRING_XADDR(sender_str), strlen(sender_str), STRING_XADDR(recipient_str), strlen(recipient_str), scratchbuf, // scratchpad xbuffer 10, 0, 1, 1, // IMPORTANT: ENTER YOUR GATEWAY’S IP ADDRESS HERE! SMTP_PORT, // port 25 = standard mailserver destination port 10000, // use a 10 second timeout (10,000 msec) for testing E_MODULENUM); // specify module number (must match hardware jumpers) return((int) Ether_Await_Response(E_MODULENUM)); // error code is in lsword }
The Email_Test
function in Listing 1-7 simply sets up the input parameter list and calls Ether_Send_Email. See the "EtherSmart/WiFi Driver Data Structures: Passing String Extended Addresses as Function Parameters" section above for a discussion of the STRING_XADDR
macro that converts a 16-bit string address to a full 32-bit xaddress as required by Ether_Send_Email. The four lines after the function invocation specify the string xaddress and count for the subject, host name, sender, and recipient, respectively.
In this example the scratchbuf
local variable is defined as an xaddress that is initialized to the recommended email scratchpad buffer Ether_Inbuf(E_MODULENUM)
. As discussed in earlier sections, it is illegal to nest operating system function calls inside a parameter list of another operating system function call. The definition and passing of scratchbuf
enables us to pass the Ether_Inbuf xaddress without violating this rule. The specified ram scratchpad buffer holds SMTP strings going to and from the Wildcard. The recommended minimum scratchpad buffer length is 128 bytes; it must be able to hold the sender, recipient, and hostname strings plus sixteen extra bytes. The email body is not transferred to the scratchpad buffer, so you can define an email body that is significantly longer than the scratchpad buffer.
This example shows a static email body, but you can create the email body "on the fly" in your application program. To dynamically build up the email string in the Ether_Outbuf buffer, use the Ether_Outbuf_CAT
function to build the email body one line at a time. If you put the email body in Ether_Outbuf, pass the buffer xaddress+2 as the string xaddress, and the contents of the buffer xaddress as the count. This is because Ether_Outbuf is an LBuffer with the 16-bit count stored in the first two bytes, followed by the data in the remainder of the buffer. Because the buffer is typically in paged (as opposed to common) memory, you must use the operating system function FetchInt
to extract the count from the buffer. In the example above, using Ether_Outbuf instead of email_body_str
would involve declaring the new variables:
uint ether_outbuf_lcount; xaddr ether_outbuf_xaddr = Ether_Outbuf(E_MODULENUM);
After the email body is loaded into the Ether_Outbuf using Ether_Outbuf_Cat, the following assignment can be performed:
ether_outbuf_lcount = FetchInt( ether_outbuf_xaddr);
Finally, in Listing 1-7, to use Ether_Outbuf for the email body you would replace the line:
STRING_XADDR(email_body_str), strlen(email_body_str),
with the line:
ether_outbuf_xaddr+2, ether_outbuf_lcount,
to specify the email body xaddress and count.
After the strings and scratchpad buffer in the parameter list in Listing 1 7, the next four parameters specify the destination IP address to which the email is directed. Often this is the IP of the gateway computer on the LAN, as the gateway often runs the mail server. Make sure to edit the demo code to specify a valid IP address on the LAN.
The next parameter is the destination TCP/IP port number. In most cases this will be port 25, the SMTP port as defined by the constant in the demo program.
The next parameter in the Ether_Send_Email invocation is a timeout in units of milliseconds. It is important not to make this too small, as there can be significant delays on a network. The example shows a 10 second (10,000 millisecond) timeout, but the value required on your network may be different.
The final parameter passed to Ether_Send_Email is the modulenum.
When the application program invokes Ether_Send_Email, a message is dispatched via the ether_command mailbox to the Ethernet task. Consequently, the Ethernet task opens a connection to the specified remote computer, sends the email, and closes the connection. If there is a failure code returned while the email "chat" is occurring, this 3-digit decimal error code is returned and the email transaction is halted. The connection is closed before this routine exits; only 1 email is deliverable per connect. The Ethernet task then sends the result error code in the ether_response mailbox. This mailbox must be cleared by the application program using either the blocking function Ether_Await_Response, or the non-blocking function Ether_Check_Response. The main loop of your program’s application task should periodically call one of these two functions to manage the interactions with the Ethernet task. In the example in Listing 1 7, the return statement calls Ether_Await_Response and returns the 16-bit error code.
Using the Image Converter to Manage Long Strings
If you need to create long static email body strings, use the "Image Converter" program that is part of your Mosaic development environment. This program converts one or more files, each containing a single string (or other resource) into a named 32-bit base xaddress and count that can be used by your application program. Simply place each string into a separate file with the file extension .str
or .html.
The file name and extension (with the dot replaced by an underscore) will become the symbol name. All files to be converted should be in a single directory. Make sure you use C-compatible filenames that include only alphanumeric and _ (underscore) characters, and do not start with a numeral. Invoke the Image Converter from your development environment. In the Image Converter control panel, select the controller platform, and check the "Web files" box. If you are programming in Forth, click the "Advanced" menu and select Forth as the programming language. In the "Directory" area of the control panel, select the directory that contains the specified file(s). Then click on "Convert Files Now".
A pair of files named image_data.txt
and image.headers.h
will be created by the Image Converter. The image_data.txt
contains S-records and operating system commands that load the string image into flash memory on the controller. Because flash memory is nonvolatile, you only need to download this file once to the controller; it need not be reloaded until you change the resources. The image_headers.h
file declares the 32-bit xaddress and count (size) constants to be used by your application program.
For example, let’s say that you have created a rather lengthy email body and stored it in a file named mail_body.str
where the .str
file extension indicates that the file contains a string. The image_headers.h
file declares the following two macros with the appropriate numeric xaddress and count values:
#define MAIL_BODY_STR_XADDR 0x700360 #define MAIL_BODY_STR_SIZE 0x98E
You can then use these macros as parameters passed to the Ether_Send_Email function to specify the email body string. The use of the Image Converter is further described in the next section and in Appendix A.
See Appendix A for a discussion of how to load the resources and the kernel extension library files onto the controller board before loading your custom application program.
See also → Setting up Embedded Email Server