POP3 email client test code

I wrote a sketch that reads a POP3 email account looking for an email with the subject "Arduino" in order to control the Arduino via email. It works with POP3 email servers that do not require TLS or SSL security to log in. If you test it, let me know if it works with your email account or not.

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

// this must be unique on your localnet
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 

// change server to your email server ip or domain
IPAddress server( 1,2,3,4 );
// char server[] = "myemailserver.com";
int port = 110;

// change to plain text user and password
char userName[] = "myusername";
char passWord[] = "mypassword";

EthernetClient client;
char rtnBuf[100];

void setup()
{
  delay(2000);
 
  Serial.begin(115200);
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  while(!Ethernet.begin(mac)) {
    Serial.println("DHCP failed. Retry in 5 seconds");
    delay(5000);
  }

  Serial.println(Ethernet.localIP());

  delay(2000);
  Serial.println(F("Ready. Press 'e' to check email."));
}

void loop()
{
  byte inChar;

  inChar = Serial.read();

  if(inChar == 'e')
  {
      if(getEmail()) Serial.println(F("Email retrieved"));
      else Serial.println(F("Email failed"));
  }

  Ethernet.maintain();
}

byte getEmail()
{
  byte thisByte = 0;
  byte respCode;
  char rtnVal[64];
  int mailCount,mailSize;
  char tBuf[64];
 
  if(client.connect(server,port) == 1) {
    Serial.println(F("connected"));
  } else {
    Serial.println(F("connection failed"));
    return 0;
  }

  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  Serial.println(F("Sending User"));
  strcpy_P(tBuf,PSTR("USER ")); 
  strcat(tBuf,userName);
  strcat_P(tBuf,PSTR("\r\n")); 
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);
 
  Serial.print(F("Sending Password "));
  strcpy_P(tBuf,PSTR("PASS ")); 
  strcat(tBuf,passWord);
  strcat_P(tBuf,PSTR("\r\n")); 

  Serial.println(tBuf);
 
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  Serial.println(F("Sending STAT"));
  strcpy_P(tBuf,PSTR("STAT\r\n")); 
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  sscanf(rtnBuf,"%s %u %u",rtnVal,&mailCount,&mailSize);
  Serial.print("mail count: ");
  Serial.println(mailCount);

  for(int i = 1;i<=mailCount;i++) {
    strcpy_P(tBuf,PSTR("RETR ")); 
    itoa(i,rtnBuf,10);
    strcat(tBuf,rtnBuf);
    strcat(tBuf,"\r\n");
    client.write(tBuf);
    ePrint();       
    Serial.println("\r\nEND");
  }

  Serial.println(F("Sending QUIT"));
  strcpy_P(tBuf,PSTR("QUIT\r\n")); 
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  client.stop();

  Serial.println(F("disconnected"));

  return 1;
}



byte eRcv()
{
  byte respCode;
  byte thisByte;
  int loopCount = 0;
  byte rtnCount = 0;
 
  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return 0;
    }
  }

  while(client.available())
  { 
    thisByte = client.read();   
//    Serial.write(thisByte);
    if(rtnCount < 99) {
      rtnBuf[rtnCount]=thisByte;
      rtnCount++;
      rtnBuf[rtnCount]=0;
    }
  }

  if(rtnBuf[0] == '-') return 0;
 
  return 1;
}

byte ePrint()
{
  byte respCode;
  byte thisByte;
  int loopCount = 0;
  byte rtnCount = 0;
 
  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return 0;
    }
  }

  byte lineLength = 0;
  bool endMsg = false;
  bool msgBody = false;
  char lineBuf[64];
 
  while(!endMsg) {
    while(client.available())
    { 
      thisByte = client.read();   

      if(thisByte == '\n') {
        // end of line       
        if(strlen(lineBuf) == 0) {
          if(!msgBody) Serial.println("Message body");
          msgBody = true;
        }
        if(strcmp(lineBuf,".") == 0) {
          // end of message
          endMsg = true;
        }
        if(!msgBody && (strncmp(lineBuf,"From:",5) == 0)) {
          // from
          Serial.println(lineBuf);
        }
        if(!msgBody && (strncmp(lineBuf,"Subject:",8) == 0)) {
          // subject
          Serial.println(lineBuf);
          if(strncmp(&lineBuf[9],"Arduino",7) == 0) Serial.println(F("For my Arduino!"));
        }
        lineLength = 0;
        lineBuf[0] = 0;
      }
      else if(thisByte != '\r') {
        // another character
        if(lineLength < 63) {
          lineBuf[lineLength] = thisByte;
          lineLength++;
          lineBuf[lineLength] = 0;
        }
       
      }
    }
  }
  return 1;
}


