MQTT and Multiple Connections for Transmission Wifi

(I apologize if this forum is not the appropriate place for these questions)

I would like to know if there is any kind of limitation.

In multiple connections wifi connections.

I have a product that connects to the internet via wifi.

I can make two MQTT connections with different or the same brokers work perfectly.

This is a requirement of my application.

However, I need to send an email. However, if mqtt is enabled, there are many errors generated when mqtt is enabled.

I use the ESP IDF 5 and MQTT Library, my code for the email is changed for the esp idf sample

My code the MQTT is:

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#include <float.h>
#include "esp_log.h"
#include "cJSON.h"
#include "mqtt_client.h"

#include "f_mqtt.h"
#include "f_config.h"
#include "f_licenca.h"
#include "f_nvs.h"
#include "f_configfile.h"
#include "f_wifi.h"
#include "f_ota.h"

EventGroupHandle_t xEventGroupMQTT_In;
EventGroupHandle_t xEventGroupMQTT_Out;
#define MQTT_In_BIT (1 << 0)
#define MQTT_Out_BIT (1 << 0)

//const int MQTT_CONNECTED_BIT = BIT0;
static const char *TAG = "MQTT";
esp_mqtt_client_handle_t cMqttIn;
esp_mqtt_client_handle_t cMqttOut;

static void log_error_if_nonzero(const char *message, int error_code){if (error_code != 0) {ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);}}

