Add smtp client example

This commit is contained in:
cpq 2022-09-20 11:34:22 +01:00
parent f94a019733
commit 48800504be
9 changed files with 114 additions and 2 deletions

View File

@ -0,0 +1,20 @@
PROG ?= example
CFLAGS ?= -W -Wall -Wextra -O2 $(EXTRA_CFLAGS)
SSL ?= MBEDTLS
ifeq "$(SSL)" "MBEDTLS"
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -lmbedtls -lmbedcrypto -lmbedx509 -L$(MBEDTLS)/lib -I$(MBEDTLS)/include
endif
ifeq "$(SSL)" "OPENSSL"
CFLAGS += -DMG_ENABLE_OPENSSL=1 -lssl -lcrypto -L$(OPENSSL)/lib -I$(OPENSSL)/include
endif
all: $(PROG)
$(RUN) ./$(PROG) $(ARGS)
$(PROG): main.c
$(CC) ../../mongoose.c -I../.. $(CFLAGS) -o $(PROG) main.c
clean:
rm -rf $(PROG) _CL* *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb mbedtls

View File

@ -0,0 +1,5 @@
# SMTP client example
This example shows how to send emails via Gmail.
Before running this example, open main.c and modify settings at the top
of the file.

1
examples/smtp-client/ca.pem Symbolic link
View File

@ -0,0 +1 @@
../../test/data/ca.pem

View File

@ -0,0 +1,80 @@
#include "mongoose.h"
static const char *user = "aaa@gmail.com"; // Change this! Your gmail account
static const char *pass = "xxxxxxxxxxxxx"; // Change this! Your gmail password
static const char *to = "bbb@gmail.com"; // Change this! Destination email
static const char *from = "My Mail Sender";
static const char *subj = "test email from mongoose library!";
static const char *mesg = "Hi!\nThis is a test message.\nBye.";
static bool s_quit;
enum { EHLO, STARTTLS, STARTTLS_WAIT, AUTH, FROM, TO, DATA, BODY, QUIT, END };
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
uint8_t *state = (uint8_t *) c->label;
if (ev == MG_EV_OPEN) {
// c->is_hexdumping = 1;
} else if (ev == MG_EV_READ) {
if (c->recv.len > 0 && c->recv.buf[c->recv.len - 1] == '\n') {
MG_INFO(("<-- %.*s", (int) c->recv.len - 2, c->recv.buf));
c->recv.len = 0;
if (*state == EHLO) {
mg_printf(c, "EHLO gmail.com\r\n");
*state = c->is_tls ? AUTH : STARTTLS;
} else if (*state == STARTTLS) {
mg_printf(c, "STARTTLS\r\n");
*state = STARTTLS_WAIT;
} else if (*state == STARTTLS_WAIT) {
struct mg_tls_opts opts = {.ca = "/tmp/ca.pem"};
mg_tls_init(c, &opts);
*state = EHLO;
} else if (*state == AUTH) {
char a[100], b[300] = "";
size_t n = mg_snprintf(a, sizeof(a), "%c%s%c%s", 0, user, 0, pass);
mg_base64_encode((uint8_t *) a, n, b);
mg_printf(c, "AUTH PLAIN %s\r\n", b);
*state = FROM;
} else if (*state == FROM) {
mg_printf(c, "MAIL FROM: <%s>\r\n", user);
*state = TO;
} else if (*state == TO) {
mg_printf(c, "RCPT TO: <%s>\r\n", to);
*state = DATA;
} else if (*state == DATA) {
mg_printf(c, "DATA\r\n");
*state = BODY;
} else if (*state == BODY) {
mg_printf(c, "From: %s <%s>\r\n", from, user); // Mail header
mg_printf(c, "Subject: %s\r\n", subj); // Mail header
mg_printf(c, "\r\n"); // End of headers
mg_printf(c, "%s\r\n", mesg); // Mail body
mg_printf(c, ".\r\n"); // End of body
*state = QUIT;
} else if (*state == QUIT) {
mg_printf(c, "QUIT\r\n");
*state = END;
} else {
c->is_draining = 1;
MG_INFO(("end"));
}
MG_INFO(("--> %.*s", (int) c->send.len - 2, c->send.buf));
}
} else if (ev == MG_EV_CLOSE) {
s_quit = true;
} else if (ev == MG_EV_TLS_HS) {
MG_INFO(("TLS handshake done!"));
mg_printf(c, "EHLO gmail.com\r\n");
}
(void) fn_data, (void) ev_data;
}
int main(void) {
struct mg_mgr mgr;
mg_mgr_init(&mgr);
// mg_log_set(MG_LL_VERBOSE);
mg_connect(&mgr, "tcp://smtp.gmail.com:587", fn, NULL);
while (s_quit == false) mg_mgr_poll(&mgr, 1000);
return 0;
}

