42    void addMissingHeaders(shared_ptr<mail::Email>& email, shared_ptr<mail::EmailAddress> 
const& from) {
 
   43        if (!email->headers().count(
"Date")) {
 
   46        if (!email->headers().count(
"From") && !from->address().empty()) {
 
   47            email->headers()[
"From"] = from->get();
 
   50        if (!email->headers().count(
"Message-ID") && !from->address().empty() && (atPos = from->address().find_last_of(
'@')) != string::npos) {
 
   55            clock_gettime(CLOCK_REALTIME, &mtime);
 
   56            base << mtime.tv_sec << mtime.tv_nsec << from->address() << rd();
 
   57            mid << 
'<' << 
crypto::md5(base.str(), 
true) << 
'@' << from->address().substr(atPos + 1) << 
'>';
 
   58            email->headers()[
"Message-ID"] = mid.str();
 
   66        std::shared_ptr<mail::Email const> email;
 
   67        std::shared_ptr<mail::EmailAddress const> from;
 
   68        std::vector<mail::EmailAddress> recipients;
 
   69        std::shared_ptr<mail::ReplacementRules> replacementRules;
 
   73struct mail::SmtpMailer::Data {
 
   74    std::string serverDomain;
 
   75    unsigned int serverPort;
 
   76    TlsMode serverTlsMode;
 
   77    bool verifyServerTlsCert;
 
   78    std::string authUsername;
 
   79    std::string authPassword;
 
   80    long connectionTimeout;
 
   81    std::vector<QueueElem> queue;
 
   83    Data(
string serverDomain, 
unsigned int serverPort, TlsMode serverTlsMode, 
bool verifyServerTlsCert,
 
   84         string authUsername, 
string authPassword, 
long connectionTimeout) : serverDomain(std::move(serverDomain)),
 
   85                                                                             serverPort(serverPort),
 
   86                                                                             serverTlsMode(serverTlsMode),
 
   87                                                                             verifyServerTlsCert(verifyServerTlsCert),
 
   88                                                                             authUsername(std::move(authUsername)),
 
   89                                                                             authPassword(std::move(authPassword)),
 
   90                                                                             connectionTimeout(connectionTimeout) {}
 
   96                             bool verifyServerTlsCert, 
string authUsername, 
string authPassword,
 
   97                             long connectionTimeout) {
 
   98    data = make_unique<Data>(std::move(serverDomain), serverPort, serverTlsMode, verifyServerTlsCert, std::move(authUsername),
 
   99                             std::move(authPassword), connectionTimeout);
 
  102void mail::SmtpMailer::setServer(std::string domain, 
unsigned int port, 
SmtpMailer::TlsMode tlsMode, 
bool verifyTlsCert) {
 
  103    data->serverDomain = std::move(domain);
 
  104    data->serverPort = port;
 
  105    data->serverTlsMode = tlsMode;
 
  106    data->verifyServerTlsCert = verifyTlsCert;
 
  109void mail::SmtpMailer::setAuth(std::string username, std::string password) {
 
  110    data->authUsername = std::move(username);
 
  111    data->authPassword = std::move(password);
 
  114void mail::SmtpMailer::setConnectionTimeout(
long timeout) {
 
  115    data->connectionTimeout = timeout;
 
  118void mail::SmtpMailer::enqueue(std::shared_ptr<Email> email, 
EmailAddress to, std::shared_ptr<EmailAddress> from,
 
  119                               std::shared_ptr<ReplacementRules> replacementRules) {
 
  120    bulkEnqueue(std::move(email), vector<EmailAddress>({std::move(to)}), std::move(from),
 
  121                std::move(replacementRules));
 
  124void mail::SmtpMailer::bulkEnqueue(std::shared_ptr<Email> email, std::vector<EmailAddress> recipients,
 
  125                                   std::shared_ptr<EmailAddress> from, std::shared_ptr<ReplacementRules> replacementRules) {
 
  126    addMissingHeaders(email, from);
 
  127    data->queue.push_back(QueueElem{.email = std::move(email), .from = std::move(from), .recipients = std::move(recipients), .replacementRules = std::move(replacementRules)});
 
  130void mail::SmtpMailer::clearQueue() {
 
  134void mail::SmtpMailer::processQueue()
 const {
 
  138    curl = curl_easy_init();
 
  142        if (!data->authUsername.empty()) {
 
  143            curl_easy_setopt(curl, CURLOPT_USERNAME, data->authUsername.c_str());
 
  144            if (!data->authPassword.empty())
 
  145                curl_easy_setopt(curl, CURLOPT_PASSWORD, data->authPassword.c_str());
 
  150            stringstream curlUrl;
 
  151            if (data->serverTlsMode == TlsMode::SMTPS) {
 
  152                curlUrl << 
"smtps://";
 
  154                curlUrl << 
"smtp://";
 
  156            curlUrl << data->serverDomain << 
":" << data->serverPort;
 
  157            curl_easy_setopt(curl, CURLOPT_URL, curlUrl.str().c_str());
 
  161        if (data->serverTlsMode == TlsMode::REQUIRE_STARTTLS) {
 
  162            curl_easy_setopt(curl, CURLOPT_USE_SSL, (
long) CURLUSESSL_ALL);
 
  163        } 
else if (data->serverTlsMode == TlsMode::TRY_STARTTLS) {
 
  164            curl_easy_setopt(curl, CURLOPT_USE_SSL, (
long) CURLUSESSL_TRY);
 
  166        if (data->serverTlsMode != TlsMode::NONE && !data->verifyServerTlsCert) {
 
  167            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
 
  168            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
 
  172        FILE* devNull = fopen(
"/dev/null", 
"wb");
 
  173        curl_easy_setopt(curl, CURLOPT_STDERR, devNull);
 
  176        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, data->connectionTimeout);
 
  179        for (
const auto& mail : data->queue) {
 
  182            curl_easy_setopt(curl, CURLOPT_MAIL_FROM, mail.from->get(
false).c_str());
 
  185            curl_slist* recipients = 
nullptr;
 
  186            for (
const auto& to : mail.recipients) {
 
  187                recipients = curl_slist_append(recipients, to.get(
false).c_str());
 
  189            curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
 
  192            string payload = mail.email->getRaw(mail.replacementRules);
 
  194            FILE* payloadFile = fmemopen((
void*) payload.c_str(), payload.length(), 
"r");
 
  195            curl_easy_setopt(curl, CURLOPT_READDATA, (
void*) payloadFile);
 
  196            curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
 
  199            res = curl_easy_perform(curl);
 
  202            curl_slist_free_all(recipients);
 
  206            if (res != CURLE_OK) {
 
  207                curl_easy_cleanup(curl);
 
  209                                string(
"CURL error: ") + curl_easy_strerror(res));
 
  213        curl_easy_cleanup(curl);
 
Structure representing an email address.
 
Exception class that can be used by apps to catch errors resulting from nawa function calls.
 
For establishing a connection to an SMTP server and sending emails.
 
A bunch of useful cryptographic functions (esp. hashing), acting as a wrapper to C crypto libraries.
 
#define NAWA_DEFAULT_DESTRUCTOR_IMPL_WITH_NS(Namespace, Class)
 
std::string md5(std::string const &input, bool hex=true)
 
std::string makeSmtpTime(time_t time)
 
Contains useful functions that improve the readability and facilitate maintenance of the NAWA code.