#ifdef USE_SENDMAIL #ifndef USE_ESP32MAIL #include "sendemail.h" // enable serial debugging //#define DEBUG_EMAIL_PORT // sendmail works only with server port 465 SSL and doesnt support STARTTLS (not supported in Arduino) // only a couple of mailservers support this (e.g. gmail,gmx,yahoo,freenetmail) // sendmail [server:port:user:passwd:from:to:subject] body // sendmail [*:*:*:*:*:to:subject] data uses defines from user_config_overwrite // #define EMAIL_USER "user" // #define EMAIL_PASSWORD "passwd" // #define EMAIL_FROM "" // #define EMAIL_SERVER "smtp.gmail.com" // #define EMAIL_PORT 465 // if email body consist of a single * and scripter is present // and a section >m is found, the lines in this section (until #) are sent // as email body // sendmail works with pre2.6 using Light BearSSL //HW Watchdog 8.44 sec. //SW Watchdog 3.2 sec. #ifndef SEND_MAIL_MINRAM #define SEND_MAIL_MINRAM 12*1024 #endif void script_send_email_body(void(*func)(char *)); #define xPSTR(a) a uint16_t SendMail(char *buffer) { char *params,*oparams; const char *mserv; uint16_t port; const char *user; const char *pstr; const char *passwd; const char *from; const char *to; const char *subject; const char *cmd; char auth=0; uint16_t status=1; SendEmail *mail=0; uint16_t blen; char *endcmd; // return if not enough memory uint16_t mem=ESP.getFreeHeap(); if (memsend(from,to,subject,cmd); delete mail; if (result==true) status=0; } exit: if (oparams) free(oparams); return status; } #ifdef ESP8266 WiFiClient *g_client; SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) : host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new BearSSL::WiFiClientSecure_light(1024,1024)) { } #else WiFiClient *g_client; SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) : host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new WiFiClientSecure()) { } #endif String SendEmail::readClient() { delay(0); String r = client->readStringUntil('\n'); r.trim(); while (client->available()) { delay(0); r += client->readString(); } return r; } bool SendEmail::send(const String& from, const String& to, const String& subject, const char *msg) { bool status=false; String buffer; if (!host.length()) { return status; } client->setTimeout(timeout); // smtp connect #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("Connecting: %s on port %d"),host.c_str(),port); #endif if (!client->connect(host.c_str(), port)) { #ifdef DEBUG_EMAIL_PORT AddLog_P(LOG_LEVEL_INFO, PSTR("Connection failed")); #endif goto exit; } buffer = readClient(); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("220"))) { goto exit; } buffer = F("EHLO "); buffer += client->localIP().toString(); client->println(buffer); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("250"))) { goto exit; } if (user.length()>0 && passwd.length()>0 ) { buffer = F("AUTH LOGIN"); client->println(buffer); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("334"))) { goto exit; } base64 b; buffer = b.encode(user); client->println(buffer); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("334"))) { goto exit; } buffer = b.encode(passwd); client->println(buffer); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("235"))) { goto exit; } } // smtp send mail buffer = F("MAIL FROM:"); buffer += from; client->println(buffer); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("250"))) { goto exit; } buffer = F("RCPT TO:"); buffer += to; client->println(buffer); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("250"))) { goto exit; } buffer = F("DATA"); client->println(buffer); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("354"))) { goto exit; } buffer = F("MIME-Version: 1.0\r\n"); client->print(buffer); buffer = F("Content-Type: Multipart/mixed; boundary=frontier\r\n"); client->print(buffer); buffer = F("From: "); buffer += from; client->println(buffer); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = F("To: "); buffer += to; client->println(buffer); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = F("Subject: "); buffer += subject; buffer += F("\r\n"); client->println(buffer); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif #ifdef USE_SCRIPT if (*msg=='*' && *(msg+1)==0) { g_client=client; script_send_email_body(xsend_message_txt); } else { client->println(msg); } #else client->println(msg); #endif client->println('.'); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = F("QUIT"); client->println(buffer); #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif status=true; exit: return status; } void xsend_message_txt(char *msg) { #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),msg); #endif #if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) if (*msg=='@') { msg++; attach_File(msg); } else if (*msg=='&') { msg++; attach_Array(msg); } else { g_client->print(F("--frontier\r\n")); g_client->print(F("Content-Type: text/plain\r\n\r\n")); g_client->println(msg); g_client->print(F("\r\n--frontier\r\n")); } #else if (*msg=='&') { msg++; attach_Array(msg); } else { g_client->print(F("--frontier\r\n")); g_client->print(F("Content-Type: text/plain\r\n\r\n")); g_client->println(msg); g_client->print(F("\r\n--frontier\r\n")); } #endif } #if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) #include extern FS *fsp; void attach_File(char *path) { g_client->print(F("--frontier\r\n")); g_client->print(F("Content-Type: text/plain\r\n")); char buff[64]; char *cp = path; while (*cp=='/') cp++; File file = fsp->open(path, "r"); if (file) { sprintf_P(buff,PSTR("Content-Disposition: attachment; filename=\"%s\"\r\n\r\n"), cp); g_client->write(buff); uint16_t flen = file.size(); uint8_t fbuff[64]; uint16_t blen = sizeof(fbuff); while (flen>0) { file.read(fbuff, blen); flen -= blen; g_client->write(fbuff, blen); if (flenprint(F("\r\n\r\nfile not found!\r\n")); } g_client->print(F("\r\n--frontier\r\n")); } #endif // defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) float *get_array_by_name(char *name, uint16_t *alen); void flt2char(float num, char *nbuff); void attach_Array(char *aname) { float *array = 0; uint16_t alen; array = get_array_by_name(aname, &alen); g_client->print(F("--frontier\r\n")); g_client->print(F("Content-Type: text/plain\r\n")); if (array && alen) { #ifdef DEBUG_EMAIL_PORT AddLog_P2(LOG_LEVEL_INFO, PSTR("array found %d"),alen); #endif char buff[64]; sprintf_P(buff,PSTR("Content-Disposition: attachment; filename=\"%s.txt\"\r\n\r\n"), aname); g_client->write(buff); // send timestamp strcpy(buff, GetDateAndTime(DT_LOCAL).c_str()); strcat(buff,"\t"); g_client->write(buff); float *fp=array; for (uint32_t cnt = 0; cntwrite(nbuff, strlen(nbuff)); } } else { g_client->print(F("\r\n\r\narray not found!\r\n")); } g_client->print(F("\r\n--frontier\r\n")); } #else /* * Created by K. Suwatchai (Mobizt) * * Email: k_suwatchai@hotmail.com * * Github: https://github.com/mobizt * * Copyright (c) 2019 mobizt * */ //To use send Email for Gmail to port 465 (SSL), less secure app option should be enabled. https://myaccount.google.com/lesssecureapps?pli=1 //To receive Email for Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en #include "ESP32_MailClient.h" #include "SD.h" //For demo only //#include "image.h" #ifndef SEND_MAIL32_MINRAM #define SEND_MAIL32_MINRAM 30*1024 #endif void script_send_email_body(void(*func)(char *)); #define xPSTR(a) a //The Email Sending data object contains config and data to send SMTPData smtpData; #define MAX_ATTCHMENTS 8 char *attachments[MAX_ATTCHMENTS]; uint8_t num_attachments; //Callback function to get the Email sending status //void sendCallback(SendStatus info); //#define DEBUG_EMAIL_PORT uint16_t SendMail(char *buffer) { char *params,*oparams; const char *mserv; uint16_t port; const char *user; const char *pstr; const char *passwd; const char *from; const char *to; const char *subject; const char *cmd; uint16_t status=1; uint16_t blen; char *endcmd; // return if not enough memory uint32_t mem=ESP.getFreeHeap(); //AddLog_P2(LOG_LEVEL_INFO, PSTR("heap: %d"),mem); if (mem"); //Set the storage types to read the attach files (SD is default) //smtpData.setFileStorageType(MailClientStorageType::SPIFFS); #ifdef USE_SCRIPT_FATFS #if USE_SCRIPT_FATFS<0 smtpData.setFileStorageType(MailClientStorageType::FFat); #else smtpData.setFileStorageType(MailClientStorageType::SD); #endif #endif //smtpData.setSendCallback(sendCallback); //Start sending Email, can be set callback function to track the status if (!MailClient.sendMail(smtpData)) { //Serial.println("Error sending Email, " + MailClient.smtpErrorReason()); AddLog_P2(LOG_LEVEL_INFO, PSTR("Error sending Email, %s"), MailClient.smtpErrorReason().c_str()); } else { status=0; } //Clear all data from Email object to free memory smtpData.empty(); for (uint32_t cnt=0; cntprint(F("\r\n\r\narray not found!\r\n")); } } void send_message_txt(char *txt) { if (*txt=='@') { txt++; smtpData.addAttachFile(txt); } else if (*txt=='&') { txt++; attach_Array(txt); } else if (*txt=='$') { txt++; #if defined(ESP32) && defined(USE_WEBCAM) uint32_t cnt; uint8_t *buff; uint32_t len,picmax; picmax=WcGetPicstore(-1,0); cnt=*txt&7; if (cnt<1 || cnt>picmax) cnt=1; len=WcGetPicstore(cnt-1,&buff); if (len) { char str[12]; sprintf(str,"img_%1d.jpg",cnt+1); smtpData.addAttachData(str, "image/jpg",buff,len); } #endif } else { smtpData.addMessage(txt); } } /* //Callback function to get the Email sending status void sendCallback(SendStatus msg) { //Print the current status Serial.println(msg.info()); //Do something when complete if (msg.success()) { Serial.println("----------------"); } } */ #endif #endif // USE_SENDMAIL