Email a file from SD card using ethernet shield

Hello all experts.

I am working on a project where I need to get a file from the SD card and email that file to some email address.
The file can be *.txt or *.xls

I have UNO and MEGA boards.

I have seen examples of sending preset mails when certain condition is met.
But, Is this possible to do so?

Please suggest.

Thanks to all.

Regards,
Krunal

Do you want to send the file? Or the contents of the file? Different processes, depending on what you want to do.

What is the Arduino doing with xls files on the SD card? They are meaningless to it.

Hi PaulS,
Thanks for the reply.

Actually its a datalogger project. I am planning to save the read values to the SD card either in txt or xls file.
I thought it would be possible to use xls file also.

I am planning to send the whole file and not only the data in that file.

Thanks again for your help.

I am planning to save the read values to the SD card either in txt or xls file.

Let me know where you find the Excel for Arduino application.

A csv file that Excel can import, sure. An xls file? Not a chance.

I am planning to send the whole file and not only the data in that file.

It's just a matter of structuring the data in the e-mail properly. I'd learn how to do that from a PC first.

Yes, Thanks for correcting me, By xls I wanted to say csv. But could not recollect the actual name for it.

I got some link from this topic...
https://forum.arduino.cc/index.php?topic=67701.15

I am going to check it tomorrow.

It seems that #18 reply from RazorBlade, should help me.
But only I am not getting in this code is what I have to actually put in the following line of code instead of "\nxxxxxxxxxxx"

Can you please suggest.

client.print("HELO\nAUTH PLAIN\nxxxxxxxxxxxxxxxxxxxxxx\r\n"); // x: base64 encoded login: \0foo@yahoo.com\0password

But only I am not getting in this code is what I have to actually put in the following line of code instead of "\nxxxxxxxxxxx"

Can you please suggest.

Sure. I suggest that you read the comment.

PaulS:
Sure. I suggest that you read the comment.

Thanks Paul for your suggestion.

From last few days, my gmail is receiving updates from Arduino google developers page on "Status of Ethernet Library" and I am reading them all very seriously as I have also faced these problems. I appreciate all your and others work on the matter. Thanks for giving us the Arduino and for your contribution.

BTW, I will test it today and will let you know.

Regards,
Krunal

Can you send email successfully without an attachment?

Hello SurferTim,

I had tough times for sending just email. I have read all your work and finally as per your tutorials, I used SMTP2GO to send emails successfully.

Thanks for your tutorial series and replies to others threads on the forum on sending emails.

Now Can you please tell me how should I add attachments in this mail.
I just want to send .txt file.

This is my working Code:
(quote tags changed to code tags by moderator - please use the </> button next time).

/*
 Email client sketch for IDE v1.0.5 and w5100/w5200
 Posted 7 May 2015 by SurferTim
*/



#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 );

char server[] = "mail.smtp2go.com";
int port = 2525;

EthernetClient client;

void setup()
{
Serial.begin(115200);
pinMode(4,OUTPUT);
digitalWrite(4,HIGH);
Ethernet.begin(mac);//, ip, gateway, gateway, subnet); 
delay(2000);
Serial.println(F("Ready. Press 'e' to send."));
Serial.println(Ethernet.localIP());
}