void efail()
{
  byte thisByte = 0;
  int loopCount = 0;

  client.println("QUIT");

  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return;
    }
  }

  while(client.available())
  { 
    thisByte = client.read();   
    Serial.write(thisByte);
  }

  client.stop();

  Serial.println(F("disconnected"));
}

If it finds an email with the subject "Arduino", it will display "For my Arduino!" on the serial monitor.

Now lets make it turn a led on, and off, when it receives the command "on", or "off" in the response email.

What free email servers work for this?

Thomas499:
Now lets make it turn a led on, and off, when it receives the command "on", or "off" in the response email.

What free email servers work for this?

If you have an earthlink account, use it.

I am considering using "command" lines in the message body. Kinda like this:
command 8 on
command 6 off
That would turn on a LED on D8, and turn off a LED on D6. How does that sound to you?

If you have an earthlink account, use it.

A mentor of mine has an earthlink account. I know he wouldn't mind me using it to test, but knowing him, he wouldn't want anyone besides him to have access to that account without him being there to log in. I just called him and he said earthlink isn't free. I have a website, I am wondering if there is a widget I can download to wordpress that allows the website to host it's own email server that would allow this function.

I am considering using "command" lines in the message body. Kinda like this:
command 8 on
command 6 off
That would turn on a LED on D8, and turn off a LED on D6. How does that sound to you?

That would be a good starting point. My ultimant intentions are to be able to send a respond in the format of a one digit number, followed by a space, followed by time.

Ex. of response format 4 3:30pm

What I want this to do, is in 4 days, at 3:30pm the led will turn on. The RTC will determine the time, and I can write the program to do this, and will post it once I have it working. Any thoughts?

I guess you could do that.

Here is the code that does what I want.

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

// this must be unique
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x59, 0x67 };  

// change network settings to yours
IPAddress ip( 192, 168, 2, 2 );    
IPAddress gateway( 192, 168, 2, 1 );
IPAddress subnet( 255, 255, 255, 0 );

// change server to your email server ip or domain
IPAddress server( 1,2,3,4 );
// char server[] = "smtpcorp.com";
int port = 110;

char userName[] = "myuser";
char passWord[] = "mypassword";

EthernetClient client;
char rtnBuf[100];

void setup()
{
  delay(2000);
  
  Serial.begin(115200);
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  pinMode(6,OUTPUT);
  pinMode(8,OUTPUT);
  
//  Ethernet.begin(mac, ip, gateway, gateway, subnet); 

  while(!Ethernet.begin(mac)) {
    Serial.println("DHCP failed. Retry in 5 seconds"); 
    delay(5000);
  }

  Serial.println(Ethernet.localIP());

  delay(2000);
  Serial.println(F("Ready. Press 'e' to receive."));
}

void loop()
{
  byte inChar;

  inChar = Serial.read();

  if(inChar == 'e')
  {
      if(getEmail()) Serial.println(F("Email received"));
      else Serial.println(F("Email failed"));
  }

  Ethernet.maintain();
}

byte getEmail()
{
  byte thisByte = 0;
  byte respCode;
  char rtnVal[64];
  int mailCount,mailSize;
  char tBuf[64];
  
  if(client.connect(server,port) == 1) {
    Serial.println(F("connected"));
  } else {
    Serial.println(F("connection failed"));
    return 0;
  }

  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  Serial.println(F("Sending User"));
  strcpy_P(tBuf,PSTR("USER "));  
  strcat(tBuf,userName);
  strcat_P(tBuf,PSTR("\r\n"));  
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);
  
  Serial.print(F("Sending Password "));
  strcpy_P(tBuf,PSTR("PASS "));  
  strcat(tBuf,passWord);
  strcat_P(tBuf,PSTR("\r\n"));  

  Serial.println(tBuf);
  
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  Serial.println(F("Sending STAT"));
  strcpy_P(tBuf,PSTR("STAT\r\n"));  
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  sscanf(rtnBuf,"%s %u %u",rtnVal,&mailCount,&mailSize);
  Serial.print(F("mail count: "));
  Serial.println(mailCount);

  for(int i = 1;i<=mailCount;i++) {
    strcpy_P(tBuf,PSTR("RETR "));  
    itoa(i,rtnBuf,10);
    strcat(tBuf,rtnBuf);
    strcat(tBuf,"\r\n");
    client.write(tBuf);
    ePrint();       
    Serial.println(F("\r\nEND"));
  }

  Serial.println(F("Sending QUIT"));
  strcpy_P(tBuf,PSTR("QUIT\r\n"));  
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  client.stop();

  Serial.println(F("disconnected"));

  return 1;
}



