How do you get the arduino to send an email notification

I want to set my laser trip wire, which has a keypad to enable/disable the laser, to send me an email notification when the laser has been crossed. I have an ethernet shield but I am new to ethernet shields. Here is my code below:

#include <Password.h> //http://www.arduino.cc/playground/uploads/Code/Password.zip
#include <Keypad.h> //http://www.arduino.cc/playground/uploads/Code/Keypad.zip

Password password = Password( "1234" );

const byte ROWS = 4; // Four rows
const byte COLS = 3; //  columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 5, 4, 3, 2 };// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = { 8, 7, 6 };


// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

int pin = 0;
int laser = 0;
int i = 0;
int alarm = 0;
int firstTime = 0;
boolean crossed;
boolean failed;

void setup()
{
  pinMode(13,OUTPUT);  //Green LED
  pinMode(12,OUTPUT);  //Red LED
  pinMode(11,OUTPUT);  //Laser
  Serial.begin(9600);
  keypad.addEventListener(keypadEvent); //add an event listener for this keypad
}

void loop()
{
  keypad.getKey();
  
  //Check to see if laser has been crossed
  if(laser == 1)
  {
    checkLaser();
    if(i >= 3)
    {
      failed = true;  //Activates alarm
      
    }
    else
    {
      failed = false;  //Deactivates alarm
    }
  }
  else
  {
    i = 0;
    crossed = false;
  }

  //Code for the alarm
  if(crossed || failed)
  {
    if(alarm < 1)
    {
      if(failed)
      {
        //Write code to send log information to servers about too many password attempts
      }
      if(crossed)
      {
        //Write code to send log info to servers about laser being crossed
      }
      
      Serial.println("Alarm Activated");
      alarm = 1;
    }
    digitalWrite(12,HIGH);  //Turns on red LED
  }
}

//take care of some special events
void keypadEvent(KeypadEvent eKey){
  switch (keypad.getState()){
    case PRESSED:
	Serial.print("Pressed: ");
	Serial.println(eKey);
	switch (eKey){
	  case '*': checkPassword(); break;
	  case '#': password.reset(); break;
	  default: password.append(eKey);
     }
  }
}

void checkPassword(){
  if (password.evaluate()){
    Serial.println("Success");
    //Flash green LED
    digitalWrite(13,HIGH);
    delay(100);
    digitalWrite(13,LOW);
    delay(100);
    digitalWrite(13,HIGH);
    delay(100);
    digitalWrite(13,LOW);
    
    i = 0;
    failed = false;
    crossed = false;
    alarm = 0;
    firstTime = 0;
    digitalWrite(12,LOW);
    password.reset();
    //Turn on/off laser
    if(laser == 0)
    {
      //Turn on laser
      laser = 1;
      Serial.println("Laser ON\n");
      digitalWrite(11,HIGH);
    }
    else
    {
      //Turn off laser
      laser = 0;
      Serial.println("Laser OFF\n");
      digitalWrite(11,LOW);
    }
   }
   else
   {
    Serial.println("Wrong");
    //Flash red LED
    digitalWrite(12,HIGH);
    delay(100);
    digitalWrite(12,LOW);
    delay(100);
    digitalWrite(12,HIGH);
    delay(100);
    digitalWrite(12,LOW);
    
    password.reset();
    //If wrong more than 3 times will activate the alarm
    i++;
  }
}

void checkLaser()
{
  //Checks laser to see if it has been crossed
  if(firstTime < 1)
  {
    delay(5000);  //Delays the alarm so that the laser has time to hit photocell
    firstTime = 1;
  }
  //Serial.println(analogRead(0));  //Used to calibrate photocell, debuging purposes only
  if(analogRead(0) > 600)  //checks the photocell's resistance
  {
    crossed = true;
  }
  else
  {
    crossed = false;
  }
}

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

Do you have access to a mail host that will accept unsecured SMTP? Most ISPs and mail providers don't, so you may need to provide your own relay.

See this thread - http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1235534880

I have successfully tested base64 algorithm to receive mail on my gmail account.

A lot of people would appreciate it if you posted your sketch.

Sure.

Try this:

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

byte MAC[]={0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};  // Your MAC
File Data_3; EthernetClient client;