void loop()
{
byte inChar;

inChar = Serial.read();

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

byte sendEmail()
{
byte thisByte = 0;
byte respCode;

if(client.connect(server,port) == 1) {
  Serial.println(F("connected"));
} else {
  Serial.println(F("connection failed"));
  return 0;
}

if(!eRcv()) return 0;

Serial.println(F("Sending hello"));
// replace 1.2.3.4 with your Arduino's ip
client.println("EHLO 1.2.3.4");  
if(!eRcv()) return 0;

Serial.println(F("Sending auth login"));
client.println("auth login");
if(!eRcv()) return 0;

Serial.println(F("Sending User"));
// Change to your base64 encoded user
client.println("64Base encode MyLogin"); 

if(!eRcv()) return 0;

Serial.println(F("Sending Password"));
// change to your base64 encoded password
client.println("64Base encode MyPassword"); 


if(!eRcv()) return 0;

// change to your email address (sender)
Serial.println(F("Sending From"));
client.println("MAIL From: <xxx@gmail.com>");
if(!eRcv()) return 0;

// change to recipient address
Serial.println(F("Sending To"));
client.println("RCPT To: <yyy@gmail.com>");
if(!eRcv()) return 0;

Serial.println(F("Sending DATA"));
client.println("DATA");
if(!eRcv()) return 0;

Serial.println(F("Sending email"));

// change to recipient address
client.println("To: You <yyy@gmail.com>");

// change to your address
client.println("From: Me <xxx@gmail.com>");

client.println("Subject: Arduino email test\r\n");

client.println("This is from my Arduino!");

client.println(".");

if(!eRcv()) return 0;

Serial.println(F("Sending QUIT"));
client.println("QUIT");
if(!eRcv()) return 0;

client.stop();

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

return 1;
}

byte eRcv()
{
byte respCode;
byte thisByte;
int loopCount = 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;
  }
}

respCode = client.peek();

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

if(respCode >= '4')
{
  efail();
  return 0;  
}

return 1;
}


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

client.println(F("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"));
}

Thanking You in anticipation.
Regards,
BK Krunal

Here is the change I made to send an image with my email code. If you are sending a text file, you can change the Content-Type to text/plain and skip the encode call and just read from the file and send it.

  client.println("Subject: Arduino email image");

// this is new 
  client.write("MIME-Version: 1.0\r\n");
  client.write("Content-Type: Multipart/mixed; boundary=frontier\r\n\r\n");
 
  client.write("--frontier\r\n");
  client.write("Content-Type: text/plain\r\n\r\n");
 
  client.write("This is an image from my Arduino!\r\n");
  
  client.write("--frontier\r\n");
//  client.write("Content-Type: text/plain\r\n");
  client.write("Content-Type: image/jpeg\r\n");
  client.write("Content-Disposition: attachment; filename=testjpg.jpg\r\n");
  client.print("Content-Transfer-Encoding: base64\r\n\r\n");
// this is where you would send your file
  int clientCount = 0;

  myFile = SD.open("/img/waterfal.jpg");
  
  if(myFile) {
    encode();
    myFile.close();                  
  }
  else {
    Serial.println(F("File open failed"));
  }

//  client.write("This is a test\r\n"); 

  client.write("--frontier--\r\n");

// end of new

  client.println(".");
  if(!eRcv()) return 0;

Here is the encode function.

