This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC3100SDK: CC3100 SDK-Ver-1.3.1 Email No Longer Works

Part Number: CC3100SDK
Other Parts Discussed in Thread: CC3100, CC3200, MSP430FR6989, CC3220SF, CC3100BOOST, UNIFLASH, CC31XXEMUBOOST, CC3100MOD, MSP430F5529

Hi Experts, 

Our customer have a concern, as shown below:

TI CC3100 SDK-Ver-1.3.1 Email No Longer Works
A. Solution Request
We are looking for a TI fix for the CC3100 email example. The current posted CC3100 email example no longer works. So please either provide a solution, or provide an update WARNING that the CC3100 no longer supports emails.
B. CC3100 Email code Working with Gmail for over 3 years
For over 3 years we have had multiple TI CC3100 BOOST using SDK-1.3.1 mounted on both F5529 and FR6989 launch pads Microcontrollers using WiFi to both “Get Timer from an SNTP Timer Server”, and “Send status emails” from GMAIL using smtp and sending the email to a number of different destination email services.
In 2021 GMAIL required AP’s like TI Microcontrollers with CC3100 WiFi cards to upgrade to use a GMAIL generated AP password. Creating the Gmail AP password enabled the TI devices to successfully send emails.
C. TI CC3100 email no long works on Gmail, Outlook.com target="_blank">Outlook.com email, or SOHO email
In the fall to 2022 Gmail posting was that they would soon not support AP passwords and less secure devices in the future. On Friday January 27, 2023 multiple TI microcontrollers with the CC3100, in different states all stopped being able to send email status. These microcontrollers have no means of remote software updates, so no code changes were made to multiple micro’s. Also there is near zero probability that multiple micro’s in multiple cities / states had a code corruption at the exact same date and hour. Obviously some Gmail code and security change is now blocking TI micro’s.
We have tried Outlook.com email, SOHO email, AOL email, and Proton email. None of these email services work with the TI CC3100 and SDK-1.3.1. All of these email services progress through the code to the same point and end with “Device couldn’t send the email”.
D. Code Sequence Trace
This shows that the device can first connect to an SNPT time server and SUCCESFULLY get the TIME. This proves that the CC3100 hardware, most of the Code, WiFi access, etc are all still working. The SEND EMAIL trace shows that it is NOT able to send an email.


Get time application - Version 1.3.0
*******************************************************************************
Line 1774 Device is configured in default state
Line 1791 Device started as STATION
Line 1803 Connection established w/ AP and IP is acquired
Line 1808 LH Just after get HostIP
Line 1818 LH Just after createConnection
Line 1825 LH Just BEFORE getSNTPTTime...
Line 336 In socket.c, sl_Sendto
Line 95 In socket.c, _sl_BuildAddress
Line 95 In socket.c, _sl_BuildAddress
Line 1829 LH Just AFTER getSNTPTTime...
Line 1488 in _i32 disconnectFromAP() after retVal = sl_WlanDisconnect();
Line 1490 in _i32 disconnectFromAP() after if(0 == retVal)
Line 1022 Device disconnected from the AP on application's request


Email application - Version 1.3.0
*******************************************************************************
Line 881 Device is configured in default state
Line 898 Device started as STATION
Line 171 email Username
Line 180 email Password
Line 159 email port, security
Line 915 Connection established w/ AP and IP is acquired
Line 918 Sending email...
Line 189 email Destination
Line 1253 After...DESTINATION_EMAIL
Line 198 email Subject
Line 1265 After...LHemailSubject
Line 208 email Message Body
Line 1278 After...LHemailBody
Line 301 In _smtpConnect after if TLS create secure socket
Line 306 In _smtpConnect Set Socket
Line 333 In _smtpConnect before connect to Socket
Line 513 In socket.c, _sl_Connect
Line 95 In socket.c, _sl_BuildAddress
Line 554 In socket.c, _sl_Connect Verify_RET_OK
Line 335 In _smtpConnect after connect to Socket
Line 339 In _smtpConnect if Status < 0 && SL_ESECSNOVERIFY != Status
Line 1281 After...Status = sl_NetAppEmailConnect()
Line 922 Device couldn't send the email
Line 1488 in _i32 disconnectFromAP() after retVal = sl_WlanDisconnect();
Line 1490 in _i32 disconnectFromAP() after if(0 == retVal)
Line 1011 Device disconnected from the AP on application's request

This is a subset longer version of the Send Email try which shows in more detail all the SPI read and writes to the CC3100 device. Just before and after the “Line 922 Device couldn’t send the email”
Line 554 In socket.c, _sl_Connect Verify_RET_OK
Line 211 in spi.c spi_Write(...)
Line 239 in spi.c spi_Read(...)
Line 239 in spi.c spi_Read(...)
Line 239 in spi.c spi_Read(...)
Line 335 In _smtpConnect after connect to Socket
Line 339 In _smtpConnect if Status < 0 && SL_ESECSNOVERIFY != Status
Line 1281 After...Status = sl_NetAppEmailConnect()
Line 922 Device couldn't send the email
Line 211 in spi.c spi_Write(...)
Line 211 in spi.c spi_Write(...)
Line 211 in spi.c spi_Write(...)
Line 239 in spi.c spi_Read(...)
Line 239 in spi.c spi_Read(...)
Line 239 in spi.c spi_Read(...)
Line 1488 in _i32 disconnectFromAP() after retVal = sl_WlanDisconnect();
Line 1490 in _i32 disconnectFromAP() after if(0 == retVal)
Line 211 in spi.c spi_Write(...)
Line 239 in spi.c spi_Read(...)
Line 239 in spi.c spi_Read(...)
Line 239 in spi.c spi_Read(...)
Line 1011 Device disconnected from the AP on application's request

E. Selected Code Extracts to show the main code path
E.1 _SetEmail
I suspect the reason CC3100 SDK-1.3.0 no longer works has something to do with Email service security changes. I have use TLS successfully from 2014 to 2023…….so for 9 years it has worked. I tried port 465 with SSL as well but that also does not work.
eMailServerSetting.Family = AF_INET;
// eMailServerSetting.Port = GMAIL_HOST_PORT; //Line 27 in config.h #define GMAIL_HOST_PORT 465
// eMailServerSetting.Port = OUTLOOK_HOST_PORT; //Line i41n config.h #define OUTLOOK_PORT 587
eMailServerSetting.Port = ZOHO_HOST_PORT; //Line i41n config.h #define OUTLOOK_PORT 587
// eMailServerSetting.Port = VERIZON_HOST_PORT; //2-14-2023 changed to Verizon so can try LBH2015NVR
eMailServerSetting.Ip = SL_IPV4_VAL(74,125,129,108);
eMailServerSetting.SecurityMethod = SL_SO_SEC_METHOD_TLSV1_2; //Original 2014 to Jan 2023
eMailServerSetting.SecurityCypher = SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA; //Original 2014 to Jan 2023

//2-23-2023 Thomas Schmitt link said Gmail port 465 with SSL
// CC3100 SDK1.3.0 shows about 25 Transport Security Options, Two with SSL
// SSLV3 SSL_RSA_WITH_RC4_128_SHA
// SSLV3 SSL_RSA_WITH_RC4_128_MD5
// eMailServerSetting.SecurityMethod = SL_SO_SEC_METHOD_SSLV3;
// eMailServerSetting.SecurityCypher = SL_SEC_MASK_SSL_RSA_WITH_RC4_128_SHA;
// eMailServerSetting.SecurityCypher = SL_SEC_MASK_SSL_RSA_WITH_RC4_128_MD5;

E.2 Config.h
See below the settings for: GMAIL, YAHOO, OUTLOOK, ZOHO per there Websites
#define SMTP_BUF_LEN 100
//#define GMAIL_HOST_NAME "smtp.gmail.com"
//#define GMAIL_HOST_PORT 465 //Line 1212 in emailAndGetTime.c eMailServerSetting.Port = GMAIL_HOST_PORT;
//#define GMAIL_HOST_PORT 465 //Line 1212 in emailAndGetTime.c 2-23-2023 link from Thomas 465 ok for use with SSL
//#define GMAIL_HOST_PORT 587 //10-5-2022 Google post says port 465 no longer accepted as the standard port, no2 587, 2525 and 25
// 2-18-2023 try 587, 2525, and 25
//Another post says for plain text use port 465 for SSL, use port 587 for TLS
// Line 1215 in emailAndGetTime.c defines the security method, ..... see below looks like TLS V1_2
// eMailServerSetting.SecurityMethod = SL_SO_SEC_METHOD_TLSV1_2;

//#define YAHOO_HOST_NAME "smtp.mail.yahoo.com"
//#define YAHOO_HOST_PORT 25

//#define OUTLOOK_HOST_NAME "smtp-mail.outlook.com"
//#define OUTLOOK_HOST_PORT 587 //Port Number: 587 (With TLS)
//#define OUTLOOK_HOST_PORT 25 //Alternative Port Number: 25 (Without TLS/SSL) 2-21-2023 but in emailAndGetTime.c I don't know how to specify none

#define ZOHO_HOST_NAME "smtp.zoho.com"
//#define ZOHO_HOST_PORT 465 //Port Number: 465 (With SSL)
#define ZOHO_HOST_PORT 587 //Port Number: 587 (With TLS)

//2-14-2023
//#define AOL_HOST_NAME "smtp.aol.com"
//#define VERIZON_HOST_NAME "smtp.verizon.net target="_blank">smtp.verizon.net"
//#define GMAIL_HOST_NAME "smtp.verizon.net" //Can't find any place were it refers to GMAIL_HOST_NAME, so I could change to Verizon so fake it
//#define VERIZON_HOST_PORT 465 //2-14-2023, found that the AOL Port is also 465

E.3 Lines 137 – 217 _i32 sl_NetAppEmailSet
_i32 sl_NetAppEmailSet(_u8 command ,_u8 pValueLen,
_u8 *pValue)
{

SlNetAppEmailOpt_t* pEmailOpt = 0;
SlNetAppSourceEmail_t* pSourceEmail = NULL;
SlNetAppSourcePassword_t* pSourcePassword = NULL;
SlNetAppDestination_t* pDestinationEmail = NULL;
SlNetAppEmailSubject_t* pSubject = NULL;

switch (command)
{
case NETAPP_ADVANCED_OPT:
pEmailOpt = (SlNetAppEmailOpt_t*)pValue;

g_EmailOpt.Port = pEmailOpt->Port;
g_EmailOpt.Family = pEmailOpt->Family;
g_EmailOpt.SecurityMethod = pEmailOpt->SecurityMethod;
g_EmailOpt.SecurityCypher = pEmailOpt->SecurityCypher;
g_EmailOpt.Ip = pEmailOpt->Ip;

g_EmailSetStatus+=1;
CLI_Write(" Line 159 email port, security \n\r"); //2-16-2023 added
// CLI_Write(" \n Line 159 email port: %d\n\", Port); //Gives errors
break;
// See Thermostat Controller code in mytimers.c; works there but not here
// printf("\nMessage Body is: %d\n", usiGMTOffsetHrSet); //%d is an integer
// CLI_Write("\nMessage Body is: %s\n", LHemailBody);
case NETAPP_SOURCE_EMAIL:
pSourceEmail = (SlNetAppSourceEmail_t*)pValue;
pal_Memset(g_Email.Username, '\0', MAX_USERNAME_LEN);
pal_Memcpy(g_Email.Username, pSourceEmail->Username, pValueLen);

g_EmailSetStatus+=2;
CLI_Write(" Line 171 email Username \n\r"); //2-16-2023 added
break;

case NETAPP_PASSWORD:
pSourcePassword = (SlNetAppSourcePassword_t*)pValue;
pal_Memset(g_SourcePass.Password, '\0', MAX_PASSWORD_LEN);
pal_Memcpy(g_SourcePass.Password, pSourcePassword->Password, pValueLen);

g_EmailSetStatus+=4;
CLI_Write(" Line 180 email Password \n\r"); //2-16-2023 added
break;

case NETAPP_DEST_EMAIL:
pDestinationEmail=(SlNetAppDestination_t*)pValue;
pal_Memset(g_Destination.Email target="_blank">Destination.Email, '\0', MAX_DEST_EMAIL_LEN);
pal_Memcpy(g_Destination.Email, pDestinationEmail->Email, pValueLen);

g_EmailSetStatus+=8;
CLI_Write(" Line 189 email Destination \n\r"); //2-16-2023 added
break;

case NETAPP_SUBJECT:
pSubject=(SlNetAppEmailSubject_t*)pValue;
pal_Memset(g_Subject.Value, '\0', MAX_SUBJECT_LEN);
pal_Memcpy(g_Subject.Value, pSubject->Value, pValueLen);

g_EmailSetStatus+=16;
CLI_Write(" Line 198 email Subject \n\r"); //2-16-2023 added
break;

case NETAPP_MESSAGE:
if(pValueLen > (MAX_MESSAGE_LEN - 1))
{
ASSERT_ON_ERROR(EMAIL_SET_INVALID_MESSAGE);
}
pal_Memset(message, '\0', MAX_MESSAGE_LEN);
pal_Memcpy(message ,pValue, pValueLen);
CLI_Write(" Line 208 email Message Body \n\r"); //2-16-2023 added
break;

default:
CLI_Write((_u8*)"\n\rLine209 Error:Default case\n\r");
ASSERT_ON_ERROR(EMAIL_SET_INVALID_CASE);
}

return SUCCESS;
}

E.4 Lines 271 – 351 _i32 _smtpConnect
static _i32 _smtpConnect(void)
{
SlSockAddrIn_t LocalAddr;
SlTimeval_t tTimeout;
_i32 cipher = 0;
_i32 LocalAddrSize = 0;
_i8 method = 0;
_i32 Status = 0;

LocalAddr.sin_family = g_EmailOpt.Family;
LocalAddr.sin_port = sl_Htons(g_EmailOpt.Port);
LocalAddr.sin_addr.s_addr = sl_Htonl(g_EmailOpt.Ip);
LocalAddrSize = sizeof(SlSockAddrIn_t);

/* If TLS is required */
if(g_EmailOpt.SecurityMethod <= 5)
{
/* Create secure socket */
smtpSocket = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_SEC_SOCKET);
ASSERT_ON_ERROR(smtpSocket);

tTimeout.tv target="_blank">tTimeout.tv_sec = 10;
tTimeout.tv_usec = 90000;
Status = sl_SetSockOpt(smtpSocket, SOL_SOCKET, SL_SO_RCVTIMEO,
&tTimeout, sizeof(SlTimeval_t));
ASSERT_ON_ERROR(Status);

method = g_EmailOpt.SecurityMethod;
cipher = g_EmailOpt.SecurityCypher;

CLI_Write(" Line 301 In _smtpConnect after if TLS create secure socket \n\r");

/* Set Socket Options that were just defined */
Status = sl_SetSockOpt(smtpSocket, SL_SOL_SOCKET, SL_SO_SECMETHOD,
&method, sizeof(method));
CLI_Write(" Line 306 In _smtpConnect Set Socket \n\r");
if( Status < 0 )
{
sl_Close(smtpSocket);
ASSERT_ON_ERROR(Status);
CLI_Write(" Line 311 In _smtpConnect sl_Close smtpSocket step 1 \n\r");
}
Status = sl_SetSockOpt(smtpSocket, SL_SOL_SOCKET, SL_SO_SECURE_MASK,
&cipher, sizeof(cipher));
if( Status < 0 )
{
sl_Close(smtpSocket);
ASSERT_ON_ERROR(Status);
CLI_Write(" Line 319 In _smtpConnect sl_Close smtpSocket step 2 \n\r");
}
}
/* If no TLS required */
else
{
/* Create socket */
smtpSocket = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_IPPROTO_TCP);
ASSERT_ON_ERROR(smtpSocket);

CLI_Write(" Line 329 In _smtpConnect after if NO TLS required create socket \n\r");
}

/* connect to socket */
CLI_Write(" Line 333 In _smtpConnect before connect to Socket \n\r");
Status = sl_Connect(smtpSocket, (SlSockAddr_t *)&LocalAddr, LocalAddrSize);
CLI_Write(" Line 335 In _smtpConnect after connect to Socket \n\r"); //2-16-2023 this prints

if((Status < 0) && (SL_ESECSNOVERIFY != Status))
{
CLI_Write(" Line 339 In _smtpConnect if Status < 0 && SL_ESECSNOVERIFY != Status \n\r"); //2-16-2023 this prints
// **************************************************************
// Jan 30, 2023 I do get the above CLI write, but then no more
// Appears that Connect to Socket is NOT successful
// Next write I get is at line 914
// **************************************************

ASSERT_ON_ERROR(Status);
CLI_Write(" Line 347 In _smtpConnect Status after connect to socket \n\r"); //2-16-2023 do not get this
}
CLI_Write(" Line 349 In _smtpConnect right before return SUCCESS \n\r"); //2-16-2023 do not get this
return SUCCESS;
}

E.5 Lines 839 – 951 int LHSendEmail()
int LHSendEmail()
{
usiEmailDummy = 0;
usiEmail1OrTime2 = 1; //In the function call set to 1 for email, set to 2 for get-time


_i32 retVal = -1;

retVal = initializeAppVariables();
ASSERT_ON_ERROR(retVal);

// /* Stop WDT and initialize the system-clock of the MCU */
// stopWDT();
// initClk();

/* Configure command line interface */
CLI_Configure();

displayBanner();

/*
* Following function configures the device to default state by cleaning
* the persistent settings stored in NVMEM (viz. connection profiles &
* policies, power policy etc)
*
* Applications may choose to skip this step if the developer is sure
* that the device is in its default state at start of application
*
* Note that all profiles and persistent settings that were done on the
* device will be lost
*/
retVal = configureSimpleLinkToDefaultState();
if(retVal < 0)
{
if (DEVICE_NOT_IN_STATION_MODE == retVal)
CLI_Write(" Line 874 Failed to configure the device in its default state \n\r");

// 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
//I think better to move on, as already printed out the failure, maybe some time later it will work
// LOOP_FOREVER();
}

CLI_Write(" Line 881 Device is configured in default state \n\r");

/*
* Initializing the CC3100 device
* Assumption is that the device is configured in station mode already
* and it is in its default state
*/
retVal = sl_Start(0, 0, 0);
if ((retVal < 0) ||
(ROLE_STA != retVal) )
{
CLI_Write(" Line 892 Failed to start the device \n\r");
// 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
//I think better to move on, as already printed out the failure, maybe some time later it will work
// LOOP_FOREVER();
}

CLI_Write(" Line 898 Device started as STATION \n\r");

/* Configure the source email */
retVal = setEmail();
if(retVal < 0)
LOOP_FOREVER();

/* Connecting to WLAN AP */
retVal = establishConnectionWithAP();
if(retVal < 0)
{
CLI_Write(" Line 909 Failed to establish connection w/ an AP \n\r");
// 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
//I think better to move on, as already printed out the failure, maybe some time later it will work
// LOOP_FOREVER();
}

CLI_Write(" Line 915 Connection established w/ AP and IP is acquired \n\r");

/* Configure and send the email */
CLI_Write(" Line 918 Sending email... \n\r"); //Jan 30, 2023 successfully get this
retVal = sendEmail();
if (retVal < 0)
{
CLI_Write(" Line 922 Device couldn't send the email \n\r");
// 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
//I think better to move on, as already printed out the failure, maybe some time later it will work
// LOOP_FOREVER();
// LOOP_FOREVER(); // Jan 30, 2023 put this back in as get Device couldn't send the email \n\r
//Did not solve the problem of not sending email and just locks at this point
}
else
{
CLI_Write(" Line 931 Email Sent successfully \n\r");
}

/* Disconnect from AP */
retVal = disconnectFromAP();
if(retVal < 0)
{
CLI_Write(" Line 938 Failed to disconnect from the AP \n\r");
// 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
//I think better to move on, as already printed out the failure, maybe some time later it will work
// LOOP_FOREVER();
}

retVal = sl_Stop(SL_STOP_TIMEOUT);
// 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
//I think better to move on, as already printed out the failure, maybe some time later it will work
// if(retVal < 0)
// LOOP_FOREVER();

return 0;
} // Closing bracket for int LHSendEmail()

E.6 Lines 1194 – 1233 _i32 setEmail()

