-
-
Notifications
You must be signed in to change notification settings - Fork 345
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bf9caa6
commit 99b88b9
Showing
10 changed files
with
1,057 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
/**** | ||
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. | ||
* Created 2015 by Skurydin Alexey | ||
* http://github.com/anakod/Sming | ||
* All files of the Sming Core are provided under the LGPL v3 license. | ||
* | ||
* SmtpClient - asynchronous SmtpClient that supports the following features: | ||
* - extended HELO command set | ||
* - support for PIPELINING | ||
* - support for STARTTLS (if the directive ENABLE_SSL=1 is set) | ||
* - support for smtp connection over SSL (if the directive ENABLE_SSL=1 is set) | ||
* - support for PLAIN and CRAM-MD5 authentication | ||
* - support for multiple attachments | ||
* - Support for base64 and quoted-printable transfer encoding | ||
* | ||
* Author: 2018 - Slavey Karadzhov <[email protected]> | ||
* | ||
****/ | ||
|
||
/** @defgroup smtpclient SMTP client | ||
* @brief Provides SMTP/S client | ||
* @ingroup tcpclient | ||
* @{ | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "TcpClient.h" | ||
#include "../Data/MailMessage.h" | ||
#include "URL.h" | ||
#include "../../Wiring/WString.h" | ||
#include "../../Wiring/WVector.h" | ||
#include "../Data/Stream/DataSourceStream.h" | ||
#include "WebConstants.h" | ||
#include "../Data/Structures.h" | ||
|
||
#include <functional> | ||
|
||
#define SMTP_PROTOCOL "smtp" | ||
#define SMTP_OVER_SSL_PROTOCOL "smtps" | ||
|
||
/* Maximum waiting emails in the mail queue */ | ||
#define SMTP_QUEUE_SIZE 5 | ||
|
||
/* Buffer size used to read the error messages */ | ||
#define SMTP_ERROR_LENGTH 40 | ||
|
||
/** | ||
* SMTP response codes | ||
*/ | ||
#define SMTP_CODE_SERVICE_READY 220 | ||
#define SMTP_CODE_BYE 221 | ||
#define SMTP_CODE_AUTH_OK 235 | ||
#define SMTP_CODE_REQUEST_OK 250 | ||
#define SMTP_CODE_AUTH_CHALLENGE 334 | ||
#define SMTP_CODE_START_DATA 354 | ||
|
||
#define SMTP_OPT_PIPELINE bit(0) | ||
#define SMTP_OPT_STARTTLS bit(1) | ||
#define SMTP_OPT_AUTH_PLAIN bit(2) | ||
#define SMTP_OPT_AUTH_LOGIN bit(3) | ||
#define SMTP_OPT_AUTH_CRAM_MD5 bit(4) | ||
|
||
enum SmtpState | ||
{ | ||
eSMTP_Banner = 0, | ||
eSMTP_Hello, | ||
eSMTP_StartTLS, | ||
eSMTP_SendAuth, | ||
eSMTP_SendingAuthLogin, | ||
eSMTP_RequestingAuthChallenge, | ||
eSMTP_SendAuthResponse, | ||
eSMTP_SendingAuth, | ||
eSMTP_Ready, | ||
eSMTP_SendMail, | ||
eSMTP_SendingMail, | ||
eSMTP_SendRcpt, | ||
eSMTP_SendingRcpt, | ||
eSMTP_SendData, | ||
eSMTP_SendingData, | ||
eSMTP_SendHeader, | ||
eSMTP_SendingHeaders, | ||
eSMTP_StartBody, | ||
eSMTP_SendingBody, | ||
eSMTP_Sent, | ||
eSMTP_Quitting, | ||
eSMTP_Disconnect | ||
}; | ||
|
||
class SmtpClient; | ||
|
||
typedef std::function<int(SmtpClient& client, int code, char* status)> SmtpClientCallback; | ||
|
||
class SmtpClient : protected TcpClient | ||
{ | ||
public: | ||
SmtpClient(bool autoDestroy=false); | ||
virtual ~SmtpClient(); | ||
|
||
/** | ||
* @brief Connects to remote URL | ||
* @param URL - provides the protocol, remote server, port and user credentials | ||
* allowed protocols: | ||
* - smtp - clear text SMTP | ||
* - smtps - SMTP over SSL connection | ||
*/ | ||
bool connect(const URL& url); | ||
|
||
/** | ||
* @brief Queues a single message before it is sent later to the SMTP server | ||
* | ||
* @param String& from | ||
* @param String& to | ||
* @param String& subject | ||
* @param String& body the body in plain text format | ||
* | ||
* @return true when the message was queued successfully, false otherwise | ||
*/ | ||
bool send(const String& from, const String& to, const String& subject, const String& body); | ||
|
||
/** | ||
* @brief Powerful method to queues a single message before it is sent later to the SMTP server | ||
* @param MailMessage* message | ||
* | ||
* @return true when the message was queued successfully, false otherwise | ||
*/ | ||
bool send(MailMessage* message); | ||
|
||
/** | ||
* @brief Gets the current message | ||
* | ||
* @return MailMessage* message - the message, or NULL if none is scheduled | ||
*/ | ||
MailMessage* getCurrentMessage(); | ||
|
||
inline size_t countPending() | ||
{ | ||
return mailQ.count(); | ||
} | ||
|
||
/** | ||
* @brief Sends a quit command to the server and closes the TCP conneciton | ||
*/ | ||
void quit(); | ||
|
||
/** | ||
* @brief Returns the current state of the SmtpClient. | ||
*/ | ||
SmtpState getState() { return state; } | ||
|
||
/** | ||
* @brief Callback that will be called every time a message is sent successfully | ||
* @param SmtpClientCallback callback | ||
*/ | ||
inline void onMessageSent(SmtpClientCallback callback) | ||
{ | ||
messageSentCallback = callback; | ||
} | ||
|
||
/** | ||
* @brief Callback that will be called every an error occurs | ||
* @param SmtpClientCallback callback | ||
*/ | ||
inline void onServerError(SmtpClientCallback callback) | ||
{ | ||
errorCallback = callback; | ||
} | ||
|
||
using TcpClient::setTimeOut; | ||
|
||
#ifdef ENABLE_SSL | ||
using TcpClient::addSslOptions; | ||
using TcpClient::addSslValidator; | ||
using TcpClient::pinCertificate; | ||
using TcpClient::setSslKeyCert; | ||
using TcpClient::freeSslKeyCert; | ||
using TcpClient::getSsl; | ||
#endif | ||
|
||
protected: | ||
virtual err_t onReceive(pbuf *buf); | ||
virtual void onReadyToSendData(TcpConnectionEvent sourceEvent); | ||
|
||
void sendMailHeaders(MailMessage* mail); | ||
bool sendMailBody(MailMessage* mail); | ||
|
||
private: | ||
URL url; | ||
Vector<String> authMethods; | ||
SimpleConcurrentQueue<MailMessage*,SMTP_QUEUE_SIZE> mailQ; | ||
char code[4] = {0}; | ||
int codeValue = 0; | ||
String authChallenge; | ||
char message[SMTP_ERROR_LENGTH + 1] = {0}; | ||
bool isLastLine = false; | ||
uint8_t codeLength = 0; | ||
int options = 0; | ||
MailMessage *outgoingMail = nullptr; | ||
SmtpState state = eSMTP_Banner; | ||
|
||
SmtpClientCallback errorCallback = nullptr; | ||
SmtpClientCallback messageSentCallback = nullptr; | ||
|
||
private: | ||
/** | ||
* @brief Simple and naive SMTP parser with a state machine | ||
*/ | ||
int smtpParse(char* data, size_t len); | ||
|
||
private: | ||
/** | ||
* @brief Takes care to fetch the correct streams for a message | ||
* @note The magic where all streams and attachments are packed together is happening here | ||
*/ | ||
HttpPartResult multipartProducer(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<projectDescription> | ||
<name>SmtpClient</name> | ||
<comment></comment> | ||
<projects> | ||
<project>SmingFramework</project> | ||
</projects> | ||
<buildSpec> | ||
<buildCommand> | ||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name> | ||
<triggers>clean,full,incremental,</triggers> | ||
<arguments> | ||
</arguments> | ||
</buildCommand> | ||
<buildCommand> | ||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name> | ||
<triggers>full,incremental,</triggers> | ||
<arguments> | ||
</arguments> | ||
</buildCommand> | ||
</buildSpec> | ||
<natures> | ||
<nature>org.eclipse.cdt.core.cnature</nature> | ||
<nature>org.eclipse.cdt.core.ccnature</nature> | ||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature> | ||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature> | ||
</natures> | ||
</projectDescription> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
##################################################################### | ||
#### Please don't change this file. Use Makefile-user.mk instead #### | ||
##################################################################### | ||
# Including user Makefile. | ||
# Should be used to set project-specific parameters | ||
include ./Makefile-user.mk | ||
|
||
# Important parameters check. | ||
# We need to make sure SMING_HOME and ESP_HOME variables are set. | ||
# You can use Makefile-user.mk in each project or use enviromental variables to set it globally. | ||
|
||
ifndef SMING_HOME | ||
$(error SMING_HOME is not set. Please configure it in Makefile-user.mk) | ||
endif | ||
ifndef ESP_HOME | ||
$(error ESP_HOME is not set. Please configure it in Makefile-user.mk) | ||
endif | ||
|
||
# Include main Sming Makefile | ||
ifeq ($(RBOOT_ENABLED), 1) | ||
include $(SMING_HOME)/Makefile-rboot.mk | ||
else | ||
include $(SMING_HOME)/Makefile-project.mk | ||
endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
## Local build configuration | ||
## Parameters configured here will override default and ENV values. | ||
## Uncomment and change examples: | ||
|
||
## Add your source directories here separated by space | ||
# MODULES = app | ||
|
||
# EXTRA_INCDIR = include | ||
|
||
## ESP_HOME sets the path where ESP tools and SDK are located. | ||
## Windows: | ||
# ESP_HOME = c:/Espressif | ||
|
||
## MacOS / Linux: | ||
# ESP_HOME = /opt/esp-open-sdk | ||
|
||
## SMING_HOME sets the path where Sming framework is located. | ||
## Windows: | ||
# SMING_HOME = c:/tools/sming/Sming | ||
|
||
## MacOS / Linux | ||
# SMING_HOME = /opt/sming/Sming | ||
|
||
## COM port parameter is reqruied to flash firmware correctly. | ||
## Windows: | ||
COM_PORT = COM6 | ||
|
||
## MacOS / Linux: | ||
# COM_PORT = /dev/tty.usbserial | ||
|
||
## Com port speed | ||
COM_SPEED = 115200 | ||
|
||
## SPIFFS options | ||
#DISABLE_SPIFFS = 1 | ||
SPIFF_FILES = files | ||
|
||
ENABLE_SSL ?= 1 | ||
|
||
ifneq ($(ENABLE_SSL),1) | ||
# Needed for hmac_md5, etc. | ||
EXTRA_LIBS += ssl | ||
endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Purpose of this Sample Code | ||
To show the basics of sending an email via SMTP | ||
|
||
# SMTP | ||
|
||
When an IOT device detects a malfunction, it is good to be able to notify the user. | ||
We can do that either by sending them an email or via a service like MQTT. | ||
|
||
This sample shows how to send an email via SMTP directly from the ESP8266. | ||
|
||
smtp2go conveniently provides a free account. | ||
|
||
Create an account here: | ||
https://www.smtp2go.com/setupguide/arduino/ . | ||
|
||
It needs some configuration: | ||
* the name of the SMTP server, eg "mail.smtp2go.com" | ||
* a username and password | ||
* the name and email of the person from whom the email will be sent | ||
* the name and email of the person to send the email to | ||
|
||
Edit the sample to replace these values and the SSID etc. | ||
|
Oops, something went wrong.