byte eRcv()
{
  byte respCode;
  byte thisByte;
  int loopCount = 0;
  byte rtnCount = 0;
  
  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return 0;
    }
  }

  while(client.available())
  {  
    thisByte = client.read();    
//    Serial.write(thisByte);
    if(rtnCount < 99) {
      rtnBuf[rtnCount]=thisByte;
      rtnCount++;
      rtnBuf[rtnCount]=0;
    }
  }

  if(rtnBuf[0] == '-') return 0;
  
  return 1;
}

byte ePrint()
{
  byte respCode;
  byte thisByte;
  int loopCount = 0;
  byte rtnCount = 0;
  byte lineLength = 0;
  bool endMsg = false;
  bool msgBody = false;
  bool forArduino = false;
  char lineBuf[64];
  byte pinNo;
  char pinState[8];
  
  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return 0;
    }
  }

  while(!endMsg) {
    while(client.available())
    {  
      thisByte = client.read();    

      // if it is for the Arduino and past the header
      if(forArduino && msgBody) Serial.write(thisByte);

      if(thisByte == '\n') {
        // end of line        
        if(strlen(lineBuf) == 0) {
          if(!msgBody) Serial.println("Message body");
          msgBody = true;
        }
        if(strcmp(lineBuf,".") == 0) {
          // end of message
          endMsg = true;
        }
        if(!msgBody && (strncmp(lineBuf,"From:",5) == 0)) {
          // from
          Serial.println(lineBuf);
        }
        if(!msgBody && (strncmp(lineBuf,"Subject:",8) == 0)) {
          // subject
          Serial.println(lineBuf);
          if(strncmp(&lineBuf[9],"Arduino",7) == 0) {
            Serial.println("For my Arduino!");
            forArduino= true;
          }
        }

        if(msgBody && strncmp(lineBuf,"command ",8) == 0) {
          Serial.print("Command! D");          
          sscanf(lineBuf,"%*s %u %s",&pinNo,pinState);
          Serial.print(pinNo);
          Serial.print(" ");
          Serial.println(pinState);
          
          if(strcmp(pinState,"on") == 0) digitalWrite(pinNo,HIGH);          
          if(strcmp(pinState,"off") == 0) digitalWrite(pinNo,LOW);          
        }
        
        lineLength = 0;
        lineBuf[0] = 0;
      }
      else if(thisByte != '\r') {
        // another character
        if(lineLength < 63) {
          lineBuf[lineLength] = thisByte;
          lineLength++;
          lineBuf[lineLength] = 0;
        }
        
      }
    }
  }
  return 1;
}

void efail()
{
  byte thisByte = 0;
  int loopCount = 0;

  client.println("QUIT");

  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return;
    }
  }

  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);
  }

  client.stop();

  Serial.println(F("disconnected"));
}

I have D6 and D8 as OUTPUT. I sent this in an email with Arduino as the subject.
command 8 on
command 6 off

It set D8 HIGH and D6 LOW.

edit: You must press the 'e' and enter to read the email, but eventually it will be on a timer.

edit: You must press the 'e' and enter to read the email, but eventually it will be on a timer.

A timer could work. What are you planning to use the timer for? For example, do you want to use the timer to automatically check the email every 30 minutes or so without being required to press 'e' and enter for that function to occur?

Is there a way to check the follow perimeters?

  1. check to see if any email is currently unread
  2. check to see if that unread email has same title as the the one that was first sent by arudino

Thomas499:
A timer could work. What are you planning to use the timer for? For example, do you want to use the timer to automatically check the email every 30 minutes or so without being required to press 'e' and enter for that function to occur?

Is there a way to check the follow perimeters?

  1. check to see if any email is currently unread
  2. check to see if that unread email has same title as the the one that was first sent by arudino

Yes. I'll play with it to see how often I want to check the emails.

I plan on deleting emails that the Arduino has already read. I may keep the settings on SD or EEPROM. I haven't decided yet.

I do try to help people improve things when I am in the position to do so. I'm really good at doing this.

I plan on deleting emails that the Arduino has already read. I may keep the settings on SD or EEPROM. I haven't decided yet.

I have another suggestion. The sd card is great! But it doesn't come with the wi-fi shield, or Ethernet shield even though the port does. I noticed on one of your post a few days ago you showed how to send a file with email. Why not write a code that shows arduino newbs how to use wi-fi and email to store information and by-pass the sd card completely?

If I understand the basics of Arduino Web Interface you can use a sd card to run an ardunios programming. Basically, a clever person could use this feature with an arduino uno, and practically run codes written for Mega... if I understand the basic concept correctly. (minus the SRAM limitation)