static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void encodeblock(unsigned char in[3],unsigned char out[4],int len) {
  out[0]=cb64[in[0]>>2]; out[1]=cb64[((in[0]&0x03)<<4)|((in[1]&0xF0)>>4)];
  out[2]=(unsigned char) (len>1 ? cb64[((in[1]&0x0F)<<2)|((in[2]&0xC0)>>6)] : '=');
  out[3]=(unsigned char) (len>2 ? cb64[in[2]&0x3F] : '=');
}
void encode() {
  unsigned char in[3],out[4]; int i,len,blocksout=0;
  while (Data_3.available()!=0) {
    len=0; for (i=0;i<3;i++) { in[i]=(unsigned char) Data_3.read(); if (Data_3.available()!=0) len++; else in[i]=0; }
    if (len) { encodeblock(in,out,len); for(i=0;i<4;i++) client.write(out[i]); blocksout++; }
    if (blocksout>=19||Data_3.available()==0) { if (blocksout) client.print("\r\n");  blocksout=0; }
  }
}

void setup() {
  Ethernet.begin(MAC); delay(2000);
  pinMode(10,OUTPUT); SD.begin(4);
}

void loop() {
  Data_3=SD.open("Data_3.csv",FILE_READ);
  client.connect("smtp.mail.yahoo.com",25);
  client.print("HELO\nAUTH PLAIN\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n");
  client.print("MAIL FROM:<foo@yahoo.com>\nRCPT TO:<YOUR_EMAIL@gmail.com>\nDATA\nFrom: \"Foo\" <foo@yahoo.com>\r\nTo: YOUR_EMAIL@gmail.com\r\nSubject: MAIL NOTIFICATION\r\n");
  client.print("Content-Type: text/html; name=\"Data_3.csv\"\r\nContent-Disposition: attachment; filename=\"Data_3.csv\"\r\nContent-Transfer-Encoding: base64\r\n\r\n");
  encode();
  client.print("\r\n.\r\nQUIT\n");
  client.stop();
  Data_3.close();
  //while(1);
}

This sketch is sending me a mail with an attachment, a file present on SD card.
I hope this helps.

What lines of your code would I need to change in order to send to my email account?

Try this.

#include <Password.h> //http://www.arduino.cc/playground/uploads/Code/Password.zip
#include <Keypad.h> //http://www.arduino.cc/playground/uploads/Code/Keypad.zip
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

