Forum Replies Created
-
AuthorPosts
-
I am using a Portenta H7, so RAM is not an issue.
I have been using the AsyncWebServer for the Web Server, but in light of no more support for those libraries. I am trying to change the application to the standard arduino Ethernet libraries.
Just wanted to make sure there were no issues running them in parallel.
Thanks
Just for the record.
I decided to finally update EmailSender to the latest version, and had the same issues as before.
I added the 2 lines as described above
... SerDebugln(F("In email routine")); //emailSend.setEHLOCommand(true); emailSend.setPublicIpDescriptor(es); emailSend.setAdditionalResponseLineOnConnection(1); emailSend.setAdditionalResponseLineOnHELO(1); EMailSender::EMailMessage msg; msg.subject = EMailData[i].emailSubject; msg.message = EMailData[i].emailMessage; EMailSender::Response resp = emailSend.send(ste, msg); ...
I ended up getting the following error
Connection error! Reduce the HELO response line!
I ended up removing them, and making the changes I had made before, and then it sends OK. The file with the mods is attached below
Attachments:
You must be logged in to view attached files.When it becomes available on the arduino library, I will update and add the lines above try.
Will let you know the results.
Thanks
Yes, with the changes as per the attached file, it works
For whatever reason, that did not work, and I had to add the 2x clint.flush (after the connect, as well as after the helo).
Also, I removed the space after the PublicIPDescriptor.
Also in my case, I have to comment out the line
//DEBUG_PRINTLN(INTERNAL_STORAGE_CLASS.exists(attachments.fileDescriptor[i].url.c_str()));in the EMailSender.cpp program, in order to allow compile when DEBUGPRINT is on
I have attached the file below
Attachments:
You must be logged in to view attached files.I made the following changes to the code, and it worked. Most of the changes are adding DEBUG_PRINTLN.
I added some client.flush() after the connect, and helo command, but they didn’t fix it.
It was only when I changed the ‘helo mischianti’ to helo + this->smtp_server that it worked.
Although the telnet connection did not care what was placed after the helo (I could even just send a helo all by itself), the exchange server was demanding a valid domain for the arduino, possibly because it is not a domain member IP address ???
Any way, here is the file
/* * EMail Sender Arduino, esp8266, stm32 and esp32 library to send email * * AUTHOR: Renzo Mischianti * VERSION: 3.0.6 * * http://mischianti.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Renzo Mischianti www.mischianti.org All right reserved. * * You may copy, alter and reuse this code in any way you like, but please leave * reference to www.mischianti.org in your comments if you redistribute this code. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "EMailSender.h" #include <stdio.h> //#include <SPIFFS.h> //#include <LittleFS.h> //#define SD SPIFFS // BASE64 ----------------------------------------------------------- const char PROGMEM b64_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; #define encode64(arr) encode64_f(arr,strlen(arr)) inline void a3_to_a4(unsigned char * a4, unsigned char * a3) { a4[0] = (a3[0] & 0xfc) >> 2; a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4); a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6); a4[3] = (a3[2] & 0x3f); } int base64_encode(char *output, char *input, int inputLen) { int i = 0, j = 0; int encLen = 0; unsigned char a3[3]; unsigned char a4[4]; while (inputLen--) { a3[i++] = *(input++); if (i == 3) { a3_to_a4(a4, a3); for (i = 0; i < 4; i++) { output[encLen++] = pgm_read_byte(&b64_alphabet[a4[i]]); } i = 0; } } if (i) { for (j = i; j < 3; j++) { a3[j] = '\0'; } a3_to_a4(a4, a3); for (j = 0; j < i + 1; j++) { output[encLen++] = pgm_read_byte(&b64_alphabet[a4[j]]); } while ((i++ < 3)) { output[encLen++] = '='; } } output[encLen] = '\0'; return encLen; } int base64_enc_length(int plainLen) { int n = plainLen; return (n + 2 - ((n + 2) % 3)) / 3 * 4; } const char* encode64_f(char* input, uint8_t len) { // encoding DEBUG_PRINTLN(F("Encoding")); DEBUG_PRINTLN(input); DEBUG_PRINTLN(len); //int encodedLen = base64_enc_length(len); static char encoded[256]; // note input is consumed in this step: it will be empty afterwards base64_encode(encoded, input, len); return encoded; } // END BASE64 --------------------------------------------------------- EMailSender::EMailSender(const char* email_login, const char* email_password, const char* email_from, const char* name_from , const char* smtp_server, uint16_t smtp_port) { this->setEMailLogin(email_login); this->setEMailFrom(email_from); this->setEMailPassword(email_password); this->setSMTPServer(smtp_server); this->setSMTPPort(smtp_port); this->setNameFrom(name_from); // this->isSecure = isSecure; } EMailSender::EMailSender(const char* email_login, const char* email_password, const char* email_from, const char* smtp_server, uint16_t smtp_port) { this->setEMailLogin(email_login); this->setEMailFrom(email_from); this->setEMailPassword(email_password); this->setSMTPServer(smtp_server); this->setSMTPPort(smtp_port); // this->isSecure = isSecure; } EMailSender::EMailSender(const char* email_login, const char* email_password, const char* email_from, const char* name_from ) { this->setEMailLogin(email_login); this->setEMailFrom(email_from); this->setEMailPassword(email_password); this->setNameFrom(name_from); this->setNameFrom(name_from); // this->isSecure = isSecure; } EMailSender::EMailSender(const char* email_login, const char* email_password, const char* email_from) { this->setEMailLogin(email_login); this->setEMailFrom(email_from); this->setEMailPassword(email_password); // this->isSecure = isSecure; } EMailSender::EMailSender(const char* email_login, const char* email_password){ this->setEMailLogin(email_login); this->setEMailFrom(email_login); this->setEMailPassword(email_password); // this->isSecure = isSecure; } void EMailSender::setSMTPPort(uint16_t smtp_port){ this->smtp_port = smtp_port; }; void EMailSender::setSMTPServer(const char* smtp_server){ delete [] this->smtp_server; this->smtp_server = new char[strlen(smtp_server)+1]; strcpy(this->smtp_server, smtp_server); }; void EMailSender::setEMailLogin(const char* email_login){ delete [] this->email_login; this->email_login = new char[strlen(email_login)+1]; strcpy(this->email_login, email_login); }; void EMailSender::setEMailFrom(const char* email_from){ delete [] this->email_from; this->email_from = new char[strlen(email_from)+1]; strcpy(this->email_from, email_from); }; void EMailSender::setNameFrom(const char* name_from){ delete [] this->name_from; this->name_from = new char[strlen(name_from)+1]; strcpy(this->name_from, name_from); }; void EMailSender::setEMailPassword(const char* email_password){ delete [] this->email_password; this->email_password = new char[strlen(email_password)+1]; strcpy(this->email_password, email_password); }; void EMailSender::setIsSecure(bool isSecure) { this->isSecure = isSecure; } #ifdef SSLCLIENT_WRAPPER EMailSender::Response EMailSender::awaitSMTPResponse(SSLClient &client, const char* resp, const char* respDesc, uint16_t timeOut) { EMailSender::Response response; uint32_t ts = millis(); while (!client.available()) { if (millis() > (ts + timeOut)) { response.code = F("1"); response.desc = String(respDesc) + "! " + F("SMTP Response TIMEOUT!"); response.status = false; return response; } } _serverResponce = client.readStringUntil('\n'); DEBUG_PRINTLN(_serverResponce); if (resp && _serverResponce.indexOf(resp) == -1){ response.code = resp; response.desc = respDesc +String(" (") + _serverResponce + String(")"); response.status = false; return response; } response.status = true; return response; } #else EMailSender::Response EMailSender::awaitSMTPResponse(EMAIL_NETWORK_CLASS &client, const char* resp, const char* respDesc, uint16_t timeOut) { EMailSender::Response response; uint32_t ts = millis(); while (!client.available()) { if (millis() > (ts + timeOut)) { DEBUG_PRINTLN(F("In response - timeout")); response.code = F("1"); response.desc = String(respDesc) + "! " + F("SMTP Response TIMEOUT!"); response.status = false; return response; } } DEBUG_PRINTLN(F("In response")); _serverResponce = client.readStringUntil('\n'); DEBUG_PRINTLN(_serverResponce); if (resp && _serverResponce.indexOf(resp) == -1){ DEBUG_PRINTLN(F("In response - bad resp")); response.code = resp; response.desc = respDesc +String(" (") + _serverResponce + String(")"); response.status = false; return response; } response.status = true; return response; } #endif static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 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] : '='); } #ifdef ENABLE_ATTACHMENTS #ifdef STORAGE_EXTERNAL_ENABLED #if (defined(DIFFERENT_FILE_MANAGE) && defined(EMAIL_FILE_EX)) || !defined(STORAGE_INTERNAL_ENABLED) #ifdef SSLCLIENT_WRAPPER void encode(EMAIL_FILE_EX *file, SSLClient *client) { unsigned char in[3],out[4]; int i,len,blocksout=0; while (file->available()!=0) { len=0; for (i=0;i<3;i++){ in[i]=(unsigned char) file->read(); if (file->available()!=0) len++; else in[i]=0; } if (len){ encodeblock(in,out,len); // for(i=0;i<4;i++) client->write(out[i]); client->write(out, 4); blocksout++; } if (blocksout>=19||file->available()==0){ if (blocksout) { client->print("\r\n"); } blocksout=0; } } } #else void encode(EMAIL_FILE_EX *file, EMAIL_NETWORK_CLASS *client) { unsigned char in[3],out[4]; int i,len,blocksout=0; while (file->available()!=0) { len=0; for (i=0;i<3;i++){ in[i]=(unsigned char) file->read(); if (file->available()!=0) len++; else in[i]=0; } if (len){ encodeblock(in,out,len); // for(i=0;i<4;i++) client->write(out[i]); client->write(out, 4); blocksout++; } if (blocksout>=19||file->available()==0){ if (blocksout) { client->print("\r\n"); } blocksout=0; } } } #endif #endif #endif #ifdef STORAGE_INTERNAL_ENABLED #if defined(DIFFERENT_FILE_MANAGE) || (!defined(DIFFERENT_FILE_MANAGE) && defined(EMAIL_FILE)) || !defined(STORAGE_EXTERNAL_ENABLED) #ifdef SSLCLIENT_WRAPPER void encode(EMAIL_FILE *file, SSLClient *client) { unsigned char in[3],out[4]; int i,len,blocksout=0; while (file->available()!=0) { len=0; for (i=0;i<3;i++){ in[i]=(unsigned char) file->read(); if (file->available()!=0) len++; else in[i]=0; } if (len){ encodeblock(in,out,len); // for(i=0;i<4;i++) client->write(out[i]); client->write(out, 4); blocksout++; } if (blocksout>=19||file->available()==0){ if (blocksout) { client->print("\r\n"); } blocksout=0; } } } #else void encode(EMAIL_FILE *file, EMAIL_NETWORK_CLASS *client) { unsigned char in[3],out[4]; int i,len,blocksout=0; while (file->available()!=0) { len=0; for (i=0;i<3;i++){ in[i]=(unsigned char) file->read(); if (file->available()!=0) len++; else in[i]=0; } if (len){ encodeblock(in,out,len); // for(i=0;i<4;i++) client->write(out[i]); client->write(out, 4); blocksout++; } if (blocksout>=19||file->available()==0){ if (blocksout) { client->print("\r\n"); } blocksout=0; } } } #endif #endif #endif #endif const char** toCharArray(String arr[], int num) { // If we ever alloc with new with have to delete const char** buffer = new const char*[num]; for(int i = 0; i < num; i++) { buffer[i] = arr[i].c_str(); } return buffer; } const char** toCharArray(char* arr[], int num) { // If we ever alloc with new with have to delete const char** buffer = new const char*[num]; for(int i = 0; i < num; i++) { buffer[i] = arr[i]; } return buffer; } EMailSender::Response EMailSender::send(char* tos[], byte sizeOfTo, EMailMessage &email, Attachments attachments) { return send(toCharArray(tos, sizeOfTo), sizeOfTo, 0, 0, email, attachments); } EMailSender::Response EMailSender::send(char* tos[], byte sizeOfTo, byte sizeOfCc, EMailMessage &email, Attachments attachments) { return send(toCharArray(tos, sizeOfTo+sizeOfCc), sizeOfTo, sizeOfCc, 0, email, attachments); } EMailSender::Response EMailSender::send(char* tos[], byte sizeOfTo, byte sizeOfCc,byte sizeOfCCn, EMailMessage &email, Attachments attachments){ return send(toCharArray(tos, sizeOfTo+sizeOfCc+sizeOfCCn), sizeOfTo, sizeOfCc, sizeOfCCn, email, attachments); } EMailSender::Response EMailSender::send(String to, EMailMessage &email, Attachments attachments){ DEBUG_PRINT(F("ONLY ONE RECIPIENT")); const char* arrEmail[] = {to.c_str()}; return send(arrEmail, 1, email, attachments); } EMailSender::Response EMailSender::send(String tos[], byte sizeOfTo, EMailMessage &email, Attachments attachments) { return send(toCharArray(tos, sizeOfTo), sizeOfTo, 0, 0, email, attachments); } EMailSender::Response EMailSender::send(String tos[], byte sizeOfTo, byte sizeOfCc, EMailMessage &email, Attachments attachments) { return send(toCharArray(tos, sizeOfTo+sizeOfCc), sizeOfTo, sizeOfCc, 0, email, attachments); } EMailSender::Response EMailSender::send(String tos[], byte sizeOfTo, byte sizeOfCc,byte sizeOfCCn, EMailMessage &email, Attachments attachments){ return send(toCharArray(tos, sizeOfTo+sizeOfCc+sizeOfCCn), sizeOfTo, sizeOfCc, sizeOfCCn, email, attachments); } EMailSender::Response EMailSender::send(const char* to, EMailMessage &email, Attachments attachments){ DEBUG_PRINT(F("ONLY ONE RECIPIENT")); const char* arrEmail[] = {to}; return send(arrEmail, 1, email, attachments); } EMailSender::Response EMailSender::send(const char* to[], byte sizeOfTo, EMailMessage &email, Attachments attachments) { DEBUG_PRINTLN(F("miltiple destination and attachments")); return send(to, sizeOfTo, 0, email, attachments); } EMailSender::Response EMailSender::send(const char* to[], byte sizeOfTo, byte sizeOfCc, EMailMessage &email, Attachments attachments) { return send(to, sizeOfTo, sizeOfCc, 0, email, attachments); } #ifdef SSLCLIENT_WRAPPER #ifdef PUT_OUTSIDE_SCOPE_CLIENT_DECLARATION // Initialize the SSL client library // We input an EthernetClient, our trust anchors, and the analog pin EMAIL_NETWORK_CLASS base_client; SSLClient client(base_client, TAs, (size_t)TAs_NUM, ANALOG_PIN, 2); #else #error "You must put outside scope the client declaration if you want use SSLClient!" #endif #else #ifdef PUT_OUTSIDE_SCOPE_CLIENT_DECLARATION EMAIL_NETWORK_CLASS client; #endif #endif EMailSender::Response EMailSender::send(const char* to[], byte sizeOfTo, byte sizeOfCc,byte sizeOfCCn, EMailMessage &email, Attachments attachments) { #ifdef SSLCLIENT_WRAPPER DEBUG_PRINTLN(F("SSLClient active!")); #else #ifndef PUT_OUTSIDE_SCOPE_CLIENT_DECLARATION EMAIL_NETWORK_CLASS client; #endif DEBUG_PRINT(F("Insecure client:")); DEBUG_PRINTLN(this->isSecure); #ifndef FORCE_DISABLE_SSL #if (EMAIL_NETWORK_TYPE == NETWORK_ESP8266 || EMAIL_NETWORK_TYPE == NETWORK_ESP8266_242) #ifndef ARDUINO_ESP8266_RELEASE_2_4_2 if (this->isSecure == false){ client.setInsecure(); bool mfln = client.probeMaxFragmentLength(this->smtp_server, this->smtp_port, 512); DEBUG_PRINT("MFLN supported: "); DEBUG_PRINTLN(mfln?"yes":"no"); if (mfln) { client.setBufferSizes(512, 512); } } #endif #elif (EMAIL_NETWORK_TYPE == NETWORK_ESP32) // String coreVersion = String(ESP.getSdkVersion()); // uint8_t firstdot = coreVersion.indexOf('.'); // // DEBUG_PRINTLN(coreVersion.substring(1, coreVersion.indexOf('.', firstdot+1)).toFloat()); // DEBUG_PRINTLN(coreVersion.substring(1, coreVersion.indexOf('.', firstdot+1)).toFloat() >= 3.3f); // if (coreVersion.substring(1, coreVersion.indexOf('.', firstdot+1)).toFloat() >= 3.3f) { // client.setInsecure(); // } #include <core_version.h> #if ((!defined(ARDUINO_ESP32_RELEASE_1_0_4)) && (!defined(ARDUINO_ESP32_RELEASE_1_0_3)) && (!defined(ARDUINO_ESP32_RELEASE_1_0_2))) client.setInsecure(); #endif #endif #endif #endif EMailSender::Response response; DEBUG_PRINTLN(this->smtp_server); DEBUG_PRINTLN(this->smtp_port); if(!client.connect(this->smtp_server, this->smtp_port)) { response.desc = F("Could not connect to mail server"); response.code = F("2"); response.status = false; client.flush(); client.stop(); return response; } client.flush(); response = awaitSMTPResponse(client, "220", "Connection Error"); if (!response.status) { DEBUG_PRINTLN("Error: in response status after connect"); client.flush(); client.stop(); return response; } if (this->additionalResponseLineOnConnection > 0){ for (int i = 0; i<=this->additionalResponseLineOnConnection; i++) { response = awaitSMTPResponse(client, "220", "Connection response error ", 2500); if (!response.status && response.code == F("1")) { response.desc = F("Connection error! Reduce the HELO response line!"); client.flush(); client.stop(); return response; } } } String commandHELO = "HELO"; if (this->useEHLO == true) { commandHELO = "EHLO"; } String helo = commandHELO + " " + this->smtp_server; DEBUG_PRINTLN(helo); client.println(helo); client.flush(); response = awaitSMTPResponse(client, "250", "Identification error"); if (!response.status) { DEBUG_PRINTLN("Error: after HELO - in response status "); client.flush(); client.stop(); return response; } // if (this->useEHLO == true) { // for (int i = 0; i<=6; i++) awaitSMTPResponse(client); // } // // for (int i = 0; i <= 6; i++) { // response = awaitSMTPResponse(client, "250", "EHLO error", 2500); // if (!response.status && response.code == F("1")) { // DEBUG_PRINTLN(response.desc); // break; // } // } DEBUG_PRINTLN("Got to after send HELO"); if (this->useEHLO == true && this->additionalResponseLineOnHELO == 0) { DEBUG_PRINTLN("In use EHLO"); this->additionalResponseLineOnHELO = DEFAULT_EHLO_RESPONSE_COUNT; } if (this->additionalResponseLineOnHELO > 0){ for (int i = 0; i<=this->additionalResponseLineOnHELO; i++) { response = awaitSMTPResponse(client, "250", "EHLO error", 2500); if (!response.status && response.code == F("1")) { DEBUG_PRINTLN("Error: after HELO - timeout"); response.desc = F("Timeout! Reduce the HELO response line!"); client.flush(); client.stop(); return response; } } } DEBUG_PRINTLN("Got to Use Auth"); if (useAuth){ if (this->isSASLLogin == true){ int size = 1 + strlen(this->email_login)+ strlen(this->email_password)+2; char * logPass = (char *) malloc(size); // strcpy(logPass, " "); // strcat(logPass, this->email_login); // strcat(logPass, " "); // strcat(logPass, this->email_password); // String logPass; int maincont = 0; logPass[maincont++] = ' '; logPass[maincont++] = (char) 0; for (unsigned int i = 0;i<strlen(this->email_login);i++){ logPass[maincont++] = this->email_login[i]; } logPass[maincont++] = (char) 0; for (unsigned int i = 0;i<strlen(this->email_password);i++){ logPass[maincont++] = this->email_password[i]; } // strcpy(logPass, "\0"); // strcat(logPass, this->email_login); // strcat(logPass, "\0"); // strcat(logPass, this->email_password); String auth = "AUTH PLAIN "+String(encode64_f(logPass, size)); // String auth = "AUTH PLAIN "+String(encode64(logPass)); DEBUG_PRINTLN(auth); client.println(auth); }else{ DEBUG_PRINTLN(F("AUTH LOGIN:")); client.println(F("AUTH LOGIN")); awaitSMTPResponse(client); DEBUG_PRINTLN(encode64(this->email_login)); client.println(encode64(this->email_login)); awaitSMTPResponse(client); DEBUG_PRINTLN(encode64(this->email_password)); client.println(encode64(this->email_password)); } response = awaitSMTPResponse(client, "235", "SMTP AUTH error"); if (!response.status) { client.flush(); client.stop(); return response; } } DEBUG_PRINT(F("MAIL FROM: <")); DEBUG_PRINT(this->email_from); DEBUG_PRINTLN(F(">")); client.print(F("MAIL FROM: <")); client.print(this->email_from); client.println(F(">")); awaitSMTPResponse(client); // String rcpt = "RCPT TO: <" + String(to) + '>'; // // DEBUG_PRINTLN(rcpt); // client.println(rcpt); int cont; for (cont=0;cont<(sizeOfTo+sizeOfCc+sizeOfCCn);cont++){ DEBUG_PRINT(F("RCPT TO: <")); DEBUG_PRINT(to[cont]); DEBUG_PRINTLN(F(">")); client.print(F("RCPT TO: <")); client.print(to[cont]); client.println(F(">")); awaitSMTPResponse(client); } DEBUG_PRINTLN(F("DATA:")); client.println(F("DATA")); response = awaitSMTPResponse(client, "354", "SMTP DATA error"); if (!response.status) { client.flush(); client.stop(); return response; } // client.println("From: <" + String(this->email_from) + '>'); client.print(F("From: ")); if (this->name_from){ client.print(this->name_from); } client.print(F(" <")); client.print(this->email_from); client.println(F(">")); // client.println("To: <" + String(to) + '>'); client.print(F("To: ")); for (cont=0;cont<sizeOfTo;cont++){ client.print(F("<")); client.print(to[cont]); client.print(">"); if (cont!=sizeOfTo-1){ client.print(","); } } client.println(); if (sizeOfCc>0){ client.print(F("Cc: ")); for (;cont<sizeOfTo+sizeOfCc;cont++){ client.print(F("<")); client.print(to[cont]); client.print(">"); if (cont!=sizeOfCc-1){ client.print(","); } } client.println(); } if (sizeOfCCn>0){ client.print(F("CCn: ")); for (;cont<sizeOfTo+sizeOfCc+sizeOfCCn;cont++){ client.print(F("<")); client.print(to[cont]); client.print(">"); if (cont!=sizeOfCCn-1){ client.print(","); } } client.println(); } client.print(F("Subject: ")); client.println(email.subject); // client.println(F("Mime-Version: 1.0")); client.println(F("MIME-Version: 1.0")); client.println(F("Content-Type: Multipart/mixed; boundary=frontier")); client.println(F("--frontier")); client.print(F("Content-Type: ")); client.print(email.mime); client.println(F("; charset=\"UTF-8\"")); // client.println(F("Content-Type: text/html; charset=\"UTF-8\"")); client.println(F("Content-Transfer-Encoding: 7bit")); client.println(); if (email.mime==F("text/html")){ // String body = "<!DOCTYPE html><html lang=\"en\">" + String(email.message) + "</html>"; client.print(F("<!DOCTYPE html><html lang=\"en\">")); client.print(email.message); client.println(F("</html>")); // client.println(body); }else{ client.println(email.message); } client.println(); #ifdef STORAGE_INTERNAL_ENABLED bool spiffsActive = false; #endif #ifdef STORAGE_EXTERNAL_ENABLED bool sdActive = false; #endif #if defined(ENABLE_ATTACHMENTS) && (defined(STORAGE_EXTERNAL_ENABLED) || defined(STORAGE_INTERNAL_ENABLED)) // if ((sizeof(attachs) / sizeof(attachs[0]))>0){ if (sizeof(attachments)>0 && attachments.number>0){ DEBUG_PRINT(F("Array: ")); // for (int i = 0; i<(sizeof(attachs) / sizeof(attachs[0])); i++){ for (int i = 0; i<attachments.number; i++){ uint8_t tBuf[64]; if (attachments.fileDescriptor[i].url.length()==0){ EMailSender::Response response; response.code = F("400"); response.desc = "Error no filename specified for the file "+attachments.fileDescriptor[i].filename; response.status = false; client.flush(); client.stop(); return response; } if (attachments.fileDescriptor[i].mime.length()==0){ EMailSender::Response response; response.code = F("400"); response.desc = "Error no mime type specified for the file "+attachments.fileDescriptor[i].url; response.status = false; client.flush(); client.stop(); return response; } if (attachments.fileDescriptor[i].filename.length()==0){ EMailSender::Response response; response.code = F("400"); response.desc = "Error no filename specified for the file "+attachments.fileDescriptor[i].url; response.status = false; client.flush(); client.stop(); return response; } DEBUG_PRINTLN(attachments.fileDescriptor[i].filename); DEBUG_PRINTLN(F("--frontier")); client.println(F("--frontier")); DEBUG_PRINTLN(F("Content-Type: ")); client.print(F("Content-Type: ")); DEBUG_PRINTLN(attachments.fileDescriptor[i].mime); client.print(attachments.fileDescriptor[i].mime); DEBUG_PRINTLN(F("; charset=\"UTF-8\"")); client.println(F("; charset=\"UTF-8\"")); if (attachments.fileDescriptor[i].encode64){ client.println(F("Content-Transfer-Encoding: base64")); } client.print(F("Content-Disposition: attachment; filename=")); client.print(attachments.fileDescriptor[i].filename); client.println(F("\n")); DEBUG_PRINT(F("Readed filename: ")); DEBUG_PRINTLN(attachments.fileDescriptor[i].filename); DEBUG_PRINT(F("Check if exist: ")); //DEBUG_PRINTLN(INTERNAL_STORAGE_CLASS.exists(attachments.fileDescriptor[i].url.c_str())); int clientCount = 0; #ifdef STORAGE_INTERNAL_ENABLED if (attachments.fileDescriptor[i].storageType==EMAIL_STORAGE_TYPE_SPIFFS || attachments.fileDescriptor[i].storageType==EMAIL_STORAGE_TYPE_LITTLE_FS || attachments.fileDescriptor[i].storageType==EMAIL_STORAGE_TYPE_SPIFM || attachments.fileDescriptor[i].storageType==EMAIL_STORAGE_TYPE_FFAT){ #ifdef OPEN_CLOSE_INTERNAL if (!INTERNAL_STORAGE_CLASS.exists(attachments.fileDescriptor[i].url.c_str())){ DEBUG_PRINTLN(F("Begin internal storage!")); #if (INTERNAL_STORAGE == STORAGE_SPIFM) Adafruit_FlashTransport_SPI flashTransport(SPIFM_CS_PIN, SPI); // Set CS and SPI interface Adafruit_SPIFlash flash(&flashTransport); // Initialize flash library and check its chip ID. if (!flash.begin()) { EMailSender::Response response; response.code = F("500"); response.desc = F("Error, failed to initialize flash chip!"); response.status = false; client.flush(); client.stop(); return response; } // close flash.begin() if(!(INTERNAL_STORAGE_CLASS.begin(&flash))){ #else if(!(INTERNAL_STORAGE_CLASS.begin())){ #endif EMailSender::Response response; response.code = F("500"); response.desc = F("Error on startup filesystem!"); response.status = false; client.flush(); client.stop(); return response; } // Close INTERNAL_STORAGE_CLASS.begin spiffsActive = true; DEBUG_PRINTLN("SPIFFS BEGIN, ACTIVE"); } // Close INTERNAL_STORAGE_CLASS.exists } // Close storageType #endif DEBUG_PRINT(F("Try to open ")); DEBUG_PRINTLN(attachments.fileDescriptor[i].url); EMAIL_FILE myFile = INTERNAL_STORAGE_CLASS.open(attachments.fileDescriptor[i].url, EMAIL_FILE_READ); if(myFile) { DEBUG_PRINT(F("Filename -> ")); DEBUG_PRINTLN(myFile.name()); if (attachments.fileDescriptor[i].encode64){ encode(&myFile, &client); }else{ while(myFile.available()) { clientCount = myFile.read(tBuf,64); DEBUG_PRINTLN(clientCount); client.write((byte*)tBuf,clientCount); } } myFile.close(); client.println(); } // Else myfile else { EMailSender::Response response; response.code = F("404"); response.desc = "Error opening attachments file "+attachments.fileDescriptor[i].url; response.status = false; client.flush(); client.stop(); return response; } // Close myfile #endif #ifdef STORAGE_EXTERNAL_ENABLED if (attachments.fileDescriptor[i].storageType==EMAIL_STORAGE_TYPE_SD){ #ifdef OPEN_CLOSE_SD DEBUG_PRINTLN(F("SD Check")); if (!EXTERNAL_STORAGE_CLASS.exists(attachments.fileDescriptor[i].url.c_str())){ #if EXTERNAL_STORAGE == STORAGE_SD || EXTERNAL_STORAGE == STORAGE_SDFAT2 if(!EXTERNAL_STORAGE_CLASS.begin(SD_CS_PIN)){ response.code = F("500"); response.desc = F("Error on startup SD filesystem!"); response.status = false; client.flush(); client.stop(); return response; } // Close EXTERNAL_STORAGE_CLASS.begin #elif EXTERNAL_STORAGE == STORAGE_SPIFM Adafruit_FlashTransport_SPI flashTransport(SS, SPI); // Set CS and SPI interface Adafruit_SPIFlash flash(&flashTransport); if (!EXTERNAL_STORAGE_CLASS.begin(&flash)) { response.code = F("500"); response.desc = F("Error on startup SDFAT2 filesystem!"); response.status = false; client.flush(); client.stop(); return response; } #endif sdActive = true; } // Close EXTERNAL_STORAGE_CLASS.exists #endif DEBUG_PRINTLN(F("Open file: ")); EMAIL_FILE_EX myFile = EXTERNAL_STORAGE_CLASS.open(attachments.fileDescriptor[i].url.c_str()); if(myFile) { myFile.seek(0); DEBUG_PRINTLN(F("OK")); if (attachments.fileDescriptor[i].encode64){ DEBUG_PRINTLN(F("BASE 64")); encode(&myFile, &client); }else{ DEBUG_PRINTLN(F("NORMAL")); while(myFile.available()) { clientCount = myFile.read(tBuf,64); client.write((byte*)tBuf,clientCount); } } myFile.close(); client.println(); } // Else myfile else { response.code = F("404"); response.desc = "Error opening attachments file "+attachments.fileDescriptor[i].url; response.status = false; client.flush(); client.stop(); return response; } // Close myFile } // Close storageType==EMAIL_STORAGE_TYPE_SD #else if (attachments.fileDescriptor[i].storageType==EMAIL_STORAGE_TYPE_SD){ response.code = F("500"); response.desc = F("EMAIL_STORAGE_TYPE_SD not enabled on EMailSenderKey.h"); response.status = false; client.flush(); client.stop(); return response; } #endif } // Close attachment cycle client.println(); client.println(F("--frontier--")); #ifdef STORAGE_EXTERNAL_ENABLED #ifdef OPEN_CLOSE_SD if (sdActive){ DEBUG_PRINTLN(F("SD end")); #ifndef ARDUINO_ESP8266_RELEASE_2_4_2 EXTERNAL_STORAGE_CLASS.end(); #endif DEBUG_PRINTLN(F("SD end 2")); } #endif #endif #ifdef STORAGE_INTERNAL_ENABLED #ifdef OPEN_CLOSE_INTERNAL #if INTERNAL_STORAGE != STORAGE_SPIFM if (spiffsActive){ INTERNAL_STORAGE_CLASS.end(); DEBUG_PRINTLN(F("SPIFFS END")); } #endif #endif #endif } // Close attachement enable #endif DEBUG_PRINTLN(F("Message end")); client.println(F(".")); response = awaitSMTPResponse(client, "250", "Sending message error"); if (!response.status) { client.flush(); client.stop(); return response; } client.println(F("QUIT")); response = awaitSMTPResponse(client, "221", "SMTP QUIT error"); if (!response.status) { client.flush(); client.stop(); return response; } response.status = true; response.code = F("0"); response.desc = F("Message sent!"); client.flush(); client.stop(); return response; }
I have created a small test program that just outputs the data to exchange server, and this works. I am not checking for correct responses, just proceeding after the client.println, and getting a response when expected – just not analyzing it.
I have tested the same code with the delays removed, and other than beiung faster, it also works.
In my main code it is a multitasking envioronment, but I had tried to run between OSCritical enable/disable, and that had not made a difference.
Can you see anything you can suggest for me to try to resolve the issue. The actual library seems to hang after ehlo or helo commands, at which point I get the
Identification error (501 5.5.4 Invalid domain name)
I am able to send an email with no issues with the code attached below (just changed the actual emails, domain names and passwords):
/* * EMailSender library for Arduino, esp8266 and esp32 * Arduino Mega and UIPEthernet send example with Sendgrid provider * * Pay attention you must set in the library * #define DEFAULT_EMAIL_NETWORK_TYPE_ARDUINO NETWORK_ENC28J60 * for UIPEthernet * * #define DEFAULT_EMAIL_NETWORK_TYPE_ARDUINO NETWORK_W5100 * for standard Ethernet * * * http://mischianti.org/category/my-libraries/emailsender-send-email-with-attachments/ * */ #include "mbed.h" #include "rtos.h" #include <Portenta_Ethernet.h> #include <Ethernet.h> //#include <UIPEthernet.h> #include <EMailSender.h> // Enter a MAC address for your controller below. // Newer Ethernet shields have a MAC address printed on a sticker on the shield byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; void awaitSMTPResponse(EthernetClient &client) { uint32_t ts = millis(); while (!client.available()) { if (millis() > (ts + 5000)) { return; } } String _serverResponce = client.readStringUntil('\n'); Serial.println(_serverResponce); return; } EMailSender emailSend("Test123@mydomainmain.com", "mypasswd", "Test123@mydomainmain.com", "192.168.0.2", 587); void setup() { // Open serial communications and wait for port to open: Serial.begin(115200); // while (!Serial) {} delay(2000); Serial.println("Starting!"); // start the Ethernet connection: if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); while (1) ; } Serial.print("IP address "); Serial.println(Ethernet.localIP()); EMailSender::Response resp1; EthernetClient testCl; testCl.connect("192.168.0.2", 587); //resp1 = EMailSender::awaitSMTPResponse(testCl, "220", "Connection Error"); awaitSMTPResponse(testCl); testCl.println("helo 127.0.0.1"); awaitSMTPResponse(testCl); delay(2000); testCl.println("AUTH LOGIN"); awaitSMTPResponse(testCl); //EMailSender::awaitSMTPResponse(testCl); delay(2000); testCl.println("base64username"); awaitSMTPResponse(testCl); //EMailSender::awaitSMTPResponse(testCl); delay(2000); testCl.println("base64pwd"); awaitSMTPResponse(testCl); //EMailSender::awaitSMTPResponse(testCl); //EMailSender::awaitSMTPResponse(testCl); delay(2000); testCl.print(F("MAIL FROM: <")); testCl.print("Test123@mydomainmain.com"); testCl.println(F(">")); awaitSMTPResponse(testCl); //EMailSender::awaitSMTPResponse(testCl); delay(2000); testCl.print(F("RCPT TO: <")); testCl.print("rs@mydomain.com"); testCl.println(F(">")); //EMailSender::awaitSMTPRespo awaitSMTPResponse(testCl); delay(1000); testCl.println(F("DATA")); //EMailSender::awaitSMTPResponse(testCl); testCl.flush(); awaitSMTPResponse(testCl); delay(200); testCl.println(F("From: <Test123@mydomainmain.com>")); testCl.flush(); //delay(200); testCl.println(F("To: <rs@mydomain.com>")); testCl.flush(); //delay(200); testCl.print(F("Subject:")); testCl.println("This is the subject"); testCl.flush(); //delay(200); testCl.println(); testCl.flush(); //delay(200); testCl.println("this is my msg"); testCl.flush(); //delay(200); testCl.println("."); testCl.flush(); //delay(200); testCl.println(); testCl.flush(); //delay(200); awaitSMTPResponse(testCl); /* EMailSender::EMailMessage message; emailSend.setEHLOCommand(true); message.subject = "Soggetto"; message.message = "Ciao come stai<br>io bene.<br>www.mischianti.org"; EMailSender::Response resp = emailSend.send("rs@mydomain.com", message); Serial.println("Sending status: "); Serial.println(resp.status); Serial.println(resp.code); Serial.println(resp.desc); */ } void loop() { }
-
This reply was modified 1 year, 10 months ago by
Renzo Mischianti.
I am actually only using the Async libraries for the web Server.
The EMailSender routine is using the
#define EMAIL_NETWORK_CLASS EthernetClient
#define EMAIL_NETWORK_SERVER_CLASS EthernetServeron line 161 of the EMailSender.h – that seems like the appropriate settings – so nothing more to do there I don’t think.
Could the issue be that I am using the Async Ethernet libraries with my portenta STM32H747.
Looking at the code, I don’t think that is the default. What would be the best way to ensure that that is used. I see no global portenta or Async.
What is the recommended way to change the header file to force the use of the Async libraries
Thanks
I am using my own hosted exchange server, and have not changed anything (have not added any new cumulative updates etc).
I tried EHLO or HELO, and both don’t work, but both work if I execute them in a TELNET window. It seems from wireshark trace (I sent it to your info email) there is no appropriate response from EHLO or HELO when sent by the code, and the program just hangs there.
Did maybe something change in the dependency libraries?
-
This reply was modified 1 year, 10 months ago by
-
AuthorPosts