If you combine that function, with the email sending file, and this code.... You could in theory store information on email, and read it later, which is the same thing people use sd cards for. This way you don't have to find a sd card that will work with the Wi-Fi shield. I know for a fact, that finding a sd card that works with the Wtv020sd16p sound module is enough to make a grown man cry. Chances are, a sd card laying around the house won't work, and for the first timers, you really want the process of success to an experiment to be as easy as possible.

Any thoughts on if bypassing sd card using an email file is possible?

Also, the whole purpose of this request was to bypass paying monthly subscriptions to do this using a sim card. If we force the user to pay for a special email account to use this, the added advantage of using email instead is significantly lower, than if we can figure out how to let them do it for free. - We really need to find a free email account that allows this, and list it up top somewhere.

=========edit====================

Yes. I'll play with it to see how often I want to check the emails.

The purpose of this code is to show newbs how to use it. I recommend the standard time on this code to be every 2 minutes. But add a comment beside that says this time is recommended for experimenting, but final code to check email may be more practical to check less often.

I don't have any problems with my SD cards. I find the SD card much more reliable than the wifi shield connection, or even the ethernet shield connection. Much less to fail. I am actually leaning towards the EEPROM. It is on board by default. No other devices needed.

I don't have any problems with my SD cards

If you have a camera at your house that uses a micro sd card, take it out and try to run it with the Ethernet shield. I know I tried at least a dozen sd cards on the WTV020-SD-16P audio module before I found one that worked. If you click on the link, every dozen or so post shows someone complaining about this. The first is on post 2

Welcome and you are clear to go. Just be careful about the micro SD card you are using. Got a lot of pain in the b... figuring out why mine did not work from the start.

The sound module may have a few bugs that the wi-fi/Ethernet shield sd port doesn't have. I haven't really played with it to find out. I will tonight though!

I am actually leaning towards the EEPROM.

I tried playing with EEPROM once, I could only get numbers to save. I have mixed feelings about either way.

For EEPROM: i'd love to learn how to use EEPROM, and it does come on the arduino without any extra hardware needed.

For SD card: You can take it out, and if anything happens to the arduino you can still read, and recover the data. You can also transfer it to another arduino if needed.

I find the SD card much more reliable than the wifi shield connection, or even the Ethernet shield connection. Much less to fail.

Can we not use both the sd card and email to save the data then? It would be pretty easy to write a code that compares the two every now and then. If something is saved on the sd card, that isn't saved on the email, the program could easily update the email file. Maybe have this self check happen every 30 days or so? - if you are willing to do the server/email part, I will write the code that compares the sd and email file, every 30 days based on the NTP time server. I know how to find out if the two files don't match.

Either way, as a project down the road, it would be cool to show people how to use email to over ride the need for an sd card. Kind of like a self made cloud storage for arduino. How cool would that be!?! If using an arudino to build your own cloud storage system isn't something to be proud of...

Results from last nights experiments:

The sd cards that don't work with the sound module, do work with the WiFi shield sd port.

I am trying to test this using earthlink now. I have the WiFi shield hooked up, and will post the code that allows this code to work with WiFi when I get it to work.

The problem I have run into converting Ethernet to WiFi is Ethernet.maintain();

void loop()
{
  byte inChar;

  inChar = Serial.read();

  if(inChar == 'e')
  {
      if(getEmail()) Serial.println(F("Email received"));
      else Serial.println(F("Email failed"));
  }

  Ethernet.maintain();
}

This is the error message that I get when I change Ethernet.maintain(); to WiFi.maintain();

sketch_may23a:122: error: 'class WiFiClass' has no member named 'maintain'

any suggestions?

Can we not use both the sd card and email to save the data then? It would be pretty easy to write a code that compares the two every now and then. If something is saved on the sd card, that isn't saved on the email, the program could easily update the email file. Maybe have this self check happen every 30 days or so? - if you are willing to do the server/email part, I will write the code that compares the sd and email file, every 30 days based on the NTP time server. I know how to find out if the two files don't match.

I will start working on this today if you are willing to do the web email side of it. This is the format that I am leaning towards that will be easy to learn from.

ID number, Date, Time, LED activated method, Total number of LED active by button, Total number of LED active by email.

The way I will make this code work, is it will first check to see if file exist when starting up. If it exist, it will read the file and will save the numbers in red from the sd card to the sketches memory, so it can add to them later. If the files doesn't exist it will create it, and add the header.

When the led comes on, it will add one to the number saved, which will make it save the new data line to the sd card. It will then check the sd card to make sure the data was successfully saved.

