#include #include "sender.hpp" #include "builder/date.hpp" #include "builder/mail_to.hpp" #include "builder/cc.hpp" #include "builder/subject.hpp" #include "builder/text.hpp" #include "builder/from.hpp" #include "logger/logger_set.hpp" namespace smtp::message { static std::string mText; // //Public methods // bool Sender::Send( manage::Settings const& settings_storage, std::string const& mail_from, general::MailsSet const& mails_to, std::string const& subject, std::string const& text ) { static const std::string METHOD_NAME = "Send message"; if( mails_to.empty() ) { return false; } CURLcode result = CURLE_OK; curl_slist* recipients = nullptr; WriteThis upload_ctx{}; auto curl = curl_easy_init(); //TODO сделать инициализацию через регистратор инициализаторов if( !InitCurl( curl, upload_ctx, settings_storage, mail_from )) { logger::LoggerSet::GetInstance()->LogError( METHOD_NAME, "Error to initializate message service" ); return false; } FillRecipients( curl, recipients, mails_to); UpdateMailText( mails_to, settings_storage.GetUserName(), subject, text ); result = curl_easy_perform( curl ); if( result != CURLE_OK ) { std::string message = "Error to send messge: " + std::string( curl_easy_strerror( result )); logger::LoggerSet::GetInstance()->LogError( METHOD_NAME, message ); return false; } curl_slist_free_all( recipients ); curl_easy_cleanup( curl ); return true; } // //Private methods // bool smtp::message::Sender::InitCurl( CURL* curl, WriteThis const& upload_ctx, manage::Settings const& settings_storage, std::string const& mail_from ) { if( !curl ) { return false; } if( settings_storage.IsNeedAuth()) { curl_easy_setopt( curl, CURLOPT_USERNAME, settings_storage.GetUserName().c_str()); curl_easy_setopt( curl, CURLOPT_PASSWORD, settings_storage.GetPassword().c_str()); } curl_easy_setopt( curl, CURLOPT_URL, GetHostPortData( settings_storage ).c_str()); settings_storage.IsNeedSsl() ? curl_easy_setopt( curl, CURLOPT_USE_SSL, ( long ) CURLUSESSL_ALL ) : curl_easy_setopt( curl, CURLOPT_USE_SSL, ( long ) CURLUSESSL_NONE ); curl_easy_setopt( curl, CURLOPT_MAIL_FROM, mail_from.c_str()); curl_easy_setopt( curl, CURLOPT_READFUNCTION, ReadCallBack ); curl_easy_setopt( curl, CURLOPT_READDATA, &upload_ctx ); curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L ); curl_easy_setopt( curl, CURLOPT_NOPROGRESS, 1L ); return true; } void Sender::FillRecipients( CURL* curl, curl_slist* recipients, general::MailsSet const& mails_to ) { for( const auto& recipient: mails_to ) { recipients = curl_slist_append( recipients, recipient.c_str()); } curl_easy_setopt( curl, CURLOPT_MAIL_RCPT, recipients ); } void Sender::UpdateMailText( general::MailsSet const& mails_to, std::string const& mail_from, std::string const& subject, std::string const& text ) const { auto text_decorator = std::make_shared < builder::Text >( text ); text_decorator->Apply( std::make_shared < builder::Date >()) .Apply( std::make_shared < builder::Subject >( subject )) .Apply( std::make_shared < builder::Cc >( mails_to )) .Apply( std::make_shared < builder::From >( mail_from )) .Apply( std::make_shared < builder::MailTo >( mails_to )); mText = text_decorator->Get(); } std::string Sender::GetHostPortData( manage::Settings const& settings_storage ) const { auto result = "smtp://" + settings_storage.GetHost(); if( !settings_storage.GetPort().empty()) { result += ":" + settings_storage.GetPort(); } return result; } //TODO Надо убрать этот ужас. Без статики!!! size_t Sender::ReadCallBack( void* ptr, size_t size, size_t nmemb, void* userp ) { auto pooh = reinterpret_cast( userp ); if( size * nmemb < 1 || pooh->counter++ > 0 ) { return 0; } memcpy( ptr, mText.c_str(), mText.size()); return mText.size(); } }