void encode() {
  unsigned char in[3],out[4];
  int i,len,blocksout=0;
  while (myFile.available()!=0) {
    len=0;
    for (i=0;i<3;i++){
      in[i]=(unsigned char) myFile.read();
      if (myFile.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||myFile.available()==0){
      if (blocksout) client.print("\r\n");  blocksout=0;
    }
  }
}

void encodeblock( byte *in, byte *out, int len )
{
    out[0] = (byte) b64Chars[ (in[0] >> 2) ];
    out[1] = (byte) b64Chars[ (in[0] & 0x03) << 4 | (in[1] & 0xf0) >> 4 ];
    out[2] = (byte) (len > 1 ? b64Chars[ (in[1] & 0x0f) << 2 | (in[2] & 0xc0) >> 6 ] : '=');
    out[3] = (byte) (len > 2 ? b64Chars[ (in[2] & 0x3f) ] : '=');
}

Hello SurferTim,

Thanks a lot for your help.

With your code, Now I can successfully add .txt attachment to my mails.

Out of curiosity, I also tried to send jpg file, But could not find the only function b64Chars.
Could you please suggest.

For those who would like to try sending txt file from SD card in email attachment, This is my working code.

/*
  Email client sketch for IDE v1.0.5 and w5100/w5200
  Posted 7 May 2015 by SurferTim
*/



#include <SPI.h>
#include <Ethernet.h>
#include <SD.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 );

char server[] = "mail.smtp2go.com";
int port = 2525;

File myFile;

 
EthernetClient client;

void setup()
{
 Serial.begin(115200);
 pinMode(4,OUTPUT);
 digitalWrite(4,HIGH);
 Ethernet.begin(mac);
 delay(2000);
 Serial.println(F("Ready. Press 'e' to send."));
 Serial.println(Ethernet.localIP());

 if (!SD.begin(4)) 
  {
   Serial.println("SD initialization failed!");
  }
  else 
  {
   Serial.println("SD initialization done.");
  }

  
 
}

void loop()
{
 byte inChar;

 inChar = Serial.read();
 
 if(inChar == 'e')
 {
     if(sendEmail()) Serial.println(F("Email sent"));
     else Serial.println(F("Email failed"));
 }
}


byte sendEmail()
{
 byte thisByte = 0;
 byte respCode;

 if(client.connect(server,port) == 1) {
   Serial.println(F("connected"));
 } else {
   Serial.println(F("connection failed"));
   return 0;
 }

 if(!eRcv()) return 0;

 Serial.println(F("Sending hello"));
// replace 1.2.3.4 with your Arduino's ip
 client.println("EHLO 1.2.3.4");  
 if(!eRcv()) return 0;

 Serial.println(F("Sending auth login"));
 client.println("auth login");
 if(!eRcv()) return 0;

 Serial.println(F("Sending User"));
// Change to your base64 encoded user
 client.println(F("Base64 encoded LoginID"));

 if(!eRcv()) return 0;

 Serial.println(F("Sending Password"));
// change to your base64 encoded password
 client.println(F("Base64 encoded password")); 


 if(!eRcv()) return 0;

// change to your email address (sender)
 Serial.println(F("Sending From"));
 client.println("MAIL From: <xxx@gmail.com>");
 if(!eRcv()) return 0;

// change to recipient address
 Serial.println(F("Sending To"));
 client.println("RCPT To: <yyy@yahoo.in>");
 if(!eRcv()) return 0;

 Serial.println(F("Sending DATA"));
 client.println("DATA");
 if(!eRcv()) return 0;

 Serial.println(F("Sending email"));

// change to recipient address
 client.println("To: You <yyy@yahoo.in>");

// change to your address
 client.println("From: ArduinoUNO <xxx@gmail.com>");

 client.println("Subject: Arduino email Text File"); //Arduino email test\r\n

 //client.println("This is from my Arduino!");


 client.write("MIME-Version: 1.0\r\n");
 client.write("Content-Type: Multipart/mixed; boundary=frontier\r\n\r\n");

 client.write("--frontier\r\n");
 client.write("Content-Type: text/plain\r\n\r\n");

 client.write("This is text file from my Arduino!\r\n");
 
 client.write("--frontier\r\n");
 client.write("Content-Type: text/plain\r\n");
//  client.write("Content-Type: image/jpeg\r\n");
 client.write("Content-Disposition: attachment; filename=test.txt\r\n");

// this is where you would send your file
 int clientCount = 0;



 myFile = SD.open("test.txt");  
 int myint;

 if(myFile) 
 {
   while (myFile.available()) 
   {
     myint = myFile.read();
     client.write(myint);
     Serial.write(myint);
   }
   client.print("\r\n");
   myFile.close();
             
 }
 else {
   Serial.println(F("File open failed"));
 }

 

//  client.write("This is a test\r\n"); 

 client.write("--frontier--\r\n");




 client.println(".");

 if(!eRcv()) return 0;

 Serial.println(F("Sending QUIT"));
 client.println("QUIT");
 if(!eRcv()) return 0;

 client.stop();

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

 return 1;
}

byte eRcv()
{
 byte respCode;
 byte thisByte;
 int loopCount = 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;
   }
 }

 respCode = client.peek();

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

 if(respCode >= '4')
 {
   efail();
   return 0;  
 }

 return 1;
}


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

 client.println(F("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"));
}

b64Chars is an array of text characters.

char b64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

Hello , I am also working on the same project .
I got the last code to send txt file as attachment in email.
But I was confused about how can I find what is my Arduino/ Ethernet's

  1. byte mac()
  2. IP Adress ip
  3. IP Adress gateway
  4. IP Adress subnet