I know how to do this, and can make it easy for a newb to understand. I've seen a lot of post about questions reading and saving information to a sd card. There really isn't any examples that show how to do all of this in an example easy to understand format.

If you do the part that saves the file to email, and the part that pulls the file from the email when needed, I will do the sd card side. Let me know if you are interested in this idea. Without your help, this is not something I can do alone, but by working together, I have no doubt we can make this work.

Thomas

There is no WiFi.maintain function. The DHCP renewal is done with the firmware. Remove the function call to maintain.

edit: This is my latest code adapted and tested on a wifi shield. It removes the emails it has read that are for the Arduino. It leaves any other emails on the server.

/*
   Email POP3 client sketch for WiFi shield
   Posted 24 May 2015 by SurferTim
*/
#include <SPI.h>
#include <WiFi.h>

WiFiClient client;
char ssid[] = "MySSID";     // the name of your network
char pass[] = "MtPassphrase";  // your network password
int status = WL_IDLE_STATUS;     // the Wifi radio's status

// change server to your email server ip or domain
IPAddress server( 1,2,3,4 );
// char server[] = "myemailserver.com";
int port = 110;

char subjectLine[] = "Arduino";
char userName[] = "myuser";
char passWord[] = "mypassword";

char rtnBuf[100];

void setup()
{
  delay(2000);
  
  Serial.begin(115200);
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  pinMode(6,OUTPUT);
  pinMode(8,OUTPUT);
  
  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println(F("WiFi shield not present")); 
    // don't continue:
    while(true);
  } 

  // check firmware version
  Serial.print(F("Firmware version: "));
  Serial.println(WiFi.firmwareVersion());
  
 // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) { 
    Serial.print(F("Attempting to connect to SSID: "));
    Serial.println(ssid);
    status = WiFi.begin(ssid,pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
   
  // you're connected now, so print out the data:
  Serial.print(F("You're connected to the network"));
  printCurrentNet();
  printWifiData();
  delay(2000);

  Serial.println(F("Ready. Press 'e' to receive."));
}

void loop()
{
  byte inChar;

  inChar = Serial.read();

  if(inChar == 'e')
  {
      if(getEmail()) Serial.println(F("Email received"));
      else Serial.println(F("Email failed"));
  }
}

byte getEmail()
{
  byte thisByte = 0;
  byte respCode;
  char rtnVal[64];
  int mailCount,mailSize;
  char tBuf[64];
  
  if(client.connect(server,port) == 1) {
    Serial.println(F("connected"));
  } else {
    Serial.println(F("connection failed"));
    return 0;
  }

  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  Serial.println(F("Sending User"));
  strcpy_P(tBuf,PSTR("USER "));  
  strcat(tBuf,userName);
  strcat_P(tBuf,PSTR("\r\n"));  
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);
  
  Serial.println(F("Sending Password"));
  strcpy_P(tBuf,PSTR("PASS "));  
  strcat(tBuf,passWord);
  strcat_P(tBuf,PSTR("\r\n"));  
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  Serial.println(F("Sending STAT"));
  strcpy_P(tBuf,PSTR("STAT\r\n"));  
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  sscanf(rtnBuf,"%s %u %u",rtnVal,&mailCount,&mailSize);
  Serial.print(F("mail count: "));
  Serial.println(mailCount);

  for(int i = 1;i<=mailCount;i++) {
    strcpy_P(tBuf,PSTR("RETR "));  
    itoa(i,rtnBuf,10);
    strcat(tBuf,rtnBuf);
    strcat(tBuf,"\r\n");
    client.write(tBuf);
    if(ePrint() == 2) {
      strcpy(tBuf,"DELE ");       
      itoa(i,rtnBuf,10);
      strcat(tBuf,rtnBuf);
      strcat(tBuf,"\r\n");
      client.write(tBuf);

      if(!eRcv) Serial.println("Not deleted");
      else Serial.println("Deleted");
    }
      
    Serial.println(F("\r\nEND"));
  }

  Serial.println(F("Sending QUIT"));
  strcpy_P(tBuf,PSTR("QUIT\r\n"));  
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  client.stop();

  Serial.println(F("disconnected"));

  return 1;
}



byte eRcv()
{
  byte respCode;
  byte thisByte;
  int loopCount = 0;
  byte rtnCount = 0;
  
  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return 0;
    }
  }

  while(client.available())
  {  
    thisByte = client.read();    
//    Serial.write(thisByte);
    if(rtnCount < 99) {
      rtnBuf[rtnCount]=thisByte;
      rtnCount++;
      rtnBuf[rtnCount]=0;
    }
  }

  if(rtnBuf[0] == '-') return 0;
  
  return 1;
}

