Ethernet Email Attachment

Hi,
I am attempting to send an email containing an attachment with an ethernet shield.
I can send an email no problem, thanks to SurferTim, but I am having an issue with the attachment.
I have tried several ways and read many posts.
However, I cannot find a complete solution.
I can get a blank file to send and a file with canned text in it to send, but not the file on the SD Card.
Any assistance would be greatly appreciated.

The code I use is below. I removed the email addresses, passwords, etc.

/*
   Email client sketch for IDE v1.0.5 and w5100/w5200
   Posted 7 May 2015 by SurferTim
   Encoding Routines by Razorblade
   https://www.base64encode.org/ Encoder Site 
   http://forum.arduino.cc/index.php?topic=296897.0 SurferTim's Addition Thread
   http://forum.arduino.cc/index.php?topic=67701.30 Encoding Thread

*/
#include <SD.h>
#include <SPI.h>
#include <EthernetV2_0.h> //Library for SEEED Ethernet Sheild Version 2.0

#define W5200_CS  10 //Denotes Pin 10 as W5200 Pin
#define SDCARD_CS 4  //Denotes Pin 4 as SD Card Pin

File SendFile;
 
static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

//Mac must be unique
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
//Change network settings to yours**************************
IPAddress ip( 0, 0, 0, 0 );    
IPAddress gateway( 0, 0, 0, 0 );
IPAddress subnet( 0, 0, 0, 0 );

char server[] = "mail.smtp2go.com";
int port = 80;
EthernetClient client;

void setup()
{
  Serial.begin(115200);
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  delay(2000);
//Initialize SD Card
  Serial.print("Initializing SD card...");
  pinMode(W5200_CS, OUTPUT);
  digitalWrite(W5200_CS,HIGH);
  pinMode(SDCARD_CS,OUTPUT);
  if (!SD.begin(SDCARD_CS)) {
    Serial.println("Initialization Failed!");
    return;
  }
  Serial.println("Initialization Successful");
  Serial.println(F("Ready. Press 'e' to send."));
}

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 authorizes login"));
  client.println("auth login");
  if(!eRcv()) return 0;

  Serial.println(F("Sending User"));
//Change to your base64 encoded user**************************
  client.println("MyUserName");
  if(!eRcv()) return 0;

  Serial.println(F("Sending Password"));
//change to your base64 encoded password**************************
  client.println("MyPassword");
  if(!eRcv()) return 0;

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

//change to recipient address**************************
  Serial.println(F("Sending To"));
  client.println("RCPT To: <Reciever@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 <Reciever@gmail.com>");

//change to your address**************************
  client.println("From: Me <Sender@gmail.com>");
  client.write("Subject: Arduino email test");



//****************************************************
//Start of Attach File
  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 from my Arduino!\r\n");
  client.write("--frontier\r\n");
  client.write("Content-Type: text/plain\r\n");
  
//This is where you would send your file
  SendFile =SD.open("test.txt",FILE_READ);
  client.print("Content-Type: text/plain; name=\"test.txt\"\r\n");
  client.print("Content-Transfer-Encoding: base64\r\n");
  client.write("Content-Disposition: attachment; filename=\"test.txt\"\r\n\r\n");
  client.write("\r\n--frontier--\r\n");
  encode();
  SendFile.close();
//End of Attach File
//****************************************************



  client.write(".\r\n");
  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("isconnected"));
}

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

Below is what I get in the Serial Monitor

Initializing SD card...Initialization Successful
Ready. Press 'e' to send.
Connected
220 mail.smtp2go.com ESMTP Exim 4.85 Thu, 05 Nov 2015 08:15:19 +0000
Sending Hello
250-mail.smtp2go.com Hello 1.2.3.4 [1.2.3.4]
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-AUTH CRAM-MD5 PLAIN LOGIN
250-STARTTLS
250 HELP
Sending authorizes login
334 VXNlcm5hbWU6
Sending User
334 UGFzc3dvcmQ6
Sending Password
235 Authentication succeeded
Sending From
250 OK
Sending To
250 Accepted <Reciever@gmail.com>
Sending DATA
354 Enter message, ending with "." on a line by itself
Sending email
250 OK id=1ZuFhY-NRKL38-Jx
Sending QUIT
221 mail.smtp2go.com closing connection
disconnected
Email Sent

Thanks

but I am having an issue with the attachment.

And the issue is?

I can get a blank file to send and a file with canned text in it to send, but not the file on the SD Card.

The file you have contains?
The data that is sent is?
The e-mail that is received contains?

Inquiring minds want to know.