//-----------------------------------------------------------------------------------------------------------------------
//--------------------------------MQTT In (Usuario)----------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
        static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data){
            ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
            esp_mqtt_event_handle_t event = event_data;
            //esp_mqtt_client_handle_t client = event->client;
            switch ((esp_mqtt_event_id_t)event_id) {
            case MQTT_EVENT_CONNECTED:
                ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED - MQTT-IN(Usuario)");
                xEventGroupSetBits(xEventGroupMQTT_In, MQTT_In_BIT);
                if (xEventGroupMQTT_In != NULL) {xEventGroupSetBits(xEventGroupMQTT_In, MQTT_In_BIT);} 
                break;
            case MQTT_EVENT_DISCONNECTED:
                ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED - MQTT-IN(Usuario)");
                xEventGroupClearBits(xEventGroupMQTT_In, MQTT_In_BIT);
                break;
            case MQTT_EVENT_DATA:
                f_SendDataMqtt(strndup(event->topic, event->topic_len), strndup(event->data, event->data_len), false);
                break;
            case MQTT_EVENT_ERROR:
                ESP_LOGI(TAG, "MQTT_EVENT_ERROR - MQTT-IN(Usuario)");
                if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
                    log_error_if_nonzero("(MQTT-IN Usuario) - reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
                    log_error_if_nonzero("(MQTT-IN Usuario) - reported from tls stack", event->error_handle->esp_tls_stack_err);
                    log_error_if_nonzero("(MQTT-IN Usuario) - captured as transport's socket errno",  event->error_handle->esp_transport_sock_errno);
                    ESP_LOGI(TAG, "(MQTT-IN Usuario) - Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
                }
                break;
            default:
                ESP_LOGI(TAG, "(MQTT-IN Usuario) - Other event id:%d - MQTT-IN(Usuario)", event->event_id);
                break;
            }
        }
//-----------------------------------------------------------------------------------------------------------------------
//---MQTT OUT(LICENCA DA ENERVISION)-------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
        static void mqtt_event_handler_out(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data){
            ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
            esp_mqtt_event_handle_t event = event_data;
            esp_mqtt_client_handle_t client = event->client;
            switch ((esp_mqtt_event_id_t)event_id) {
            case MQTT_EVENT_CONNECTED:
                ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED - MQTT-OUT(Licenca Enervision)");
                esp_mqtt_client_subscribe(client, TOPICO_OTA, 0);
                esp_mqtt_client_subscribe(client, f_topico(TOPICO_LICENCA), 0);
                f_mqttPublica(f_topico(zMQTT_sufixo), f_prepJsonConfig(mqtt_ON), cMqttOut);
                f_mqttPublica(f_topico(zMQTT_sufixo_Config), f_prepJsonConfig(mqtt_Config), cMqttOut);
                xEventGroupSetBits(xEventGroupMQTT_Out, MQTT_Out_BIT);
                break;
            case MQTT_EVENT_DISCONNECTED:
                ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED - MQTT-OUT(Licenca Enervision)");
                xEventGroupClearBits(xEventGroupMQTT_Out, MQTT_Out_BIT);
                break;
            case MQTT_EVENT_DATA:
                ESP_LOGI(TAG, "MQTT_EVENT_DATA - MQTT-OUT(Licenca Enervision)");
                printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
                printf("DATA=%.*s\r\n", event->data_len, event->data);
                //Testa qual tópico foi recebido e começa a fazer as coisas conforme o tópico
                if (strncmp(event->topic, TOPICO_OTA, event->topic_len) == 0) {
                    f_otaMQTT(event->topic, event->topic_len, event->data, event->data_len);
                }
                if (strncmp(event->topic, f_topico(TOPICO_LICENCA), event->topic_len) == 0) {
                    cJSON *token = cJSON_GetObjectItem(cJSON_Parse((char *)event->data), "token");
                    if (!cJSON_IsString(token)){ESP_LOGE(TAG, "Erro na leitura do json");}
                    f_nvsSet(zTokenTemp, token->valuestring, false);
                    xTaskCreatePinnedToCore(v_InsertLicenca, "v_InsertLicenca", 8000, NULL, tskIDLE_PRIORITY, NULL, tskNO_AFFINITY);
                }
                break;
            case MQTT_EVENT_ERROR:
                ESP_LOGI(TAG, "MQTT_EVENT_ERROR - MQTT-OUT(Licenca Enervision)");
                if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
                    log_error_if_nonzero("(MQTT-OUT Licenca Enervision) - reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
                    log_error_if_nonzero("r(MQTT-OUT Licenca Enervision) - eported from tls stack", event->error_handle->esp_tls_stack_err);
                    log_error_if_nonzero("(MQTT-OUT Licenca Enervision) - captured as transport's socket errno",  event->error_handle->esp_transport_sock_errno);
                    ESP_LOGI(TAG, "(MQTT-OUT Licenca Enervision) - Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
                }
                break;
            default:
                ESP_LOGI(TAG, "Other event id:%d  - MQTT-OUT(Licenca Enervision)", event->event_id);
                break;
            }
        }

void f_mqttPublica(const char * topico, const char * payload, esp_mqtt_client_handle_t handle){
     EventBits_t bits = xEventGroupWaitBits(xEventGroupWifi, WIFI_BIT_0, pdFALSE, pdFALSE, 200);
     if((bits & WIFI_BIT_0)){
          int len = strlen(payload);
          int resp = esp_mqtt_client_publish(handle, topico, payload, len, 0, 0);
          if (resp==0){
            //  ESP_LOGI(TAG, "JSON publicado via MQTT. Com sucesso");
          }else if(resp<0){
             ESP_LOGE(TAG, "Publicação não enviada. Erro");
          }
     }
}

void f_setupMQTT_In(void *pvParameters){
        xEventGroupMQTT_In = xEventGroupCreate();
        Dados_Mqtt_t DadosMqtt;
        if(f_DadosMqtt(&DadosMqtt, mqtt_IN) == ESP_OK){  
                bool is_secure = strstr(DadosMqtt.mqtt_server, "mqtts://") == DadosMqtt.mqtt_server;
                esp_mqtt_client_config_t mqtt_cfg = {
                    .broker.address.uri = DadosMqtt.mqtt_server,
                    .broker.address.port = DadosMqtt.mqtt_port,
                    .credentials.username = DadosMqtt.mqtt_user,
                    .credentials.authentication.password = DadosMqtt.mqtt_pass,
                    .credentials.client_id = f_mqttId_In(),
                    .session.last_will.msg = f_prepJsonConfig(mqtt_OFF),
                    .session.last_will.msg_len = strlen(f_prepJsonConfig(mqtt_OFF)),
                    .session.last_will.topic = f_topico(zMQTT_sufixo),
                    .session.last_will.retain = true,
                    .session.last_will.qos = 1,
                    .session.keepalive = 120, // DadosMqtt.mqtt_keepalive
                    //.task.stack_size = 3200,
                    //.task.priority = tskIDLE_PRIORITY + 1
                };
                if (is_secure) {
                    char *cert_data = f_lerCertificado(DadosMqtt.mqtt_cert);
                    if (cert_data != NULL) {
                        mqtt_cfg.broker.verification.certificate = cert_data;
                        mqtt_cfg.broker.verification.certificate_len = strlen(cert_data) + 1;
                    } else {
                        ESP_LOGE("MQTT", "Falha ao carregar o certificado: %s", DadosMqtt.mqtt_cert);
                    }
                }
                EventBits_t bits = xEventGroupWaitBits(xEventGroupWifi, WIFI_BIT_0, pdFALSE, pdFALSE, portMAX_DELAY);
                if((bits & WIFI_BIT_0)){
                        cMqttIn = esp_mqtt_client_init(&mqtt_cfg);
                        esp_mqtt_client_register_event(cMqttIn, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
                        esp_mqtt_client_start(cMqttIn);
                }
        }
        vTaskDelete(NULL);
}

void f_setupMQTT_Out(void *pvParameters){
        xEventGroupMQTT_Out = xEventGroupCreate();
        Dados_Mqtt_t DadosMqttout;
        if(f_DadosMqtt(&DadosMqttout, mqtt_OUT) == ESP_OK){
                bool is_secure = strstr(DadosMqttout.mqtt_server, "mqtts://") == DadosMqttout.mqtt_server;
                esp_mqtt_client_config_t mqtt_cfg_out = {
                    .broker.address.uri = DadosMqttout.mqtt_server,
                    .broker.address.port = DadosMqttout.mqtt_port,
                    .credentials.username = DadosMqttout.mqtt_user,
                    .credentials.authentication.password = DadosMqttout.mqtt_pass,
                    .credentials.client_id = f_mqttId_Out(),
                    .session.last_will.msg = f_prepJsonConfig(mqtt_OFF),
                    .session.last_will.msg_len = strlen(f_prepJsonConfig(mqtt_OFF)),
                    .session.last_will.topic = f_topico(zMQTT_sufixo),
                    .session.last_will.retain = true,
                    .session.last_will.qos = 1,
                    .session.keepalive = 120, // DadosMqttout.mqtt_keepalive
                    //.task.stack_size = 3200,
                    //.task.priority = tskIDLE_PRIORITY + 1
                };
                if (is_secure) {
                    char *cert_data_out = f_lerCertificado(DadosMqttout.mqtt_cert);
                    if (cert_data_out != NULL) {
                        mqtt_cfg_out.broker.verification.certificate = cert_data_out;
                        mqtt_cfg_out.broker.verification.certificate_len = strlen(cert_data_out) + 1;
                    } else {
                        ESP_LOGE("MQTT", "Falha ao carregar o certificado: %s", DadosMqttout.mqtt_cert);
                    }
                }
                EventBits_t bits = xEventGroupWaitBits(xEventGroupWifi, WIFI_BIT_0, pdFALSE, pdFALSE, portMAX_DELAY);
                if((bits & WIFI_BIT_0)){
                        cMqttOut = esp_mqtt_client_init(&mqtt_cfg_out);
                        esp_mqtt_client_register_event(cMqttOut, ESP_EVENT_ANY_ID, mqtt_event_handler_out, NULL);
                        esp_mqtt_client_start(cMqttOut);
                }
        }
        vTaskDelete(NULL);
}


void f_startRestartMQTT_In()  {xTaskCreate(f_restartMQTT_In, "f_setupMQTT_In", 3000, NULL, tskIDLE_PRIORITY, NULL);}
void f_startRestartMQTT_Out() {xTaskCreate(f_restartMQTT_Out, "f_setupMQTT_Out", 3000, NULL, tskIDLE_PRIORITY, NULL);}

void f_restartMQTT_In(void *pvParameters){
        ESP_LOGI(TAG, "Reiniciando MQTT_In");
        if (xEventGroupGetBits(xEventGroupMQTT_In) & MQTT_In_BIT) {
            esp_mqtt_client_stop(cMqttIn);  // Para o cliente MQTT
            ESP_LOGI(TAG, "Stop MQTT_In");
        }
        ESP_LOGI(TAG, "Aguardando...Stop MQTT");
        xEventGroupWaitBits(xEventGroupMQTT_In, MQTT_In_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
        xTaskCreate(f_setupMQTT_In, "f_setupMQTT_In", 3000, NULL, tskIDLE_PRIORITY, NULL);
        ESP_LOGI(TAG, "Startado MQTT_In");
        vTaskDelete(NULL);  // Exclui a task após a execução
}

void f_restartMQTT_Out(void *pvParameters){
        ESP_LOGI(TAG, "Reiniciando MQTT_Out");
        if (xEventGroupGetBits(xEventGroupMQTT_Out) & MQTT_Out_BIT) {
            esp_mqtt_client_stop(cMqttOut);  // Para o cliente MQTT
            ESP_LOGI(TAG, "Stop MQTT_Out");
        }
        ESP_LOGI(TAG, "Aguardando...Stop MQTT Out");
        xEventGroupWaitBits(xEventGroupMQTT_Out, MQTT_Out_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
        xTaskCreate(f_setupMQTT_Out, "f_setupMQTT_Out", 3000, NULL, tskIDLE_PRIORITY, NULL);
        ESP_LOGI(TAG, "Startado MQTT_Out");
        vTaskDelete(NULL);  // Exclui a task após a execução
}
void f_startMQTT_In(){
        xTaskCreate(f_setupMQTT_In, "f_setupMQTT_In", 3000, NULL, tskIDLE_PRIORITY, NULL);
        ESP_LOGI(TAG, "Startado MQTT_In");
}

void f_startMQTT_Out(){
    xTaskCreate(f_setupMQTT_Out, "f_setupMQTT_Out", 3000, NULL, tskIDLE_PRIORITY, NULL);
    ESP_LOGI(TAG, "Startado MQTT_Out");
}

void f_stopMQTT_In(){
        ESP_LOGI(TAG, "Stopando MQTT_In");
        if (xEventGroupGetBits(xEventGroupMQTT_In) & MQTT_In_BIT) {
            esp_mqtt_client_disconnect(cMqttIn);
            esp_mqtt_client_stop(cMqttIn);
            esp_mqtt_client_destroy(cMqttIn);
            ESP_LOGI(TAG, "Procedimentos de Stop do MQTT_In - Realizado");
        }
}

void f_stopMQTT_Out(){
        ESP_LOGI(TAG, "Stopando MQTT_Out");
        if (xEventGroupGetBits(xEventGroupMQTT_Out) & MQTT_Out_BIT) {
            esp_mqtt_client_disconnect(cMqttOut);
            esp_mqtt_client_stop(cMqttOut);
            esp_mqtt_client_destroy(cMqttOut);
            ESP_LOGI(TAG, "Procedimentos de Stop do MQTT_Out - Realizado");
        }
}


char* f_topico(const char* sufixo) {
        int tamanho = snprintf(NULL, 0, "%s/%s/%s", TOPICO_PREFIXO, f_serialNumber(), sufixo);
        char* topico = (char*)malloc(tamanho + 1);
        if (topico == NULL) {return NULL;}
        snprintf(topico, tamanho + 1, "%s/%s/%s", TOPICO_PREFIXO, f_serialNumber(), sufixo);
        return topico;
}

void f_otaMQTT(char * topico, int tam_Topico, char * payload, int tam_Payload){
        ESP_LOGW(TAG, "Recebi um pedido para atualizar o software");
        char *url_dynamic = (char *)malloc(tam_Payload + 1);
        if (url_dynamic != NULL) {
            strncpy(url_dynamic, payload, tam_Payload);
            url_dynamic[tam_Payload] = '\0';
            f_startOTA(url_dynamic);
        } else {
            ESP_LOGE(TAG, "Failed to allocate memory for URL");
        }
}

char * f_prepJsonConfig(prepMQTT_t tipo){
        Dados_Licenca_t DadosLicenca;
        f_DadosLicenca(&DadosLicenca);
        cJSON *json = cJSON_CreateObject();
        cJSON_AddStringToObject(json, "serial", f_serialNumber());
        if (tipo == mqtt_Config){
            cJSON_AddStringToObject(json, "versao-firmware", DadosLicenca.VersaoFirmware ? DadosLicenca.VersaoFirmware : "");
            cJSON_AddStringToObject(json, "data-update", DadosLicenca.DataFirmware ? DadosLicenca.DataFirmware : "");
            cJSON_AddStringToObject(json, "listen-topic", TOPICO_OTA);
            cJSON_AddStringToObject(json, "hardware", Serial_Prefix);
            cJSON_AddStringToObject(json, "usuario", DadosLicenca.Usuario);
            cJSON_AddStringToObject(json, "tipo-licenca", DadosLicenca.TipoLicenca);
            cJSON_AddNumberToObject(json, "tempo-validade", DadosLicenca.tempovalidade);
            cJSON_AddNumberToObject(json, "licence-count", DadosLicenca.licencecount);
        }
        if(tipo == mqtt_ON) {cJSON_AddStringToObject(json, "status", "ON");}
        if(tipo == mqtt_OFF){cJSON_AddStringToObject(json, "status", "OFF");}
        char *json_str = cJSON_PrintUnformatted(json);
        cJSON_Delete(json);
        return json_str;
}

esp_err_t f_DadosMqtt(Dados_Mqtt_t *data, connMQTT_t conn){
        cJSON *oJson;
        if (conn == mqtt_IN){
            oJson = read_json_file(FILE_MQTT_JSON);
        } else{
            oJson = read_json_file(FILE_MQTT_OUT_JSON);
        }
        
        if (oJson!=NULL){
            data->mqtt_server = cJSON_GetStringValue(cJSON_GetObjectItem(oJson, "mqtt_server"));
            data->mqtt_port = strtoul(cJSON_GetStringValue(cJSON_GetObjectItem(oJson, "mqtt_port")), NULL, 10);
            data->mqtt_user = cJSON_GetStringValue(cJSON_GetObjectItem(oJson, "mqtt_user"));
            data->mqtt_pass = cJSON_GetStringValue(cJSON_GetObjectItem(oJson, "mqtt_pass"));
            data->mqtt_cert = cJSON_GetStringValue(cJSON_GetObjectItem(oJson, "mqtt_cert"));
            data->mqtt_cert_len = data->mqtt_cert ? strlen(data->mqtt_cert) : 0;
            if (data->mqtt_server == NULL)  {ESP_LOGW(TAG, "Chave não encontrada (mqtt_server)");return ESP_FAIL;}
            if (data->mqtt_port == 0)       {ESP_LOGW(TAG, "Chave não encontrada (mqtt_port)"); return ESP_FAIL;}
            if (data->mqtt_user == NULL)    {ESP_LOGW(TAG, "Chave não encontrada (mqtt_user)");return ESP_FAIL;}
            if (data->mqtt_pass == NULL)    {ESP_LOGW(TAG, "Chave não encontrada (mqtt_pass)");return ESP_FAIL;}
            bool is_secure = strstr(data->mqtt_server, "mqtts://") == data->mqtt_server;
            if(is_secure){
                if (data->mqtt_cert == NULL)    {ESP_LOGW(TAG, "Conteudo vazio ou chave não encontrada (mqtt_cert)");return ESP_FAIL;}
                if (data->mqtt_cert_len < 10)   {ESP_LOGW(TAG, "Conteudo vazio ou chave não encontrada (mqtt_cert_len)");return ESP_FAIL;}
            }
            return ESP_OK;
        }
        return ESP_FAIL;
}

bool f_ValidaTopico(const char *topic) {
        if (topic == NULL || strlen(topic) == 0) {return false;}
        int len = strlen(topic);
        if (len > 65535) {return false;}
        for (int i = 0; i < len; i++) {
            if (iscntrl((unsigned char)topic[i])) {
                return false;
            }
        }
        // Verificar regras específicas de MQTT para os caracteres '+' e '#'
        for (int i = 0; i < len; i++) {
            if (topic[i] == '+') {
                // O caractere '+' deve estar sozinho em um nível
                if (i > 0 && topic[i-1] != '/') return false;
                if (i < len - 1 && topic[i+1] != '/') return false;
            } else if (topic[i] == '#') {
                // O caractere '#' só pode estar no final do tópico
                if (i != len - 1) return false;
                if (i > 0 && topic[i-1] != '/') return false;
            } else if (topic[i] == '/' && i < len - 1 && topic[i+1] == '/') {
                // Verificar se há dois '/' consecutivos
                return false;
            }
        }
        return true;
}

void f_subscribe(char * topico){
        esp_mqtt_client_subscribe(cMqttIn, topico, 0);
        ESP_LOGW(TAG, "Topico[%s] assinado", topico);
}

char *strndup(const char *src, size_t len) {
        char *dst = (char *)malloc(len + 1);
        if (dst) {
            memcpy(dst, src, len);
            dst[len] = '\0';
        }
        return dst;
}

char* f_mqttId_In() {
        int tamanho = snprintf(NULL, 0, "%s:%s", "user", f_serialNumber());
        char* msg = (char*)malloc(tamanho + 1);
        if (msg == NULL) {return NULL;}
        snprintf(msg, tamanho + 1, "%s:%s", "user", f_serialNumber());
        return msg;
}
char* f_mqttId_Out() {
        int tamanho = snprintf(NULL, 0, "%s:%s", "enervision", f_serialNumber());
        char* msg = (char*)malloc(tamanho + 1);
        if (msg == NULL) {return NULL;}
        snprintf(msg, tamanho + 1, "%s:%s", "enervision", f_serialNumber());
        return msg;
}


void f_SendDataMqtt(char *topico, char *payload, bool Print) {

}


and my code for send mail is:

#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "mbedtls/platform.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/esp_debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include <mbedtls/base64.h>
#include <sys/param.h>
#include "f_email.h"
#include "f_wifi.h"
#include "f_validaemail.h"
#include "f_configfile.h"
#include "cJSON.h"
#include <stdio.h>
#include "f_mqtt.h"

static const char *TAG = "EMAIL";

#define VALIDATE_MBEDTLS_RETURN(ret, min_valid_ret, max_valid_ret, goto_label)  \
    do {                                                                        \
        if (ret < min_valid_ret || ret > max_valid_ret) {                       \
            goto goto_label;                                                    \
        }                                                                       \
    } while (0)                                                                 \

static int write_ssl_and_get_response(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len){
            int ret;
            const size_t DATA_SIZE = 128;
            unsigned char data[DATA_SIZE];
            char code[4];
            size_t i, idx = 0;
            if (len) {ESP_LOGD(TAG, "%s", buf);}
            while (len && (ret = mbedtls_ssl_write(ssl, buf, len)) <= 0) {
                    if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {ESP_LOGE(TAG, "mbedtls_ssl_write failed with error -0x%x", -ret);
                        goto exit;
                    }
            }
            do {
                    len = DATA_SIZE - 1;
                    memset(data, 0, DATA_SIZE);
                    ret = mbedtls_ssl_read(ssl, data, len);

                    if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
                        continue;
                    }

                    if (ret <= 0) {
                        ESP_LOGE(TAG, "mbedtls_ssl_read failed with error -0x%x", -ret);
                        goto exit;
                    }
                    ESP_LOGD(TAG, "%s", data);
                    len = ret;
                    for (i = 0; i < len; i++) {
                        if (data[i] != '\n') {
                            if (idx < 4) {
                                code[idx++] = data[i];
                            }
                            continue;
                        }

                        if (idx == 4 && code[0] >= '0' && code[0] <= '9' && code[3] == ' ') {
                            code[3] = '\0';
                            ret = atoi(code);
                            goto exit;
                        }

                        idx = 0;
                    }
            } while (1);
    exit:
            return ret;
}


static int perform_tls_handshake(mbedtls_ssl_context *ssl) {
            int ret = -1;
            uint32_t flags;
            char *buf = NULL;
            size_t buf_size = 0;

            ESP_LOGI(TAG, "Performing the SSL/TLS handshake...");

            fflush(stdout);
            while ((ret = mbedtls_ssl_handshake(ssl)) != 0) {
                if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
                    ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%x", -ret);
                    return ret;  // Retorna imediatamente em caso de erro
                }
            }

            ESP_LOGI(TAG, "Verifying peer X.509 certificate...");
            flags = mbedtls_ssl_get_verify_result(ssl);

            if (flags != 0) {
                ESP_LOGW(TAG, "Failed to verify peer certificate!");

                // Calcula o tamanho necessário para o buffer
                buf_size = mbedtls_x509_crt_verify_info(NULL, 0, "  ! ", flags) + 1;  // +1 para o caractere nulo
                buf = (char *)malloc(buf_size);
                if (buf == NULL) {
                    ESP_LOGE(TAG, "Falha ao alocar memória para o buffer de verificação do certificado.");
                    return -1;  // Retorna imediatamente em caso de falha de alocação
                }

                // Preenche o buffer com as informações de verificação
                mbedtls_x509_crt_verify_info(buf, buf_size, "  ! ", flags);
                ESP_LOGW(TAG, "Verification info: %s", buf);

                // Libera o buffer após o uso
                free(buf);
            } else {
                ESP_LOGI(TAG, "Certificate verified.");
            }

            ESP_LOGI(TAG, "Cipher suite is %s", mbedtls_ssl_get_ciphersuite(ssl));

            return 0;  // Nenhum erro
}

mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_net_context server_fd;

bool f_conecta(email_params_t *params) {
            char *buf = NULL;
            int ret, len;
            mbedtls_ssl_init(&ssl);
            mbedtls_ctr_drbg_init(&ctr_drbg);
            mbedtls_ssl_config_init(&conf);
            mbedtls_entropy_init(&entropy);
            ESP_LOGI(TAG, "Seeding the random number generator");
            ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
            if (ret != 0) {ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%x", -ret);return false;}
            ESP_LOGI(TAG, "Setting up the SSL/TLS structure...");
            ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
            if (ret != 0) {ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned -0x%x", -ret);return false;}
            mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE);  // Desativa a verificação do certificado
            mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
            ret = mbedtls_ssl_setup(&ssl, &conf);
            if (ret != 0) {ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x", -ret);return false;}
            mbedtls_net_init(&server_fd);
            ESP_LOGI(TAG, "Connecting to %s:%s...", params->server, params->port);
            ret = mbedtls_net_connect(&server_fd, params->server, params->port, MBEDTLS_NET_PROTO_TCP);
            if (ret != 0) {ESP_LOGE(TAG, "mbedtls_net_connect returned -0x%x", -ret);return false;}
            ESP_LOGI(TAG, "Connected.");
            mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
            ret = perform_tls_handshake(&ssl);
            if (ret != 0) {return false;}
            ret = write_ssl_and_get_response(&ssl, NULL, 0);
            if (ret < 200 || ret > 299) {return false;}
            ESP_LOGI(TAG, "Writing EHLO to server...");
            len = snprintf(NULL, 0, "EHLO %s\r\n", "ESP32");
            if (len < 0) {ESP_LOGE(TAG, "Erro ao calcular tamanho para EHLO.");return false;}
            buf = (char *)malloc(len + 1);  // +1 para o caractere nulo
            if (buf == NULL) {ESP_LOGE(TAG, "Falha ao alocar memória.");return false;}
            snprintf(buf, len + 1, "EHLO %s\r\n", "ESP32");
            ret = write_ssl_and_get_response(&ssl, (unsigned char *)buf, len);
            free(buf);  // Libera o buffer após uso
            if (ret < 200 || ret > 299) {return false;}
            return true;
}

bool f_autentica(email_params_t *params) {
            int ret, len;
            unsigned char base64_buffer[128];
            size_t base64_len;
            char *buf = NULL;

            ESP_LOGI(TAG, "Authentication...");

            // Calcula o tamanho necessário para "AUTH LOGIN" e aloca o buffer
            len = snprintf(NULL, 0, "AUTH LOGIN\r\n");
            if (len < 0) {
                ESP_LOGE(TAG, "Erro ao calcular o tamanho para AUTH LOGIN.");
                return false;
            }

            buf = (char *)malloc(len + 1);  // +1 para o caractere nulo
            if (buf == NULL) {
                ESP_LOGE(TAG, "Falha ao alocar memória.");
                return false;
            }

            // Preenche o buffer com o comando "AUTH LOGIN"
            snprintf(buf, len + 1, "AUTH LOGIN\r\n");

            // Envia o comando "AUTH LOGIN"
            ret = write_ssl_and_get_response(&ssl, (unsigned char *)buf, len);
            free(buf);  // Libera o buffer após uso
            if (ret < 200 || ret > 399) {
                return false;
            }

            ESP_LOGI(TAG, "Write USER NAME");

            // Codifica o e-mail em Base64
            ret = mbedtls_base64_encode(base64_buffer, sizeof(base64_buffer), &base64_len, (unsigned char *)params->authorEmail, strlen(params->authorEmail));
            if (ret != 0) {
                ESP_LOGE(TAG, "Erro ao codificar o nome de usuário! ret = -0x%x", -ret);
                return false;
            }

            // Calcula o tamanho necessário para o nome de usuário codificado e aloca o buffer
            len = snprintf(NULL, 0, "%s\r\n", base64_buffer);
            if (len < 0) {
                ESP_LOGE(TAG, "Erro ao calcular o tamanho para o nome de usuário.");
                return false;
            }

            buf = (char *)malloc(len + 1);
            if (buf == NULL) {
                ESP_LOGE(TAG, "Falha ao alocar memória.");
                return false;
            }

            // Preenche o buffer com o nome de usuário codificado
            snprintf(buf, len + 1, "%s\r\n", base64_buffer);

            // Envia o nome de usuário codificado
            ret = write_ssl_and_get_response(&ssl, (unsigned char *)buf, len);
            free(buf);  // Libera o buffer após uso
            if (ret < 300 || ret > 399) {
                return false;
            }

            ESP_LOGI(TAG, "Write PASSWORD");

            // Codifica a senha em Base64
            ret = mbedtls_base64_encode(base64_buffer, sizeof(base64_buffer), &base64_len, (unsigned char *)params->password, strlen(params->password));
            if (ret != 0) {
                ESP_LOGE(TAG, "Erro ao codificar a senha! ret = -0x%x", -ret);
                return false;
            }

            // Calcula o tamanho necessário para a senha codificada e aloca o buffer
            len = snprintf(NULL, 0, "%s\r\n", base64_buffer);
            if (len < 0) {
                ESP_LOGE(TAG, "Erro ao calcular o tamanho para a senha.");
                return false;
            }

            buf = (char *)malloc(len + 1);
            if (buf == NULL) {
                ESP_LOGE(TAG, "Falha ao alocar memória.");
                return false;
            }

            // Preenche o buffer com a senha codificada
            snprintf(buf, len + 1, "%s\r\n", base64_buffer);

            // Envia a senha codificada
            ret = write_ssl_and_get_response(&ssl, (unsigned char *)buf, len);
            free(buf);  // Libera o buffer após uso
            if (ret < 200 || ret > 399) {
                return false;
            }

            ESP_LOGI(TAG, "Autenticacao concluida com sucesso.");
            return true;
}


bool f_ComporEmail(email_params_t *params) {
            int ret, len;
            char *buf = NULL;

            ESP_LOGI(TAG, "Write MAIL FROM");

            // Calcula o tamanho necessário para o comando "MAIL FROM"
            len = snprintf(NULL, 0, "MAIL FROM:<%s>\r\n", params->authorEmail);
            if (len < 0) {
                ESP_LOGE(TAG, "Erro ao calcular tamanho para MAIL FROM.");
                return false;
            }

            // Aloca buffer para "MAIL FROM"
            buf = (char *)malloc(len + 1);  // +1 para o caractere nulo
            if (buf == NULL) {
                ESP_LOGE(TAG, "Falha ao alocar memória.");
                return false;
            }

            // Preenche o buffer com o comando "MAIL FROM"
            snprintf(buf, len + 1, "MAIL FROM:<%s>\r\n", params->authorEmail);

            // Envia o comando "MAIL FROM"
            ret = write_ssl_and_get_response(&ssl, (unsigned char *)buf, len);
            free(buf);  // Libera o buffer após uso
            if (ret < 200 || ret > 299) {
                ESP_LOGE(TAG, "Falha ao enviar MAIL FROM");
                return false;
            }

            ESP_LOGI(TAG, "Write RCPT");

            // Calcula o tamanho necessário para o comando "RCPT TO"
            len = snprintf(NULL, 0, "RCPT TO:<%s>\r\n", params->toEmail);
            if (len < 0) {
                ESP_LOGE(TAG, "Erro ao calcular tamanho para RCPT TO.");
                return false;
            }

            // Aloca buffer para "RCPT TO"
            buf = (char *)malloc(len + 1);
            if (buf == NULL) {
                ESP_LOGE(TAG, "Falha ao alocar memória.");
                return false;
            }

            // Preenche o buffer com o comando "RCPT TO"
            snprintf(buf, len + 1, "RCPT TO:<%s>\r\n", params->toEmail);

            // Envia o comando "RCPT TO"
            ret = write_ssl_and_get_response(&ssl, (unsigned char *)buf, len);
            free(buf);  // Libera o buffer após uso
            if (ret < 200 || ret > 299) {
                ESP_LOGE(TAG, "Falha ao enviar RCPT TO");
                return false;
            }

            ESP_LOGI(TAG, "Write DATA");

            // Calcula o tamanho necessário para o comando "DATA"
            len = snprintf(NULL, 0, "DATA\r\n");
            if (len < 0) {
                ESP_LOGE(TAG, "Erro ao calcular tamanho para DATA.");
                return false;
            }

            // Aloca buffer para o comando "DATA"
            buf = (char *)malloc(len + 1);
            if (buf == NULL) {
                ESP_LOGE(TAG, "Falha ao alocar memória.");
                return false;
            }

            // Preenche o buffer com o comando "DATA"
            snprintf(buf, len + 1, "DATA\r\n");

            // Envia o comando "DATA"
            ret = write_ssl_and_get_response(&ssl, (unsigned char *)buf, len);
            free(buf);  // Libera o buffer após uso
            if (ret < 300 || ret > 399) {
                ESP_LOGE(TAG, "Falha ao enviar DATA");
                return false;
            }

            ESP_LOGI(TAG, "Escrevendo conteúdo do email em HTML...");

            // Calcula o tamanho necessário para o conteúdo do e-mail
            len = snprintf(NULL, 0,
                        "From: \"%s\" <%s>\r\n"
                        "To: \"%s\" <%s>\r\n"
                        "Subject: %s\r\n"
                        "MIME-Version: 1.0\r\n"
                        "Content-Type: text/html; charset=\"UTF-8\"\r\n\r\n"
                        "%s\r\n.\r\n",
                        params->authorName, params->authorEmail, params->toName, params->toEmail, params->subject, params->msgBody);
            if (len < 0) {
                ESP_LOGE(TAG, "Erro ao calcular tamanho para o conteúdo do email.");
                return false;
            }

            // Aloca buffer para o conteúdo do e-mail
            buf = (char *)malloc(len + 1);
            if (buf == NULL) {
                ESP_LOGE(TAG, "Falha ao alocar memória.");
                return false;
            }

            // Preenche o buffer com o conteúdo do e-mail
            snprintf(buf, len + 1,
                    "From: \"%s\" <%s>\r\n"
                    "To: \"%s\" <%s>\r\n"
                    "Subject: %s\r\n"
                    "MIME-Version: 1.0\r\n"
                    "Content-Type: text/html; charset=\"UTF-8\"\r\n\r\n"
                    "%s\r\n.\r\n",
                    params->authorName, params->authorEmail, params->toName, params->toEmail, params->subject, params->msgBody);

            // Envia o conteúdo do e-mail
            ret = write_ssl_and_get_response(&ssl, (unsigned char *)buf, len);
            free(buf);  // Libera o buffer após uso
            if (ret < 200 || ret > 299) {
                ESP_LOGE(TAG, "Falha ao enviar conteúdo do email.");
                return false;
            }

            ESP_LOGI(TAG, "Email composto com sucesso");
            return true;
}

char* allocate_buffer(size_t size) {
            char *buf = (char *)malloc(size);
            if (buf == NULL) {
                ESP_LOGE(TAG, "Falha ao alocar memória.");
            }
            return buf;
}

char* f_prepFilename(char *filename) {
        if (filename[0] == '/') {
            return filename + 1;  // Retorna o ponteiro para o segundo caractere da string
        }
        return filename;  // Se não houver barra, retorna o nome original
}

char* f_generateEmailHeader(email_params_t *params, char* attachment_path, size_t *buf_len) {
        if (params->toEmail2 != NULL && strlen(params->toEmail2) > 0) {
            *buf_len = snprintf(NULL, 0,
                "From: \"%s\" <%s>\r\n"
                "To: \"%s\" <%s>\r\n"
                "Cc: \"%s\" <%s>\r\n"
                "Subject: %s\r\n"
                "MIME-Version: 1.0\r\n"
                "Content-Type: multipart/mixed; boundary=\"XYZabcd1234\"\r\n\r\n"
                "--XYZabcd1234\r\n"
                "Content-Type: text/html; charset=\"UTF-8\"\r\n\r\n"
                "%s\r\n"
                "--XYZabcd1234\r\n"
                "Content-Type: text/csv\r\n"
                "Content-Disposition: attachment; filename=\"%s\"\r\n"
                "Content-Transfer-Encoding: base64\r\n\r\n",
                params->authorName, params->authorEmail, params->toName, params->toEmail, params->toName2, params->toEmail2,
                params->subject, params->msgBody, f_prepFilename(attachment_path));

                char *buf = (char *)malloc(*buf_len + 1);
                if (!buf) {
                    ESP_LOGE("EMAIL", "Falha ao alocar memória para o cabeçalho do email.");
                    return NULL;
                }
            snprintf(buf, *buf_len + 1,
                "From: \"%s\" <%s>\r\n"
                "To: \"%s\" <%s>\r\n"
                "Cc: \"%s\" <%s>\r\n"
                "Subject: %s\r\n"
                "MIME-Version: 1.0\r\n"
                "Content-Type: multipart/mixed; boundary=\"XYZabcd1234\"\r\n\r\n"
                "--XYZabcd1234\r\n"
                "Content-Type: text/html; charset=\"UTF-8\"\r\n\r\n"
                "%s\r\n"
                "--XYZabcd1234\r\n"
                "Content-Type: text/csv\r\n"
                "Content-Disposition: attachment; filename=\"%s\"\r\n"
                "Content-Transfer-Encoding: base64\r\n\r\n",
                params->authorName, params->authorEmail, params->toName, params->toEmail, params->toName2, params->toEmail2,
                params->subject, params->msgBody, f_prepFilename(attachment_path));
                return buf; 
        } else {               // Email sem cópia
            *buf_len = snprintf(NULL, 0,
                "From: \"%s\" <%s>\r\n"
                "To: \"%s\" <%s>\r\n"
                "Subject: %s\r\n"
                "MIME-Version: 1.0\r\n"
                "Content-Type: multipart/mixed; boundary=\"XYZabcd1234\"\r\n\r\n"
                "--XYZabcd1234\r\n"
                "Content-Type: text/html; charset=\"UTF-8\"\r\n\r\n"
                "%s\r\n"
                "--XYZabcd1234\r\n"
                "Content-Type: text/csv\r\n"
                "Content-Disposition: attachment; filename=\"%s\"\r\n"
                "Content-Transfer-Encoding: base64\r\n\r\n",
                params->authorName, params->authorEmail, params->toName, params->toEmail,
                params->subject, params->msgBody, f_prepFilename(attachment_path));

                char *buf = (char *)malloc(*buf_len + 1);
                if (!buf) {
                    ESP_LOGE("EMAIL", "Falha ao alocar memória para o cabeçalho do email.");
                    return NULL;
                }
            snprintf(buf, *buf_len + 1,
                "From: \"%s\" <%s>\r\n"
                "To: \"%s\" <%s>\r\n"
                "Subject: %s\r\n"
                "MIME-Version: 1.0\r\n"
                "Content-Type: multipart/mixed; boundary=\"XYZabcd1234\"\r\n\r\n"
                "--XYZabcd1234\r\n"
                "Content-Type: text/html; charset=\"UTF-8\"\r\n\r\n"
                "%s\r\n"
                "--XYZabcd1234\r\n"
                "Content-Type: text/csv\r\n"
                "Content-Disposition: attachment; filename=\"%s\"\r\n"
                "Content-Transfer-Encoding: base64\r\n\r\n",
                params->authorName, params->authorEmail, params->toName, params->toEmail, 
                params->subject, params->msgBody, f_prepFilename(attachment_path));
                return buf; 
        }
        return NULL; // Nunca deve chegar aqui...
}

static int write_ssl_data(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) {
            int ret = 0;  // Inicializa 'ret' com zero

            while (len && (ret = mbedtls_ssl_write(ssl, buf, len)) <= 0) {
                if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
                    ESP_LOGE("SSL_DATA", "mbedtls_ssl_write falhou com erro -0x%x ao enviar %d bytes", -ret, len);
                    return ret;  // Retorna o erro diretamente se não for MBEDTLS_ERR_SSL_WANT_READ ou MBEDTLS_ERR_SSL_WANT_WRITE
                }
            }
            return ret;  // Retorna o número de bytes escritos ou o erro
}


bool f_ComporEmailAttachedFile(email_params_t *params, char* attachment_path) {
            int ret, len;
            char *buf = NULL;
            unsigned char file_buffer[128];
            unsigned char base64_buffer[200];
            size_t base64_len;
            FILE *file;
            size_t read_bytes;
            len = snprintf(NULL, 0, "MAIL FROM:<%s>\r\n", params->authorEmail);
            buf = allocate_buffer(len + 1);
            if (!buf) return false;
            snprintf(buf, len + 1, "MAIL FROM:<%s>\r\n", params->authorEmail);
            ret = write_ssl_and_get_response(&ssl, (unsigned char *)buf, len);
            free(buf);
            if (ret < 200 || ret > 299) return false;
        ESP_LOGI(TAG, "Write RCPT - 1");
            len = snprintf(NULL, 0, "RCPT TO:<%s>\r\n", params->toEmail);
            buf = allocate_buffer(len + 1);
            if (!buf) return false;
            snprintf(buf, len + 1, "RCPT TO:<%s>\r\n", params->toEmail);
            ret = write_ssl_and_get_response(&ssl, (unsigned char *)buf, len);
            free(buf);
            if (ret < 200 || ret > 299) return false;

            // Envia o comando "RCPT TO" para o destinatário de cópia (CC)
            if (params->toEmail2 != NULL && strlen(params->toEmail2) > 0) {
                ESP_LOGI(TAG, "Write RCPT - 2");
                    len = snprintf(NULL, 0, "RCPT TO:<%s>\r\n", params->toEmail2);
                    buf = allocate_buffer(len + 1);
                    if (!buf) return false;
                    snprintf(buf, len + 1, "RCPT TO:<%s>\r\n", params->toEmail2);
                    ret = write_ssl_and_get_response(&ssl, (unsigned char *)buf, len);
                    free(buf);
                    if (ret < 200 || ret > 299) return false;
            }

        ESP_LOGI(TAG, "Write DATA");
            len = snprintf(NULL, 0, "DATA\r\n");
            buf = allocate_buffer(len + 1);
            if (!buf) return false;
            snprintf(buf, len + 1, "DATA\r\n");
            ret = write_ssl_and_get_response(&ssl, (unsigned char *)buf, len);
            free(buf);
            if (ret < 300 || ret > 399) return false;
           
        ESP_LOGI(TAG, "Compondo corpo do e-mail com anexo...");
            size_t header_len;
            char *email_header = f_generateEmailHeader(params, attachment_path, &header_len);
            if (!email_header) {return false;}
            ret = write_ssl_data(&ssl, (unsigned char *)email_header, header_len);
            free(email_header);  // Libera a memória após o envio
            if (ret < 0) {ESP_LOGE(TAG, "Erro ao enviar os cabeçalhos.");return false;}
        ESP_LOGI(TAG, "Enviando anexo em Base64...");
            file = fopen(attachment_path, "rb");
            if (!file) {ESP_LOGE(TAG, "Falha ao abrir o arquivo: %s", attachment_path);return false;}
            int count=0;
            while ((read_bytes = fread(file_buffer, 1, sizeof(file_buffer), file)) > 0) {
                    ret = mbedtls_base64_encode(base64_buffer, sizeof(base64_buffer), &base64_len, file_buffer, read_bytes);
                    if (ret != 0) {ESP_LOGE(TAG, "Erro na codificação Base64: -0x%x", -ret);fclose(file);return false;}
                    ret = write_ssl_data(&ssl, (unsigned char *)base64_buffer, base64_len);
                    if (ret < 0) {ESP_LOGE(TAG, "Erro ao enviar o chunk do anexo.");fclose(file);return false;}
                    count++;
            }
        ESP_LOGI(TAG, "Arquivo enviado em %d partes", count);
            fclose(file);

        ESP_LOGI(TAG, "Finalizando envio do e-mail...");
            const char *end_of_email = "\r\n--XYZabcd1234--\r\n.\r\n";
            ret = write_ssl_and_get_response(&ssl, (unsigned char *)end_of_email, strlen(end_of_email));
            if (ret < 200 || ret > 299) {
                ESP_LOGE(TAG, "Falha ao finalizar envio do e-mail.");
                return false;
            }

            ESP_LOGI(TAG, "Email com anexo enviado com sucesso.");
            return true;
}


void f_EnviaEmail(void *args) {
                ESP_LOGW(TAG, "Ponto A");
                    EventBits_t bitsMQTT_In = xEventGroupGetBits(xEventGroupMQTT_In);
                    EventBits_t bitsMQTT_Out = xEventGroupGetBits(xEventGroupMQTT_Out);
                    if (bitsMQTT_In & MQTT_In_BIT) {
                        ESP_LOGI(TAG, "Parando MQTT In...");
                        f_stopMQTT_In();
                        xEventGroupWaitBits(xEventGroupMQTT_In, MQTT_In_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
                    } else {
                        ESP_LOGI(TAG, "MQTT In não está rodando, ignorando stop.");
                    }
                    if (bitsMQTT_Out & MQTT_Out_BIT) {
                        ESP_LOGI(TAG, "Parando MQTT Out...");
                        f_stopMQTT_Out();
                        xEventGroupWaitBits(xEventGroupMQTT_Out, MQTT_Out_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
                    } else {
                        ESP_LOGI(TAG, "MQTT Out não está rodando, ignorando stop.");
                    }
    
                    email_params_t *params = (email_params_t *)args;
                    bool success = true;

                    if (f_conecta(params)) {
                        ESP_LOGI(TAG, "SMTP Conectado");
                    } else {
                        ESP_LOGE(TAG, "Erro de Conexão. Encerrando envio de e-mail.");
                        success = false;
                    }

                    if (success && f_autentica(params)) {
                        ESP_LOGI(TAG, "SMTP Autenticado");
                    } else if (success) {
                        ESP_LOGE(TAG, "Erro de Autenticação. Encerrando envio de e-mail.");
                        success = false;
                    }

                    bool file_exists = f_fileCheck(params->attachment_file);    // Verifica se o arquivo existe
                    if (success) {
                        if (file_exists) {
                            ESP_LOGI(TAG, "Arquivo encontrado(%s). Enviando e-mail com anexo.", params->attachment_file);
                            success = f_ComporEmailAttachedFile(params, params->attachment_file);  // Com anexo
                        } else {
                            ESP_LOGI(TAG, "Arquivo não encontrado. Enviando e-mail sem anexo.");
                            success = f_ComporEmail(params);  // Sem anexo
                        }
                    }

                    if (success) {
                        ESP_LOGI(TAG, "Email composto e enviado com sucesso!");
                    } else {
                        ESP_LOGE(TAG, "Erro ao compor ou enviar o e-mail.");
                    }

                    // Libera recursos do mbedtls
                    mbedtls_ssl_close_notify(&ssl);
                    mbedtls_net_free(&server_fd);
                    mbedtls_ssl_free(&ssl);
                    mbedtls_ssl_config_free(&conf);
                    mbedtls_ctr_drbg_free(&ctr_drbg);
                    mbedtls_entropy_free(&entropy);

                    UBaseType_t highWaterMark = uxTaskGetStackHighWaterMark(NULL);
                    ESP_LOGI(TAG, "Uso de memoria da tarefa f_EnviaEmail: %d bytes", highWaterMark * sizeof(StackType_t));

                    if (params) {
                        free(params);
                    }

            f_startMQTT_In(NULL);
            f_startMQTT_Out(NULL);
            vTaskDelete(NULL);
}

When I turn off the wifi the email is sent perfectly.

I can do this as many times as I want.

But was if the enable MQTT Tasks, is wrong send mail.

Generate this error: mbedtls_ssl_setup returned -0x7f00

As an alternative, I decided to implement a stop and termination of MQTT actions so that it frees up the memory and/or items that occupy the connections.

This alternative partially worked, because it really works, I can stop MQTT sending the email and then start MQTT.

However, if I repeat this operation more than 3 times, I get some kind of crash.

This First send:

The second send:

The third submission stops the task

When I make this third attempt it freezes and does not start the task.

If I try to log into the webserver, it responds with an error.

My unhappiness is that when I restart everything goes back to normal and again I can send at least 2 emails.

Remembering that this is a complex product with several tasks involved:

Does anyone have any idea what problem I might be experiencing?

From a quick look, it seems that you using some TLS connection to send email. Is it possible that you are running out of memory and some mbedTLS malloc call fails? Have you redirected mbedTLS malloc/free to FreeRTOS pvPortMalloc/vPortFree? If yes, you can use configUSE_MALLOC_FAILED_HOOK to catch that.

Seems like your application hangs. You need to break it in debugger and see where it is stuck.

The error code -0x7f00 is for MBEDTLS_ERR_SSL_ALLOC_FAILED, see here. So most probably your application is running out of heap space.

You should post this on the ESP forum as well, as the issue seems to be arising from their library.

2 Likes

I don’t know what this is?

There is no advanced content about freertos on the web, especially in my language. Portuguese.

So I’m a little sold on the more Expert items, so to speak.

Here is an example -

You’ll also need to enable MBEDTLS_PLATFORM_MEMORY in your mbedTLS config file - FreeRTOS/FreeRTOS-Plus/VisualStudio_StaticProjects/MbedTLS/mbedtls_config_v3.5.1.h at main · FreeRTOS/FreeRTOS · GitHub.

As @DakshitBabbar already pointed, you are running out of memory - so you need to see if there is way to increase the heap space or free some memory.