1

I have asked this question on the arduino forum as well.

I have used SMTP before using client.print (and client.println) but I am now trying to move as much text as I can from RAM to SD (and so I need the <SD.h> library). It does not work and I am thinking it may be because the SMTP server "dies of boredom" as it waits for my Arduino to read from the SD card and write it to the client (server?). In the code below, I have included what I am trying (it will be uncommented if you copy+paste the code) and what already works (which will be commented when you copy+paste the code, but you can uncomment and comment the other section relatively easily). The text file I have on the SD in the code (commented). If anyone can think of a workaround, that would be great.

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

//-v--- Ethernet -----------
byte MyMac[] = {0xFE, 0xED, 0xBE, 0xEF, 0xFE, 0xED}; // <- The physical address of the machine's network card. Should be unique (no two network cards have the same MAC address)
byte MyIp[] = {1, 1, 1, 1}; // <- This is the not the real IP address, but for the real address I have verified that the static IP works for sending mail
byte Dns[] = {1, 1, 1, 1}; // <- Not the real DNS but I got it once through Serial.println(Ethernet.dnsServerIP()); and I know that it works
byte Gateway[] = {1, 1, 1, 1}; //<- Not real
byte Subnet[] = {1, 1, 1, 1}; //<- Not Real

EthernetClient client ;
//-^--- Ethernet -----------

//-v-- Smtp --------
char ServerChar[] = "blahblah";
//-^-- Smtp --------

//-v--- SD ------
File theFile; String line;
//-^--- SD ------

void setup() {
  Ethernet.begin(MyMac, MyIp, Dns, Gateway, Subnet);
  SD.begin(4);
  bool test = TrySend();
}

void loop() {
  // put your main code here, to run repeatedly:
 
}

bool TrySend(){
 
  //*-v---- What I am trying ---
  bool SuccessOrNot;
 
  if(client.connect(ServerChar, 25)){
    SuccessOrNot = true;
    theFile = SD.open("Smtp.txt");   //Smtp.txt is listed toward the bottom of the code
   
    if(theFile){
      while(theFile.available()){
        client.write( theFile.read() );
      }
      theFile.close();
    }
  }
 
  else{ SuccessOrNot = false; }
  return SuccessOrNot;
  //-^---- What I am trying --- */
 
  /*-v-- The following works if used in place of [What I am trying] ---
  bool SuccessOrNot;
 
  if(client.connect(ServerChar, 25)){
    SuccessOrNot = true;
    client.println("EHLO ktlan");
    client.println("AUTH LOGIN");
    //-v- Most SMTP servers require verification in the form of base64-encoded username and base64-encoded password. However, since your IP must be whitelisted by the SMTP server, you don't need authentication
    //client.println("ThisIsInBase64"); // Encoded version of 'sender@blah.blah'
    //client.println("ThisIsInBase64"); // Encoded version of the password
    //-^-
    client.println("MAIL FROM:<sender@blah.blah>");
    client.println("RCPT TO:<receiver@blah.blah>");
    client.println("DATA");
    client.println("to:receiver@blah.blah");
    client.println("from:sender@blah.blah");
    client.print("SUBJECT: TRIGGER");
    client.println();
    client.println("The temperature Monitor Triggered.");
    client.println(".");
    client.println("QUIT");
  }
  else{ SuccessOrNot = false; }
 
  //-^-- The following works if used in place of [What I am trying] ---*/
}

/*-v--- Smtp.txt -------
EHLO ktlan
AUTH LOGIN
MAIL FROM:<sender@blah.blah>
RCPT TO:<receiver@blah.blah>
DATA
to:receiver@blah.blah
from:sender@blah.blah
SUBJECT: TRIGGER

The temperature Monitor Triggered.
.
QUIT

//-^--- Smtp.txt -------*/

// NO NEED for authentication. For many Smtp servers you need:
//client.println("ThisIsInBase64"); // Encoded version of 'sender@blah.blah'
//client.println("ThisIsInBase64"); // Encoded version of the password
// My IP must be whitelisted by the SMTP server, and since it is, I don't need authentication
4
  • It would be very useful to also see the SMTP Server side of things (logs), if you have access to it. Also, you do not wait for any replies from the server so there's no way to determine when the server's ready for your next command. – StarCat Nov 25 '20 at 9:33
  • 1
    You're reading and writing a byte at a time, which might not be optimal. Try and do that in larger chunks (SD page size if you have enough memory) – Mat Nov 25 '20 at 11:25
  • Many email servers will refuse to serve to a client that sends EHLO before it's sent its identification banner. – Majenko Nov 25 '20 at 11:53
  • Thank all. Added a "ReadClient()", it works []. Tried readStringUntil(), print line by line, works [], tried not returning bool, works (!?) ... revert back to original code, works []. I say [] because when re-upload the code, email sends, but won't send another when reset-buttoned & won't send if re-uploaded with serial monitor active. Was 1 time in troubleshooting it worked fully & I saw output of client on serial monitor & email each reset. Couldn't replicate. Sorry for unclarity: since I claim unrepeatable results I should post [lengthy] instructions. I'll reinstall & if persists do so. – elscan Dec 5 '20 at 16:40
0

Try a simpler approach (with some code refactoring)

bool TrySend(){
 
  if(client.connect(ServerChar, 25)){
    theFile = SD.open("Smtp.txt");
   
    if(theFile){
      while(theFile.available()){
        client.print(theFile.readStringUntil('\n'));
        client.print('\n');
      }
      theFile.close();
      return true;
    }
  }
  return false;
}

As a side note, you might want to consider some better code structure (e.g. local variables). But I assume this is just a sample/test. Also, the code above assumes the file uses \r\n at the end of each line. If it only has \n, then you can simply use: client.println(theFile.readStringUntil('\n')); (notice the print*ln*). println sends both \r\n.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.