Email from the core

Hello,
I’m looking to send an email from the spark core when triggered by a sensor. I’ve been trying with some code from a topic here called “Sending emails from the core, locking up!”

I’m not having any luck getting it to run.

Can anyone help with some code that successfully sends email out via SMTP? Or direct me to somewhere with some documentation that will help?

Thanks!

I need also that if someone can write an example, would be nice…

Hey Guys,

Sure thing, gimme a few minutes and I’ll post an example. :smile:

Thanks,
David

2 Likes

ok @Dave many people waiting you :smiley:

I have one that works with arduino, was working on the core but since a couple of days it doesnt work anymore… I was using println command… tired of problems and uneven performance of this thing. :frowning:

Hi @MartyMart,

I don’t have to write a fresh email example for you if you wanted to post your code and we could help debug what’s going wrong!

Thanks,
David

Hey Guys,

Found another thread on this as well, so I’ll use that code as a starting point:

Hi @MartyMart,

It looks like you had working email code, and BDub was helping you in this thread: https://community.spark.io/t/tcpclient-connect-with-authentication-to-smtp-server/2538/2

But you had a single bad over the air firmware update? Did you try to flash your code again?

Thanks,
David

Hey Guys,

I’m getting close, still working on this, just making the function a little more robust when handling AUTH with some SMTP servers. :slight_smile:

edit: This isn’t instant you know!
edit 2: Okay, this is weird, I was having problems with the first SMTP server, so I switched, and this one doesn’t want me to say EHLO, etc. So I’m digging in, not gonna give up!

Thanks,
David

Ok David , we are already waiting )))

Okay, here we go! This took me way too long! :slight_smile:

Here’s a nice overview of what SMTP servers expect protocol wise:
http://www.smtp2go.com/articles/smtp-protocol

Make sure you base64 encode your username / password ahead of time (node.js example):

new Buffer("username").toString("base64")
new Buffer("password").toString("base64")

Here’s the Sending Email code I modified based on @jboswell’s code:
https://gist.github.com/dmiddlecamp/8943011

I got this to send me an email, I think we can do a lot of work to improve on this though!

P.S: Be careful when sending emails! Your SMTP server will throttle or ban you if you send too many too fast, or wrongly! Also check your spam folder! :slight_smile:

Thanks,
David

2 Likes

Thank you, David, I’ll get this code and get to work!
Jim

1 Like

This is very neat @Dave – it would have never occurred to me to call SPARK_WAN_Loop() directly. I guess the stack will get untangled eventually.

I did notice that authenticate has three 5 second timeouts in a row before a call to idle() so that could still be a problem.

Also just so everybody knows, not all sendmail programs return the exact same codes for all commands. The RFC has a list, but the best thing might be to telnet into your mail service and do the transaction by hand and see what the response codes are. For instance, my mail server replies with a 350 for the AUTH LOGIN and the rest of the text from the service is base64 encoded until you get the username and password in. In general, the 2xx codes mean success and the 3xx codes mean success so far but please go on. The 4xx codes mean please try again and 5xx codes mean error.

1 Like

Hi @bko,

Totally, just in the event the socket behavior took longer, I wanted to make sure nothing was blocked for long. You’re absolutely right that SMTP servers won’t return exactly the same codes, that would be a great upgrade to this library.

Thanks,
David

Hi Dave,

OK, I must be missing something… I’ve cut and pasted your code into the IDE, but it won’t compile, it gives me the errors below. Maybe I need to open the .cpp file instead of just cut and past of the text? But I can’t figure out how to do that in Spark Build.

So can you point me to somewhere that could help me figure out why I can’t make it work?

Sorry for the Noob-ness!

Thanks!
Jim