static _i32 setEmail()
{
_i32 retVal = -1;
SlNetAppSourceEmail_t sourceEmailId = {0};
SlNetAppSourcePassword_t sourceEmailPwd = {0};
SlNetAppEmailOpt_t eMailServerSetting = {0};

pal_Memcpy(sourceEmailId.Username,USER,pal_Strlen(USER)+1);
retVal = sl_NetAppEmailSet(NETAPP_SOURCE_EMAIL,pal_Strlen(USER)+1,
(_u8*)&sourceEmailId);
ASSERT_ON_ERROR(retVal);

pal_Memcpy(sourceEmailPwd.Password,PASS,pal_Strlen(PASS)+1);
retVal = sl_NetAppEmailSet(NETAPP_PASSWORD,pal_Strlen(PASS)+1,
(_u8*)&sourceEmailPwd);
ASSERT_ON_ERROR(retVal);

eMailServerSetting.Family = AF_INET;
// eMailServerSetting.Port = GMAIL_HOST_PORT; //Line 27 in config.h #define GMAIL_HOST_PORT 465
// eMailServerSetting.Port = OUTLOOK_HOST_PORT; //Line i41n config.h #define OUTLOOK_PORT 587
eMailServerSetting.Port = ZOHO_HOST_PORT; //Line i41n config.h #define OUTLOOK_PORT 587
// eMailServerSetting.Port = VERIZON_HOST_PORT; //2-14-2023 changed to Verizon so can try LBH2015NVR
eMailServerSetting.Ip = SL_IPV4_VAL(74,125,129,108);
eMailServerSetting.SecurityMethod = SL_SO_SEC_METHOD_TLSV1_2; //Original 2014 to Jan 2023
eMailServerSetting.SecurityCypher = SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA; //Original 2014 to Jan 2023

//2-23-2023 Thomas Schmitt link said Gmail port 465 with SSL
// CC3100 SDK1.3.0 shows about 25 Transport Security Options, Two with SSL
// SSLV3 SSL_RSA_WITH_RC4_128_SHA
// SSLV3 SSL_RSA_WITH_RC4_128_MD5
// eMailServerSetting.SecurityMethod = SL_SO_SEC_METHOD_SSLV3;
// eMailServerSetting.SecurityCypher = SL_SEC_MASK_SSL_RSA_WITH_RC4_128_SHA;
// eMailServerSetting.SecurityCypher = SL_SEC_MASK_SSL_RSA_WITH_RC4_128_MD5;

retVal = sl_NetAppEmailSet(NETAPP_ADVANCED_OPT,sizeof(SlNetAppEmailOpt_t),
(_u8*)&eMailServerSetting);
ASSERT_ON_ERROR(retVal);

return SUCCESS;
}



E.7 Lines 1246 – 1290 _i32 sendEmail()
static _i32 sendEmail()
{
_i32 Status = -1;

Status = sl_NetAppEmailSet(NETAPP_DEST_EMAIL,
pal_Strlen(DESTINATION_EMAIL),
(_u8 *)DESTINATION_EMAIL);
ASSERT_ON_ERROR(Status);
CLI_Write(" Line 1253 After...DESTINATION_EMAIL \n\r"); //Jan 30, 2023 added this
// Status = sl_NetAppEmailSet(NETAPP_SUBJECT,
// pal_Strlen(EMAIL_SUBJECT),
// (_u8 *)EMAIL_SUBJECT);

//LH added 5-20-2020 to use my character array for the email subject
Status = sl_NetAppEmailSet(NETAPP_SUBJECT,
pal_Strlen(LHemailSubject),
(_u8 *)LHemailSubject);


ASSERT_ON_ERROR(Status);
CLI_Write(" Line 1265 After...LHemailSubject \n\r"); //Jan 30, 2023 added, this is printed

// Status = sl_NetAppEmailSet(NETAPP_MESSAGE,
// pal_Strlen(EMAIL_MESSAGE),
// (_u8 *)EMAIL_MESSAGE);

//LH added 5-20-2020 to use my character array for the email message
Status = sl_NetAppEmailSet(NETAPP_MESSAGE,
pal_Strlen(LHemailBody),
(_u8 *)LHemailBody);


ASSERT_ON_ERROR(Status);
CLI_Write(" Line 1278 After...LHemailBody \n\r"); //Jan 30, 2023 added this, this IS printed

Status = sl_NetAppEmailConnect(); //2-16-2022 looks like this function does not complete
CLI_Write(" Line 1281 After...Status = sl_NetAppEmailConnect() \n\r"); //2-16-2022, this is NOT printed
ASSERT_ON_ERROR(Status);
CLI_Write(" Line 1283 After...sl_NetAppEmailConnect \n\r"); //Jan 30, 2023 added this, this is NOT printed

Status = sl_NetAppEmailSend();
ASSERT_ON_ERROR(Status);
CLI_Write(" Line 1287 After...sl_NetAppEmailSend \n\r"); //Jan 30, 2023 added, this is NOT printed
return SUCCESS;
}

E.8 Lines 1480 – 1498 _i32 disconnectFromAP()
static _i32 disconnectFromAP()
{
_i32 retVal = -1;

/*
* The function returns 0 if 'Disconnected done', negative number if already disconnected
* Wait for 'disconnection' event if 0 is returned, Ignore other return-codes
*/
retVal = sl_WlanDisconnect();
CLI_Write(" Line 1488 in _i32 disconnectFromAP() after retVal = sl_WlanDisconnect(); \n\r");
if(0 == retVal)
CLI_Write(" Line 1490 in _i32 disconnectFromAP() after if(0 == retVal) \n\r");
{
/* Wait */
while(IS_CONNECTED(g_Status)) { _SlNonOsMainLoopTask(); }
}

return SUCCESS;
}


END

The Terma Term trace show line by line how the code is stepping throught the various function calls. I have the included lines of code so you can see exatly what lines it executed up until it said cannot send email.

Here it is again
LH
Email application - Version 1.3.0
*******************************************************************************
Line 881 Device is configured in default state
Line 898 Device started as STATION
Line 171 email Username
Line 180 email Password
Line 159 email port, security
Line 915 Connection established w/ AP and IP is acquired
Line 918 Sending email...
Line 189 email Destination
Line 1253 After...DESTINATION_EMAIL
Line 198 email Subject
Line 1265 After...LHemailSubject
Line 208 email Message Body
Line 1278 After...LHemailBody
Line 301 In _smtpConnect after if TLS create secure socket
Line 306 In _smtpConnect Set Socket
Line 333 In _smtpConnect before connect to Socket
Line 513 In socket.c, _sl_Connect
Line 95 In socket.c, _sl_BuildAddress
Line 554 In socket.c, _sl_Connect Verify_RET_OK
Line 335 In _smtpConnect after connect to Socket
Line 339 In _smtpConnect if Status < 0 && SL_ESECSNOVERIFY != Status
Line 1281 After...Status = sl_NetAppEmailConnect()
Line 922 Device couldn't send the email
Line 1488 in _i32 disconnectFromAP() after retVal = sl_WlanDisconnect();
Line 1490 in _i32 disconnectFromAP() after if(0 == retVal)
Line 1011 Device disconnected from the AP on application's request
 
I believe it has something to do with security settings
 
eMailServerSetting.Family = AF_INET;
// eMailServerSetting.Port = GMAIL_HOST_PORT; //Line 27 in config.h #define GMAIL_HOST_PORT 465
// eMailServerSetting.Port = OUTLOOK_HOST_PORT; //Line i41n config.h #define OUTLOOK_PORT 587
eMailServerSetting.Port = ZOHO_HOST_PORT; //Line i41n config.h #define OUTLOOK_PORT 587
// eMailServerSetting.Port = VERIZON_HOST_PORT; //2-14-2023 changed to Verizon so can try LBH2015NVR
eMailServerSetting.Ip = SL_IPV4_VAL(74,125,129,108);
eMailServerSetting.SecurityMethod = SL_SO_SEC_METHOD_TLSV1_2; //Original 2014 to Jan 2023
eMailServerSetting.SecurityCypher = SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA; //Original 2014 to Jan 2023
 
1) a couple of lines code change that I need to make. or 2) A current working example of CC3100 with FR6989 sending an email using GMAIL, Outlook.com or SOHO email services. The current posted email example on TI CC3100 no longer works.
 
If you need any more code uploads I am happy to do that but I believe you have all you need. I could even upload a whole Code Composser Studio working project, of except the email part no longer works.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

I am sure TI would like to advertise that they have a fix so CC3100 SDK-1.3.0 can still send emails.

I mentioned it in the Chat but I do not see it in the attached emails.

We get an SMTP return code of -111.

Google says

The SMTP 111 error occurs when an issue is present while connecting with the remote SMTP server. For example, you would run into this error due to invalid sender domains or firewall issues.

Please let me know if you need anymore information. I believe I have submitted all the sections of code that you need.  I have pasted the complete Code Composer Studio emailAndGetTime.c and .h that had run for 9 years with F5529 and FR6989 micros, with the simplelink files, and includes for SDK_1.3.0.

You should be able to load and run this file. Call from main is:

    ret = LHGetTime ();    //Calls functions in emailAndGetTime.c; to get the time

ret  =  LHSendEmail ();  //Calls functions in emailAndGetTime.c; to send an email

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

I updated the problem description document that I want to post. I also plan to post a Code Composer Studio Exported working Application based on the FR6989 with the CC3100 Boost.

I am pleased to share this working code so it will be very easy for TI email / security experts to just load and run this program and work on a solution. The emailAndGetTime.c code is 99% untouched original TI SDK-1.3.0 code with enhanced links to the application. So all the WiFi, smpt, etc code is all original TI code, but obviously now lacking in being able to deal with new email server security protocols.

I also hope that other TI customers find the extensive LCD display code and Email message creation framework / code helpful as a basis for their projects.

Attached is the Posting and the CCS Exported Application ready to load into and FR6989 microcontroller with an CC3100 Boost daughter card. 

CS1635787.zip

Thanks for your help,

