mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-28 06:37:11 +01:00
773 lines
22 KiB
C++
773 lines
22 KiB
C++
/*************************************************************************/
|
|
/* smtp_client.cpp */
|
|
/*************************************************************************/
|
|
/* This file is part of: */
|
|
/* PANDEMONIUM ENGINE'S SMTP MODULE */
|
|
/* https://github.com/Relintai/pandemonium_engine */
|
|
/*************************************************************************/
|
|
/* Copyright (c) 2022-present Péter Magyar. */
|
|
/* Copyright (c) 2021-2024 Nicolò Santilio */
|
|
/* */
|
|
/* 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 "smtp_client.h"
|
|
|
|
#include "core/bind/core_bind.h"
|
|
#include "core/config/engine.h"
|
|
#include "core/io/stream_peer_ssl.h"
|
|
#include "core/io/stream_peer_tcp.h"
|
|
#include "core/log/logger.h"
|
|
#include "core/os/os.h"
|
|
|
|
#include "email.h"
|
|
|
|
String SMTPClient::get_client_id() const {
|
|
return client_id;
|
|
}
|
|
void SMTPClient::set_client_id(const String &p_value) {
|
|
client_id = p_value;
|
|
}
|
|
|
|
String SMTPClient::get_host() const {
|
|
return host;
|
|
}
|
|
void SMTPClient::set_host(const String &p_value) {
|
|
host = p_value;
|
|
}
|
|
|
|
int SMTPClient::get_port() const {
|
|
return port;
|
|
}
|
|
void SMTPClient::set_port(const int p_value) {
|
|
port = p_value;
|
|
}
|
|
|
|
SMTPClient::TLSMethod SMTPClient::get_tls_method() const {
|
|
return tls_method;
|
|
}
|
|
void SMTPClient::set_tls_method(const TLSMethod p_value) {
|
|
tls_method = p_value;
|
|
}
|
|
|
|
String SMTPClient::get_server_auth_username() const {
|
|
return server_auth_username;
|
|
}
|
|
void SMTPClient::set_server_auth_username(const String &p_value) {
|
|
server_auth_username = p_value;
|
|
}
|
|
|
|
String SMTPClient::get_server_auth_password() const {
|
|
return server_auth_password;
|
|
}
|
|
void SMTPClient::set_server_auth_password(const String &p_value) {
|
|
server_auth_password = p_value;
|
|
}
|
|
|
|
SMTPClient::ServerAuthMethod SMTPClient::get_server_auth_method() const {
|
|
return server_auth_method;
|
|
}
|
|
void SMTPClient::set_server_auth_method(const ServerAuthMethod p_value) {
|
|
server_auth_method = p_value;
|
|
}
|
|
|
|
String SMTPClient::get_email_default_sender_email() const {
|
|
return email_default_sender_email;
|
|
}
|
|
void SMTPClient::set_email_default_sender_email(const String &p_value) {
|
|
email_default_sender_email = p_value;
|
|
}
|
|
|
|
String SMTPClient::get_email_default_sender_name() const {
|
|
return email_default_sender_name;
|
|
}
|
|
void SMTPClient::set_email_default_sender_name(const String &p_value) {
|
|
email_default_sender_name = p_value;
|
|
}
|
|
|
|
bool SMTPClient::get_use_threads() const {
|
|
return _use_threads;
|
|
}
|
|
void SMTPClient::set_use_threads(const bool p_value) {
|
|
if (_use_threads == p_value) {
|
|
return;
|
|
}
|
|
|
|
if (Engine::get_singleton()->is_editor_hint()) {
|
|
_use_threads = p_value;
|
|
return;
|
|
}
|
|
|
|
if (is_inside_tree()) {
|
|
if (should_use_threading()) {
|
|
//currently using threads, will no longer be the case
|
|
|
|
if (_worker_thread) {
|
|
_worker_thread_running = false;
|
|
//slow quit = let the current mail finish processing
|
|
_worker_thread_fast_quit = false;
|
|
|
|
_worker_semaphore.post();
|
|
_worker_thread->wait_to_finish();
|
|
memdelete(_worker_thread);
|
|
_worker_thread = NULL;
|
|
}
|
|
|
|
} else {
|
|
//currently not using threads, we want to
|
|
|
|
if (should_use_threading()) {
|
|
_worker_thread_running = true;
|
|
_worker_thread = memnew(Thread);
|
|
_worker_thread->start(_worker_thread_func, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
_use_threads = p_value;
|
|
}
|
|
|
|
int SMTPClient::get_thread_sleep_usec() const {
|
|
return thread_sleep_usec;
|
|
}
|
|
void SMTPClient::set_thread_sleep_usec(const int p_value) {
|
|
thread_sleep_usec = p_value;
|
|
}
|
|
|
|
void SMTPClient::send_email(const Ref<EMail> &p_email) {
|
|
ERR_FAIL_COND(Engine::get_singleton()->is_editor_hint());
|
|
ERR_FAIL_COND(!is_inside_tree());
|
|
ERR_FAIL_COND(!p_email.is_valid());
|
|
|
|
if (should_use_threading()) {
|
|
_mail_queue_mutex.lock();
|
|
_mail_queue.push_back(p_email);
|
|
_mail_queue_mutex.unlock();
|
|
|
|
_worker_semaphore.post();
|
|
} else {
|
|
if (_current_session_email.is_valid()) {
|
|
_mail_queue.push_back(p_email);
|
|
return;
|
|
}
|
|
|
|
_send_email(p_email);
|
|
}
|
|
}
|
|
|
|
bool SMTPClient::should_use_threading() const {
|
|
#if !defined(NO_THREADS)
|
|
return _use_threads;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
void SMTPClient::_send_email(const Ref<EMail> &p_email) {
|
|
_current_session_email = p_email;
|
|
|
|
if (!_current_session_email.is_valid()) {
|
|
return;
|
|
}
|
|
|
|
IP_Address ip;
|
|
|
|
if (host.is_valid_ip_address()) {
|
|
ip = host;
|
|
} else {
|
|
ip = IP::get_singleton()->resolve_hostname(host);
|
|
}
|
|
|
|
Error err = _tcp_client->connect_to_host(ip, port);
|
|
if (err != OK) {
|
|
PLOG_ERR("Could not connect! " + itos(err));
|
|
|
|
Dictionary error_body;
|
|
|
|
error_body["message"] = "Error connecting to host.";
|
|
error_body["code"] = err;
|
|
|
|
emit_signal("error", error_body);
|
|
|
|
Dictionary result;
|
|
result["success"] = false;
|
|
result["error"] = error_body;
|
|
|
|
emit_signal("result", result);
|
|
|
|
if (!should_use_threading()) {
|
|
_no_thread_next_email();
|
|
}
|
|
}
|
|
|
|
_current_session_status = SESSION_STATUS_HELO;
|
|
|
|
if (!should_use_threading()) {
|
|
set_process(true);
|
|
}
|
|
}
|
|
|
|
Error SMTPClient::poll_client() {
|
|
if (_current_tls_started || _current_tls_established) {
|
|
_tls_client->poll();
|
|
return OK;
|
|
} else {
|
|
return OK;
|
|
}
|
|
}
|
|
|
|
bool SMTPClient::client_get_status() {
|
|
if (_current_tls_started) {
|
|
return _tls_client->get_status() == StreamPeerSSL::STATUS_CONNECTED;
|
|
}
|
|
|
|
return _tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED;
|
|
}
|
|
|
|
int SMTPClient::client_get_available_bytes() {
|
|
if (_current_tls_started) {
|
|
return _tls_client->get_available_bytes();
|
|
}
|
|
|
|
return _tcp_client->get_available_bytes();
|
|
}
|
|
|
|
String SMTPClient::client_get_string(int bytes) {
|
|
if (_current_tls_started) {
|
|
return _tls_client->get_string(bytes);
|
|
}
|
|
|
|
return _tcp_client->get_string(bytes);
|
|
}
|
|
|
|
bool SMTPClient::start_auth() {
|
|
if (server_auth_method == SERVER_AUTH_PLAIN) {
|
|
_current_session_status = SESSION_STATUS_AUTHENTICATED;
|
|
return true;
|
|
}
|
|
|
|
if (!write_command("AUTH LOGIN")) {
|
|
return false;
|
|
}
|
|
|
|
_current_session_status = SESSION_STATUS_AUTH_LOGIN;
|
|
return true;
|
|
}
|
|
bool SMTPClient::start_hello() {
|
|
//_current_session_status = SESSION_STATUS_HELO
|
|
if (!write_command("HELO " + client_id)) {
|
|
return false;
|
|
}
|
|
|
|
_current_session_status = SESSION_STATUS_HELO_ACK;
|
|
return true;
|
|
}
|
|
|
|
Error SMTPClient::client_put_data(const String &data) {
|
|
Vector<uint8_t> buffer = data.to_utf8_buffer();
|
|
|
|
if (_current_tls_established) {
|
|
return _tls_client->put_data(buffer.ptr(), buffer.size());
|
|
}
|
|
|
|
return _tcp_client->put_data(buffer.ptr(), buffer.size());
|
|
}
|
|
|
|
bool SMTPClient::write_command(const String &command) {
|
|
//PLOG_ERR("COMMAND: " + command + "\n");
|
|
Error err = client_put_data(command + "\n");
|
|
|
|
if (err != OK) {
|
|
_current_session_status = SESSION_STATUS_COMMAND_NOT_SENT;
|
|
|
|
Dictionary error_body;
|
|
error_body["message"] = "Session error on command: " + command;
|
|
error_body["code"] = err;
|
|
|
|
emit_signal("error", error_body);
|
|
|
|
Dictionary result;
|
|
result["success"] = false;
|
|
result["error"] = error_body;
|
|
|
|
emit_signal("result", result);
|
|
}
|
|
|
|
return (err == OK);
|
|
}
|
|
|
|
Error SMTPClient::write_data(const String &data) {
|
|
return client_put_data(data + "\r\n.\r\n");
|
|
}
|
|
|
|
void SMTPClient::close_connection() {
|
|
_current_session_status = SESSION_STATUS_NONE;
|
|
_tls_client->disconnect_from_stream();
|
|
_tcp_client->disconnect_from_host();
|
|
_current_session_email.unref();
|
|
_current_to_index = 0;
|
|
_current_tls_started = false;
|
|
_current_tls_established = false;
|
|
|
|
if (!should_use_threading()) {
|
|
_no_thread_next_email();
|
|
}
|
|
}
|
|
|
|
String SMTPClient::encode_username() {
|
|
return _Marshalls::get_singleton()->utf8_to_base64(server_auth_username);
|
|
}
|
|
String SMTPClient::encode_password() {
|
|
return _Marshalls::get_singleton()->utf8_to_base64(server_auth_password);
|
|
}
|
|
|
|
void SMTPClient::_process_email() {
|
|
if (_current_session_status == SESSION_STATUS_SERVER_ERROR) {
|
|
close_connection();
|
|
}
|
|
|
|
if (poll_client() == OK) {
|
|
bool connected = client_get_status();
|
|
|
|
if (connected) {
|
|
// We need to wait until the connection is properly set up before starting ssl
|
|
if (tls_method == TLS_METHOD_SMTPS && !_current_tls_started) {
|
|
Error err = _tls_client->connect_to_stream(_tcp_client, false, host);
|
|
|
|
if (err != OK) {
|
|
_current_session_status = SESSION_STATUS_SERVER_ERROR;
|
|
|
|
Dictionary error_body;
|
|
|
|
error_body["message"] = "Error connecting to TLS Stream.";
|
|
error_body["code"] = err;
|
|
|
|
emit_signal("error", error_body);
|
|
|
|
Dictionary result;
|
|
result["success"] = false;
|
|
result["error"] = error_body;
|
|
|
|
emit_signal("result", result);
|
|
|
|
if (!should_use_threading()) {
|
|
_no_thread_next_email();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
_current_tls_started = true;
|
|
_current_tls_established = true;
|
|
}
|
|
|
|
int bytes = client_get_available_bytes();
|
|
|
|
if (bytes > 0) {
|
|
String msg = client_get_string(bytes);
|
|
//PLOG_ERR("RECEIVED: " + msg)
|
|
String code = msg.left(3);
|
|
|
|
if (code == "220") {
|
|
if (_current_session_status == SESSION_STATUS_HELO) {
|
|
start_hello();
|
|
} else if (_current_session_status == SESSION_STATUS_STARTTLS) {
|
|
Error err = _tls_client->connect_to_stream(_tcp_client, false, host);
|
|
|
|
if (err != OK) {
|
|
_current_session_status = SESSION_STATUS_SERVER_ERROR;
|
|
|
|
Dictionary error_body;
|
|
error_body["message"] = "Error connecting to TLS Stream.";
|
|
error_body["code"] = err;
|
|
|
|
emit_signal("error", error_body);
|
|
|
|
Dictionary result;
|
|
result["success"] = false;
|
|
result["error"] = error_body;
|
|
|
|
emit_signal("result", result);
|
|
|
|
return;
|
|
}
|
|
|
|
_current_tls_started = true;
|
|
_current_tls_established = true;
|
|
|
|
// We need to do HELO + EHLO again
|
|
_current_session_status = SESSION_STATUS_HELO;
|
|
start_hello();
|
|
}
|
|
|
|
} else if (code == "250") {
|
|
if (_current_session_status == SESSION_STATUS_HELO_ACK) {
|
|
if (!write_command("EHLO " + client_id)) {
|
|
return;
|
|
}
|
|
|
|
_current_session_status = SESSION_STATUS_EHLO_ACK;
|
|
|
|
} else if (_current_session_status == SESSION_STATUS_EHLO_ACK) {
|
|
if (tls_method == TLS_METHOD_STARTTLS) {
|
|
if (_current_tls_started) {
|
|
// second round of HELO + EHLO done
|
|
if (!start_auth()) {
|
|
return;
|
|
}
|
|
|
|
} else {
|
|
if (!write_command("STARTTLS")) {
|
|
return;
|
|
}
|
|
|
|
_current_session_status = SESSION_STATUS_STARTTLS;
|
|
}
|
|
} else {
|
|
if (!start_auth()) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
} else if (_current_session_status == SESSION_STATUS_MAIL_FROM) {
|
|
if (_current_to_index < _current_session_email->get_recipient_count()) {
|
|
if (!write_command("RCPT TO: <" + _current_session_email->get_recipient_address(_current_to_index) + ">")) {
|
|
return;
|
|
}
|
|
|
|
_current_to_index += 1;
|
|
}
|
|
|
|
if (_current_cc_index < _current_session_email->get_cc_count()) {
|
|
if (!write_command("RCPT TO: <" + _current_session_email->get_cc_address(_current_cc_index) + ">")) {
|
|
return;
|
|
}
|
|
|
|
_current_cc_index += 1;
|
|
}
|
|
|
|
_current_session_status = SESSION_STATUS_RCPT_TO;
|
|
|
|
} else if (_current_session_status == SESSION_STATUS_RCPT_TO) {
|
|
if (_current_to_index < _current_session_email->get_recipient_count()) {
|
|
_current_session_status = SESSION_STATUS_MAIL_FROM;
|
|
return;
|
|
}
|
|
|
|
if (_current_cc_index < _current_session_email->get_cc_count()) {
|
|
_current_session_status = SESSION_STATUS_MAIL_FROM;
|
|
return;
|
|
}
|
|
|
|
if (!write_command("DATA")) {
|
|
return;
|
|
}
|
|
|
|
_current_session_status = SESSION_STATUS_DATA;
|
|
|
|
} else if (_current_session_status == SESSION_STATUS_DATA_ACK) {
|
|
if (!write_command("QUIT")) {
|
|
return;
|
|
}
|
|
|
|
_current_session_status = SESSION_STATUS_QUIT;
|
|
}
|
|
|
|
} else if (code == "221") {
|
|
if (_current_session_status == SESSION_STATUS_QUIT) {
|
|
close_connection();
|
|
emit_signal("email_sent");
|
|
|
|
Dictionary result;
|
|
result["success"] = true;
|
|
|
|
emit_signal("result", result);
|
|
}
|
|
} else if (code == "235") {
|
|
// Authentication Succeeded
|
|
|
|
if (_current_session_status == SESSION_STATUS_PASSWORD) {
|
|
_current_session_status = SESSION_STATUS_AUTHENTICATED;
|
|
}
|
|
|
|
} else if (code == "334") {
|
|
if (_current_session_status == SESSION_STATUS_AUTH_LOGIN) {
|
|
if (msg.begins_with("334 VXNlcm5hbWU6")) {
|
|
if (!write_command(encode_username())) {
|
|
return;
|
|
}
|
|
|
|
_current_session_status = SESSION_STATUS_USERNAME;
|
|
}
|
|
} else if (_current_session_status == SESSION_STATUS_USERNAME) {
|
|
if (msg.begins_with("334 UGFzc3dvcmQ6")) {
|
|
if (!write_command(encode_password())) {
|
|
return;
|
|
}
|
|
|
|
_current_session_status = SESSION_STATUS_PASSWORD;
|
|
}
|
|
}
|
|
} else if (code == "354") {
|
|
if (_current_session_status == SESSION_STATUS_DATA) {
|
|
if (!(write_data(_current_session_email->get_email_data_string(email_default_sender_name, email_default_sender_email)) == OK)) {
|
|
_current_session_status = SESSION_STATUS_SERVER_ERROR;
|
|
return;
|
|
}
|
|
|
|
_current_session_status = SESSION_STATUS_DATA_ACK;
|
|
}
|
|
} else {
|
|
PLOG_ERR(msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_current_session_email.is_valid() && (_current_session_status == SESSION_STATUS_AUTHENTICATED)) {
|
|
_current_session_status = SESSION_STATUS_MAIL_FROM;
|
|
|
|
String sender_address = _current_session_email->get_sender_address();
|
|
|
|
String fn;
|
|
|
|
if (sender_address.size() > 0) {
|
|
fn = "<" + sender_address + ">";
|
|
} else {
|
|
fn = "<" + email_default_sender_email + ">";
|
|
}
|
|
|
|
if (!write_command("MAIL FROM: " + fn)) {
|
|
return;
|
|
}
|
|
} else {
|
|
return;
|
|
}
|
|
} else {
|
|
PLOG_ERR("Couldn't poll!")
|
|
}
|
|
}
|
|
|
|
void SMTPClient::_no_thread_next_email() {
|
|
if (should_use_threading()) {
|
|
return;
|
|
}
|
|
|
|
Ref<EMail> mail;
|
|
|
|
int size = _mail_queue.size();
|
|
if (size > 0) {
|
|
mail = _mail_queue[0];
|
|
_mail_queue.remove(0);
|
|
} else {
|
|
set_process(false);
|
|
return;
|
|
}
|
|
|
|
if (mail.is_valid()) {
|
|
_send_email(mail);
|
|
}
|
|
}
|
|
|
|
void SMTPClient::_worker_thread_func(void *user_data) {
|
|
SMTPClient *self = (SMTPClient *)user_data;
|
|
|
|
while (self->_worker_thread_running) {
|
|
Ref<EMail> _mail;
|
|
|
|
self->_mail_queue_mutex.lock();
|
|
|
|
int size = self->_mail_queue.size();
|
|
if (size > 0) {
|
|
_mail = self->_mail_queue[0];
|
|
self->_mail_queue.remove(0);
|
|
}
|
|
|
|
self->_mail_queue_mutex.unlock();
|
|
|
|
if (_mail.is_valid()) {
|
|
self->_send_email(_mail);
|
|
}
|
|
|
|
while (self->_current_session_email.is_valid()) {
|
|
OS::get_singleton()->delay_usec(self->thread_sleep_usec);
|
|
|
|
// Early return if we want to quit
|
|
if (!self->_worker_thread_running && self->_worker_thread_fast_quit) {
|
|
self->close_connection();
|
|
return;
|
|
}
|
|
|
|
self->_process_email();
|
|
}
|
|
|
|
if (!self->_worker_thread_running) {
|
|
return;
|
|
}
|
|
|
|
if (self->_mail_queue.size() == 0) {
|
|
self->_worker_semaphore.wait();
|
|
}
|
|
}
|
|
}
|
|
|
|
SMTPClient::SMTPClient() {
|
|
client_id = "smtp.pandemoniumengine.org";
|
|
port = 465;
|
|
|
|
tls_method = TLS_METHOD_SMTPS;
|
|
|
|
server_auth_method = SERVER_AUTH_LOGIN;
|
|
|
|
_use_threads = true;
|
|
_worker_thread = NULL;
|
|
// 10 msec
|
|
thread_sleep_usec = 10000;
|
|
|
|
// Networking
|
|
_tcp_client.instance();
|
|
_tls_client = Ref<StreamPeerSSL>(StreamPeerSSL::create());
|
|
|
|
//SessionStatus
|
|
_current_session_status = SESSION_STATUS_NONE;
|
|
_current_to_index = 0;
|
|
_current_cc_index = 0;
|
|
|
|
_current_tls_started = false;
|
|
_current_tls_established = false;
|
|
|
|
// Threading
|
|
_worker_thread_running = false;
|
|
_worker_thread_fast_quit = false;
|
|
|
|
set_process(false);
|
|
}
|
|
SMTPClient::~SMTPClient() {
|
|
}
|
|
|
|
void SMTPClient::_notification(int p_what) {
|
|
switch (p_what) {
|
|
case NOTIFICATION_PROCESS: {
|
|
if (Engine::get_singleton()->is_editor_hint()) {
|
|
set_process(false);
|
|
return;
|
|
}
|
|
|
|
if (should_use_threading()) {
|
|
set_process(false);
|
|
return;
|
|
}
|
|
|
|
_process_email();
|
|
} break;
|
|
case NOTIFICATION_ENTER_TREE: {
|
|
if (Engine::get_singleton()->is_editor_hint()) {
|
|
set_process(false);
|
|
return;
|
|
}
|
|
|
|
set_process(false);
|
|
|
|
_worker_thread_fast_quit = false;
|
|
|
|
if (should_use_threading()) {
|
|
_worker_thread_running = true;
|
|
_worker_thread = memnew(Thread);
|
|
_worker_thread->start(_worker_thread_func, this);
|
|
}
|
|
|
|
} break;
|
|
case NOTIFICATION_EXIT_TREE: {
|
|
if (Engine::get_singleton()->is_editor_hint()) {
|
|
set_process(false);
|
|
return;
|
|
}
|
|
|
|
if (_worker_thread) {
|
|
_worker_thread_running = false;
|
|
_worker_thread_fast_quit = true;
|
|
_worker_semaphore.post();
|
|
_worker_thread->wait_to_finish();
|
|
memdelete(_worker_thread);
|
|
_worker_thread = NULL;
|
|
}
|
|
|
|
} break;
|
|
}
|
|
}
|
|
|
|
void SMTPClient::_bind_methods() {
|
|
ADD_SIGNAL(MethodInfo("error", PropertyInfo(Variant::DICTIONARY, "error")));
|
|
ADD_SIGNAL(MethodInfo("email_sent"));
|
|
ADD_SIGNAL(MethodInfo("result", PropertyInfo(Variant::DICTIONARY, "content")));
|
|
|
|
ClassDB::bind_method(D_METHOD("get_client_id"), &SMTPClient::get_client_id);
|
|
ClassDB::bind_method(D_METHOD("set_client_id", "val"), &SMTPClient::set_client_id);
|
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "client_id"), "set_client_id", "get_client_id");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_host"), &SMTPClient::get_host);
|
|
ClassDB::bind_method(D_METHOD("set_host", "val"), &SMTPClient::set_host);
|
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "host"), "set_host", "get_host");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_port"), &SMTPClient::get_port);
|
|
ClassDB::bind_method(D_METHOD("set_port", "val"), &SMTPClient::set_port);
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "port"), "set_port", "get_port");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_tls_method"), &SMTPClient::get_tls_method);
|
|
ClassDB::bind_method(D_METHOD("set_tls_method", "val"), &SMTPClient::set_tls_method);
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "tls_method", PROPERTY_HINT_ENUM, "NONE,STARTTLS,SMTPS"), "set_tls_method", "get_tls_method");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_server_auth_username"), &SMTPClient::get_server_auth_username);
|
|
ClassDB::bind_method(D_METHOD("set_server_auth_username", "val"), &SMTPClient::set_server_auth_username);
|
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "server_auth_username"), "set_server_auth_username", "get_server_auth_username");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_server_auth_password"), &SMTPClient::get_server_auth_password);
|
|
ClassDB::bind_method(D_METHOD("set_server_auth_password", "val"), &SMTPClient::set_server_auth_password);
|
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "server_auth_password"), "set_server_auth_password", "get_server_auth_password");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_server_auth_method"), &SMTPClient::get_server_auth_method);
|
|
ClassDB::bind_method(D_METHOD("set_server_auth_method", "val"), &SMTPClient::set_server_auth_method);
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "server_auth_method", PROPERTY_HINT_ENUM, "Plain,Login"), "set_server_auth_method", "get_server_auth_method");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_email_default_sender_email"), &SMTPClient::get_email_default_sender_email);
|
|
ClassDB::bind_method(D_METHOD("set_email_default_sender_email", "val"), &SMTPClient::set_email_default_sender_email);
|
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "email_default_sender_email"), "set_email_default_sender_email", "get_email_default_sender_email");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_email_default_sender_name"), &SMTPClient::get_email_default_sender_name);
|
|
ClassDB::bind_method(D_METHOD("set_email_default_sender_name", "val"), &SMTPClient::set_email_default_sender_name);
|
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "email_default_sender_name"), "set_email_default_sender_name", "get_email_default_sender_name");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_use_threads"), &SMTPClient::get_use_threads);
|
|
ClassDB::bind_method(D_METHOD("set_use_threads", "val"), &SMTPClient::set_use_threads);
|
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_threads"), "set_use_threads", "get_use_threads");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_thread_sleep_usec"), &SMTPClient::get_thread_sleep_usec);
|
|
ClassDB::bind_method(D_METHOD("set_thread_sleep_usec", "val"), &SMTPClient::set_thread_sleep_usec);
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "thread_sleep_usec"), "set_thread_sleep_usec", "get_thread_sleep_usec");
|
|
|
|
ClassDB::bind_method(D_METHOD("send_email", "email"), &SMTPClient::send_email);
|
|
|
|
BIND_ENUM_CONSTANT(TLS_METHOD_NONE);
|
|
BIND_ENUM_CONSTANT(TLS_METHOD_STARTTLS);
|
|
BIND_ENUM_CONSTANT(TLS_METHOD_SMTPS);
|
|
|
|
BIND_ENUM_CONSTANT(SERVER_AUTH_PLAIN);
|
|
BIND_ENUM_CONSTANT(SERVER_AUTH_LOGIN);
|
|
}
|