the_user_app.cpp:9:22: error: variable or field ‘echoSocketWrite’ declared void
the_user_app.cpp:9:22: error: ‘TCPClient’ was not declared in this scope
the_user_app.cpp:9:37: error: expected primary-expression before 'const’
the_user_app.cpp:10:22: error: variable or field ‘echoSocketWrite’ declared void
the_user_app.cpp:10:22: error: ‘TCPClient’ was not declared in this scope
the_user_app.cpp:10:37: error: ‘String’ was not declared in this scope
the_user_app.cpp:11:20: error: variable or field ‘flushToSerial’ declared void
the_user_app.cpp:11:20: error: ‘TCPClient’ was not declared in this scope
the_user_app.cpp:3:6: error: previous declaration of ‘void setup()’ with ‘C++’ linkage
In file included from …/inc/spark_wiring.h:31:0,
from …/inc/application.h:29,
from the_user_app.cpp:10:
…/inc/spark_utilities.h:116:35: error: conflicts with new declaration with ‘C’ linkage
the_user_app.cpp:4:6: error: previous declaration of ‘void loop()’ with ‘C++’ linkage
In file included from …/inc/spark_wiring.h:31:0,
from …/inc/application.h:29,
from the_user_app.cpp:10:
…/inc/spark_utilities.h:117:34: error: conflicts with new declaration with ‘C’ linkage
the_user_app.cpp: In function ‘void loop()’:
the_user_app.cpp:43:138: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp:43:138: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp:43:138: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp:43:138: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp:43:138: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp:43:138: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp:43:138: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp: In function ‘int SendEmail(char*, char*, char*, char*, char*, char*, char*)’:
the_user_app.cpp:83:101: error: ‘echoSocketWrite’ was not declared in this scope
the_user_app.cpp:85:25: error: ‘flushToSerial’ was not declared in this scope
the_user_app.cpp:101:37: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp:107:37: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp: In function ‘int handshake(char*)’:
the_user_app.cpp:120:25: error: ‘flushToSerial’ was not declared in this scope
the_user_app.cpp:122:37: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp:129:82: error: ‘echoSocketWrite’ was not declared in this scope
the_user_app.cpp:130:37: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp: In function ‘int authenticate(char*, char*)’:
the_user_app.cpp:142:45: error: ‘echoSocketWrite’ was not declared in this scope
the_user_app.cpp:143:33: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp:146:33: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp:149:33: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
the_user_app.cpp: In function ‘void echoSocketWrite(TCPClient, String)’:
the_user_app.cpp:162:19: error: ‘flushToSerial’ was not declared in this scope
the_user_app.cpp: In function ‘int SendEmail(char*, char*, char*, char*, char*, char*, char*)’:
the_user_app.cpp:114:1: warning: control reaches end of non-void function [-Wreturn-type]
make: *** [the_user_app.o] Error 1

Error: Could not compile. Please review your code.

Hi @jimbol,

Ahh sorry about that! Take out this from my code and then it should compile:

#include "application.h"

Thanks!
David

David,
Thanks, it compiles fine now, I’ll see if I can make the next steps!
Jim

1 Like

Hey @MartyMart, would you please do this to your code above:

Thanks!

and @Dave, very nice example! You need to write more examples :smile: I also like the use of the:

void idle() {
    SPARK_WLAN_Loop();
}

I’m sure this would keep the heartbeat up to date, but would it also allow you to receive a flash update OTA?

1 Like

Thanks! It’s a super-rough example. At some point I’ll have to go back and do proper response checking and actually break it into a library and whatnot. :slight_smile:

The general TCP functions of “listen for this kind of response” is something I’d like to build a few more of, since I suspect it’ll go a long way to make it way easier to expand on and write more networking libraries like this.

I’m not 1200% sure, but I think calling “SPARK_WLAN_Loop” will also call “Spark_Communication_Loop”, which should handle stuff like responding to flashing, responding to variable / function requests, etc.

Thanks!
David

So I have had some time to play around tonight, the code works fabulously but I am seeing some strangeness in the serial output. It starts in this section of the code:

Serial.println("sending mail...\n");
echoSocketWrite(client, String("MAIL FROM:<") + String(fromEmail) + String(">") + String("\r\n"));
echoSocketWrite(client, String("RCPT TO:<") + String(toEmail) + String(">") + String("\r\n"));
flushToSerial(client); //client.flush();

The serial output looks good up to there, once it gets past there it starts looking like this:

 2.7.0 Authentication successful
MAIL FROM:<blah@gmail.com>
 2.7.0 AuthenRCPT TO:<blah@gmail.com>
 2.7.0 AuthenDATA
 2.7.0 Authenfrom: blah@gmail.com
 2.7.0 Authento: blah@gmail.com

Notice the ‘2.7.0 Authen’ prefixing all the commands after it, this continues to happen all the way through to the ‘End Data’ I think.

Still going through stuff, mainly just getting the formatting right in putty so I can diagnose the problem via the output. I suppose it’s only semantic at this point because the emails seem pretty solid.