Emailing from the Arduino

I’ve been playing around with sending emails from the arduino (see post “Ethernet DNS and the Client”).
I do believe the road blocks are simply the IP address (or DNS) issues graciously provided by my ISP.
So i’ve given up on that and gone back to what I know works.
Enter PHP.
I have my arduino, with ethernet sheild, hit a PHP script on my server and the PHP actually does the sending. The Arduino sends in parameters including who the email is to and it works like a charm - - but only as long as the client.connect command is in the Setup of the sketch.
As soon as I move it into the loop, even if I put a trigger test around it so that it only fires on demand and not every time through the loop, I can’t for the life of me make this work.

What’s different? I tried putting delays in thinking that perhaps the setup code fires at a slower rate and the code in the loop was just whizzing by in the time it takes the connection to happen. (yes, a hail Mary gambit but…)

The code is literally identical, save for the connection command grouping being moved to the loop. I have the serial monitor feeding back where code is at and the connection command is truly being fired.

See both version attached

Works:

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

// mac address for arduino
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
//local static address
IPAddress ip(192, 168, 0, 19);


EthernetClient client;

int incomingByte = 0; //this holds my serial input that acts as the send trigger


void setup() {


  Serial.begin(9600);
   while (!Serial) {
    ; 
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Ethernet using DHCP failed");
//use static IP
    Ethernet.begin(mac, ip);
  }

  delay(1000);
  Serial.println("connecting...");



  char server[] = "www.myServer.com";
  if (client.connect(server, 80)) 
  {
    Serial.println("connected");

    // Make a HTTP request:
    client.println("GET /subfolder/sendEmail.php?to=someperson@address.com&from=otherperson@address.com&subject=subject&msg=Message HTTP/1.1");
    client.println("Host: www.myServer.com");
    client.println("Connection: close");
    client.println();
    
  } 
  else 
  {

    // mail connection failed
    Serial.println("connection failed");
   
  }
 
}

void loop()
{
        if (Serial.available() > 0) {
                // read the incoming byte:
                incomingByte = Serial.read();
                if(incomingByte==99) {
                  Serial.println("SerialSuccessful");
                }
        }
}

Doesnt Work

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

//Set the address of the arduino
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };


// Set the local static IP address to use if the DHCP fails to assign
IPAddress ip(192,168,0,19);

// Initialize the Ethernet client library

EthernetClient client;

int incomingByte = 0; //this holds my serial input that acts as the send trigger

void setup() {

 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Ethernet using DHCP failed");
// use static IP instead
    Ethernet.begin(mac, ip);
  }
  delay(1000);
  Serial.println("connecting...");
 
}


void loop()
{
        if (Serial.available() > 0) {
                // read the incoming byte:
                incomingByte = Serial.read();
                if(incomingByte==99) {
                  Serial.println("SerialSuccessful");
delay(1000); //hail mary delay
char server[] = "http://www.myServer.com";
    if (client.connect(server, 80)) {
    Serial.println("connected");
     
    // Make a HTTP request:
     client.println("GET /subfolder/sendEmail.php?to=someperson@address.com&from=otehrperson@address.com&subject=subject&msg=Message HTTP/1.1");
   delay(1000);
    client.println("Host: www.myServer.com");
    client.println("Connection: close");
    client.println();
// I never hear back from this email attempt -  Serial mon shows the code is being run
  } 
  else {
 
    // if no connection to server
    Serial.println("connection failed");
 
  }

  }
    
      }

   

   
  }

I don't know about the rest, but this won't work with the protocol. Remove the "http://" part.

// change this
char server[] = "http://www.myServer.com";
// to this
char server[] = "www.myServer.com";

edit: and change the evaluation of the connect function. The only success return value is 1. A negative number will be returned if the dns resolution fails, and will evaluate to true.

// change this
    if (client.connect(server, 80))
// to this
    if (client.connect(server, 80) == 1)

Thanks Tim, ironically we had the http removed the first couple of times of no joy in both cases and added it in as desperate lark and low and behold the one with the setup connection worked.

My bad on that one - a poor copy and paste job. The HTTP is in both sketches of my originals - it fell out when i was retyping the urls to remove our actual server address.

To be clear, the changes you suggest, are they loop specific? I ask because the code works perfectly when in the set up.

I'll make these changes regardless and report back.

It should work in setup or loop. Does your code show "connection failed" or "connected" when it is attempting the connection? If you don't change the evaluation of the connect function as I posted above, it will show "connected" if the dns resolution fails.

Solved, thanks Tim,

Looking back through the versions of the code, it looks like we started with the connection command in the set up, couldn't get that to work and in flailing added in the HTTP://. That solved the problem.
Then we moved the connection code to the loop and the frowns appeared. (but we kept the HTTP because, hey, it solved our initial issue)

So now I have one version with the connection in the setup using HTTP and that works great. I also now have a version with the connection in the loop with no HTTP and that works great.
That's very odd that there would differing results (same arduino and shield BTW)

As for the truth test of the connection, it's been fine the way it was (and it's a pretty standard statement when we do this sort of thing, so its worked that way for years with 5100 shields) but I can see your point and will add it in. But it did given me an idea for problem we were having with a 5200 shield. I'll bet if I include your suggestion we can get that solved too.

Thanks again.

It always shows "connected". So we knew the connection code had fired but waited in vain for the email (with the version where the connection was in the loop).

The connection code may have fired, but with an invalid IP address because the dns resolution failed. The "http://" will normally cause the dns resolution to fail and return -5. That will evaluate to true and give you a "connected" message, but is not actually connected to your server, and you will never receive an email.

You must use the evaluation I suggested above, or you will show "connected" when the dns resolution fails and the send function calls will not work. I know. I tested it. Only the return value of 1 is a successful connection. A return value of -5 (also evaluates to true) is not a successful connection, and any send attempts will fail.

Gotcha. That explains the problem we were having with a 5200 shield. Even with a bogus URL, we were getting a connected thumbs up.
I guess because it's our server we always talk to and (until now) using 5100 boards, we've never run into a failed connection so when the code is right we've always had a fine time without the explicit test of "1".

But I see your point and it is better form.

Just out of curiosity, is -5 the non connection response? or are there levels of severity? I would have thought a non connection would have returned a null value or a 0, or at the very wildest a -1.

There are different levels of dns fail, anything from -1 to -10. A -5 is "server dns not found". If the domain dns resolution is successful, and the connect function does not find the server at the resolved IP, it will return 0.

I tried your code with the www.myServer.com domain as the server, and it shows "connected" here, even tho I know it fails. When I changed the return value check of 1 only, it shows "connection failed".

Thanks for that. I was just expecting a simple boolean response to the query. And I hadn't thought to test with an obviously wrong connection to see what we get. Good idea that.

Cheers