byte ePrint()
{
  byte respCode;
  byte thisByte;
  int loopCount = 0;
  byte rtnCount = 0;
  byte lineLength = 0;
  bool endMsg = false;
  bool msgBody = false;
  bool forArduino = false;
  char lineBuf[64];
  byte pinNo;
  char pinState[8];
  
  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return 0;
    }
  }

  while(!endMsg) {
    while(client.available())
    {  
      thisByte = client.read();    

      // if it is for the Arduino and past the header
      if(forArduino && msgBody) Serial.write(thisByte);

      if(thisByte == '\n') {
        // end of line        
        if(strlen(lineBuf) == 0) {
          if(!msgBody) Serial.println("Message body");
          msgBody = true;
        }
        if(strcmp(lineBuf,".") == 0) {
          // end of message
          endMsg = true;
        }
        if(!msgBody && (strncmp(lineBuf,"From:",5) == 0)) {
          // from
          Serial.println(lineBuf);
        }
        if(!msgBody && (strncmp(lineBuf,"Subject:",8) == 0)) {
          // subject
          Serial.println(lineBuf);
          if(strcmp(&lineBuf[9],subjectLine) == 0) {
            Serial.println("For my Arduino!");
            forArduino= true;
          }
        }

        if(msgBody && strncmp(lineBuf,"command ",8) == 0) {
          Serial.print("Command! D");          
          sscanf(lineBuf,"%*s %u %s",&pinNo,pinState);
          Serial.print(pinNo);
          Serial.print(" ");
          Serial.println(pinState);
          
          if(strcmp(pinState,"on") == 0) digitalWrite(pinNo,HIGH);          
          if(strcmp(pinState,"off") == 0) digitalWrite(pinNo,LOW);          
        }
        
        lineLength = 0;
        lineBuf[0] = 0;
      }
      else if(thisByte != '\r') {
        // another character
        if(lineLength < 63) {
          lineBuf[lineLength] = thisByte;
          lineLength++;
          lineBuf[lineLength] = 0;
        }
        
      }
    }
  }

  if(forArduino) return 2;
  return 1;
}

void efail()
{
  byte thisByte = 0;
  int loopCount = 0;

  client.println("QUIT");

  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return;
    }
  }

  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);
  }

  client.stop();

  Serial.println(F("disconnected"));
}

void printCurrentNet() {
  // print the SSID of the network you're attached to:
  Serial.print(F("SSID: "));
  Serial.println(WiFi.SSID());

  // print the MAC address of the router you're attached to:
  byte bssid[6];
  WiFi.BSSID(bssid);    
  Serial.print(F("BSSID: "));
  Serial.print(bssid[5],HEX);
  Serial.print(F(":"));
  Serial.print(bssid[4],HEX);
  Serial.print(F(":"));
  Serial.print(bssid[3],HEX);
  Serial.print(F(":"));
  Serial.print(bssid[2],HEX);
  Serial.print(F(":"));
  Serial.print(bssid[1],HEX);
  Serial.print(F(":"));
  Serial.println(bssid[0],HEX);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print(F("signal strength (RSSI):"));
  Serial.println(rssi);

  // print the encryption type:
  byte encryption = WiFi.encryptionType();
  Serial.print(F("Encryption Type:"));
  Serial.println(encryption,HEX);
}

void printWifiData() {
  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
    Serial.print(F("IP Address: "));
  Serial.println(ip);
  Serial.println(ip);
  
  // print your MAC address:
  byte mac[6];  
  WiFi.macAddress(mac);
  Serial.print(F("MAC address: "));
  Serial.print(mac[5],HEX);
  Serial.print(F(":"));
  Serial.print(mac[4],HEX);
  Serial.print(F(":"));
  Serial.print(mac[3],HEX);
  Serial.print(F(":"));
  Serial.print(mac[2],HEX);
  Serial.print(F(":"));
  Serial.print(mac[1],HEX);
  Serial.print(F(":"));
  Serial.println(mac[0],HEX);
  
  // print your subnet mask:
  IPAddress subnet = WiFi.subnetMask();
  Serial.print(F("NetMask: "));
  Serial.println(subnet);

  // print your gateway address:
  IPAddress gateway = WiFi.gatewayIP();
  Serial.print(F("Gateway: "));
  Serial.println(gateway);
}

Here is a universal code that will work with WiFi or Ethernet. Will you take a look at it and make sure everything is set up correctly?