Gerald

  • The Code Composser Studio application ZIP file needs your specific WIFI and email addresses and password 

    sl-common: Your WiFi acccess name and SSID

    config.h: Sending email service name and password, and destination email name

  • Hi Gerald,

    The CC3100 is a very old device. We have no plans to update the CC3100 SDK or this email example.

    You can use the source code and update it or use a different email application (should be easy to port it on top of the Simplelink BSD API). 

    The examples were given as a reference design. We can't maintain them when the servers are updated.

    Br,

    Kobi

  • Thanks Kobi the reply,

    1. We are disappointed that TI is no longer supporting the CC3100 and SDK-1.3.0 (My mistake in Post I had typo 1.3.1 vs 1.3.0) We had many applications, and I am sure other customers did as well, that are now email status shut down.
    2. For protype development the FR6989 with the LCD display, and a WiFi card like the CC3100 to send status data is excellent. Hourly – Daily- Monthly Email status data from remote IOT devices helps us refine / optimize product algorithms. We have searched to see if there is a newer replacement for the CC3100 Boost but have not found such a daughter card. Please identify if such a newer WiFi daughter card does exist and has a proven still working send email example.
    3. If TI is no longer going to support the Email example, please flag this so other developers do not waste time on trying to make it work. Plus it is FALSE ADVERTIZING.
    4. Has some other customers on the E2E form, has a developer who is an expert on Email server security and has come up with an update fix. This would be a huge benefit for many customers.
    5. We have down loaded CC3200 SDK-1.5.0 and have started to look at the email example code to see if we can see any or what enhancements have been made that we can port back to include with the CC3100.
    6. Has the CC3200 SDK-1.5.0 email example been verified to still work after Feb 1, 2023, GMAIL, AOL, OUTLOOK.com, SOHO etc email services security updates? Is there any email service that has recently been proven to still work that all the customers can use.
    7. iPhones, Smartphones, PC’s can all still send email from GMAIL, AOL, OUTLOOK.com, SOHO etc email services. What do they do? Can this not be incorporated into the TI WiFi email or is the code size and processing power requirements more than a microcontroller can handle? TI is pushing IOT of everything, even for very small devices so we would think it would be very beneficial for TI to have a working “send email example”. We understand it would be limited to say 64 bytes vs multi-megabytes, but for IOT only need ability to send measurement / variable status, and not lines / paragraphs of text, or large data files..

     

    PS We always focus on TI parts first if possible, so we want TI to succeed. Happy to work with you on a solution.

  • Hi,

    SMTP protocol is a pretty simple and creating own implementation is work for a few days. I think CC3100 + MSP430FR6989 still should work with majority of SMTP server unless is required TLS 1.3, STARTTLS encryption or OAuth 2. As I know STARTTLS support may to be issue for outlook.com. For using Gmail without OAuth 2.0, it need to be enabled 2FA and app password.

    If you want to have functional implementation of SMTP, you can do it by yourself. It is really not hard task. If you will read carefully RFCs for SMTP, you will discover, that TI is not should be blame at this case.

    I use CC3220SF device with own SMTP implementation which works with majority of SMTP servers. I can't provide you my SMTP code, but I can answer your questions if you will decide implement your SMTP code.

    Jan

  • There were no updates for the application in the CC3200 SDK.

    There are some fixes in the host driver (if you want to port code from the latest CC3200 SDK 1.5.0) but they are not relevant for your issue.

    As Jan mentioned, you can fix the reference SMTP code from the SDK or use a different SMTP implementation on top of the CC3100 sockets.

  • Thanks Jan and Kobi for your replies. I have talked to several other developers and the view is that to support the enhanced security of current email services will likely require much more memory and processing power than the FR6989 provides. Analysis of CC3200 SKD 1.5.0 email example shows the email code and security code, looks identical to the CC3100 SDK-1.3.0. I am sure the CC3200 email example also no longer works.

    It would be great Jan if you or some person on this form could post a working example of the security code that works with GMAIL after Feb 1, 2023. You don’t need to post the whole SMTP email example, even just the code dealing with security.

     

    Another option we are investigating is the IFTTT (“If this, then that”) service https://ifttt.com/  

    We are investigating using this example as a framework to create an FR6989 with CC3100 to send email status.

    Arduino Send Email through IFTTT using Ethernet Shield (microcontrollerslab.com)

    An HTTP post can be made to https://maker.ifttt.com. The service has all the email certificates / security to enable it to send an email to a defined email address.

    maker.ifttt.com/.../XXXXXXXXXXXXXXXXXXXXX

    Remember to change REPLACE_WITH_YOUR_EVENT_NAME with the event name that you set and the XXXXXXXXXXXXXXXXXXXXX with the Webhooks private key

    In our case, we are using the following URL:    maker.ifttt.com/.../SEND EMAIL/with/key/gkb_HtIpE-FeOWMH20*************************?value1=31.2

    If / When we get this working, we would be pleased to share the code with other users on the E2E form. If some other user already has this working, it would be greatly appreciated if you could post a working example.

    Lorne

  • Hi Lorne,

    I am not sure whether less number of supported cipher suites  by CC3100 in comparison with CC3x20 may play here role. But if not, there is not signe reason for any memory or performance problem for CC3100 with MSP430FR6989 and sending emails via smtp.gmail.com:465 (TLS) with enabled application password. You need to realize that TLS is done inside CC3100 not a MSP430.

    I have re-tested my implementation and CC3220SF have not issue with:

    • smtp.gmail.com :465 (TLS) :587 (STARTTLS)
    • smtp-mail.outlook.com :587 (STARTTLS)
    • smtp.mail.yahoo.com :465 (TLS) :587 (STARTTLS)
    • smtp.aol.com :465 (TLS) :587 (STARTTLS)
    • mail.gmx.com :465 (TLS) :587 (STARTTLS)
    • smtp.seznam.cz :465 (TLS) :587 (STARTTLS) : 25 (AUTH LOGIN in plaintext)
    • smtp.centrum.cz :465 (TLS) :587 (STARTTLS) : 25 (AUTH LOGIN in plaintext)

    If there is an issue with outdated cipher suites at CC3100 then you will not be able use CC3100 with gmail. But if not there is not technical reason that  CC3100 + MSP430FR6989 should not work regardless other developers said to you. Of course you will need figure out what is reason of incompatibility of your SMTP library. But this will be job for you. I don't want to spend my time to play with CC3100...

    Jan

  • Thanks Jan for this update.

    We have tried SSL and TLS on ports 465 and port 587 for gmail, outlook, and yahoo and all fail.

    We have not changed the TI CC3100 email example Security Method nor Cypher Suit.

    Security Method:  SL_SO_SEC_METHOD_SSLv3_TLSV1_2

    Cipher Suit:  SL_SEC_MASK_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256

        eMailServerSetting.Ip = SL_IPV4_VAL(74,125,129,108);

        eMailServerSetting.SecurityMethod = SL_SO_SEC_METHOD_TLSV1_2; //Original 2014 to Jan 2023 worked perfectly

        eMailServerSetting.SecurityCypher = SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA; //Original 2014 to Jan 2023 worked perfectly

    ******We then tried every one of the TLS Cypher suits and all of them fail. ********

     

    This is copied from: “CC3100/CC3200 SimpleLink Wi-Fi Internet-on-a-Chip User's Guide”,  SWRU368B–April 2014–Revised May 2018

    The title says both CC3100 and the CC3200 family

    9.2.2.1 Selecting a Method

    Manually defines the SSL method. In simplelink WiFi device, SSLv3 TLSv 1.0/1.1/1.2 is supported. SlSockSecureMethod method; method.secureMethod = Choose one of the following defines:

    • SL_SO_SEC_METHOD_SSLV3
    • SL_SO_SEC_METHOD_TLSV1
    • SL_SO_SEC_METHOD_TLSV1_1
    • SL_SO_SEC_METHOD_TLSV1_2
    • SL_SO_SEC_METHOD_SSLv3_TLSV1_2
    • SL_SO_SEC_METHOD_DLSV1 Sl_SetSockOpt(sockID, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(SlSockSecureMethod));

     

    What did you enter to use STARTTLS?  It is not an option that is documented as supported.

     

    9.2.2.2 Selecting a Cipher Suit

    Manually defines the SSL connection and handshake security algorithms, also known as cipher suits. SlSockSecureMask Mask; mask.secureMask = Choose logic or between the following:

    • SL_SEC_MASK_SSL_RSA_WITH_RC4_128_SHA
    • SL_SEC_MASK_SSL_RSA_WITH_RC4_128_MD5
    • SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA
    • SL_SEC_MASK_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
    • SL_SEC_MASK_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
    • SL_SEC_MASK_TLS_ECDHE_RSA_WITH_RC4_128_SHA
    • SL_SEC_MASK_TLS_RSA_WITH_AES_128_CBC_SHA256
    • SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA256
    • SL_SEC_MASK_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
    • SL_SEC_MASK_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256

    Sl_SetSockOpt(sockID, SL_SOL_SOCKET, SL_SO_SECMETHOD, &mask, sizeof(SlSockSecureMask))

     

    As you can see STARTTLS is not an option that is supported in the CC3100 or CC3200, maybe it is supported and just not documented.

    What did you enter to use STARTTLS?  It is not an option that is documented as supported.

    Questions & assistance

    1. What Security Method are you using?
    2. What Cypher Suit are you using?
    3. Please post just the code to handle the STARTTLS?

         We know that very smart SMTP and Security Experts like yourself who have likely spent years working in in SMTP and Security code this is very easy. For general Electrical Engineers and Software Developers although we have decades of experience and have written many 10’s of thousands of lines of Application C-code, since this is not our primary area of expertise, helping clues and sample code is invaluable. If we had that I am confident we could figure out how to integrate it with the existing TI CC31000 SDK-1.3.0 WiFi suite. I am sure we already have 95% of what we need to make the TI Send Email Example work again.

    Attached is the complete TI CC3100 WiFi code with only our application function calls integrated into it. ****This is 95% all TI code not our code***.

    Looking forward to your STARTTLS code subset.

    Thanks,

    Lorne and team

    emailAndGetTime.c    99% TI WiFi code with Application function calls

    /*LH created file to merge both Send Email and Get Time
     * Identical file for F5529, FR5969, and FR6989
     * Major changes to make it work with function calls from main
     * Commented out almost all Loop Forever which just hangs my whole application
     *
     * email.c - function implementation to send email
     *
     * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
     *
     *
     * All rights reserved. Property of Texas Instruments Incorporated.
     * Restricted rights to use, duplicate or disclose this code are
     * granted through contract.
     *
     * The program may not be used without the written permission of
     * Texas Instruments Incorporated or against the terms and conditions
     * stipulated in the agreement under which this program has been supplied,
     * and under no circumstances can it be used with non-TI connectivity device.
     *
     */
    
    /*
     * Protocol Name     -  Simple Mail Transfer Protocol
     * Protocol Overview -  The objective of the Simple Mail Transfer Protocol (SMTP) is to
     *                      transfer mail reliably and efficiently.SMTP is independent of the
     *                      particular transmission subsystem and requires only a reliable
     *                      ordered data stream channel.
     *                      Refer: https://www.ietf.org/rfc/rfc2821.txt
     */
    volatile unsigned short usiEmail1OrTime2 = 0; //In the function call set to 1 for email, set to 2 for get-time
    //Same function call can be used but inside the function the specific statements are for email or get time
    //I do not want to create a similar function with a different name as I do not know where else in simplelink it may be calling these functions
    
    #include <emailAndGetTime.h>
    #include "base64.h"
    #include "config.h"
    #include "sl_common.h"
    
    #include "myGPIO.h" //8-23-2020 LH added
    
    /*NetApp Email protocol types */
    #define SL_NET_APP_SMTP_PROTOCOL        (1)
    #define INVALID_SOCKET_DESC             0xFFFFFFFF
    
    /* Strings used to configure the Email msg in proper format */
    const _u8 smtp_helo[] = {'H','E','L','O','\0'};
    const _u8 smtp_mail_from[]={'M','A','I','L',' ','F','R','O','M',':',' ','\0'};
    const _u8 smtp_rcpt[] = {'R','C','P','T',' ','T','O',':',' ','\0'};
    const _u8 smtp_data[] = "DATA";
    const _u8 smtp_crlf[] = "\r\n";
    const _u8 smtp_dcrlf[] = "\r\n\r\n";
    const _u8 smtp_subject[] = "Subject: ";
    const _u8 smtp_to[] = "To: ";
    const _u8 smtp_from[] = "From: ";
    /* <CRLF>.<CRLF> Terminates the data portion */
    const _u8 smtp_data_end[] = {'\r','\n','.','\r','\n','\0'};
    const _u8 smtp_quit[] = {'Q','U','I','T','\r','\n','\0'};
    
    /* Return Codes */
    const _u8 smtp_code_ready[] = {'2','2','0','\0'};
    const _u8 smtp_ok_reply[] = {'2','5','0','\0'};
    const _u8 smtp_intermed_reply[] = {'3','5','4','\0'};
    const _u8 smtp_auth_reply[] = {'3','3','4','\0'};
    const _u8 smtp_auth_success[] = {'2','3','5','\0'};
    
    /* states for smtp state machine */
    typedef enum
    {
        smtpINACTIVE = 0,
        smtpINIT,
        smtpHELO,
        smtpAUTH,
        smtpFROM,
        smtpRCPT,
        smtpDATA,
        smtpMESSAGE,
        smtpQUIT,
        smtpERROR
    }_SlsmtpStatus_e;
    
    /* Initialize SMTP State Machine */
    _u16 g_smtpStatus = smtpINIT;
    
    _u16 g_EmailSetStatus = 0;
    
    /* error handling flags for smtp state machine */
    typedef enum
    {
        smtpNOERROR = 0,
        atINIT,
        atHELO,
        atAUTH,
        atFROM,
        atRCPT,
        atDATA,
        atMESSAGE,
        atQUIT
    }_SlsmtpERROR_e;
    
    /* Initialize Error handling flag */
    _u16 g_smtpErrorInfo = smtpNOERROR;
    _i32 smtpSocket;
    _u8 g_cmdBuf[SMTP_BUF_LEN];
    _u8 buf[SMTP_BUF_LEN];
    _u8 basekey1[BASEKEY_LEN];
    _u8 basekey2[BASEKEY_LEN];
    _u8 message[MAX_MESSAGE_LEN];
    
    SlNetAppEmailOpt_t g_EmailOpt;
    SlNetAppSourceEmail_t g_Email;
    SlNetAppSourcePassword_t g_SourcePass;
    SlNetAppDestination_t g_Destination;
    SlNetAppEmailSubject_t g_Subject;
    
    _u8 email_rfc[MAX_EMAIL_RCF_LEN];
    
    static _i32 _smtpConnect(void);
    static _i32 _smtpSend(void);
    static void _smtpHandleERROR(_u8 * servermessage);
    static _i32 _sendSMTPCommand(_i32 socket, _u8 * cmd, _u8 * cmdparam, _u8 * respBuf);
    static void _generateBase64Key(_u8 * basekey1, _u8 * basekey2);
    
    
    /*!
        \brief This function sets the email parameters
    
        \param[in]      command -   Command send for processing
        \param[in]      pValueLen - Length of data to be processed
        \param[in]      pValue -     Data to be processed
    
        \return         0 for success, -1 otherwise
    
        \note
    
        \warning
    */
    _i32 sl_NetAppEmailSet(_u8 command ,_u8 pValueLen,
                          _u8 *pValue)
    {
    
        SlNetAppEmailOpt_t* pEmailOpt = 0;
        SlNetAppSourceEmail_t* pSourceEmail = NULL;
        SlNetAppSourcePassword_t* pSourcePassword = NULL;
        SlNetAppDestination_t* pDestinationEmail = NULL;
        SlNetAppEmailSubject_t* pSubject = NULL;
    
        switch (command)
        {
          case NETAPP_ADVANCED_OPT:
            pEmailOpt = (SlNetAppEmailOpt_t*)pValue;
    
            g_EmailOpt.Port = pEmailOpt->Port;
            g_EmailOpt.Family = pEmailOpt->Family;
            g_EmailOpt.SecurityMethod = pEmailOpt->SecurityMethod;
            g_EmailOpt.SecurityCypher = pEmailOpt->SecurityCypher;
            g_EmailOpt.Ip = pEmailOpt->Ip;
    
            g_EmailSetStatus+=1;
            CLI_Write(" Line 159 email port, security \n\r"); //2-16-2023 added
    //        CLI_Write(" \n Line 159 email port: %d\n\", Port); //Gives errors
            break;
    // See Thermostat Controller code in mytimers.c; works there but not here
    //    printf("\nMessage Body is: %d\n", usiGMTOffsetHrSet); //%d is an integer
    //    CLI_Write("\nMessage Body is: %s\n", LHemailBody);
          case NETAPP_SOURCE_EMAIL:
            pSourceEmail = (SlNetAppSourceEmail_t*)pValue;
            pal_Memset(g_Email.Username, '\0', MAX_USERNAME_LEN);
            pal_Memcpy(g_Email.Username, pSourceEmail->Username, pValueLen);
    
            g_EmailSetStatus+=2;
            CLI_Write(" Line 171 email Username \n\r"); //2-16-2023 added
            break;
    
          case NETAPP_PASSWORD:
            pSourcePassword = (SlNetAppSourcePassword_t*)pValue;
            pal_Memset(g_SourcePass.Password, '\0', MAX_PASSWORD_LEN);
            pal_Memcpy(g_SourcePass.Password, pSourcePassword->Password, pValueLen);
    
            g_EmailSetStatus+=4;
            CLI_Write(" Line 180 email Password \n\r"); //2-16-2023 added
            break;
    
          case NETAPP_DEST_EMAIL:
            pDestinationEmail=(SlNetAppDestination_t*)pValue;
            pal_Memset(g_Destination.Email, '\0', MAX_DEST_EMAIL_LEN);
            pal_Memcpy(g_Destination.Email, pDestinationEmail->Email, pValueLen);
    
            g_EmailSetStatus+=8;
            CLI_Write(" Line 189 email Destination \n\r"); //2-16-2023 added
            break;
    
          case NETAPP_SUBJECT:
            pSubject=(SlNetAppEmailSubject_t*)pValue;
            pal_Memset(g_Subject.Value, '\0', MAX_SUBJECT_LEN);
            pal_Memcpy(g_Subject.Value, pSubject->Value, pValueLen);
    
            g_EmailSetStatus+=16;
            CLI_Write(" Line 198 email Subject \n\r"); //2-16-2023 added
            break;
    
          case NETAPP_MESSAGE:
            if(pValueLen > (MAX_MESSAGE_LEN - 1))
            {
                ASSERT_ON_ERROR(EMAIL_SET_INVALID_MESSAGE);
            }
            pal_Memset(message, '\0', MAX_MESSAGE_LEN);
            pal_Memcpy(message ,pValue, pValueLen);
            CLI_Write(" Line 208 email Message Body \n\r"); //2-16-2023 added
            break;
    
          default:
            CLI_Write((_u8*)"\n\rLine209 Error:Default case\n\r");
            ASSERT_ON_ERROR(EMAIL_SET_INVALID_CASE);
        }
    
        return SUCCESS;
    }
    
    /*!
        \brief Create a secure socket and connects to SMTP server
    
        \param[in]      none
        \return         0 if success and negative in case of error
        \note
        \warning
    */
    _i32 sl_NetAppEmailConnect()
    {
        if (!(g_EmailSetStatus >= 0x07))
        {
            CLI_Write((_u8*)"\n\rLine231 Error:Email and Subject is not configured\n\r");
            ASSERT_ON_ERROR(EMAIL_CONNECT_INVALID_CONFIURATION);
        }
    
        return _smtpConnect();
    }
    
    /*!
        \brief Check the connection status and sends the Email
    
        \param[in]      none
    
        \return         0 if success otherwise -1
    
        \note
    
        \warning
    */
    _i32 sl_NetAppEmailSend()
    {
        _i32 retVal = -1;
        retVal = _smtpSend();
        if(retVal < 0)
            sl_Close(smtpSocket);
    
        return retVal;
    }
    
    
    /*!
        \brief Creates a secure socket and connects to SMTP server
    
        \param[in]      none
    
        \return         0 if success and negative in case of error
    
        \note
    
        \warning
    */
    static _i32 _smtpConnect(void)
    {
        SlSockAddrIn_t  LocalAddr;
        SlTimeval_t     tTimeout;
        _i32           cipher = 0;
        _i32           LocalAddrSize = 0;
        _i8            method = 0;
        _i32            Status = 0;
    
        LocalAddr.sin_family = g_EmailOpt.Family;
        LocalAddr.sin_port = sl_Htons(g_EmailOpt.Port);
        LocalAddr.sin_addr.s_addr = sl_Htonl(g_EmailOpt.Ip);
        LocalAddrSize = sizeof(SlSockAddrIn_t);
    
        /* If TLS is required */
        if(g_EmailOpt.SecurityMethod <= 5)
        {
            /* Create secure socket */
            smtpSocket = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_SEC_SOCKET);
            ASSERT_ON_ERROR(smtpSocket);
    
            tTimeout.tv_sec = 10;
            tTimeout.tv_usec = 90000;
            Status = sl_SetSockOpt(smtpSocket, SOL_SOCKET, SL_SO_RCVTIMEO,
                                   &tTimeout, sizeof(SlTimeval_t));
            ASSERT_ON_ERROR(Status);
    
            method = g_EmailOpt.SecurityMethod;
            cipher = g_EmailOpt.SecurityCypher;
    
            CLI_Write(" Line 301 In _smtpConnect after if TLS create secure socket \n\r");
    
            /* Set Socket Options that were just defined */
            Status = sl_SetSockOpt(smtpSocket, SL_SOL_SOCKET, SL_SO_SECMETHOD,
                                   &method, sizeof(method));
            CLI_Write(" Line 306 In _smtpConnect Set Socket \n\r");
            if( Status < 0 )
            {
                sl_Close(smtpSocket);
                ASSERT_ON_ERROR(Status);
                CLI_Write(" Line 311 In _smtpConnect sl_Close smtpSocket step 1 \n\r");
            }
            Status = sl_SetSockOpt(smtpSocket, SL_SOL_SOCKET, SL_SO_SECURE_MASK,
                                   &cipher, sizeof(cipher));
            if( Status < 0 )
            {
                sl_Close(smtpSocket);
                ASSERT_ON_ERROR(Status);
                CLI_Write(" Line 319 In _smtpConnect sl_Close smtpSocket step 2 \n\r");
            }
        }
        /* If no TLS required */
        else
        {
            /* Create socket */
            smtpSocket = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_IPPROTO_TCP);
            ASSERT_ON_ERROR(smtpSocket);
    
            CLI_Write(" Line 329 In _smtpConnect after if NO TLS required create socket \n\r");
        }
    
        /* connect to socket */
        CLI_Write(" Line 333 In _smtpConnect before connect to Socket \n\r");
        Status = sl_Connect(smtpSocket, (SlSockAddr_t *)&LocalAddr, LocalAddrSize);
        CLI_Write(" Line 335 In _smtpConnect after connect to Socket \n\r"); //2-16-2023 this prints
    
        if((Status < 0) && (SL_ESECSNOVERIFY != Status))
        {
            CLI_Write(" Line 339 In _smtpConnect if Status < 0 && SL_ESECSNOVERIFY != Status \n\r");  //2-16-2023 this prints
    // **************************************************************
    // Jan 30, 2023 I do get the above CLI write, but then no more
    // Appears that Connect to Socket is NOT successful
    // Next write I get is at line 914
    // **************************************************
    
            ASSERT_ON_ERROR(Status);
            CLI_Write(" Line 347 In _smtpConnect Status after connect to socket \n\r"); //2-16-2023 do not get this
        }
        CLI_Write(" Line 349 In _smtpConnect right before return SUCCESS \n\r"); //2-16-2023 do not get this
        return SUCCESS;
    }
    
    /*!
        \brief This function will send the email
    
        \param[in]      none
    
        \return         0 if success otherwise -1
    
        \note
    
        \warning
    */
    static _i32 _smtpSend(void)
    {
        _i16 exit = 0;
        _i32 retVal = -1;
    
        /* If socket has been opened, check for acknowledge from SMTP server */
        while(exit == 0)
        {
            switch(g_smtpStatus)
            {
                /*
                 * An SMTP session is initiated when a client opens a connection to
                 * a server and the server responds with an opening message.
                 */
                case smtpINIT:
                    /* Create buffer, Read so we can check for 220 'OK' from server */
                    pal_Memset(buf, 0, SMTP_BUF_LEN);
    
                    retVal = sl_Recv(smtpSocket, buf, sizeof(buf), 0);
                    if(retVal <= 0)
                    {
                        ASSERT_ON_ERROR(TCP_RECV_ERROR);
                    }
    
                    /* If buffer has 220, set state to HELO */
                    if(buf[0] == smtp_code_ready[0] &&
                       buf[1] == smtp_code_ready[1] &&
                       buf[2] == smtp_code_ready[2])
                    {
                        g_smtpStatus = smtpHELO;
                    }
                    /* Else error, set state to ERROR */
                    else
                    {
                        g_smtpStatus = smtpERROR;
                        g_smtpErrorInfo = atINIT;
                    }
                break;
    
                /*
                 * The client normally sends the EHLO command to the
                 * server, indicating the client's identity.  In addition to opening the
                 * session, use of EHLO indicates that the client is able to process
                 * service extensions and requests that the server provide a list of the
                 * extensions it supports.
                 */
                case smtpHELO:
                    retVal = _sendSMTPCommand(smtpSocket, "HELO localhost", NULL, buf);
                    ASSERT_ON_ERROR(retVal);
    
                    /* If response has 250, set state to AUTH */
                    if(buf[0] == smtp_ok_reply[0] &&
                       buf[1] == smtp_ok_reply[1] &&
                       buf[2] == smtp_ok_reply[2])
                    {
                        g_smtpStatus = smtpAUTH;
                    }
                    /* Else error, set state to ERROR */
                    else
                    {
                        g_smtpStatus = smtpERROR;
                        g_smtpErrorInfo = atHELO;
                    }
                break;
    
                /* The client sends the AUTH command with SASL mechanism to use with */
                case smtpAUTH:
                    /*
                     * SASL PLain - Authentication with server username and password
                     * Refer - http://www.ietf.org/rfc/rfc4616.txt
                     */
                    _generateBase64Key((_u8*)g_Email.Username, basekey1);
                    _generateBase64Key((_u8*)g_SourcePass.Password, basekey2);
    
                    /* Send request to server for authentication */
                    retVal = _sendSMTPCommand(smtpSocket, "AUTH LOGIN", NULL, buf);
                    ASSERT_ON_ERROR(retVal);
                    /* If response has 334, give username in base64 */
                    if(buf[0] == smtp_auth_reply[0] &&
                       buf[1] == smtp_auth_reply[1] &&
                       buf[2] == smtp_auth_reply[2])
                    {
                        retVal = _sendSMTPCommand(smtpSocket, basekey1, NULL, buf);
                        ASSERT_ON_ERROR(retVal);
                        /* If response has 334, give password in base64 */
                        if(buf[0] == smtp_auth_reply[0] &&
                           buf[1] == smtp_auth_reply[1] &&
                           buf[2] == smtp_auth_reply[2])
                        {
                            retVal = _sendSMTPCommand(smtpSocket, basekey2, NULL, buf);
                            ASSERT_ON_ERROR(retVal);
                        }
                    }
    
                    if(buf[0] == smtp_auth_success[0] &&
                       buf[1] == smtp_auth_success[1] &&
                       buf[2] == smtp_auth_success[2])
                    {
                        /* Authentication was successful, set state to FROM */
                        g_smtpStatus = smtpFROM;
                    }
                    /* Else error, set state to ERROR */
                    else
                    {
                        g_smtpStatus = smtpERROR;
                        g_smtpErrorInfo = atAUTH;
                    }
                break;
    
                /*
                 * The SMTP transaction starts with a MAIL command which includes the
                 * sender information
                 * MAIL FROM:<reverse-path> [SP <mail-parameters> ] <CRLF>
                 */
                case smtpFROM:
                    retVal = _sendSMTPCommand(smtpSocket, (_u8 *)smtp_mail_from,
                                     (_u8 *)g_Email.Username, buf);
                    ASSERT_ON_ERROR(retVal);
    
                    /* If response has 250, set state to RCPT */
                    if(buf[0] == smtp_ok_reply[0] &&
                       buf[1] == smtp_ok_reply[1] &&
                       buf[2] == smtp_ok_reply[2])
                    {
                        g_smtpStatus = smtpRCPT;
                    }
                    else
                    {
                        pal_Memset(email_rfc,'\0',MAX_EMAIL_RCF_LEN);
                        pal_Memcpy(email_rfc,"<",1);
                        pal_Memcpy(&email_rfc[1], g_Email.Username,
                               pal_Strlen(g_Email.Username));
                        pal_Memcpy(&email_rfc[1+pal_Strlen(g_Email.Username)],">",1);
    
                        retVal = _sendSMTPCommand(smtpSocket, (_u8 *)smtp_mail_from,
                                         email_rfc, buf);
                        ASSERT_ON_ERROR(retVal);
    
                        if(buf[0] == smtp_ok_reply[0] &&
                           buf[1] == smtp_ok_reply[1] &&
                           buf[2] == smtp_ok_reply[2])
                        {
                            g_smtpStatus = smtpRCPT;
                        }
                        else
                        {
                            g_smtpStatus = smtpERROR;
                            g_smtpErrorInfo = atFROM;
                        }
                    }
                break;
    
                /* Send the destination email to the smtp server
                 * RCPT TO:<forward-path> [ SP <rcpt-parameters> ] <CRLF>
                 */
                case smtpRCPT:
                    retVal = _sendSMTPCommand(smtpSocket, (_u8 *)smtp_rcpt,
                                     (_u8 *)g_Destination.Email, buf);
                    ASSERT_ON_ERROR(retVal);
    
                    /* If response has 250, set state to DATA */
                    if(buf[0] == smtp_ok_reply[0] &&
                       buf[1] == smtp_ok_reply[1] &&
                       buf[2] == smtp_ok_reply[2])
                    {
                        g_smtpStatus = smtpDATA;
                    }
                    else
                    {
                        pal_Memset(email_rfc,'\0',MAX_EMAIL_RCF_LEN);
                        pal_Memcpy(email_rfc,"<",1);
                        pal_Memcpy(&email_rfc[1], g_Destination.Email,
                               pal_Strlen(g_Destination.Email));
                        pal_Memcpy(&email_rfc[1+pal_Strlen(g_Destination.Email)],">",1);
                        retVal = _sendSMTPCommand(smtpSocket, (_u8 *)smtp_rcpt,email_rfc, buf);
                        ASSERT_ON_ERROR(retVal);
                        /* If response has 250, set state to DATA */
                        if(buf[0] == smtp_ok_reply[0] &&
                           buf[1] == smtp_ok_reply[1] &&
                           buf[2] == smtp_ok_reply[2])
                        {
                            g_smtpStatus = smtpDATA;
                        }
                        else
                        {
                            g_smtpStatus = smtpERROR;
                            g_smtpErrorInfo = atRCPT;
                        }
                    }
                break;
    
                /*Send the "DATA" message to the server, indicates client is ready
                * to construct the body of the email
                * DATA <CRLF>
                */
                case smtpDATA:
                    retVal = _sendSMTPCommand(smtpSocket, (_u8 *)smtp_data, NULL, buf);
                    ASSERT_ON_ERROR(retVal);
                    /* If Response has 250, set state to MESSAGE */
                    if(buf[0] == smtp_intermed_reply[0] &&
                    buf[1] == smtp_intermed_reply[1] && buf[2] == smtp_intermed_reply[2])
                    {
                        g_smtpStatus = smtpMESSAGE;
                    }
                    else
                    {
                        g_smtpStatus = smtpERROR;
                        g_smtpErrorInfo = atDATA;
                    }
                break;
    
                case smtpMESSAGE:
                    /* Send actual Message, preceded by FROM, TO and Subject */
    
                    /* Start with E-Mail's "Subject:" field */
                    retVal = _sendSMTPCommand(smtpSocket, (_u8 *)smtp_subject,
                                                    (_u8 *)g_Subject.Value, NULL);
                    ASSERT_ON_ERROR(retVal);
    
                    /* Add E-mail's "To:" field */
                    retVal = _sendSMTPCommand(smtpSocket, (_u8 *)smtp_to,
                                                (_u8 *)g_Destination.Email, NULL);
                    ASSERT_ON_ERROR(retVal);
    
                    /* Add E-mail's "From:" field */
                    retVal = _sendSMTPCommand(smtpSocket, (_u8 *)smtp_from,
                                                    (_u8 *)g_Email.Username, NULL);
                    ASSERT_ON_ERROR(retVal);
    
                    /* Send CRLF */
                    retVal = sl_Send(smtpSocket,smtp_crlf,pal_Strlen(smtp_crlf),0);
                    if(retVal <= 0)
                        ASSERT_ON_ERROR(TCP_SEND_ERROR);
    
                    /* Send body of message */
                    retVal = _sendSMTPCommand(smtpSocket, message, NULL, NULL);
                    ASSERT_ON_ERROR(retVal);
    
                    /* End Message */
                    retVal = _sendSMTPCommand(smtpSocket,(_u8 *)smtp_data_end,NULL,buf);
                    ASSERT_ON_ERROR(retVal);
    
                    /* Server will send 250 for successful. Move into QUIT state. */
                    if(buf[0] == smtp_ok_reply[0] && buf[1] == smtp_ok_reply[1] &&
                                                            buf[2] == smtp_ok_reply[2])
                    {
                        /* Disconnect from server by sending QUIT command */
                        retVal = sl_Send(smtpSocket,smtp_quit,pal_Strlen(smtp_quit),0);
                        if(retVal <= 0)
                            ASSERT_ON_ERROR(TCP_SEND_ERROR);
    
                        /* Close socket and reset */
                        retVal = sl_Close(smtpSocket);
                        smtpSocket = INVALID_SOCKET_DESC;
                        /* Reset the state machine */
                        g_smtpStatus = smtpINIT;
                        exit = 1;
                    }
                    else
                    {
                        g_smtpStatus = smtpERROR;
                        g_smtpErrorInfo = atMESSAGE;
                    }
                break;
    
                case smtpERROR:
                    /* Error Handling for SMTP */
                    _smtpHandleERROR(buf);
                    /* Close socket and reset */
                    retVal = sl_Close(smtpSocket);
                    /*Reset the state machine */
                    g_smtpStatus = smtpINIT;
    
                    ASSERT_ON_ERROR(SMTP_ERROR);
    
                default:
                    ASSERT_ON_ERROR(SMTP_INVALID_CASE);
            }
        }
    
        return SUCCESS;
    }
    
    /*!
        \brief This function converts the string to Base64 format needed for
               authentication
    
        \param[in]      input - pointer to string to be converted
        \param[out]     basekey1 - Pointer to string for base64 converted output
    
        \return         None
    
        \note
    
        \warning
    */
    static void _generateBase64Key(_u8 *input, _u8 *basekey1)
    {
        _u8 *pIn = input;
    
        /* Convert to base64 format  */
        ConvertToBase64(basekey1, (void *)pIn, pal_Strlen(input));
    }
    
    /*!
        \brief Performs Error Handling for SMTP State Machine
    
        \param[in]      servermessage - server response message
    
        \return         None
    
        \note
    
        \warning
    */
    static void _smtpHandleERROR(_u8 *servermessage)
    {
        /* Errors are handled using flags set in the smtpStateMachine */
        switch(g_smtpErrorInfo)
        {
            case atINIT:
                /* Server connection could not be established */
                CLI_Write((_u8*)"Line 686 Server connection error.\r\n");
                CLI_Write((_u8*)servermessage);
            break;
    
            case atHELO:
                /* Server did not accept the HELO command from server */
                CLI_Write((_u8*)"Line 692 Server did not accept HELO:\r\n");
                CLI_Write((_u8*)servermessage);
            break;
    
            case atAUTH:
                /* Server did not accept authorization credentials */
                CLI_Write((_u8*)"Line 698 Authorization unsuccessful, ");
                CLI_Write((_u8*)"Line 699 check username/password.\r\n");
                CLI_Write((_u8*)servermessage);
            break;
    
            case atFROM:
                /* Server did not accept source email. */
                CLI_Write((_u8*)"Line 705 Email of sender not accepted by server.\r\n");
                CLI_Write((_u8*)servermessage);
            break;
    
            case atRCPT:
                /* Server did not accept destination email */
                CLI_Write((_u8*)"Line 711 Email of recipient not accepted by server.\r\n");
                CLI_Write((_u8*)servermessage);
            break;
    
            case atDATA:
                /* 'DATA' command to server was unsuccessful */
                CLI_Write((_u8*)"Line 717 smtp 'DATA' command not accepted by server.\r\n");
                CLI_Write((_u8*)servermessage);
            break;
    
            case atMESSAGE:
                /* Message body could not be sent to server */
                CLI_Write((_u8*)"Line 723 Email Message was not accepted by the server.\r\n");
                CLI_Write((_u8*)servermessage);
            break;
    
            case atQUIT:
                /* Message could not be finalized */
                CLI_Write((_u8*)"Line 729 Connection could not be properly closed.");
                CLI_Write((_u8*)" Line 730 Message not sent.\r\n");
                CLI_Write((_u8*)servermessage);
            break;
        }
    }
    
    /*!
        \brief  Sends the SMTP command and receives the server response.
                If cmd and cmd parameter are NULL, it will only send <CR><LF>
    
        \param[in]      socket - Socket Descriptor
        \param[in]      cmd -    command to be send to server
        \param[in]      cmdparam - command parameter to be send
        \param[in]      respBuf -    Pointer to buffer for SMTP server response
    
        \return         None
    
        \note
    
        \warning
    */
    static _i32 _sendSMTPCommand(_i32 socket, _u8 *cmd, _u8 * cmdparam, _u8 *respBuf)
    {
        _i16 sendLen = 0;
        _i32 retVal = -1;
    
        pal_Memset(g_cmdBuf, 0, sizeof(g_cmdBuf));
    
        if(cmd != NULL)
        {
            sendLen = pal_Strlen(cmd);
            pal_Memcpy(g_cmdBuf,cmd,pal_Strlen(cmd));
        }
    
        if(cmdparam != NULL)
        {
            pal_Memcpy(&g_cmdBuf[sendLen], cmdparam, pal_Strlen(cmdparam));
            sendLen += pal_Strlen(cmdparam);
        }
    
        pal_Memcpy(&g_cmdBuf[sendLen], smtp_crlf, pal_Strlen(smtp_crlf));
        sendLen += pal_Strlen(smtp_crlf);
        retVal = sl_Send(socket, g_cmdBuf,sendLen,0);
        if(retVal <= 0)
            ASSERT_ON_ERROR(TCP_SEND_ERROR);
    
        if(respBuf != NULL)
        {
            pal_Memset(respBuf,0,SMTP_BUF_LEN);
            retVal = sl_Recv(socket, respBuf,SMTP_BUF_LEN,0);
            if(retVal <= 0)
                ASSERT_ON_ERROR(TCP_RECV_ERROR);
        }
    
        return SUCCESS;
    }
    
    //***************************************************************************
    // End of Original Email file
    //***************************************************************************
    
    
    
    
    //***************************************************************************
    // Start of Email cut and paste from Main
    //***************************************************************************
    //LH These 3 defines already in email.c, so copy from main not needed here
    //#include "email.h"
    //#include "config.h"
    //#include "sl_common.h"
    
    #define APPLICATION_VERSION "1.3.0"
    
    #define SL_STOP_TIMEOUT        0xFF
    
    /*
     * GLOBAL VARIABLES -- Start
     */
    _u32  g_Status = 0;
    /*
     * GLOBAL VARIABLES -- End
     */
    
    volatile unsigned short usiEmailDummy = 0;
    
    /*
     * STATIC FUNCTION DEFINITIONS -- Start
     */
    static _i32 establishConnectionWithAP();
    static _i32 disconnectFromAP();
    static _i32 configureSimpleLinkToDefaultState();
    
    static _i32 initializeAppVariables();
    static void  displayBanner();
    
    static _i32 setEmail();
    static _i32 sendEmail();
    /*
     * STATIC FUNCTION DEFINITIONS -- End
     */
    
    //***************************************
    // Start of function int LHSendEmail()
    //***************************************
    /*
     * Application's entry point
     */
    //void LHSendEmail (void)
    int LHSendEmail()
    {
        usiEmailDummy = 0;
        usiEmail1OrTime2 = 1; //In the function call set to 1 for email, set to 2 for get-time
    
    
        _i32 retVal = -1;
    
        retVal = initializeAppVariables();
        ASSERT_ON_ERROR(retVal);
    
    //    /* Stop WDT and initialize the system-clock of the MCU */
    //    stopWDT();
    //    initClk();
    
        /* Configure command line interface */
        CLI_Configure();
    
        displayBanner();
    
        /*
         * Following function configures the device to default state by cleaning
         * the persistent settings stored in NVMEM (viz. connection profiles &
         * policies, power policy etc)
         *
         * Applications may choose to skip this step if the developer is sure
         * that the device is in its default state at start of application
         *
         * Note that all profiles and persistent settings that were done on the
         * device will be lost
         */
        retVal = configureSimpleLinkToDefaultState();
        if(retVal < 0)
        {
            if (DEVICE_NOT_IN_STATION_MODE == retVal)
                CLI_Write(" Line 874 Failed to configure the device in its default state \n\r");
    
    // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
            //I think better to move on, as already printed out the failure, maybe some time later it will work
    //        LOOP_FOREVER();
        }
    
        CLI_Write(" Line 881 Device is configured in default state \n\r");
    
        /*
         * Initializing the CC3100 device
         * Assumption is that the device is configured in station mode already
         * and it is in its default state
         */
        retVal = sl_Start(0, 0, 0);
        if ((retVal < 0) ||
            (ROLE_STA != retVal) )
        {
            CLI_Write(" Line 892 Failed to start the device \n\r");
    // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
            //I think better to move on, as already printed out the failure, maybe some time later it will work
    //       LOOP_FOREVER();
        }
    
        CLI_Write(" Line 898 Device started as STATION \n\r");
    
        /* Configure the source email */
        retVal = setEmail();
        if(retVal < 0)
            LOOP_FOREVER();
    
        /* Connecting to WLAN AP */
        retVal = establishConnectionWithAP();
        if(retVal < 0)
        {
            CLI_Write(" Line 909 Failed to establish connection w/ an AP \n\r");
    // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
            //I think better to move on, as already printed out the failure, maybe some time later it will work
    //        LOOP_FOREVER();
        }
    
        CLI_Write(" Line 915 Connection established w/ AP and IP is acquired \n\r");
    
        /* Configure and send the email */
        CLI_Write(" Line 918 Sending email... \n\r"); //Jan 30, 2023 successfully get this
        retVal = sendEmail();
        if (retVal < 0)
        {
            CLI_Write(" Line 922 Device couldn't send the email \n\r");
    // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
            //I think better to move on, as already printed out the failure, maybe some time later it will work
    //        LOOP_FOREVER();
    //        LOOP_FOREVER(); // Jan 30, 2023 put this back in as get  Device couldn't send the email \n\r
            //Did not solve the problem of not sending email and just locks at this point
        }
        else
        {
            CLI_Write(" Line 931 Email Sent successfully \n\r");
        }
    
        /* Disconnect from AP */
        retVal = disconnectFromAP();
        if(retVal < 0)
        {
            CLI_Write(" Line 938 Failed to disconnect from the AP \n\r");
    // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
            //I think better to move on, as already printed out the failure, maybe some time later it will work
    //        LOOP_FOREVER();
        }
    
        retVal = sl_Stop(SL_STOP_TIMEOUT);
    // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
    //I think better to move on, as already printed out the failure, maybe some time later it will work
    //    if(retVal < 0)
    //        LOOP_FOREVER();
    
        return  0;
    } // Closing bracket for int LHSendEmail()
    
    
    //***************************************
    // End of function.....Start of function int LHSendEmail()
    //***************************************
    /*
     * ASYNCHRONOUS EVENT HANDLERS -- Start
     */
    
    /*!
        \brief This function handles WLAN events
    
        \param[in]      pWlanEvent is the event passed to the handler
    
        \return         None
    
        \note
    
        \warning
    */
    void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent)
    {
        if(pWlanEvent == NULL)
        {
            CLI_Write(" Line 976 [WLAN EVENT] NULL Pointer Error \n\r");
            return;
        }
    
        switch(pWlanEvent->Event)
        {
            case SL_WLAN_CONNECT_EVENT:
            {
                SET_STATUS_BIT(g_Status, STATUS_BIT_CONNECTION);
    
                /*
                 * Information about the connected AP (like name, MAC etc.) will be
                 * available in 'slWlanConnectAsyncResponse_t' - Applications
                 * can use it if required
                 *
                 * slWlanConnectAsyncResponse_t *pEventData = NULL;
                 * pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected;
                 *
                 */
            }
            break;
    
            case SL_WLAN_DISCONNECT_EVENT:
            {
                slWlanConnectAsyncResponse_t*  pEventData = NULL;
    
                CLR_STATUS_BIT(g_Status, STATUS_BIT_CONNECTION);
                CLR_STATUS_BIT(g_Status, STATUS_BIT_IP_ACQUIRED);
    
                pEventData = &pWlanEvent->EventData.STAandP2PModeDisconnected;
    
        if (usiEmail1OrTime2 == 1){  //In the function call set to 1 for email, set to 2 for get-time
                /* If the user has initiated 'Disconnect' request, 'reason_code' is SL_USER_INITIATED_DISCONNECTION */
                if(SL_WLAN_DISCONNECT_USER_INITIATED_DISCONNECTION == pEventData->reason_code)
                {
                    CLI_Write(" Line 1011 Device disconnected from the AP on application's request \n\r");
                }
                else
                {
                    CLI_Write(" Line 1015 Device disconnected from the AP on an ERROR..!! \n\r");
                }
        }
         else if (usiEmail1OrTime2 == 2){  //In the function call set to 1 for email, set to 2 for get-time
                 /* If the user has initiated 'Disconnect' request, 'reason_code' is SL_USER_INITIATED_DISCONNECTION */
                 if(SL_WLAN_DISCONNECT_USER_INITIATED_DISCONNECTION == pEventData->reason_code)
                 {
                     CLI_Write((_u8 *)" Line 1022 Device disconnected from the AP on application's request \n\r"); //LH Line 11, last line
                 }
                 else
                 {
                     CLI_Write((_u8 *)" Line 1026 Device disconnected from the AP on an ERROR..!! \n\r");
                 }
    
         }
            }
            break;
    
            default:
            {
                CLI_Write(" Line 1035 [WLAN EVENT] Unexpected event \n\r");
            }
            break;
        }
    }
    
    /*!
        \brief This function handles events for IP address acquisition via DHCP
               indication
    
        \param[in]      pNetAppEvent is the event passed to the handler
    
        \return         None
    
        \note
    
        \warning
    */
    void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent)
    {
        if(pNetAppEvent == NULL)
        {
            CLI_Write(" Line 1057 [NETAPP EVENT] NULL Pointer Error \n\r");
            return;
        }
    
        switch(pNetAppEvent->Event)
        {
            case SL_NETAPP_IPV4_IPACQUIRED_EVENT:
            {
                SET_STATUS_BIT(g_Status, STATUS_BIT_IP_ACQUIRED);
    
                /*
                 * Information about the connected AP's IP, gateway, DNS etc.
                 * will be available in 'SlIpV4AcquiredAsync_t' - Applications
                 * can use it if required
                 *
                 * SlIpV4AcquiredAsync_t *pEventData = NULL;
                 * pEventData = &pNetAppEvent->EventData.ipAcquiredV4;
                 * <gateway_ip> = pEventData->gateway;
                 *
                 */
            }
            break;
    
            default:
            {
                CLI_Write(" Line 1082 [NETAPP EVENT] Unexpected event \n\r");
            }
            break;
        }
    }
    
    /*!
        \brief This function handles callback for the HTTP server events
    
        \param[in]      pHttpEvent - Contains the relevant event information
        \param[in]      pHttpResponse - Should be filled by the user with the
                        relevant response information
    
        \return         None
    
        \note
    
        \warning
    */
    void SimpleLinkHttpServerCallback(SlHttpServerEvent_t *pHttpEvent,
                                      SlHttpServerResponse_t *pHttpResponse)
    {
        /*
         * This application doesn't work with HTTP server - Hence these
         * events are not handled/expected here
         */
        CLI_Write(" Line 1108 [HTTP EVENT] Unexpected event \n\r");
    }
    
    /*!
        \brief This function handles general error events indication
    
        \param[in]      pDevEvent is the event passed to the handler
    
        \return         None
    */
    void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent)
    {
        /*
         * Most of the general errors are not FATAL are are to be handled
         * appropriately by the application
         */
        CLI_Write(" Line 1124 [GENERAL EVENT] \n\r");
    }
    
    /*!
        \brief This function handles socket events indication
    
        \param[in]      pSock is the event passed to the handler
    
        \return         None
    */
    void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
    {
        if(pSock == NULL)
        {
            CLI_Write(" Line 1138 [SOCK EVENT] NULL Pointer Error \n\r");
            return;
        }
    
        switch( pSock->Event )
        {
            case SL_SOCKET_TX_FAILED_EVENT:
            {
                /*
                * TX Failed
                *
                * Information about the socket descriptor and status will be
                * available in 'SlSockEventData_t' - Applications can use it if
                * required
                *
                * SlSockEventData_u *pEventData = NULL;
                * pEventData = & pSock->socketAsyncEvent;
                */
                switch( pSock->socketAsyncEvent.SockTxFailData.status )
                {
                    case SL_ECLOSE:
                        CLI_Write(" Line 1159[SOCK EVENT] Close socket operation failed to transmit all queued packets\n\r");
                    break;
    
    
                    default:
                        CLI_Write(" Line 1164 [SOCK EVENT] Unexpected event \n\r");
                    break;
                }
            }
            break;
    
            default:
                CLI_Write(" Line 1171 [SOCK EVENT] Unexpected event \n\r");
            break;
        }
    }
    /*
     * ASYNCHRONOUS EVENT HANDLERS -- End
     */
    
    
    
    
    /*!
        \brief This function configures the source email using parameters defined
               in "config.h" file
    
        \param[in]      none
    
        \return         none
    
        \note
    
        \warning
    */
    //Security Methods CC3100 SWRU368B User's Guide
    //    • SL_SO_SEC_METHOD_SSLV3
    //    • SL_SO_SEC_METHOD_TLSV1
    //    • SL_SO_SEC_METHOD_TLSV1_1
    //    • SL_SO_SEC_METHOD_TLSV1_2    //TI example use
    //    • SL_SO_SEC_METHOD_SSLv3_TLSV1_2
    
    //Security Cipher CC3100 SWRU368B User's Guide
    //    • SL_SEC_MASK_SSL_RSA_WITH_RC4_128_SHA
    //    • SL_SEC_MASK_SSL_RSA_WITH_RC4_128_MD5
    //    • SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA   //TI example uses
    //    • SL_SEC_MASK_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
    //    • SL_SEC_MASK_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
    //    • SL_SEC_MASK_TLS_ECDHE_RSA_WITH_RC4_128_SHA
    //    • SL_SEC_MASK_TLS_RSA_WITH_AES_128_CBC_SHA256
    //    • SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA256
    //    • SL_SEC_MASK_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
    //    • SL_SEC_MASK_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
    
    static _i32 setEmail()
    {
        _i32 retVal = -1;
        SlNetAppSourceEmail_t sourceEmailId = {0};
        SlNetAppSourcePassword_t sourceEmailPwd = {0};
        SlNetAppEmailOpt_t eMailServerSetting = {0};
    
        pal_Memcpy(sourceEmailId.Username,USER,pal_Strlen(USER)+1);
        retVal = sl_NetAppEmailSet(NETAPP_SOURCE_EMAIL,pal_Strlen(USER)+1,
                          (_u8*)&sourceEmailId);
        ASSERT_ON_ERROR(retVal);
    
        pal_Memcpy(sourceEmailPwd.Password,PASS,pal_Strlen(PASS)+1);
        retVal = sl_NetAppEmailSet(NETAPP_PASSWORD,pal_Strlen(PASS)+1,
                          (_u8*)&sourceEmailPwd);
        ASSERT_ON_ERROR(retVal);
    
        eMailServerSetting.Family = AF_INET;
        eMailServerSetting.Port = GMAIL_HOST_PORT; //Line 27 in config.h    #define GMAIL_HOST_PORT         465
    //    eMailServerSetting.Port = OUTLOOK_HOST_PORT; //Line  i41n config.h    #define OUTLOOK_PORT         587
    //    eMailServerSetting.Port = ZOHO_HOST_PORT; //Line  i41n config.h    #define OUTLOOK_PORT         587
    //    eMailServerSetting.Port = VERIZON_HOST_PORT; //2-14-2023 changed to Verizon so can try abc2015NVR
        eMailServerSetting.Ip = SL_IPV4_VAL(74,125,129,108);
        eMailServerSetting.SecurityMethod = SL_SO_SEC_METHOD_TLSV1_2; //Original 2014 to Jan 2023
        eMailServerSetting.SecurityCypher = SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA; //Original 2014 to Jan 2023
    
    //  Gmail port 465 with SSL
    //  CC3100 SDK1.3.0 shows multiple Transport Security Options, Two with SSL
    //  SSLV3 SSL_RSA_WITH_RC4_128_SHA
    //  SSLV3 SSL_RSA_WITH_RC4_128_MD5
    //  eMailServerSetting.SecurityMethod = SL_SO_SEC_METHOD_SSLV3;
    //  eMailServerSetting.SecurityCypher = SL_SEC_MASK_SSL_RSA_WITH_RC4_128_SHA;
    //  eMailServerSetting.SecurityCypher = SL_SEC_MASK_SSL_RSA_WITH_RC4_128_MD5;
    
    
        retVal = sl_NetAppEmailSet(NETAPP_ADVANCED_OPT,sizeof(SlNetAppEmailOpt_t),
                          (_u8*)&eMailServerSetting);
        ASSERT_ON_ERROR(retVal);
    
        return SUCCESS;
    }
    
    /*!
        \brief Send the email to the preconfigured email ID
    
        \param[in]      none
    
        \return         0 for success , -1 otherwise
    
        \note
    
        \warning
    */
    static _i32 sendEmail()
    {
        _i32 Status = -1;
    
        Status = sl_NetAppEmailSet(NETAPP_DEST_EMAIL,
                                   pal_Strlen(DESTINATION_EMAIL),
                                   (_u8 *)DESTINATION_EMAIL);
        ASSERT_ON_ERROR(Status);
        CLI_Write(" Line 1253 After...DESTINATION_EMAIL \n\r"); //Jan 30, 2023 added this
    //    Status = sl_NetAppEmailSet(NETAPP_SUBJECT,
    //                               pal_Strlen(EMAIL_SUBJECT),
    //                               (_u8 *)EMAIL_SUBJECT);
    
    //LH added 5-20-2020 to use my character array for the email subject
        Status = sl_NetAppEmailSet(NETAPP_SUBJECT,
                                   pal_Strlen(LHemailSubject),
                                   (_u8 *)LHemailSubject);
    
    
        ASSERT_ON_ERROR(Status);
        CLI_Write(" Line 1265 After...LHemailSubject \n\r"); //Jan 30, 2023 added, this is printed
    
    //    Status = sl_NetAppEmailSet(NETAPP_MESSAGE,
    //                               pal_Strlen(EMAIL_MESSAGE),
    //                               (_u8 *)EMAIL_MESSAGE);
    
    //LH added 5-20-2020 to use my character array for the email message
        Status = sl_NetAppEmailSet(NETAPP_MESSAGE,
                                   pal_Strlen(LHemailBody),
                                   (_u8 *)LHemailBody);
    
    
        ASSERT_ON_ERROR(Status);
        CLI_Write(" Line 1278 After...LHemailBody \n\r"); //Jan 30, 2023 added this, this IS printed
    
        Status = sl_NetAppEmailConnect(); //2-16-2022 looks like this function does not complete
        CLI_Write(" Line 1281 After...Status = sl_NetAppEmailConnect() \n\r"); //2-16-2022, this is NOT printed
        ASSERT_ON_ERROR(Status);
        CLI_Write(" Line 1283 After...sl_NetAppEmailConnect \n\r"); //Jan 30, 2023 added this, this is NOT printed
    
        Status = sl_NetAppEmailSend();
        ASSERT_ON_ERROR(Status);
        CLI_Write(" Line 1287 After...sl_NetAppEmailSend \n\r"); //Jan 30, 2023 added, this is NOT printed
        return SUCCESS;
    }
    
    /*!
        \brief This function configure the SimpleLink device in its default state. It:
               - Sets the mode to STATION
               - Configures connection policy to Auto and AutoSmartConfig
               - Deletes all the stored profiles
               - Enables DHCP
               - Disables Scan policy
               - Sets Tx power to maximum
               - Sets power policy to normal
               - Unregisters mDNS services
               - Remove all filters
        \param[in]      none
    
        \return         On success, zero is returned. On error, negative is returned
    */
    static _i32 configureSimpleLinkToDefaultState()
    {
        SlVersionFull   ver = {0};
        _WlanRxFilterOperationCommandBuff_t  RxFilterIdMask = {0};
    
        _u8           val = 1;
        _u8           configOpt = 0;
        _u8           configLen = 0;
        _u8           power = 0;
    
        _i32          retVal = -1;
        _i32          mode = -1;
    
        mode = sl_Start(0, 0, 0);
        ASSERT_ON_ERROR(mode);
    
        /* If the device is not in station-mode, try configuring it in station-mode */
        if (ROLE_STA != mode)
        {
            if (ROLE_AP == mode)
            {
                /* If the device is in AP mode, we need to wait for this event before doing anything */
                while(!IS_IP_ACQUIRED(g_Status)) { _SlNonOsMainLoopTask(); }
            }
    
            /* Switch to STA role and restart */
            retVal = sl_WlanSetMode(ROLE_STA);
            ASSERT_ON_ERROR(retVal);
    
            retVal = sl_Stop(SL_STOP_TIMEOUT);
            ASSERT_ON_ERROR(retVal);
    
            retVal = sl_Start(0, 0, 0);
            ASSERT_ON_ERROR(retVal);
    
            /* Check if the device is in station again */
            if (ROLE_STA != retVal)
            {
                /* We don't want to proceed if the device is not coming up in station-mode */
                ASSERT_ON_ERROR(DEVICE_NOT_IN_STATION_MODE);
            }
        }
    
        /* Get the device's version-information */
        configOpt = SL_DEVICE_GENERAL_VERSION;
        configLen = sizeof(ver);
        retVal = sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &configOpt, &configLen, (_u8 *)(&ver));
        ASSERT_ON_ERROR(retVal);
    
        /* Set connection policy to Auto + SmartConfig (Device's default connection policy) */
        retVal = sl_WlanPolicySet(SL_POLICY_CONNECTION, SL_CONNECTION_POLICY(1, 0, 0, 0, 1), NULL, 0);
        ASSERT_ON_ERROR(retVal);
    
        /* Remove all profiles */
        retVal = sl_WlanProfileDel(0xFF);
        ASSERT_ON_ERROR(retVal);
    
        /*
         * Device in station-mode. Disconnect previous connection if any
         * The function returns 0 if 'Disconnected done', negative number if already disconnected
         * Wait for 'disconnection' event if 0 is returned, Ignore other return-codes
         */
        retVal = sl_WlanDisconnect();
        if(0 == retVal)
        {
            /* Wait */
            while(IS_CONNECTED(g_Status)) { _SlNonOsMainLoopTask(); }
        }
    
        /* Enable DHCP client*/
        retVal = sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE,1,1,&val);
        ASSERT_ON_ERROR(retVal);
    
        /* Disable scan */
        configOpt = SL_SCAN_POLICY(0);
        retVal = sl_WlanPolicySet(SL_POLICY_SCAN , configOpt, NULL, 0);
        ASSERT_ON_ERROR(retVal);
    
        /* Set Tx power level for station mode
           Number between 0-15, as dB offset from max power - 0 will set maximum power */
        power = 0;
        retVal = sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_STA_TX_POWER, 1, (_u8 *)&power);
        ASSERT_ON_ERROR(retVal);
    
        /* Set PM policy to normal */
        retVal = sl_WlanPolicySet(SL_POLICY_PM , SL_NORMAL_POLICY, NULL, 0);
        ASSERT_ON_ERROR(retVal);
    
        /* Unregister mDNS services */
        retVal = sl_NetAppMDNSUnRegisterService(0, 0);
        ASSERT_ON_ERROR(retVal);
    
        /* Remove  all 64 filters (8*8) */
        pal_Memset(RxFilterIdMask.FilterIdMask, 0xFF, 8);
        retVal = sl_WlanRxFilterSet(SL_REMOVE_RX_FILTER, (_u8 *)&RxFilterIdMask,
                           sizeof(_WlanRxFilterOperationCommandBuff_t));
        ASSERT_ON_ERROR(retVal);
    
        retVal = sl_Stop(SL_STOP_TIMEOUT);
        ASSERT_ON_ERROR(retVal);
    
        retVal = initializeAppVariables();
        ASSERT_ON_ERROR(retVal);
    
        return retVal; /* Success */
    }
    
    /*!
        \brief Connecting to a WLAN Access point
    
        This function connects to the required AP (SSID_NAME).
        The function will return once we are connected and have acquired IP address
    
        \param[in]  None
    
        \return     0 on success, negative error-code on error
    
        \note
    
        \warning    If the WLAN connection fails or we don't acquire an IP address,
                    We will be stuck in this function forever.
    */
    static _i32 establishConnectionWithAP()
    {
        if (usiEmail1OrTime2 == 1){  //In the function call set to 1 for email, set to 2 for get-time
    
        SlSecParams_t secParams = {0};
        _i32 retVal = 0;
    
        secParams.Key = PASSKEY;
        secParams.KeyLen = PASSKEY_LEN;
        secParams.Type = SEC_TYPE;
    
        retVal = sl_WlanConnect(SSID_NAME, pal_Strlen(SSID_NAME), 0, &secParams, 0);
        ASSERT_ON_ERROR(retVal);
    
        /* Wait */
        while((!IS_CONNECTED(g_Status)) || (!IS_IP_ACQUIRED(g_Status))) { _SlNonOsMainLoopTask(); }
    
    //    return SUCCESS;
        }
        else if (usiEmail1OrTime2 == 2){  //In the function call set to 1 for email, set to 2 for get-time
        SlSecParams_t secParams = {0};
         _i32 retVal = 0;
    
         secParams.Key = PASSKEY;
         secParams.KeyLen = pal_Strlen(secParams.Key);
         secParams.Type = SEC_TYPE;
    
         retVal = sl_WlanConnect(SSID_NAME, pal_Strlen(SSID_NAME), 0, &secParams, 0);
         ASSERT_ON_ERROR(retVal);
    
         /* Wait */
         while((!IS_CONNECTED(g_Status)) || (!IS_IP_ACQUIRED(g_Status))) { _SlNonOsMainLoopTask(); }
    
    //     return SUCCESS;
        }
        return SUCCESS;
    }
    
    /*!
        \brief Disconnecting from a WLAN Access point
    
        This function disconnects from the connected AP
    
        \param[in]      None
    
        \return         none
    
        \note
    
        \warning        If the WLAN disconnection fails, we will be stuck in this function forever.
    */
    static _i32 disconnectFromAP()
    {
        _i32 retVal = -1;
    
        /*
         * The function returns 0 if 'Disconnected done', negative number if already disconnected
         * Wait for 'disconnection' event if 0 is returned, Ignore other return-codes
         */
        retVal = sl_WlanDisconnect();
        CLI_Write(" Line 1488  in _i32 disconnectFromAP() after retVal = sl_WlanDisconnect(); \n\r");
        if(0 == retVal)
        CLI_Write(" Line 1490  in _i32 disconnectFromAP() after if(0 == retVal) \n\r");
        {
            /* Wait */
            while(IS_CONNECTED(g_Status)) { _SlNonOsMainLoopTask(); }
        }
    
        return SUCCESS;
    }
    
    /*!
        \brief This function initializes the application variables
    
        \param[in]  None
    
        \return     0 on success, negative error-code on error
    */
    static _i32 initializeAppVariables()
    {
        if (usiEmail1OrTime2 == 1){  //In the function call set to 1 for email, set to 2 for get-time
        g_Status = 0;
    
    //    return SUCCESS;
        }
        else if (usiEmail1OrTime2 == 2){  //In the function call set to 1 for email, set to 2 for get-time
        g_Status = 0;
        pal_Memset(&appData, 0, sizeof(appData)); //This line not in email wifi call
    
    //    return SUCCESS;
        }
        return SUCCESS;
    }
    
    /*!
        \brief This function displays the application's banner
    
        \param      None
    
        \return     None
    */
    static void displayBanner()
    {
        usiEmailDummy = 0;
        if (usiEmail1OrTime2 == 1){  //In the function call set to 1 for email, set to 2 for get-time
        CLI_Write("\n\r\n\r");
        CLI_Write(" Email application - Version ");
        CLI_Write(APPLICATION_VERSION);
        CLI_Write("\n\r*******************************************************************************\n\r");
        }
        else if (usiEmail1OrTime2 == 2){  //In the function call set to 1 for email, set to 2 for get-time
            usiEmailDummy = 0;
            CLI_Write((_u8 *)"\n\r\n\r");           //LH Line 0 = blank
            CLI_Write((_u8 *)" Get time application - Version ");   //LH line 1
            CLI_Write(APPLICATION_VERSION); //LH last half of line 1
            CLI_Write((_u8 *)"\n\r*******************************************************************************\n\r"); //LH Line 2 *** under top line
    
        }
    }
    
    
    //*********************************************************************************************
    //****get-timeLH****get-timeLH****get-timeLH****get-timeLH****get-timeLH****get-timeLH
    //****get-timeLH****get-timeLH****get-timeLH****get-timeLH****get-timeLH****get-timeLH
    //****get-timeLH****get-timeLH****get-timeLH****get-timeLH****get-timeLH****get-timeLH
    //*********************************************************************************************
    
    /*
     * get-time-LH.c
     *
     *  Created on: Jul 30, 2020
     *      Author: lorne
     */
    
    /*
     * Application Name     -   Get time
     * Application Overview -   This sample application demonstrates how
     *                          to connect to an SNTP server and request for time
     *                          information. The application processes the received
     *                          data and displays the time on console
     * Application Details  -   http://processors.wiki.ti.com/index.php/CC31xx_Get_Time_Application
     *                          doc\examples\get_time.pdf
     */
    
    //#include "simplelink.h"  //8-1-2020 comment out as duplicate with email file above
    //#include "sl_common.h"   //8-1-2020 comment out as duplicate with email file above
    //#include "email.h"
    //#include "get-time-LH.h"
    //#include "base64.h"
    //#include "config.h"
    //#include "sl_common.h"
    #include <stdio.h> //For printf function
    
    #define APPLICATION_VERSION "1.3.0"
    
    #define SL_STOP_TIMEOUT        0xFF
    
    #define MAX_BUF_SIZE    48
    
    #define TIME2013        3566160000       /* 43 years + 13 days of leap years */ //LH try adding 2 more days of leap years seconds
    //This gives the correct date number but as expected the Day of the week is then 2 days advanced in error
    //I do not use the Day of the week at this time, so OK
    
    //#define TIME2013        3565987200       /* 43 years + 11 days of leap years */ //LH 7-29-2020; Date # is 2 days advanced
    #define YEAR2013        2013
    #define SEC_IN_MIN      60
    #define SEC_IN_HOUR     3600
    #define SEC_IN_DAY      86400
    
    /*
     * Values for below macros shall be modified for setting the time-zone
     */
    
    signed short GMT_TIME_ZONE_HR = -5;
    //#define GMT_TIME_ZONE_HR    -5    //****Note that our time zone needs to be entered as a negative number
    #define GMT_TIME_ZONE_MIN   00
    
    /* Application specific status/error codes */
    //LH 8-2-2020 added these to config.h line 70 otherwise this typedef define twice
    //typedef enum{
    //    DEVICE_NOT_IN_STATION_MODE = -0x7D0,        /* Choosing this number to avoid overlap w/ host-driver's error codes */
    //    SNTP_SEND_ERROR = DEVICE_NOT_IN_STATION_MODE - 1,
    //    SNTP_RECV_ERROR = SNTP_SEND_ERROR - 1,
    //    SNTP_SERVER_RESPONSE_ERROR = SNTP_RECV_ERROR - 1,
    //
    //    STATUS_CODE_MAX = -0xBB8
    //}e_AppStatusCodes;
    
    /*
     * GLOBAL VARIABLES -- Start
     */
    //_u32  g_Status = 0; //8-1-2020 comment out as duplicate with email file above
    
    //LH 8-2-2020 getting errors that appData is not defined so try pasting it in email.h, I added the word typedef in front to make it the same
    // Doing that generates 100's of errors, every place appData was used; took word typdef off and get a clean compile????
    //struct{
    //    _u32   DestinationIP;
    //    _u32   elapsedSec;
    //    _u32   uGeneralVar;
    //    _u32   uGeneralVar1;
    //
    //    _u16   ccLen;
    //
    //    _i32   SockID;
    //    _i32   sGeneralVar;
    //
    //    _u8 time[30];  //LH time is a structure with 30 elements so it can display a string like this Tue Oct 10 2018 11:26:13
    //    _u8 *ccPtr;
    //
    //}appData;
    
    volatile unsigned short usiBreakDummy = 0;
    volatile unsigned short usiYearGetTime = 0;
    volatile unsigned short usiMonthOfYearGetTime = 0;
    volatile unsigned short usiDayOfMonthGetTime = 0;
    volatile unsigned short usiDayOfWeekGetTime = 0;
    volatile unsigned short usiHrsGetTime = 0;
    volatile unsigned short usiMinutesGetTime = 0;
    volatile unsigned short usiSecondsGetTime = 0;
    
     char ChrHrTens = '\0';   //Initialized to null
    
    /*
     * GLOBAL VARIABLES -- End
     */
    
    
    /*
     * CONTSTANT -- Start
     */
    /*! ######################### List of SNTP servers ############################
     *! ##
     *! ##          hostname         |        IP        |       location
     *! ## ------------------------------------------------------------------------
     *! ## time-a.nist.gov           | 129.6.15.28      | NIST, Gaithersburg, Maryland
     *! ## time-b.nist.gov           | 129.6.15.29      | NIST, Gaithersburg, Maryland
     *! ## time-c.nist.gov           | 129.6.15.30      | NIST, Gaithersburg, Maryland
     *! ## nist1-macon.macon.ga.us   | 98.175.203.200   | Macon, Georgia
     *! ## 0.in.pool.ntp.org         | 123.108.225.6    | India
    
     *! ## For more SNTP server link visit 'http://tf.nist.gov/tf-cgi/servers.cgi'
     *! ###########################################################################
     */
    //8-31-2022 did not find a, b, or c server worked any better to get the time
     const _u8 SNTPserver[30] = "time-a.nist.gov"; /* Add any one of the above servers */
    //const _u8 SNTPserver[30] = "time-b.nist.gov"; /* Add any one of the above servers */
    //const _u8 SNTPserver[30] = "time-c.nist.gov"; /* Add any one of the above servers */
    //const _u8 SNTPserver[30] = "nist1-macon.macon.ga.us"; /* Add any one of the above servers */ //LH-7-29-2020 never got a reply
    
    /* Tuesday is the 1st day in 2013 - the relative year */
    const _u8 daysOfWeek2013[7][3] = {{"Tue"},
                                       {"Wed"},
                                       {"Thu"},
                                       {"Fri"},
                                       {"Sat"},
                                       {"Sun"},
                                       {"Mon"}};
    
    const _u8 monthOfYear[12][3] = {{"Jan"},
                                     {"Feb"},
                                     {"Mar"},
                                     {"Apr"},
                                     {"May"},
                                     {"Jun"},
                                     {"Jul"},
                                     {"Aug"},
                                     {"Sep"},
                                     {"Oct"},
                                     {"Nov"},
                                     {"Dec"}};
    
    const _u8 numOfDaysPerMonth[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
    
    const _u8 digits[] = "0123456789";
    /*
     * CONTSTANT -- End
     */
    
    
    /*
     * STATIC FUNCTION DEFINITIONS -- Start
     */
    //static _i32 establishConnectionWithAP();  //Already defined at around line 700
    //static _i32 disconnectFromAP();             //Already defined at line 792
    //static _i32 configureSimpleLinkToDefaultState();
    
    //static _i32 initializeAppVariables(); //Already defined at around line 795
    //static void  displayBanner(); //Already defined at line 796
    
    //LH even in the original code these functions are not in the get-time file, must be in sl-common or some other WiFi library
    static _i32 getHostIP();
    static _i32 createConnection();
    static _i32 getSNTPTime(_i16 gmt_hr, _i16 gmt_min);
    static _u16 itoa(_i16 cNum, _u8 *cString);
    
    /*
     * STATIC FUNCTION DEFINITIONS -- End
     */
    
    
    
    /*
     * Application's entry point
     */
    int LHGetTime ()
    //int main(int argc, char** argv)
    {
        //usiGMTOffsetHrSet is set in mode = Settings, so End user can set GMT for their Time zone and Day light saving time
        GMT_TIME_ZONE_HR = (-1 * usiGMTOffsetHrSet);
    
        usiEmail1OrTime2 = 2; //In the function call set to 1 for email, set to 2 for get-time
        _i32 retVal = -1;
    
        retVal = initializeAppVariables();
        ASSERT_ON_ERROR(retVal);
    
        /* Stop WDT and initialize the system-clock of the MCU */
    //    stopWDT();
    //    initClk();
    
        /* Configure command line interface */
        CLI_Configure();
    
        displayBanner();
    
        /*
         * Following function configures the device to default state by cleaning
         * the persistent settings stored in NVMEM (viz. connection profiles &
         * policies, power policy etc)
         *
         * Applications may choose to skip this step if the developer is sure
         * that the device is in its default state at start of application
         *
         * Note that all profiles and persistent settings that were done on the
         * device will be lost
         */
        retVal = configureSimpleLinkToDefaultState();
        if(retVal < 0)
        {
            if (DEVICE_NOT_IN_STATION_MODE == retVal)
                CLI_Write((_u8 *)" Line 1757 Failed to configure the device in its default state \n\r");
            // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
                    //I think better to move on, as already printed out the failure, maybe some time later it will work
            //LOOP_FOREVER();
        }
    
        CLI_Write((_u8 *)" Line 1774 Device is configured in default state \n\r");    //LH line 3
    
        /*
         * Initializing the CC3100 device
         * Assumption is that the device is configured in station mode already
         * and it is in its default state
         */
        retVal = sl_Start(0, 0, 0);
        if ((retVal < 0) ||
            (ROLE_STA != retVal) )
        {
            CLI_Write((_u8 *)" Line 1785 Failed to start the device \n\r");
            // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
                    //I think better to move on, as already printed out the failure, maybe some time later it will work
            //LOOP_FOREVER();
        }
    
        CLI_Write((_u8 *)" Line 1791 Device started as STATION \n\r"); //LH line 4
    
        /* Connecting to WLAN AP */
        retVal = establishConnectionWithAP();
        if(retVal < 0)
        {
            CLI_Write((_u8 *)" Line 1797 Failed to establish connection w/ an AP \n\r");
            // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
                    //I think better to move on, as already printed out the failure, maybe some time later it will work
            //LOOP_FOREVER();
        }
    
        CLI_Write(" Line 1803 Connection established w/ AP and IP is acquired \n\r"); //LH Line 5
    
    //8-2-2020 8:30 PM Does complete the above statement, then no further
    
        retVal = getHostIP();
        CLI_Write(" Line 1808 LH Just after get HostIP \n\r");
    
        if(retVal < 0)
        {
            CLI_Write((_u8 *)" Line 1812 Unable to get host IP\n\r\n\r");
            // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
                    //I think better to move on, as already printed out the failure, maybe some time later it will work
            //LOOP_FOREVER();
        }
        appData.SockID = createConnection();
        CLI_Write(" Line 1818 LH Just after createConnection \n\r");
    
    // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
    //I think better to move on, as already printed out the failure, maybe some time later it will work
    //    if(appData.SockID < 0)
            //LOOP_FOREVER();
    
            CLI_Write(" Line 1825 LH Just BEFORE getSNTPTTime... \n\r");
    
        retVal = getSNTPTime(GMT_TIME_ZONE_HR,GMT_TIME_ZONE_MIN);
    
           CLI_Write(" Line 1829 LH Just AFTER getSNTPTTime... \n\r");
    
    // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
    //I think better to move on, as already printed out the failure, maybe some time later it will work
    //    if(retVal < 0)
            //LOOP_FOREVER();
    
        usiBreakDummy = 0;
        retVal = sl_Close(appData.SockID);
    
    // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
    //I think better to move on, as already printed out the failure, maybe some time later it will work
    //    if(retVal < 0)
            //LOOP_FOREVER();
    
        usiBreakDummy = 0;
        retVal = disconnectFromAP();
        if(retVal < 0)
        {
            CLI_Write((_u8 *)" Line 1848 Failed to disconnect from the AP \n\r");
            // 5-24-2020, I don't see the value of LOOP_FOREVER(); as this just hangs the program forever at this point
                    //I think better to move on, as already printed out the failure, maybe some time later it will work
            //LOOP_FOREVER();
        }
    
    //LH added 7-31-2020
        usiBreakDummy = 0;
        retVal = sl_Stop(SL_STOP_TIMEOUT);
    
        return 0;
    }
    
    
    //******End of Application Function called from main*************
    
    
    
    
    /*
     * ASYNCHRONOUS EVENT HANDLERS -- Start
     */
    //LH-8-1-2020 copied from get-time-LH, duplicate in email.c above
    ///*!
    //    \brief This function handles WLAN events
    //
    //    \param[in]      pWlanEvent is the event passed to the handler
    //
    //    \return         None
    //
    //    \note
    //
    //    \warning
    //*/
    //void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent)
    //{
    //    if(pWlanEvent == NULL)
    //    {
    //        CLI_Write(" [WLAN EVENT] NULL Pointer Error \n\r");
    //        return;
    //    }
    //
    //    switch(pWlanEvent->Event)
    //    {
    //        case SL_WLAN_CONNECT_EVENT:
    //        {
    //            SET_STATUS_BIT(g_Status, STATUS_BIT_CONNECTION);
    //
    //            /*
    //             * Information about the connected AP (like name, MAC etc) will be
    //             * available in 'slWlanConnectAsyncResponse_t' - Applications
    //             * can use it if required
    //             *
    //             * slWlanConnectAsyncResponse_t *pEventData = NULL;
    //             * pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected;
    //             *
    //             */
    //        }
    //        break;
    //
    //        case SL_WLAN_DISCONNECT_EVENT:
    //        {
    //            slWlanConnectAsyncResponse_t*  pEventData = NULL;
    //
    //            CLR_STATUS_BIT(g_Status, STATUS_BIT_CONNECTION);
    //            CLR_STATUS_BIT(g_Status, STATUS_BIT_IP_ACQUIRED);
    //
    //            pEventData = &pWlanEvent->EventData.STAandP2PModeDisconnected;
    //
    //            /* If the user has initiated 'Disconnect' request, 'reason_code' is SL_USER_INITIATED_DISCONNECTION */
    //            if(SL_WLAN_DISCONNECT_USER_INITIATED_DISCONNECTION == pEventData->reason_code)
    //            {
    //                CLI_Write((_u8 *)" Device disconnected from the AP on application's request \n\r"); //LH Line 11, last line
    //            }
    //            else
    //            {
    //                CLI_Write((_u8 *)" Device disconnected from the AP on an ERROR..!! \n\r");
    //            }
    //        }
    //        break;
    //
    //        default:
    //        {
    //            CLI_Write((_u8 *)" [WLAN EVENT] Unexpected event \n\r");
    //        }
    //        break;
    //    }
    //}
    
    
    //LH-8-1-2020 copied from get-time-LH, duplicate in email.c above
    ///*!
    //    \brief This function handles events for IP address acquisition via DHCP
    //           indication
    //
    //    \param[in]      pNetAppEvent is the event passed to the handler
    //
    //    \return         None
    //
    //    \note
    //
    //    \warning
    //*/
    //void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent)
    //{
    //    if(pNetAppEvent == NULL)
    //    {
    //        CLI_Write(" [NETAPP EVENT] NULL Pointer Error \n\r");
    //        return;
    //    }
    //
    //    switch(pNetAppEvent->Event)
    //    {
    //        case SL_NETAPP_IPV4_IPACQUIRED_EVENT:
    //        {
    //            SET_STATUS_BIT(g_Status, STATUS_BIT_IP_ACQUIRED);
    //
    //            /*
    //             * Information about the connected AP's IP, gateway, DNS etc
    //             * will be available in 'SlIpV4AcquiredAsync_t' - Applications
    //             * can use it if required
    //             *
    //             * SlIpV4AcquiredAsync_t *pEventData = NULL;
    //             * pEventData = &pNetAppEvent->EventData.ipAcquiredV4;
    //             * <gateway_ip> = pEventData->gateway;
    //             *
    //             */
    //        }
    //        break;
    //
    //        default:
    //        {
    //            CLI_Write((_u8 *)" [NETAPP EVENT] Unexpected event \n\r");
    //        }
    //        break;
    //    }
    //}
    
    //LH-8-1-2020 copied from get-time-LH, duplicate in email.c above
    ///*!
    //    \brief This function handles callback for the HTTP server events
    //
    //    \param[in]      pHttpEvent - Contains the relevant event information
    //    \param[in]      pHttpResponse - Should be filled by the user with the
    //                    relevant response information
    //
    //    \return         None
    //
    //    \note
    //
    //    \warning
    //*/
    //void SimpleLinkHttpServerCallback(SlHttpServerEvent_t *pHttpEvent,
    //                                  SlHttpServerResponse_t *pHttpResponse)
    //{
    //    /*
    //     * This application doesn't work with HTTP server - Hence these
    //     * events are not handled here
    //     */
    //    CLI_Write((_u8 *)" [HTTP EVENT] Unexpected event \n\r");
    //}
    
    //LH-8-1-2020 copied from get-time-LH, duplicate in email.c above
    ///*!
    //    \brief This function handles general error events indication
    //
    //    \param[in]      pDevEvent is the event passed to the handler
    //
    //    \return         None
    //*/
    //void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent)
    //{
    //    /*
    //     * Most of the general errors are not FATAL are to be handled
    //     * appropriately by the application
    //     */
    //    CLI_Write((_u8 *)" [GENERAL EVENT] \n\r");
    //}
    
    //LH-8-1-2020 copied from get-time-LH, duplicate in email.c above
    ///*!
    //    \brief This function handles socket events indication
    //
    //    \param[in]      pSock is the event passed to the handler
    //
    //    \return         None
    //*/
    //void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
    //{
    //    if(pSock == NULL)
    //    {
    //        CLI_Write(" [SOCK EVENT] NULL Pointer Error \n\r");
    //        return;
    //    }
    //
    //    switch( pSock->Event )
    //    {
    //        case SL_SOCKET_TX_FAILED_EVENT:
    //        {
    //            /*
    //            * TX Failed
    //            *
    //            * Information about the socket descriptor and status will be
    //            * available in 'SlSockEventData_t' - Applications can use it if
    //            * required
    //            *
    //            * SlSockEventData_u *pEventData = NULL;
    //            * pEventData = & pSock->socketAsyncEvent;
    //            */
    //            switch( pSock->socketAsyncEvent.SockTxFailData.status )
    //            {
    //                case SL_ECLOSE:
    //                    CLI_Write((_u8 *)" [SOCK EVENT] Close socket operation failed to transmit all queued packets\n\r");
    //                break;
    //
    //
    //                default:
    //                    CLI_Write((_u8 *)" [SOCK EVENT] Unexpected event \n\r");
    //                break;
    //            }
    //        }
    //        break;
    //
    //        default:
    //            CLI_Write((_u8 *)" [SOCK EVENT] Unexpected event \n\r");
    //        break;
    //    }
    //}
    /*
     * ASYNCHRONOUS EVENT HANDLERS -- End
     */
    
    
    
    /*!
        \brief Convert integer to ASCII in decimal base
    
        \param[in]      cNum - integer number to convert
    
        \param[OUT]     cString - output string
    
        \return         number of ASCII characters
    
        \warning
    */
    static _u16 itoa(_i16 cNum, _u8 *cString)
    {
        _u16 length = 0;
        _u8* ptr = NULL;
        _i16 uTemp = cNum;
    
        /* value 0 is a special case */
        if (cNum == 0)
        {
            length = 1;
            *cString = '0';
    
            return length;
        }
    
        /* Find out the length of the number, in decimal base */
        length = 0;
        while (uTemp > 0)
        {
            uTemp /= 10;
            length++;
        }
    
        /* Do the actual formatting, right to left */
        uTemp = cNum;
        ptr = cString + length;
        while (uTemp > 0)
        {
            --ptr;
            *ptr = digits[uTemp % 10];
            uTemp /= 10;
        }
    
        return length;
    }
    
    /*!
        \brief Get the required data from the server.
    
        \param[in]      gmt_hr - GMT offset hours
    
        \param[in]      gmt_min - GMT offset minutes
    
        \return         0 on success, -ve otherwise
    
        \warning
    */
    static _i32 getSNTPTime(_i16 gmt_hr, _i16 gmt_min)
    {
        /*
                                    NTP Packet Header:
    
    
               0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9  0  1
              +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
              |LI | VN  |Mode |    Stratum    |     Poll      |   Precision    |
              +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
              |                          Root  Delay                           |
              +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
              |                       Root  Dispersion                         |
              +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
              |                     Reference Identifier                       |
              +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
              |                                                                |
              |                    Reference Time-stamp (64)                    |
              |                                                                |
              +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
              |                                                                |
              |                    Originate Time-stamp (64)                    |
              |                                                                |
              +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
              |                                                                |
              |                     Receive Time-stamp (64)                     |
              |                                                                |
              +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
              |                                                                |
              |                     Transmit Time-stamp (64)                    |
              |                                                                |
              +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
              |                 Key Identifier (optional) (32)                 |
              +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
              |                                                                |
              |                                                                |
              |                 Message Digest (optional) (128)                |
              |                                                                |
              |                                                                |
              +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        */
    
        SlSockAddrIn_t  LocalAddr;
        SlSockAddr_t Addr;
    
        _u8    dataBuf[MAX_BUF_SIZE];
        _i32     retVal = -1;
        _i16     AddrSize = 0;
    
        /* For time zone with negative GMT value, change minutes to negative for
         * computation */
        if(gmt_hr < 0 && gmt_min > 0)
            gmt_min = gmt_min * (-1);
    
        sl_Memset(dataBuf, 0, sizeof(dataBuf));
        dataBuf[0] = '\x1b';
    
        Addr.sa_family = AF_INET;
        /* the source port */
        Addr.sa_data[0] = 0x00;
        Addr.sa_data[1] = 0x7B;    /* 123 */
        Addr.sa_data[2] = (_u8)((appData.DestinationIP >> 24) & 0xff);
        Addr.sa_data[3] = (_u8)((appData.DestinationIP >> 16) & 0xff);
        Addr.sa_data[4] = (_u8)((appData.DestinationIP >> 8) & 0xff);
        Addr.sa_data[5] = (_u8) (appData.DestinationIP & 0xff);
    
        retVal = sl_SendTo(appData.SockID, dataBuf, sizeof(dataBuf), 0,
                         &Addr, sizeof(Addr));
        if (retVal != sizeof(dataBuf))
        {
            /* could not send SNTP request */
            CLI_Write((_u8 *)" Line 2211 Device couldn't send SNTP request\n\r\n\r");
            ASSERT_ON_ERROR(SNTP_SEND_ERROR);
        }
    
        AddrSize = sizeof(SlSockAddrIn_t);
        LocalAddr.sin_family = SL_AF_INET;
        LocalAddr.sin_port = 0;
        LocalAddr.sin_addr.s_addr = 0;
    
        retVal = sl_Bind(appData.SockID,(SlSockAddr_t *)&LocalAddr, AddrSize);
        if(retVal < 0)
            ASSERT_ON_ERROR(retVal);
    
        retVal = sl_RecvFrom(appData.SockID, dataBuf, sizeof(dataBuf), 0,
                           (SlSockAddr_t *)&LocalAddr,  (SlSocklen_t*)&AddrSize);
        if (retVal <= 0)
        {
            CLI_Write((_u8 *)" Line 2228 Device couldn't receive time information \n\r");
            ASSERT_ON_ERROR(SNTP_RECV_ERROR);
        }
    
        if ((dataBuf[0] & 0x7) != 4)    /* expect only server response */
        {
            /* MODE is not server, abort */
            CLI_Write((_u8 *)" Line 2235 Device is expecting response from server only!\n\r");
            ASSERT_ON_ERROR(SNTP_SERVER_RESPONSE_ERROR);
        }
        else
        {
            _u8 index;
    
            appData.elapsedSec = dataBuf[40];
            appData.elapsedSec <<= 8;
            appData.elapsedSec += dataBuf[41];
            appData.elapsedSec <<= 8;
            appData.elapsedSec += dataBuf[42];
            appData.elapsedSec <<= 8;
            appData.elapsedSec += dataBuf[43];
    
            appData.elapsedSec -= TIME2013;
    
            /* correct the time zone */
            appData.elapsedSec += (gmt_hr * SEC_IN_HOUR);
            appData.elapsedSec += (gmt_min * SEC_IN_MIN);
    
            appData.ccPtr = &appData.time[0];
    
            /* day */
    //        appData.sGeneralVar = appData.elapsedSec/SEC_IN_DAY;
            appData.sGeneralVar = (appData.elapsedSec + 172800) /SEC_IN_DAY; //LH Day of week 2 days behind due to leap years
    
            //This fixed the Day of week, but then re-broke the Date number
            pal_Memcpy(appData.ccPtr, daysOfWeek2013[appData.sGeneralVar%7], 3);
    //Day of the week
            usiDayOfWeekGetTime = appData.sGeneralVar%7;
    /* Tuesday is the 1st day in 2013 - the relative year */
    //const _u8 daysOfWeek2013[7][3] = {{"Tue"},    // 0 = Tuesday
    //                                   {"Wed"},   // 1 = Wednesday
    //                                   {"Thu"},   // 2 = Thursday
    //                                   {"Fri"},   // 3 = Friday
    //                                   {"Sat"},   // 4 = Saturday
    //                                   {"Sun"},   // 5 = Sunday
    //                                   {"Mon"}};  // 6 = Monday
            appData.sGeneralVar = appData.elapsedSec /SEC_IN_DAY; //LH restore the sGeneralVar so date calculates correctly
    
            appData.ccPtr += 3;
            *appData.ccPtr++ = '\x20';
    
            /* month */
            appData.sGeneralVar %= 365;
            for (index = 0; index < 12; index++)
            {
                appData.sGeneralVar -= numOfDaysPerMonth[index];
                if (appData.sGeneralVar < 0)
                    break;
            }
    
            pal_Memcpy(appData.ccPtr, monthOfYear[index], 3);
    //Month of the Year
            usiMonthOfYearGetTime = index + 1; //See Reference table at top of Get time section, Array starts at zero, so if want normal mth # add 1
            appData.ccPtr += 3;
            *appData.ccPtr++ = '\x20';
    
            /* date */
            /* restore the day in current month*/
            appData.sGeneralVar += numOfDaysPerMonth[index];
            appData.ccLen = itoa(appData.sGeneralVar + 1, appData.ccPtr); //Calls function itoa integer to ASCII decimal
            //LH Convert integer to ASCII in decimal base; param[in] cNum - integer number to convert
            //param[OUT] cString - output string; \return  number of ASCII characters
            //So at this point uGeneralVar must be a 2 digit integer that contains the day of the month
    //Day of the Month
            usiDayOfMonthGetTime = appData.sGeneralVar +1; //note this is s not u  GeneralVar; Had to add the +1 like above, not sure why but do
            usiBreakDummy = 0;
    
            appData.ccPtr += appData.ccLen;
            *appData.ccPtr++ = '\x20';
    
            /* year */
            /* number of days since beginning of 2013 */
            appData.uGeneralVar = appData.elapsedSec/SEC_IN_DAY;
            appData.uGeneralVar /= 365;
            appData.ccLen = itoa(YEAR2013 + appData.uGeneralVar , appData.ccPtr); //So this would be 2013 + 7 = 2020, so uGeneralVar must = # incr yr after 2013
            appData.ccPtr += appData.ccLen;
            *appData.ccPtr++ = '\x20';
    //Year
            usiYearGetTime = YEAR2013 + appData.uGeneralVar;
    
            /* time */
            appData.uGeneralVar = appData.elapsedSec%SEC_IN_DAY;
            /* number of seconds per hour */
            appData.uGeneralVar1 = appData.uGeneralVar%SEC_IN_HOUR;
            appData.uGeneralVar /= SEC_IN_HOUR;               /* number of hours */
            appData.ccLen = itoa(appData.uGeneralVar, appData.ccPtr);   //LH believe Hrs to Char
            //So at this point uGeneralVar must be a 2 digit integer that contains hours
            usiBreakDummy = 0;
    //Hours
            usiHrsGetTime = appData.uGeneralVar;
            usiBreakDummy = 0;
    
            appData.ccPtr += appData.ccLen;
            *appData.ccPtr++ = ':';                                     //LH believe colon between Hr and Min
            /* number of minutes per hour */
            appData.uGeneralVar = appData.uGeneralVar1/SEC_IN_MIN;
            /* number of seconds per minute */
            appData.uGeneralVar1 %= SEC_IN_MIN;
            appData.ccLen = itoa(appData.uGeneralVar, appData.ccPtr);   //LH believe minutes to Char
            //So at this point uGeneralVar must be a 2 digit integer that contains minutes
    //Minutes
            usiMinutesGetTime = appData.uGeneralVar;
            usiBreakDummy = 0;
    
            appData.ccPtr += appData.ccLen;
            *appData.ccPtr++ = ':';                                     //LH believe colon between Min and Sec
            appData.ccLen = itoa(appData.uGeneralVar1, appData.ccPtr);  //LH believe seconds to Char
            //So at this point uGeneralVar1 must be a 2 digit integer that contains seconds
    //Seconds
            usiSecondsGetTime = appData.uGeneralVar1;
            usiBreakDummy = 0;
    
            appData.ccPtr += appData.ccLen;
            *appData.ccPtr++ = '\x20';
    
            *appData.ccPtr++ = '\0';
    
            CLI_Write((_u8 *)"\r\n Server "); //LH Line 7
            CLI_Write((_u8 *)SNTPserver);
            CLI_Write((_u8 *)" Line 2346 has responded with time information");
            CLI_Write((_u8 *)"\n\r\r\n ");  //LH Line 8 which is blank
            CLI_Write((_u8 *)appData.time);  //LH when look at time structure it only uses 23 of the 30 elements in the structure; Line 9 with the time
            CLI_Write((_u8 *)"\n\r\r\n");   //LH line 10 which is a blank line
    
            //time element 16 HrTens, element 17 HrUnits; element 19 MinTens, element 20 MinUnits, element 22 SecTens, element 23 SecUnits
            //LH added 7-31-2020
            //CLI is set up for characters, so it prints the characters but not the integers
    //        CLI_Write((_u8 *)"\r\n usiDayOfMonth:  ");
    //        CLI_Write((_u8 *)usiDayOfMonth);
    //        CLI_Write((_u8 *)"\r\n usiHrs:  ");
    //        CLI_Write((_u8 *)usiHrs);
    //        CLI_Write((_u8 *)"\r\n usiMinutes:  ");
    //        CLI_Write((_u8 *)usiMinutes);
    //        CLI_Write((_u8 *)"\r\n usiDayOfMonth:  ");
    //        CLI_Write((_u8 *)usiSeconds);
    //printf compiles and runs but no seen on the console, not sure were it has gone to
    //        printf("\r\n usiDayOfMonth: %d", usiDayOfMonth);
    //        printf("\r\n usiHrs: %d", usiHrs);
    //        printf("\r\n usiMinutes: %d", usiMinutes);
    //        printf("\r\n usiSeconds: %d", usiSeconds);
    
        }
    
        return SUCCESS;
    }
    
    /*!
        \brief Create UDP socket to communicate with server.
    
        \param[in]      none
    
        \return         Socket descriptor for success otherwise negative
    
        \warning
    */
    static _i32 createConnection()
    {
        _i32 sd = 0;
    
        sd = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, IPPROTO_UDP);
        if( sd < 0 )
        {
            CLI_Write((_u8 *)"Error creating socket\n\r\n\r");
        }
    
        return sd;
    }
    
    /*!
        \brief Gets the Server IP address
    
        \param[in]      none
    
        \return         zero for success and -1 for error
    
        \warning
    */
    static _i32 getHostIP()
    {
        _i32 status = 0;
        appData.DestinationIP = 0;
    
        status = sl_NetAppDnsGetHostByName((_i8*)SNTPserver, pal_Strlen(SNTPserver),
                                           &appData.DestinationIP, SL_AF_INET);
        ASSERT_ON_ERROR(status);
    
        return SUCCESS;
    }

    emailAnd GetTime.h  99% TI WiFi code with additions for Application function calls

    /* L Hinz Group LLC
     * email.h - email header file
     *
     * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
     *
     *
     * All rights reserved. Property of Texas Instruments Incorporated.
     * Restricted rights to use, duplicate or disclose this code are
     * granted through contract.
     *
     * The program may not be used without the written permission of
     * Texas Instruments Incorporated or against the terms and conditions
     * stipulated in the agreement under which this program has been supplied,
     * and under no circumstances can it be used with non-TI connectivity device.
     *
     */
    
    #include "simplelink.h"
    
    #ifndef __EMAIL_H__
    #define __EMAIL_H__
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    /* SMTP defines */
    #define SMTP_BUF_LEN               100
    
    /* NetApp Email set/get options */
    #define NETAPP_ADVANCED_OPT        (1)
    #define NETAPP_SOURCE_EMAIL        (2)
    #define NETAPP_PASSWORD            (3)
    #define NETAPP_DEST_EMAIL          (4)
    #define NETAPP_SUBJECT             (5)
    #define NETAPP_MESSAGE             (6)
    
    #define MAX_DEST_EMAIL_LEN         30
    #define MAX_USERNAME_LEN           30
    #define MAX_PASSWORD_LEN           30
    //5-28-2020 LH Change Max subject length to 64
    //#define MAX_SUBJECT_LEN            30
    #define MAX_SUBJECT_LEN            64
    #define MAX_MESSAGE_LEN            64
    #define BASEKEY_LEN                128
    
    #define MAX_EMAIL_RCF_LEN        (MAX_DEST_EMAIL_LEN + 2)
    
    /* NetApp Email protocol types */
    #define SL_NET_APP_SMTP_PROTOCOL    (1)
    typedef struct
    {
        _u32  ProtocolSubType;
        _u32  Port;
        _u32  Family;
        _u32  SecurityMethod;
        _u32  SecurityCypher;
        _u32  Ip;                     /* IPv4 address or IPv6 first 4 bytes */
        _u32  Ip1OrPaadding;
        _u32  Ip2OrPaadding;
        _u32  Ip3OrPaadding;
    }SlNetAppEmailOpt_t;
    
    typedef struct
    {
        _u8 Username[MAX_USERNAME_LEN];
    }SlNetAppSourceEmail_t;
    
    typedef struct
    {
        _u8 Password[MAX_PASSWORD_LEN];
    }SlNetAppSourcePassword_t;
    
    typedef struct
    {
        _u8 Email[MAX_DEST_EMAIL_LEN];
    }SlNetAppDestination_t;
    
    typedef struct
    {
        _u8 Value[MAX_SUBJECT_LEN];
    }SlNetAppEmailSubject_t;
    
    //LH 8-2-2020 getting errors that appData is not defined so try pasting it here, I added the word typedef in front to make it the same
    //typedef struct{
    //Taking the word typedef off gave a clean compile.....why do not know
    struct{
        _u32   DestinationIP;
        _u32   elapsedSec;
        _u32   uGeneralVar;
        _u32   uGeneralVar1;
    
        _u16   ccLen;
    
        _i32   SockID;
        _i32   sGeneralVar;
    
        _u8 time[30];  //LH time is a structure with 30 elements so it can display a string like this Tue Oct 10 2018 11:26:13
        _u8 *ccPtr;
    
    }appData;
    
    
    
    
    /*!
        \brief          This function handles WLAN events
    
        \param[in]      command -   Command sent for processing
        \param[in]      pValueLen - Length of data to be processed
        \param[in]      pValue -    Data to be processed
    
        \return         0 for success, -1 otherwise
    
        \note
    
        \warning
    */
    _i32 sl_NetAppEmailSet(_u8 command, _u8 pValueLen,
                          _u8 *pValue);
    
    /*!
        \brief          Create a secure socket and connects to SMTP server
    
        \param[in]      none
    
        \return         0 if success and negative in case of error
    
        \note
    
        \warning
    */
    _i32 sl_NetAppEmailConnect();
    
    /*!
        \brief          Checks the connection status and sends the Email
    
        \param[in]      none
    
        \return         0 if success otherwise -1
    
        \note
    
        \warning
    */
    _i32 sl_NetAppEmailSend();
    
    //LH added
    
    //void LHSendEmail (void);
    int LHSendEmail ();
    int LHGetTime (); //8-1-2020
    
    //From main
    extern volatile signed short usiGMTOffsetHrSet;
    
    //From myTimers
    extern char LHemailSubject[64];
    extern char LHemailBody[64];
    
    
    //End of ...//LH added
    
    #ifdef  __cplusplus
    }
    #endif /* __cplusplus */
    
    #endif /* __NETAPP_H__ */

  • Hi,

    You cannot use STARTTLS SMTP command with CC3100 or CC3200. These 1st generation devices are lacking support for feature which can upgrade opened non-TLS socket (pure TCP socket) to TLS socket. From this reason you cannot use STARTTLS command with CC3100. STARTTLS is a SMTP command which is sent before upgrading socket to TLS. Only way will be used TLS stack on MSP430. This can be hard to achieve. Not from not sufficient resources, because there are some MSP430 with bigger memory (e.g. MSP430F5/6), but because MSP430 is 16 bit MCU. Almost all SSL/TLS stacks are designed for 32bit MCU. Rewriting TLS code from 32bit to 16bit architecture will require enormous quantity of work with expertise level of knowledge of cryptography. I use 2nd generation device CC3220. This device supports upgrading sockets from unsecured to secured (TLS). From this reason I have no issue using STARTLS for SMTP.

    Important (for you case) differences between 1rst and 2nd generation devices are:

    • CC3x00 does not support upgrading sockets from unsecured to secured
    • CC3x20 supports more cipher suites

    Inside my SMTP implementation I just set TLS 1.2 mode only (SL_SO_SEC_METHOD_TLSV1_2), for cipher suites I use default mask. I am not sure whether you issue can be caused supported cipher suites by CC3100 of not (this is not clear from log above). This is key thing which you need to determine. That means whether you are able open TLS connection to Gmail server (return codes from sl_Connect()). If you will be able TLS open connection, your issue will be narrowed to SMTP library code or Gmail account settings. But if you will not be able open TLS connection, there will not be easy solution.

    Here is reason why I don't believe that your issue is related to supported cipher suites by CC3100. CC3100 supports SL_SEC_MASK_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA and SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA. And according this Gmail supports page (March 2023) this TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA and TLS_RSA_WITH_AES_256_CBC_SHA are supported. That means according Google documentation should be supported cipher suites by CC3100 fine.

    btw: Do you have properly configured security at your Goole accounts - that means configured application password?

    Jan

  • - Thanks Jan we sincerely appreciate your help.

    - We also how that this dialog is beneficial for other TI Customers who I am sure are experiencing the same problem.

    - Thanks for confirming that for GMAIL we are using the right “Security Method” and “Cypher Suit.”

    - Yes we are using GMAIL AP passwords. That is an update we made in 2022, and Send Email again worked.

    - As outlined below, I believe the answer to your question is that sl_connect is not successful as we get return code -111.

    - Most important question:

    TI Send Email code has worked for 9 plus years across multiple Microcontrollers and Applications. So we are not trying to fix code that has never worked. WHAT HAS CHANGED? We know GMAIL and other email services have announced they no longer support less secure APPS. We know that last year APP Passwords allowed TI CC3100 and Microcontrollers to continue to work. In January 2023 GMAIL obviously made an unknown change that is now blocking CC3100 Send Email. We know that you can use a newer device and still send an email via gmail. The question is: Is there a change that can be made to the TI CC3100 SDK-1.3.0 code which will also enable it to still work?

    Below are three attachments with inline comments, but let me first paste the summary here so my comments are not lost in the longer attached text. The complete TI “emailAndGetTime.c” and “emailAndGetTime.h” were attached in my last post. These are extracts showing you variable values as the code is running. 

    Attachment 1: Tera Term CLI output that shows Send Email going through the TI code

    We have added numerous CLI lines so we can clearly see how the Send Email is stepping through all the TI Simplelink code. *****TI example Code, Not our Code**** That worked for over 9 years.

     

    Attachment 2: sl_NetAppEmailSet() function.

    At line 159 Email port is 587 and all Email parameters are set as expected / specified.

    *****Note port is 587************Note port is 587************Note port is 587*******

    Attachment 3: smtpConnect()

    Next the code goes to smtpConnect.

    Why does this now use Port 80? Or is Port 80 just the smtp generic port to the server and then it tells it than it wants to use email port 587?

    Status return code is -111

     

    Research

    The SMTP 111 error occurs when an issue is present while connecting with the remote SMTP server. For example, you would run into this error due to invalid sender domains or firewall issues.

    Additionally, you may encounter the 111 error due to invalid login credentials or if the email sending port gets blocked by the recipient.

    Solution - Here's How To Resolve It

    1. First, ensure that the email address to which you're sending the email is spelled correctly (especially the domain name). For example, if you're sending the email to a Gmail domain, ensure that the domain is "gmail.com."
    2. Then, ensure that you've provided the correct username and password for SMTP authentication.
    3. Finally, ensure that the email sending port is available for use on your end, and ensure that the port gets accepted on the recipient's end.

    Multiple applications that worked for years, so all the above had to have been correct, all blocked starting the same day.

     

    Attachment 1: Tera Term CLI output that shows Send Email going through the TI code

     

    Email application - Version 1.3.0

    *******************************************************************************

     Line 881 Device is configured in default state

     Line 898 Device started as STATION

     Line 171 email Username

     Line 180 email Password

     Line 159 email port, security

     Line 915 Connection established w/ AP and IP is acquired

     Line 918 Sending email...

     Line 189 email Destination

     Line 1253 After...DESTINATION_EMAIL

     Line 198 email Subject

     Line 1265 After...LHemailSubject

     Line 208 email Message Body

     Line 1278 After...LHemailBody

     Line 301 In _smtpConnect after if TLS create secure socket

     Line 306 In _smtpConnect Set Socket

     Line 333 In _smtpConnect before connect to Socket

     Line 513 In socket.c, _sl_Connect

     Line 95 In socket.c, _sl_BuildAddress

     Line 554 In socket.c, _sl_Connect Verify_RET_OK

     Line 335 In _smtpConnect after connect to Socket

     Line 339 In _smtpConnect if Status < 0 && SL_ESECSNOVERIFY != Status

     Line 1281 After...Status = sl_NetAppEmailConnect()

     Line 922 Device couldn't send the email

     Line 1488  in _i32 disconnectFromAP() after retVal = sl_WlanDisconnect();

     Line 1490  in _i32 disconnectFromAP() after if(0 == retVal)

     Line 1011 Device disconnected from the AP on application's request

     

    Attachment 2

    sl_NetAppEmailSet() function.

    At line 159 Email port is 587 and all Email parameters are set as expected / specified.

     

    _i32 sl_NetAppEmailSet(_u8 command ,_u8 pValueLen,

                          _u8 *pValue)

    {

        SlNetAppEmailOpt_t* pEmailOpt = 0;

        SlNetAppSourceEmail_t* pSourceEmail = NULL;

        SlNetAppSourcePassword_t* pSourcePassword = NULL;

        SlNetAppDestination_t* pDestinationEmail = NULL;

        SlNetAppEmailSubject_t* pSubject = NULL;

        switch (command)

        {

          case NETAPP_ADVANCED_OPT:

            pEmailOpt = (SlNetAppEmailOpt_t*)pValue;

            g_EmailOpt.Port = pEmailOpt->Port;

            g_EmailOpt.Family = pEmailOpt->Family;

            g_EmailOpt.SecurityMethod = pEmailOpt->SecurityMethod;

            g_EmailOpt.SecurityCypher = pEmailOpt->SecurityCypher;

            g_EmailOpt.Ip = pEmailOpt->Ip;

            g_EmailSetStatus+=1;

            CLI_Write(" Line 159 email port, security \n\r"); //2-16-2023 added and this prints

            break;

     

    Attachment 3

    smtpConnect()

    Next the code goes to smtpConnect.

    Why does this now use Port 80? Or is Port 80 just the smtp generic port to the server and then it tells it than it wants to use email port 587?

    Status return code is -111

     

    static _i32 _smtpConnect(void)

    {

        SlSockAddrIn_t  LocalAddr;

        SlTimeval_t     tTimeout;

        _i32           cipher = 0;

        _i32           LocalAddrSize = 0;

        _i8            method = 0;

        _i32            Status = 0;

     

        LocalAddr.sin_family = g_EmailOpt.Family;

        LocalAddr.sin_port = sl_Htons(g_EmailOpt.Port);

        LocalAddr.sin_addr.s_addr = sl_Htonl(g_EmailOpt.Ip);

        LocalAddrSize = sizeof(SlSockAddrIn_t);

     

        /* If TLS is required */

        if(g_EmailOpt.SecurityMethod <= 5)

        {

            /* Create secure socket */

    smtpSocket already = 80

            smtpSocket = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_SEC_SOCKET);

    smtpSocket still  = 80

            ASSERT_ON_ERROR(smtpSocket);

            tTimeout.tv_sec = 10;

            tTimeout.tv_usec = 90000;

            Status = sl_SetSockOpt(smtpSocket, SOL_SOCKET, SL_SO_RCVTIMEO,

                                   &tTimeout, sizeof(SlTimeval_t));

            ASSERT_ON_ERROR(Status);

            method = g_EmailOpt.SecurityMethod;

            cipher = g_EmailOpt.SecurityCypher;

            CLI_Write(" Line 301 In _smtpConnect after if TLS create secure socket \n\r");

            /* Set Socket Options that were just defined */

    smtpSocket = 80

            Status = sl_SetSockOpt(smtpSocket, SL_SOL_SOCKET, SL_SO_SECMETHOD,

                                   &method, sizeof(method));

            CLI_Write(" Line 306 In _smtpConnect Set Socket \n\r");

    Status = -111

            if( Status < 0 )

            {

                sl_Close(smtpSocket);

                ASSERT_ON_ERROR(Status);

                CLI_Write(" Line 311 In _smtpConnect sl_Close smtpSocket step 1 \n\r");

            }

            Status = sl_SetSockOpt(smtpSocket, SL_SOL_SOCKET, SL_SO_SECURE_MASK,

                                   &cipher, sizeof(cipher));

            if( Status < 0 )

            {

                sl_Close(smtpSocket);

                ASSERT_ON_ERROR(Status);

                CLI_Write(" Line 319 In _smtpConnect sl_Close smtpSocket step 2 \n\r");

            }

        }

        /* If no TLS required */

        else

        {

            /* Create socket */

            smtpSocket = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_IPPROTO_TCP);

            ASSERT_ON_ERROR(smtpSocket);

     

            CLI_Write(" Line 329 In _smtpConnect after if NO TLS required create socket \n\r");

        }

     

        /* connect to socket */

        CLI_Write(" Line 333 In _smtpConnect before connect to Socket \n\r");

        Status = sl_Connect(smtpSocket, (SlSockAddr_t *)&LocalAddr, LocalAddrSize);

        CLI_Write(" Line 335 In _smtpConnect after connect to Socket \n\r"); //2-16-2023 this prints

     

        if((Status < 0) && (SL_ESECSNOVERIFY != Status))

        {

            CLI_Write(" Line 339 In _smtpConnect if Status < 0 && SL_ESECSNOVERIFY != Status \n\r");  //2-16-2023 this prints

    // **************************************************************

    // Jan 30, 2023 I do get the above CLI write, but then no more

    // Appears that Connect to Socket is NOT successful

    // Next write I get is at line 914

    // ************************************************** 

            ASSERT_ON_ERROR(Status);

            CLI_Write(" Line 347 In _smtpConnect Status after connect to socket \n\r"); //2-16-2023 do not get this

        }

        CLI_Write(" Line 349 In _smtpConnect right before return SUCCESS \n\r"); //2-16-2023 do not get this

        return SUCCESS;

    }

    We hope this clearly shows where the TI Send Email is getting blocked.

     

    Thanks Lorne

  • Hi Lorne,

    Error -111 from sl_Connet() generally means that CC3100 is not able to open TCP (TLS) connection. There can be plenty reasons for this error. Some clue may to give you captured communication using network sniffer (Wireshark or tcpdum). Reasons may to be following:

    • issue at infrastructure (firewall) or ISP connectivity
    • remote server is not responding or wrong settings of server domain or port
    • wrong settings of TLS or cipher suites inside your code
    • mistake at gmail support page (that cipher TLS_RSA_WITH_AES_256_CBC_SHA is not supported)
    • some kind compatibility issue at CC3100 side with TLS connection

    Important reminders:

    • you cannot use port 587 for Gmail, because this port is used for STARTTLS. You need to use port for SSL/TLS - 465. Error code -111 is pretty expected when you wan to use TLS with port which uses plain TCP connection (like at port 587).
    • do you have uploaded latest ServicePack inside CC3100?

    For further investigation will be needed captured communication by sniffer. NWP log according this, may to be useful as well. But for decoding of NWP log you will need to wait for answer from TI (I don't have tool for decoding this log).

    Jan

  • Thanks Jan for the reply,

    You are very helpful. I hope this dialog will help many other TI customers / users.

    I was using Port 465 with TLS for over 9 years. I tried 587 but thanks for correcting me that I should not be trying that port.

    I get the same Error -111 when using port 465.

    Actually, since yesterday, I was also wondering if the Service Pack level could be the issue. So for the last 24 hours I have been researching how to Check the Service Pack Level and then upgrade it.

    I am testing on a CC3100BOOST with a manufacturing date of May 28, 2019. I see there is 2021 Service Pack so yes it needs to be upgraded.

    I downloaded Service Pack CC3100/CC3200 Service Pack image 

    Version:               1.0.1.15-2.14.0.0

    Date:                    May 11th, 2021

    Files:

    - servicepack_1.0.1.15-2.14.0.0.bin

     

    This ServicePack image can be used with production silicon only.

    The list of silicon that are compatible with this ServicePack are:

     - CC3100R1

     - CC3200R1

     

    1. This Service Pack 0.1.15-2.14.0.0 should be compatible with CC3100BOOST, as it has the CC3100R1 chip on it.
    2. Can the CC3100BOOST Service Pack level be read from Code Composer Studio or just CCS UniFlash?
    3. I found that UniFlash 8.2.0 does not support the CC3100/CC3200, it advises to use Version 3.x.
    4. I installed CCS UniFlash 3.4. It starts, I can select CC3100 and it opens a programing GUI.
    5. Via Google I found UniFlash v3 Quick Start Guide (ti.com)
    6. I have the CC3100BOOST mounted on the CC3XXEMUBOOST, and Power Jumpers are set as specified.
    7. USB is connected to CCXXEMUBOOST J6 USB port. I see under devices COM Ports CC3100BP ports 10, 7, 8 and 9. I believe J6 is the correct USB Port. I also tried J5, same error.
    8. Ports are all 9,600 Baud, tried 19,200 but that also does not work. The above Guide of course does not provide that information. I found one Google site suggested 921,600, but that also does not work.
    9. What is the required baud rate and other ports settings?

    I tried “Get Version”, “Service Pack Programing”, “List File System” All give the Error

    [20:27:45] FATAL: --- Can't connect to device !! ---

    [20:27:47] FATAL: Error connecting to the device. Please check your COM port settings. Error code: 1

     

    1. I have researched extensively but cannot find a detailed CC31XXEMUBOOST User’s Guide so I can read the CC3100BOOST Service Pack Level and then update the Service Pack to the latest version.

    There is extremely limited information on how to use the CC31XXEMUBOOST.

    1. Please confirm that to update the CC3100 Service Pack:
      1. Must have CC3100 mounted on CCXXEMUBOOST
      2. Use J6 USB connector on the CCXXEMUBOOST
      3. COM Port Baud rate ???? and Other Settings ????
      4. CCS UNIFLASH 3.4 is the correct application to check the version and update the CC3100 Service Pack

    On some site in TI there must be a STEP by STEP Guide on how to Read the Service Pack Level and Update the Service Pack on the CC3100. USB Connections, Port Configurations, STEP by STEP GUI steps..

    This should be so easy……..but obviously I have not found the right information yet.

    I agree loading CC3100BOOST with the latest Service Pack is the first most important step to achieve.

    Thanks

    Lorne

  • Hi Lorne,

    Using CC31xx devices without properly updated Service Pack is not a greatest idea. Device can be affected by security threats and other bugs. Even that your CC3100BOOST were manufactured at May 2019, I will expect it will contain much older ServicePack, because TI does not ship CC3100BOOST with latest service pack. Updating Service Pack is responsibility of end-user.

    • For updating ServicePack you need to use Uniflash version 3.4
    • Service pack version you can read via sl_ API - sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION... for more details see description at SimpleLink CC3100/CC3200 Host Driver guide another option may to be using webpages and GET tag  like __SL_G_V.A. Uniflash command "Get Version" does not read version of Service Pack (it reads version of hardware only).
    • Guide for using Uniflash with CC3100/CC3200 device you will find here
    • Usage CC3100BOOST + CC3XXEMUBOOST is most straight forward way how to update Service pack. Some details you can find here.
    • I used Uniflash 3.4 long time ago, but I think there is no need to set baudrate anywhere. You need to set proper COM port number only.

    Jan

  • Hi Jan, again thanks for all your help.

    I should have thought of checking the Service Pack level earlier, and we were getting hopeful that this may be the solution to enable a CC3100 to still Send Email.

    Thanks so much for links to additional documents to provide clues how to upgrade the Service Pack.

    I was able to finally successfully load the latest Service Pack to 2 different CC3100BOOST devices.

    ***Unfortunately, the CC3100 is still not able to Send Email.*** I have only tried it on GMAIL port 465 with TLS.

    I think SEND EMAIL using TI CC3100 parts is no longer feasible, and not solvable.

    Of course still open to any additional ideas you, others at TI, or other Customers / User have that will still make this possible.

    Attached below are 2 big attachments: 1) List of Key Documents for CC3100, and 2) Step by Step how to upgrade the Service Pack on a CC3100 or CC3200.

     

    1. To help other TI customers and User here is list to key documents to reference for CC3100 and CC3100 Service Pack updating.

     

    CC3100 Service Pack Loading Key Documents and key data items

    1. CC3100 SimpleLink WiFI and IOT Solution BoosterPack Hardware User’s Guide

    SWRU371B Jan 2015

    CC3100 SimpleLink Wi-Fi and IoT Solution BoosterPack Hardware (Rev. B)

     

    - Page 7: 8 Mbit serial flash, so 1 Mbyte serial flash

    - Page 8: Push Buttons, LED’s, Jumper Settings; SW3 for FLASHING firmware

    - Page 15: J6 (right side USB) Ports, port 3 for Flash Programing

    - Page16: The first Port in the list is used for FLASH Programing

    - Page 16: J5 ports ONLY for TI internal debug

    - Page 17: Jumpers for CCXXEMUBOOST powering CC3100BOOST

    - Page 19: Jumpers and USB for powering with FRAM launch pads

     

    1. SimpleLink WiFi CC3100, CC3200 UniFlash

    SWRU588 June 2020

    SimpleLinkTm Wi-Fi® CC3100, CC3200 UniFlash User's Guide (ti.com)

     

    - Page 4: CC31XXEMUBOOST needed to flash CC3100BP

    - Page 12: BAUD rate 921,600 ONLY

    - Page 12: Table 1: CC3100 Booster Pack Pre-Flashed FTDI,

    # COM Ports = 2,

    # of Com Port for Flashing = The lower COM port

    Above table is written: “Ideally all FTDI chipsets on evaluation boards are pre-flashed.”

    - So believe should only see 2 COM ports and use the lower one.

    - Future Technology Devices International Limited, commonly known by its acronym FTDI, is a Scottish privately held semiconductor device company, specializing in Universal Serial Bus (USB) technology. FTDI. Type. FTDI chips are used in USB adapters to connect to RS232 and parallel FIFO hardware interfaces.

    - Page 12: Table 1: CC3100 Booster Pack Non-Flashed FTDI,

    # COM Ports = 4,

    # of Com Port for Flashing = The 3rd COM port

    - Page 13: Format: See SWRU371B page 7, CC3100 8Mbit, 1 Mbyte, so select 1 Mbyte

    - Page 16: Service Pack Programing, list 4 easy steps

    - Note COM Port must first be entered

     

    1. Application Report CC3X00 Production Line Guide

    SWRA658 Jan 2021

    https://www.ti.com/lit/an/swra658/swra658.pdf

    CC3x00 Production Line Guide

    - Page 5: CC3100 Programing Options

    - Page 6: CC3100MOD Programing Options

    - Page 10: Programing over UART CC3100, uses the CC3100 UART pins

    - Baud rate: 921,600

    - Data bits: 8 bits

    - Flow control: None

    - Parity: None

    - Stop bits: 1

    - Polarity: Positive

    - Page 13: Programing using UniFlash CC3100, using the CC31XXEMUBOOST

     - *****When UniFlash begins, it will prompt the user to restart the device ********

    - Use CC3XXEMUBOOST USB J6, right hand side of the board

     

    1. CC3100 SimpleLink WiFi and IOT Solution Getting Started Guide

    SWRU375 May 2018

    CC3100 SimpleLink Wi-Fi and IoT Solution Getting Started Guide (Rev. D)

    - Page 6 & 7: CC3XXEMUBOOST and CC3100 jumpers and connections

    - Page 8: Windows Device Manager showing 4 COM ports

    - Page 13: Jumper J8 moved, 1st pin visible when connecting to MSP430F5529

     

    1. CC3100 CC3200 SimpleLink WiFi Network Processor Subsystem Programmers Guide

    SWRU368 June 2014

    CC3100/CC3200 SimpleLink Wi-Fi Internet-on-a-Chip User's Guide (Rev. C) (ti.com)

     

    -Not key for Service Pack programing, but another key CC3100 document found

     

     

    1. To help other TI customers and users here is step by step how to upgrade the CC3100 Service Pack.
    2. Download and install CCS UniFlash 3.4., UniFlash 8.2.0 does not support the CC3100/CC3200,

          UNIFLASH Software programming tool | TI.com

     

    1. Download CC3100 Service Pack

    CC3100SDK Software development kit (SDK) | TI.com

    Version:       1.0.1.15-2.14.0.0

    Date: May 11th, 2021

    Files: - servicepack_1.0.1.15-2.14.0.0.bin

     

    This Service Pack image can be used with production silicon only.

    The list of silicon that are compatible with this ServicePack are:

     - CC3100R1

     - CC3200R1

     

    1. Configure the CC3XXEMUBOOST and CC31000BOOST jumpers, and mate the devices

    - See Document 1 above “CC3100 SimpleLink WiFI and IOT Solution BoosterPack Hardware User’s Guide”, SWRU371B Jan 2015

     

    1. Launch / Start CCS UniFlash 3.4
      1. Click on New Target Configuration
      2. Select CC3x Serial(UART) Interface from the pull down list
      3. Board or Device will auto populate “SimpleLink Wifi CC3100/CC3200
      4. Press OK this will open the GUI for the CC31xx/CC32xx Flash Setup and Contol
      5. This will show:
        1. COMM PORT
        2. FORMAT
    • Program
    1. Service Pack Programming
    2. Image Programing
    3. Get Version
    • Add File
    • List File System

     

    1. Connect a USB cable from the CC3XXEMUBOOST J6 port (right side) to your PC
    2. PC Windows Settings, Device Manager, Ports

    - Mine came up with 4 Ports

                - CC3100BP PORT (COM10)

                - CC3100BP PORT (COM7)

                - CC3100BP PORT (COM8)

                - CC3100BP PORT (COM9)

    - The TI documentation 2 below says to use the 3rd port.

    - I found 3rd Port does not work, I had to use the 4th PORT COM9

    - Click on the 4th line and then Port Settings Tab

    - ****Change the Baud rate to 921,600, and other settings as show in Document 3 below****

    - Baud rate: 921,600

    - Data bits: 8 bits

    - Flow control: None

    - Parity: None

    - Stop bits: 1

    - Polarity: Positive

    - *****Extremely critical to ensure the above change is done and accepted. Ie After setting it go back and re-verify.

    1. Back to CCS UniFlash GUI screen enter the COM PORT to match your COM PORT, in my case it is 9
    2. CCS UniFlash GUI, click on Format
      1. I found it was already set to 1 MB
      2. See document 1 below SWRU371B 2015 page 7; YES 1 Mbyte is correct
    3. Click on “Get Version”
      1. This step is mainly to confirm a working connection to the CC3100BOOST

    [17:11:05] Begin GetVersion operation.

    [17:11:06] INFO: > Executing Operation: Connect

    [17:11:08] INFO: setting break signal

    [17:11:09] INFO: detecting FTDI for device reset

    [17:11:10] INFO: connection succeeded

    [17:11:10] INFO: getting storage list

    [17:11:10] INFO: > Executing Operation: GetVersion

    [17:11:10] INFO: reading version info

    [17:11:10] INFO: > Bootloader version: 2.0.4.0

    [17:11:10] INFO: > Executing Operation: Disconnect

    [17:11:10] Operation GetVersion returned.

    1. Click on “Service Pack Programing”

    Browse to the Service Pack Bin file: servicepack_1.0.1.15-2.14.0.0.bin

    Then click OK

    [17:41:26] Begin ServicePackProgramming operation.

    [17:41:26] INFO: > Executing Operation: Connect

    [17:41:28] INFO: setting break signal

    [17:41:29] INFO: detecting FTDI for device reset

    [17:41:30] INFO: connection succeeded

    [17:41:30] INFO: getting storage list

    [17:41:30] INFO: > Executing Operation: ServicePackProgramming

    [17:41:30] INFO: Path to the service pack file: C:/ti/CC3100_CC3200_ServicePack_1.0.1.15-2.14.0.0/servicepack_1.0.1.15-2.14.0.0.bin

    [17:41:30] INFO: reading version info

    [17:41:30] INFO: CC3100R Device detected.

    [17:41:30] INFO: NWP/MAC/PHY Version from Service Pack:

    [17:41:30] INFO:  NWP Patch version: 2.14.0.0

    [17:41:30] INFO:  MAC Patch version: 1.6.0.2

    [17:41:30] INFO:  PHY Patch version: 1.0.3.37

    [17:41:30] INFO: reading version info

    [17:41:30] INFO: DEVICE CC3100 ES1.33

    [17:41:30] INFO: reading version info

    [17:41:32] INFO: Downloading file "/sys/servicepack.ucf" with size 38868

    [17:41:34] INFO:

     

    New Token is 0x0

    [17:41:34] INFO: Download complete

    [17:41:34] INFO: > Executing Operation: Disconnect

    [17:41:34] Operation ServicePackProgramming returned.

    1. Click on ListFileSystem

    - This step is not required to upgrade the Service Pack. It is show here to show what my device returned.

    [17:16:36] Begin ListFileSystem operation.

    [17:16:36] INFO: > Executing Operation: Connect

    [17:16:38] INFO: setting break signal

    [17:16:39] INFO: detecting FTDI for device reset

    [17:16:40] INFO: connection succeeded

    [17:16:40] INFO: getting storage list

    [17:16:40] INFO: > Executing Operation: Init

    [17:16:40] INFO: reading version info

    [17:16:40] INFO: DEVICE CC3100 ES1.33

    [17:16:40] INFO: reading version info

    [17:16:42] INFO: > Executing Operation: ListFileSystem

    [17:16:42] INFO: extracting file system information...

    [17:16:42] INFO: Serial Flash block size: 4096 bytes

    [17:16:42] INFO: Serial Flash capacity:         256 blocks

     

    [17:16:42] INFO: file  start size  fail  total size  filename

    [17:16:42] INFO: index block [BLKs]      safe  [BLKs]

    [17:16:42] INFO: ----------------------------------------------------------------------------

    [17:16:42] INFO: N/A   0     5     N/A   5           FATFS

    [17:16:42] INFO: 4     5     33    yes   66          /sys/servicepack.ucf

    [17:16:42] INFO: 6     71    5     yes   10          /tmp/phy.cal

    [17:16:42] INFO: 7     81    1     yes   2           /sys/stacfg.ini

    [17:16:42] INFO: 8     83    3     no    3           www/safe/about.html

    [17:16:42] INFO: 9     86    1     no    1           www/safe/overview.html

    [17:16:42] INFO: 10    87    2     no    2           www/safe/portal.html

    [17:16:42] INFO: 11    89    4     no    4           www/safe/setup.html

    [17:16:42] INFO: 12    93    1     no    1           www/safe/index.html

    [17:16:42] INFO: 13    94    1     no    1           www/safe/param_about.html

    [17:16:42] INFO: 14    95    1     no    1           www/safe/param_config.html

    [17:16:42] INFO: 15    96    1     no    1           www/safe/param_online.html

    [17:16:42] INFO: 16    97    1     no    1           www/safe/js/com.ti.tokenpoller.js

    [17:16:42] INFO: 17    98    24    no    24          www/safe/js/jquery-1.8.3.min.js

    [17:16:42] INFO: 18    122   1     no    1           www/safe/js/jquery.rwdimagemaps.min.js

    [17:16:42] INFO: 19    123   1     no    1           www/safe/js/page-actions.js

    [17:16:42] INFO: 20    124   1     no    1           www/safe/images/ti-logo.png

    [17:16:42] INFO: 21    125   1     no    1           www/safe/images/icon_l_html_a.png

    [17:16:42] INFO: 22    126   1     no    1           www/safe/images/tab-line.gif

    [17:16:42] INFO: 23    127   1     no    1           www/safe/images/ticom3-tab-left.gif

    [17:16:42] INFO: 24    128   1     no    1           www/safe/images/ticom3-tab-right.gif

    [17:16:42] INFO: 26    129   4     no    4           www/safe/images/hw-sbd.gif

    [17:16:42] INFO: 27    133   4     no    4           www/safe/images/sw-sbd.gif

    [17:16:42] INFO: 28    137   3     no    3           www/safe/css/style.css

    [17:16:42] INFO:

    [17:16:42] INFO: Flash usage

    [17:16:42] INFO: -------------------------

    [17:16:42] INFO: used space:  140 blocks

    [17:16:42] INFO: free space:  116 blocks

    [17:16:42] INFO: memory hole: [140-255]

    [17:16:42] INFO: > Executing Operation: Disconnect

    [17:16:43] Operation ListFileSystem returned.

     

    End 

    Lorne

  • it is unfortunate that you were not able to use the email application.

    The -111 is very strange. seems like you have an issue with the port.

    If you can arrange a sniffer log we can get some better understanding of this.

    If you have enough memory on the host you can add a TLS stack (e.g. mbedTLS) on the host to avoid to security limitations of the old device (in case this is what prevents the connection, the -111 is not related).

  • Thanks Kobi for the reply.

    This is highly unproductive for both TI and my company.  We are not trying to debug my code. We are trying to get the TI CC3100 SDK-1.3.0 “Send Email Example” that has worked for 9+ years to again work.

    Ridiculous for me to do code traces on 100% TI code and send them to you and others at TI.

    TI needs to take a CC3100BOOST, mount it on a F5529 launch pad, or an FR6989 launch pad and load and run the TI email-application example. You will see the following output.

     

    Email application - Version 1.3.0

    ***********************************************

     Line 483 main.c confiqureSimpleLinkToDefaultState

     Device is configured in default state

     Device started as STATION

     Connection established w/ AP and IP is acquired.

     Sending email...

     Line 185 email.c After...NETAPP_SUBJECT

     Device couldn't send the email

     

    TI Email code experts then need to do all the traces they wish and the end results is one of two options:

    Fix the example code so it is now possible to again send an email. Post the revised code here, and update the CC3100 SDK-1.3.0 example code.

    OR B. If not technically possible with this device, upgrade the CC3100 Web pages and documentation to state SEND-EMAIL is no longer possible.  (STOP FALSE ADVERTIZING)

    We are now focusing on “If This Then That”, IFTTT.com service. Early test code shows that doing a http PUT with the data in the attached URL results in an email being sent. Once we have this fully working, we will be pleased to share step by step how to do this and the http code for the CC3100.

     

    We are hoping TI will fix your send-email example, but confidence of that is dimensioning as to date no one in TI has actually run your current posted email example.

    Lorne

  • If i understand correctly the issue is the connection to the SMTP port that is rejected by the server (-111). Let me know if you see something else.

    if you can provide air sniffer logs (showing the connection attempt) and/or nwp logs (/cfs-file/__key/communityserver-discussions-components-files/968/CC3100-_2600_-CC3200-Capture-NWP-Logs-_2D00_-Texas-Instruments-Wiki.pdf) we can verify if this is the case or something else blocks the connection. And this may enable us to offer fixes.

    As said before we are not supporting the SMTP example anymore. From what i'm seeing it seems that the CC3100 still supports the framework for the connection (socket and TLS wise) and it requires just an update to the email app or the SMTP stack. As Jan mentioned SMTP is relatively simple (though we don't have email code experts here) and if you can find another stack implementation it should be possible to port it on top of the CC3100 sockets. This is one option. Your alternative method is just as good.

  • Thanks Kobi for the reply,

    So no one in your organization, or product organization has a physical CC3100BOOST to physically test and debug your TI Send Email example? They are available in your TI Store!

    As already stated in my previous post, the most productive action is for TI engineers  to take a physical CC3100BOOST, mount it on an F5529 Launch pad and run your TI CC-1.3.0 Send Email example, try to send an email to GMAIL, OUTLOOK, any other free email service, and gather all the logs you need.

    I can try to help you debug your TI email example. (Asking a customer to debug a TI posted example,…..strange……but willing to help.)

    I downloaded the document you listed above. I have a CC3100BOOST and a CC3XXEMUBOOST. The problem is that there is no TI example code to load into the CC3XEMUBOOST to run the send email example, thus no way to get NWP logs.

    If there is a way to load the TI Send Email example into the CCXXEMUBOOST and run it, please advise detailed steps how to do this.

    Is there is a way I can capture NWP logs with the F5529 launch pad, please provide a detailed step by step process of how to do this.

     

    Thanks

    Lorne

  • We are willing to help debug new issues with the existing code (such as what you are facing). But we are not maintaining this old example and we are not planning to update the SDK with fixes.

    I just sent you the the instructions for capturing NWP log. You just need to receive the UART DEBUG (PIN 62) line from the CC3100 into a terminal application on a PC (using a serial to USB converter, eg you can use https://www.ti.com/tool/CC31XXEMUBOOST).