View File

@ -5101,6 +5101,7 @@ void mg_tls_handshake(struct mg_connection *c) {
if (rc == 0) { // Success
MG_DEBUG(("%lu success", c->id));
c->is_tls_hs = 0;
mg_call(c, MG_EV_TLS_HS, NULL);
} else if (rc == MBEDTLS_ERR_SSL_WANT_READ ||
rc == MBEDTLS_ERR_SSL_WANT_WRITE) { // Still pending
MG_VERBOSE(("%lu pending, %d%d %d (-%#x)", c->id, c->is_connecting,
@ -5238,7 +5239,7 @@ size_t mg_tls_pending(struct mg_connection *c) {
long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
struct mg_tls *tls = (struct mg_tls *) c->tls;
long n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len);
if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE)
if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE)
return MG_IO_WAIT;
if (n <= 0) return MG_IO_ERR;
return n;
@ -5375,6 +5376,7 @@ void mg_tls_handshake(struct mg_connection *c) {
if (rc == 1) {
MG_DEBUG(("%lu success", c->id));
c->is_tls_hs = 0;
mg_call(c, MG_EV_TLS_HS, NULL);
} else {
int code = mg_tls_err(tls, rc);
if (code != 0) mg_error(c, "tls hs: rc %d, err %d", rc, code);

View File

@ -993,6 +993,7 @@ enum {
MG_EV_RESOLVE, // Host name is resolved NULL
MG_EV_CONNECT, // Connection established NULL
MG_EV_ACCEPT, // Connection accepted NULL
MG_EV_TLS_HS, // TLS handshake succeeded NULL
MG_EV_READ, // Data received from socket long *bytes_read
MG_EV_WRITE, // Data written to socket long *bytes_written
MG_EV_CLOSE, // Connection closed NULL

View File

@ -13,6 +13,7 @@ enum {
MG_EV_RESOLVE, // Host name is resolved NULL
MG_EV_CONNECT, // Connection established NULL
MG_EV_ACCEPT, // Connection accepted NULL
MG_EV_TLS_HS, // TLS handshake succeeded NULL
MG_EV_READ, // Data received from socket long *bytes_read
MG_EV_WRITE, // Data written to socket long *bytes_written
MG_EV_CLOSE, // Connection closed NULL

View File

@ -48,6 +48,7 @@ void mg_tls_handshake(struct mg_connection *c) {
if (rc == 0) { // Success
MG_DEBUG(("%lu success", c->id));
c->is_tls_hs = 0;
mg_call(c, MG_EV_TLS_HS, NULL);
} else if (rc == MBEDTLS_ERR_SSL_WANT_READ ||
rc == MBEDTLS_ERR_SSL_WANT_WRITE) { // Still pending
MG_VERBOSE(("%lu pending, %d%d %d (-%#x)", c->id, c->is_connecting,
@ -185,7 +186,7 @@ size_t mg_tls_pending(struct mg_connection *c) {
long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
struct mg_tls *tls = (struct mg_tls *) c->tls;
long n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len);
if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE)
if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE)
return MG_IO_WAIT;
if (n <= 0) return MG_IO_ERR;
return n;

View File

@ -116,6 +116,7 @@ void mg_tls_handshake(struct mg_connection *c) {
if (rc == 1) {
MG_DEBUG(("%lu success", c->id));
c->is_tls_hs = 0;
mg_call(c, MG_EV_TLS_HS, NULL);
} else {
int code = mg_tls_err(tls, rc);
if (code != 0) mg_error(c, "tls hs: rc %d, err %d", rc, code);