#include <SPI.h>
/*=======Ethernet Shield only======
//#include <Ethernet.h>
*///==========Ethernet Shield End==
//====WiFi shield only====
#include <SPI.h>
#include <WiFi.h>
char ssid[] = "name";    //  your network SSID (name)
char pass[] = "password";   //  your network Password
int status = WL_IDLE_STATUS;
IPAddress ip(1,1,1,1);      // change to match your settings. 
IPAddress gateway(1,1,1,1); // change to match your settings. 
IPAddress subnet(1,1,1,1);// change to match your settings. 
unsigned int localPort = 8888;
//  ======WiFi shield End========
/*========Ethernet Shield only========
// this must be unique on your localnet
//byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
*///=====Ethernet Shield End=====
// change server to your email server ip or domain
//IPAddress server( 1,2,3,4 );
// char server[] = "myemailserver.com";
char server[] = "pop.earthlink.net"; // change to the email server that you use.
int port = 110;

// change to plain text user and password
char userName[] = "myusername"; // for email account
char passWord[] = "mypassword"; // for email account
//  ====WiFi shield Only=====
WiFiClient client;
//  ======WiFi shield End======
/* ======Ethernet shield Only=====
WiFiClient client;
*///  =====Ethernet shield End=======
char rtnBuf[100];

void setup()
{
  delay(2000);
  Serial.begin(115200);
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);
//  =====WiFi shield Only====
  WiFi.config(ip,gateway,gateway,subnet);
  while(!WiFi.status()==WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    while(true);
  }
  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if ( fv != "1.1.0" )
    Serial.println("Please upgrade the firmware");

  // attempt to connect to Wifi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
    
  }
  Serial.println("Connected to wifi");
  printWifiStatus();

  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.println();
  }
  //  =======WiFi shield End=======
  /*  ====Ethernet shield Only====
  //  Ethernet.begin(mac, ip, gateway, gateway, subnet);

  while(!Ethernet.begin(mac)) {
    Serial.println("DHCP failed. Retry in 5 seconds");
    delay(5000);
  }

  Serial.println(Ethernet.localIP());
  *///  ====Ethernet shield Only====
  
  delay(2000);
  Serial.println(F("Ready. Press 'e' to check email."));
}


//  =====WiFi shield Only=====
void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}
//  =====WiFi shield End======


void loop()
{
  byte inChar;

  inChar = Serial.read();

  if(inChar == 'e')
  {
      if(getEmail()) Serial.println(F("Email retrieved"));
      else Serial.println(F("Email failed"));
  }
  //  ======WiFi shield Only=====
while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting from server.");
    client.stop();

    // do nothing forevermore:
    while (true);
  }
  // ======WiFi shield End=====
  /*  =====Ethernet shield Only=====
  Ethernet.maintain();
  *///  =====Ethernet shield End=====
  // if the server's disconnected, stop the client:
  
}

byte getEmail()
{
  byte thisByte = 0;
  byte respCode;
  char rtnVal[64];
  int mailCount,mailSize;
  char tBuf[64];
 
  if(client.connect(server,port) == 1) {
    Serial.println(F("connected"));
  } else {
    Serial.println(F("connection failed"));
    return 0;
  }

  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  Serial.println(F("Sending User"));
  strcpy_P(tBuf,PSTR("USER "));
  strcat(tBuf,userName);
  strcat_P(tBuf,PSTR("\r\n"));
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);
 
  Serial.print(F("Sending Password "));
  strcpy_P(tBuf,PSTR("PASS "));
  strcat(tBuf,passWord);
  strcat_P(tBuf,PSTR("\r\n"));

  Serial.println(tBuf);
 
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  Serial.println(F("Sending STAT"));
  strcpy_P(tBuf,PSTR("STAT\r\n"));
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  sscanf(rtnBuf,"%s %u %u",rtnVal,&mailCount,&mailSize);
  Serial.print("mail count: ");
  Serial.println(mailCount);

  for(int i = 1;i<=mailCount;i++) {
    strcpy_P(tBuf,PSTR("RETR "));
    itoa(i,rtnBuf,10);
    strcat(tBuf,rtnBuf);
    strcat(tBuf,"\r\n");
    client.write(tBuf);
    ePrint();       
    Serial.println("\r\nEND");
  }

  Serial.println(F("Sending QUIT"));
  strcpy_P(tBuf,PSTR("QUIT\r\n"));
  client.write(tBuf);
  if(!eRcv()) return 0;
  Serial.println(rtnBuf);

  client.stop();

  Serial.println(F("disconnected"));

  return 1;
}