byte MAC[]={0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
File logFile; EthernetClient client;
int CS_pin = 10;

static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void encodeblock(unsigned char in[3],unsigned char out[4],int len) {
  out[0]=cb64[in[0]>>2]; out[1]=cb64[((in[0]&0x03)<<4)|((in[1]&0xF0)>>4)];
  out[2]=(unsigned char) (len>1 ? cb64[((in[1]&0x0F)<<2)|((in[2]&0xC0)>>6)] : '=');
  out[3]=(unsigned char) (len>2 ? cb64[in[2]&0x3F] : '=');
}
void encode() {
  unsigned char in[3],out[4]; int i,len,blocksout=0;
  while (logFile.available()!=0) {
    len=0; for (i=0;i<3;i++) { in[i]=(unsigned char) logFile.read(); if (logFile.available()!=0) len++; else in[i]=0; }
    if (len) { encodeblock(in,out,len); for(i=0;i<4;i++) client.write(out[i]); blocksout++; }
    if (blocksout>=19||logFile.available()==0) { if (blocksout) client.print("\r\n");  blocksout=0; }
  }
}

Password password = Password( "1234" );

const byte ROWS = 4; // Four rows
const byte COLS = 3; //  columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 5, 4, 3, 2 };// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = { 8, 7, 6 };


// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

int pin = 0;
int laser = 0;
int i = 0;
int alarm = 0;
int firstTime = 0;
boolean crossed;
boolean failed;

void setup()
{
  Ethernet.begin(MAC);
  Wire.begin();
  SPI.begin();
  pinMode(10,OUTPUT); SD.begin(4);
  pinMode(13,OUTPUT);  //Green LED
  pinMode(12,OUTPUT);  //Red LED
  pinMode(11,OUTPUT);  //Laser
  Serial.begin(9600);
  keypad.addEventListener(keypadEvent); //add an event listener for this keypad
}

void loop()
{
  keypad.getKey();
  
  //Check to see if laser has been crossed
  if(laser == 1)
  {
    checkLaser();
    if(i >= 3)
    {
      failed = true;  //Activates alarm
      
    }
    else
    {
      failed = false;  //Deactivates alarm
    }
  }
  else
  {
    i = 0;
    crossed = false;
  }

  //Code for the alarm
  if(crossed || failed)
  {
    if(alarm < 1)
    {
      if(failed)
      {
        SDWrite();
        send_email(); //Write code to send log information to servers about too many password attempts
      }
      if(crossed)
      {
        //Write code to send log info to servers about laser being crossed
      }
      
      Serial.println("Alarm Activated");
      alarm = 1;
    }
    digitalWrite(12,HIGH);  //Turns on red LED
  }
}

//take care of some special events
void keypadEvent(KeypadEvent eKey){
  switch (keypad.getState()){
    case PRESSED:
   Serial.print("Pressed: ");
   Serial.println(eKey);
   switch (eKey){
     case '*': checkPassword(); break;
     case '#': password.reset(); break;
     default: password.append(eKey);
     }
  }
}

void checkPassword(){
  if (password.evaluate()){
    Serial.println("Success");
    //Flash green LED
    digitalWrite(13,HIGH);
    delay(100);
    digitalWrite(13,LOW);
    delay(100);
    digitalWrite(13,HIGH);
    delay(100);
    digitalWrite(13,LOW);
    
    i = 0;
    failed = false;
    crossed = false;
    alarm = 0;
    firstTime = 0;
    digitalWrite(12,LOW);
    password.reset();
    //Turn on/off laser
    if(laser == 0)
    {
      //Turn on laser
      laser = 1;
      Serial.println("Laser ON\n");
      digitalWrite(11,HIGH);
    }
    else
    {
      //Turn off laser
      laser = 0;
      Serial.println("Laser OFF\n");
      digitalWrite(11,LOW);
    }
   }
   else
   {
    Serial.println("Wrong");
    //Flash red LED
    digitalWrite(12,HIGH);
    delay(100);
    digitalWrite(12,LOW);
    delay(100);
    digitalWrite(12,HIGH);
    delay(100);
    digitalWrite(12,LOW);
    
    password.reset();
    //If wrong more than 3 times will activate the alarm
    i++;
  }
}

void checkLaser()
{
  //Checks laser to see if it has been crossed
  if(firstTime < 1)
  {
    delay(5000);  //Delays the alarm so that the laser has time to hit photocell
    firstTime = 1;
  }
  //Serial.println(analogRead(0));  //Used to calibrate photocell, debuging purposes only
  if(analogRead(0) > 600)  //checks the photocell's resistance
  {
    crossed = true;
  }
  else
  {
    crossed = false;
  }
}

void SDWrite() {
  if (!SD.begin(CS_pin))
  {
      Serial.println("Card Failure");
      return;
  }
  Serial.println("Card Ready");
  
  File logFile = SD.open("logFile.txt", FILE_WRITE);
  if (logFile)
  {
    String note = "Alarm Activated";
    logFile.println(note);
    logFile.close();
    Serial.println(note);
  }
  else
  {
    Serial.println("Couldn't open logFile");
  }
}


void send_email() {
  logFile=SD.open("logFile.txt",FILE_READ);
  client.connect("smtp.mail.yahoo.com",25);
  client.print("HELO\nAUTH PLAIN\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n");  // x: base64 encoded login: \0foo@yahoo.com\0password
  client.print("MAIL FROM:<foo@yahoo.com>\nRCPT TO:<YOUREMAIL@gmail.com>\nDATA\nFrom: \"Foo\" <foo@yahoo.com>\r\nTo: YOUREMAIL@gmail.com\r\nSubject: Ardunio sending Notification\r\n");
  client.print("Content-Type: text/html; name=\"logFile.txt\"\r\nContent-Disposition: attachment; filename=\"logFile.txt\"\r\nContent-Transfer-Encoding: base64\r\n\r\n");
  encode();
  client.print("\r\n.\r\nQUIT\n");
  client.stop();
  logFile.close();
}

Some instructions:

  1. Insert an SD card into the slot
  2. If you are using UNO board, ignore this. If using Mega, change:
int CS_pin = 53;

pinMode(53,OUTPUT); in the setup, 53 instead of 10.

  1. Search in the code for “YOUREMAIL@gmail.com” to replace with your gmail ID.

Let me know if this works.

Z

First you need to figure out which authentication/encryption method your mail server requires. Chances are that the code zeus2kx posted wont work for you e.g. if your server requires TSL. If your server supports plain authentication you can use zeus2kx code as a template for your implementation. Before writing code for the Arduino try test the stmp communication from a PC using telnet. On Windows start the command prompt and telnet to the the smtp(25) port of your mail server:

C:\> telnet stmp.somewhere.net 25

When the telnet connection is established, type the stmp commands that send the message. The following commands work when the server do not require authentication (for example, if you send a message to an email address that is hosted locally on that server).

EHLO somewhere.net
mail from: <me@somewhere.net>
rcpt to: <joe@somewhere.net>
data
Subject: test

the body of the message.
.

You will see that the server writes back when you type the commands. For example, after you have typed the “mail from: me@somewhere.net” it may respond with “me@somewhere.net… Sender ok”.

When you have successfully sent an email from your PC just transfer the command to client.print()-lines for the Arduino. It should work. On the other hand, if you can’t send a message from a PC sending email won’t work from the Arduino either.

zeus2kx, When I compiled the code I got an error saying: Ethernet_Test_ino:55: error: 'Wire' was not declared in this scope.

Do i need to install a library in order for it to work or do I need to declare a value for that?

https://rapidshare.com/files/3947890642/libraries.zip Download and paste in your Arduino libraries folder..

ok, I got it to compile, but my keypad does not work, which means I cannot turn on the laser and no data will be sent to my email. I am using the UNO and only have limited number of digital inputs. Also, the LEDs are always on, which I am assuming that means that the digital inputs are being used to control the ethernet shield. Is there anyway around this?

Check your code

if(failed)
      {
        SDWrite();
        send_email(); //Write code to send log information to servers about too many password attempts
      }
      if(crossed)
      {
        //Write code to send log info to servers about laser being crossed
      }

I had inserted these two functions "SDWrite" and "send_email" without knowing how does your code work. So you can remove and place them wherever you want to get notification from.

Do you see "logFile.txt" on SD card? What is written in the file? Are you receiving emails?

If in serial monitor you see “Couldn’t open logFile”, try changing CS pin.

int CS_pin = 4;
pinMode(4,OUTPUT); instead of pinMode(10,OUTPUT);

If problem persists, try

int CS_pin = 4;
pinMode(10,OUTPUT);

You must not use these pins for any other connections. Leave them unused.

It seems to not be doing anything. I open the serial monitor and no activity shows up. I even condensed the code so that it would just send an email and commented all the keypad and laser stuff out, but still nothing.

Okay try to test this:

  1. create a file on SD card by name “Data_3.csv”
  2. Change YOUR_EMAIL@gmail.com to your email.
  3. Connect to internet and wait 5 mins, you will see an email in your inbox.
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

byte MAC[]={0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};  // Your MAC
File Data_3; EthernetClient client;

static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void encodeblock(unsigned char in[3],unsigned char out[4],int len) {
  out[0]=cb64[in[0]>>2]; out[1]=cb64[((in[0]&0x03)<<4)|((in[1]&0xF0)>>4)];
  out[2]=(unsigned char) (len>1 ? cb64[((in[1]&0x0F)<<2)|((in[2]&0xC0)>>6)] : '=');
  out[3]=(unsigned char) (len>2 ? cb64[in[2]&0x3F] : '=');
}
void encode() {
  unsigned char in[3],out[4]; int i,len,blocksout=0;
  while (Data_3.available()!=0) {
    len=0; for (i=0;i<3;i++) { in[i]=(unsigned char) Data_3.read(); if (Data_3.available()!=0) len++; else in[i]=0; }
    if (len) { encodeblock(in,out,len); for(i=0;i<4;i++) client.write(out[i]); blocksout++; }
    if (blocksout>=19||Data_3.available()==0) { if (blocksout) client.print("\r\n");  blocksout=0; }
  }
}

void setup() {
  Ethernet.begin(MAC); delay(2000);
  pinMode(10,OUTPUT); SD.begin(4);
}

void loop() {
  Data_3=SD.open("Data_3.csv",FILE_READ);
  client.connect("smtp.mail.yahoo.com",25);
  client.print("HELO\nAUTH PLAIN\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n");
  client.print("MAIL FROM:<foo@yahoo.com>\nRCPT TO:<YOUR_EMAIL@gmail.com>\nDATA\nFrom: \"Foo\" <foo@yahoo.com>\r\nTo: YOUR_EMAIL@gmail.com\r\nSubject: MAIL NOTIFICATION\r\n");
  client.print("Content-Type: text/html; name=\"Data_3.csv\"\r\nContent-Disposition: attachment; filename=\"Data_3.csv\"\r\nContent-Transfer-Encoding: base64\r\n\r\n");
  encode();
  client.print("\r\n.\r\nQUIT\n");
  client.stop();
  Data_3.close();
  //while(1);
}

I did all that and put in some debugging lines but it still did nothing and nothing showed up in the serial monitor.

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

byte MAC[]={0x90, 0xA2, 0xDA, 0x00, 0xA8, 0x8C};  // Your MAC
File Data_3; EthernetClient client;

static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void encodeblock(unsigned char in[3],unsigned char out[4],int len) {
  out[0]=cb64[in[0]>>2]; out[1]=cb64[((in[0]&0x03)<<4)|((in[1]&0xF0)>>4)];
  out[2]=(unsigned char) (len>1 ? cb64[((in[1]&0x0F)<<2)|((in[2]&0xC0)>>6)] : '=');
  out[3]=(unsigned char) (len>2 ? cb64[in[2]&0x3F] : '=');
}
void encode() {
  unsigned char in[3],out[4]; int i,len,blocksout=0;
  while (Data_3.available()!=0) {
    len=0; for (i=0;i<3;i++) { in[i]=(unsigned char) Data_3.read(); if (Data_3.available()!=0) len++; else in[i]=0; }
    if (len) { encodeblock(in,out,len); for(i=0;i<4;i++) client.write(out[i]); blocksout++; }
    if (blocksout>=19||Data_3.available()==0) { if (blocksout) client.print("\r\n");  blocksout=0; }
  }
}

void setup() {
  Ethernet.begin(MAC); delay(2000);
  pinMode(10,OUTPUT); SD.begin(4);
}

void loop() {
  Serial.println("Intializing...");
  Data_3=SD.open("Data_3.csv",FILE_READ);
  client.connect("smtp.mail.yahoo.com",25);
  client.print("HELO\nAUTH PLAIN\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n");
  client.print("MAIL FROM:<foo@yahoo.com>\nRCPT TO:<YOUR_EMAIL@gmail.com>\nDATA\nFrom: \"Foo\" <foo@yahoo.com>\r\nTo: YOUR_EMAIL@gmail.com\r\nSubject: MAIL NOTIFICATION\r\n");
  client.print("Content-Type: text/html; name=\"Data_3.csv\"\r\nContent-Disposition: attachment; filename=\"Data_3.csv\"\r\nContent-Transfer-Encoding: base64\r\n\r\n");
  Serial.println("Encoding...");
  encode();
  client.print("\r\n.\r\nQUIT\n");
  client.stop();
  Data_3.close();
  Serial.println("Done.");
  //while(1);
}

In the above code I don't see you have inserted your email instead of YOUR_EMAIL@gmail.com change it, I am sure it will work.

I want to set my laser trip wire, which has a keypad to enable/disable the laser, to send me an email notification when the laser has been crossed. I have an ethernet shield but I am new to ethernet shields.

How will the arduino be connected to the internet? If it is thru a router to a cable provider then you probably could use the provider's smtp email server. That is usually a simple setup.

I did change the YOUR_EMAIL to mine, I just changed it back on the post so that way it was just not out there. It still does not work which makes me think that the ethernet library is not installed correctly on my computer or something like that. And does it need to be plugged straight into the router, that is what I am planning on doing, but for now I am just plugging it into my computer.

And does it need to be plugged straight into the router, that is what I am planning on doing, but for now I am just plugging it into my computer.

Depending on how you have configured your computer, that may or may not work. Why not do it the proper way and plug it into the router?