Hi PaulS,

Quote

but I am having an issue with the attachment.

And the issue is?

The issue with the attachment that I am having is that I cannot get the program to send the file located on my SD card.
It seems that the program is creating a file and attaching it.

The file you have contains?
The data that is sent is?
The e-mail that is received contains?

The file that I have on my SD card contains:

testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
testing 1, 2, 3.
11-4--15

The Data that is sent is a text file that contains nothing.
When opened it is a gray screen with the words testing.txt in italics.
or I can get it to contain:

Content-Transfer-Encoding: base64
Content-Type: text/plain; name="test.txt"

The email that I receive contains an attachment named text.txt

I have tried about 30 different modifications to the attachment section with no success.

When opened it is a gray screen with the words testing.txt in italics.

If you right click, and select view source (if you have that option), what do you see?

I don't understand why you need to encode the text.

I do not have the ability to view the source.
As for the encoding, I was just following what I could find on the forum etc.

I have successfully got it working for text files.
Below is the full code I am using.
I will try to send multiple attachments and other items like csv files and images.
Any items that work I will post on this thread.

/*
   Email client sketch for IDE v1.0.5 and w5100/w5200
   Posted 7 May 2015 by SurferTim
   Encoding Routines by Razorblade
   https://www.base64encode.org/ Encoder Site
   http://forum.arduino.cc/index.php?topic=296897.0 SurferTim's Addition Thread
   http://forum.arduino.cc/index.php?topic=67701.30 Encoding Thread by Razorblade

*/
#include <SD.h>
#include <SPI.h>
#include <EthernetV2_0.h> //Library for SEEED Ethernet Sheild Version 2.0

#define W5200_CS  10 //Denotes Pin 10 as W5200 Pin
#define SDCARD_CS 4  //Denotes Pin 4 as SD Card Pin

File SendFile;
 
static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

//Mac must be unique
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
//Change network settings to yours**************************
IPAddress ip( 0, 0, 0, 0 );   
IPAddress gateway( 0, 0, 0, 0 );
IPAddress subnet( 0, 0, 0, 0 );

char server[] = "mail.smtp2go.com";
int port = 80;
EthernetClient client;

void setup()
{
  Serial.begin(115200);
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  delay(2000);
//Initialize SD Card
  Serial.print("Initializing SD card...");
  pinMode(W5200_CS, OUTPUT);
  digitalWrite(W5200_CS,HIGH);
  pinMode(SDCARD_CS,OUTPUT);
  if (!SD.begin(SDCARD_CS)) {
    Serial.println("Initialization Failed!");
    return;
  }
  Serial.println("Initialization Successful");
  Serial.println(F("Ready. Press 'e' to send."));
}

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 authorizes login"));
  client.println("auth login");
  if(!eRcv()) return 0;

  Serial.println(F("Sending User"));
//Change to your base64 encoded user**************************
  client.println("MyUserName");
  if(!eRcv()) return 0;

  Serial.println(F("Sending Password"));
//change to your base64 encoded password**************************
  client.println("MyPassword");
  if(!eRcv()) return 0;

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

//change to recipient address**************************
  Serial.println(F("Sending To"));
  client.println("RCPT To: <Reciever@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 <Reciever@gmail.com>");

//change to your address**************************
  client.println("From: Me <Sender@gmail.com>");
  client.write("Subject: Arduino email test");
  
//****************************************************
//Start of Attach File
  SendFile =SD.open("test.txt",FILE_READ);
  client.print("Content-Type: text/txt; name=\"test.txt\"\r\n");
  client.write("Content-Disposition: attachment; filename=test.txt\r\n");
  client.print("Content-Transfer-Encoding: base64\r\n\r\n");
  encode();
  SendFile.close();
//End of Attach File
//****************************************************
  client.print("\r\n.\r\nQUIT\n");
  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("isconnected"));
}

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

Image Files:

  SendFile =SD.open("image.jpg",FILE_READ);
  client.print("Content-Type: image/jpg; name=\"image.jpg\"\r\n");
  client.write("Content-Disposition: attachment; filename=image.jpg\r\n");
  client.print("Content-Transfer-Encoding: base64\r\n\r\n");
  encode();
  SendFile.close();

CSV Files:

  SendFile =SD.open("data.csv",FILE_READ);
  client.print("Content-Type: application/csv; name=\"data.csv\"\r\n");
  client.write("Content-Disposition: attachment; filename=data.csv\r\n");
  client.print("Content-Transfer-Encoding: base64\r\n\r\n");
  encode();
  SendFile.close();