byte eRcv()
{
  byte respCode;
  byte thisByte;
  int loopCount = 0;
  byte rtnCount = 0;
 
  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return 0;
    }
  }

  while(client.available())
  {
    thisByte = client.read();   
//    Serial.write(thisByte);
    if(rtnCount < 99) {
      rtnBuf[rtnCount]=thisByte;
      rtnCount++;
      rtnBuf[rtnCount]=0;
    }
  }

  if(rtnBuf[0] == '-') return 0;
 
  return 1;
}

byte ePrint()
{
  byte respCode;
  byte thisByte;
  int loopCount = 0;
  byte rtnCount = 0;
 
  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return 0;
    }
  }

  byte lineLength = 0;
  bool endMsg = false;
  bool msgBody = false;
  char lineBuf[64];
 
  while(!endMsg) {
    while(client.available())
    {
      thisByte = client.read();   

      if(thisByte == '\n') {
        // end of line       
        if(strlen(lineBuf) == 0) {
          if(!msgBody) Serial.println("Message body");
          msgBody = true;
        }
        if(strcmp(lineBuf,".") == 0) {
          // end of message
          endMsg = true;
        }
        if(!msgBody && (strncmp(lineBuf,"From:",5) == 0)) {
          // from
          Serial.println(lineBuf);
        }
        if(!msgBody && (strncmp(lineBuf,"Subject:",8) == 0)) {
          // subject
          Serial.println(lineBuf);
          if(strncmp(&lineBuf[9],"Arduino",7) == 0) Serial.println(F("For my Arduino!"));
        }
        lineLength = 0;
        lineBuf[0] = 0;
      }
      else if(thisByte != '\r') {
        // another character
        if(lineLength < 63) {
          lineBuf[lineLength] = thisByte;
          lineLength++;
          lineBuf[lineLength] = 0;
        }
       
      }
    }
  }
  return 1;
}


void efail()
{
  byte thisByte = 0;
  int loopCount = 0;

  client.println("QUIT");

  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return;
    }
  }

  while(client.available())
  {
    thisByte = client.read();   
    Serial.write(thisByte);
  }

  client.stop();

  Serial.println(F("disconnected"));
}

Let me know if you are interested in the sd card cloud storage idea and I will get started on my end.

It's up to you how you combine the wifi and ethernet sketches. I prefer to keep them separate. I'll post them on the playground that way.

Have you tested it yet?

I prefer to keep them separate.

After reading the code I wrote, I agree. It's much cleaner to have them separate.

Have you tested it yet?

No, I called my mentor and he was ok with letting me come over to use his earthlink email account to try it... until i mentioned I might have to set up his account to allow that function. Then he wasn't ok with the idea. Old people are so afraid you'll mess something up that can't be fixed.

I found this link that suggest there might be a way to do it using gmail. Use gmail’s smtp server without SSL I'm reading the links now trying to figure it out. Everyone has free access to gmail, this would make the code usable for everyone without requiring a special email that charges to use.

You can't use Gmail's SMTP or POP3 email server without TLS or SSL. You can send to gmail addresses using port 25, but only if you have a commercial static IP. Otherwise, you may get rejected.

I tried the POP3 server at gmail. No luck. :frowning:

I tried the POP3 server at Yahoo. No luck. :frowning:

I found this article that talks about starttls, though I have no idea what that is yet. email - Using SMTP, Gmail, and STARTTLS - Stack Overflow

What service do you use? Is it free? Is there a way to host a non TLS or SSL email account using wordpress and a domain name?

What are your thoughts about the sd card cloud storage?

I use my own email server using Linux, Sendmail, and IMAP, so it is free in a way. Not exactly for the beginner tho.

I'm not thinking about SD card cloud storage.

Not exactly for the beginner tho.

I think it's pretty important for a beginner to be able to figure this out. Otherwise we may have to look into sending a website link that allows the user to click on the link and make changes using a web address. Last time I looked into that it I seem to remember that even that required the user having a commercial static IP set up though. - We need solutions.

What is the easiest free way to teach a beginner how to control an arduino using the internet, not requiring the user to be connected to the same internet modem that the arduino is connected to?

I think it's pretty important for a beginner to be able to figure this out.

I disagree. The ethernet and wifi shields are not devices for the beginner, nor are any of the protocols they use.

I'm still looking for someone to verify this works with their POP3 server. This will NOT WORK with Gmail, Yahoo (Hotmail), Outlook (live.com), or Verizon. All require TLS or SSL.

It should work with Earthlink and Cox Communications servers, but I would like confirmation.

edit: It does work with the free POP3 account at Inbox.com. You must activate POP3 and access to your spam folder.

Added ethernet example sketch to playground.
http://playground.arduino.cc/Code/POP3Email