Mailer 1.0.5
C++ daemon for sending order emails via SMTP
Loading...
Searching...
No Matches
email_sender.cpp
Go to the documentation of this file.
1#include <constants.h>
2#include <email_sender.h>
3#include <logger.h>
4
5/// @brief Конструктор.
6EmailSender::EmailSender(const std::string &smtp_server, const int smtp_port,
7 const std::string &protocol,
8 const std::string &from_email,
9 const std::string &password,
10 const std::string &from_name) {
11 m_smtp_url = protocol + "://" + smtp_server + ':' + std::to_string(smtp_port);
12 m_from = std::make_pair(from_email, from_name);
13 m_password = password;
14}
15
16/// @brief Деструктор. Очищает списки получателей и вложений.
18 m_recvs.clear();
19 m_ccs.clear();
20 m_attachments.clear();
21}
22
23/// @brief Устанавливает тему и тело письма.
24void EmailSender::setEmailContent(const std::string &subject,
25 const std::string &body) {
26 // set email title and body content
27 m_email_subject = subject;
28 m_email_body = body;
29}
30
31/// @brief Добавляет получателя в список "Кому".
32void EmailSender::addRecvEmailAddr(const std::string &email_addr,
33 const std::string &name) {
34 m_recvs.push_back(std::make_pair(email_addr, name));
35}
36
37/// @brief Добавляет получателя в скрытую копию.
38void EmailSender::addCcEmailAddr(const std::string &email_addr,
39 const std::string &name) {
40 m_ccs.push_back(std::make_pair(email_addr, name));
41}
42
43/// @brief Прикрепляет файл к письму.
44void EmailSender::addAttachment(const std::string &filename) {
45 m_attachments.push_back(filename);
46}
47
48/// @brief Отправляет письмо через SMTP (libcurl).
50 int status = SUCCESS;
51
52 CURL *curl;
53 CURLcode res = CURLE_OK;
54
55 curl = curl_easy_init();
56 if (curl) {
57 struct curl_slist *headers = NULL;
58 struct curl_slist *recipients = NULL;
59 struct curl_slist *slist = NULL;
60 curl_mime *mime;
61 curl_mime *alt;
62 curl_mimepart *part;
63
64 /* This is the URL for your mailserver */
65 curl_easy_setopt(curl, CURLOPT_URL, m_smtp_url.c_str());
66
67 /* Login smtp server to verify */
68 curl_easy_setopt(curl, CURLOPT_USERNAME, m_from.first.c_str());
69 curl_easy_setopt(curl, CURLOPT_PASSWORD, m_password.c_str());
70
71 /* Note that this option isn't strictly required, omitting it will result
72 * in libcurl sending the MAIL FROM command with empty sender data. All
73 * autoresponses should have an empty reverse-path, and should be directed
74 * to the address in the reverse-path which triggered them. Otherwise,
75 * they could cause an endless loop. See RFC 5321 Section 4.5.5 for more
76 * details.
77 */
78 std::string from_email_addr =
79 '<' + m_from.first + '>'; // should be like <example@126.com>
80 curl_easy_setopt(curl, CURLOPT_MAIL_FROM, from_email_addr.c_str());
81
82 /* Add recipients, in this particular case they correspond to the
83 * To: and Cc: addressees in the header, but they could be any kind of
84 * recipient. */
85 // receiver
86 for (auto &email_pair : m_recvs) {
87 std::string email_addr = '<' + email_pair.first + '>';
88 recipients = curl_slist_append(recipients, email_addr.c_str());
89 }
90 // cc
91 for (auto &email_pair : m_ccs) {
92 std::string email_addr = '<' + email_pair.first + '>';
93 recipients = curl_slist_append(recipients, email_addr.c_str());
94 }
95 curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
96
97 /* Build and set the message header list. */
98 std::string header;
99
100 header += "From:";
101 header += m_from.second + '<' + m_from.first + '>' + "\n";
102
103 header += "To:";
104 for (unsigned int i = 0; i < m_recvs.size(); i++) {
105 header += m_recvs[i].second += '<' + m_recvs[i].first + '>';
106 if (i != m_recvs.size() - 1)
107 header += ',';
108 }
109 header += "\n";
110
111 header += "Cc:";
112 for (unsigned int i = 0; i < m_ccs.size(); i++) {
113 header += m_ccs[i].second += '<' + m_ccs[i].first + '>';
114 if (i != m_ccs.size() - 1)
115 header += ',';
116 }
117 header += "\n";
118
119 header += "Subject:";
120 header += m_email_subject + "\n";
121
122 headers = curl_slist_append(headers, header.c_str());
123 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
124
125 /* Build the mime message. */
126 mime = curl_mime_init(curl);
127
128 /* The inline part is an alternative proposing the html and the text
129 versions of the e-mail. */
130 alt = curl_mime_init(curl);
131
132 /* HTML message. */
133 part = curl_mime_addpart(alt);
134 curl_mime_data(part, m_email_body.c_str(), CURL_ZERO_TERMINATED);
135 curl_mime_type(part, "text/html; charset=utf-8");
136
137 /* Text message. */
138 // part = curl_mime_addpart(alt);
139 // curl_mime_data(part, m_email_body.c_str(),, CURL_ZERO_TERMINATED);
140
141 /* Create the inline part. */
142 part = curl_mime_addpart(mime);
143 curl_mime_subparts(part, alt);
144 curl_mime_type(part, "multipart/alternative");
145 slist = curl_slist_append(NULL, "Content-Disposition: inline");
146 curl_mime_headers(part, slist, 1);
147
148 /* Add the attachments */
149 for (std::string &filename : m_attachments) {
150 part = curl_mime_addpart(mime);
151 curl_mime_filedata(part, filename.c_str());
152 }
153
154 curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
155 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
156
157 curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY);
158 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
159 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
160
161 /* Send the message */
162 curl_easy_setopt(
163 curl, CURLOPT_VERBOSE,
164 Logger::isLevel(Logger::L_DEBUG)); // 1 means open info print, 0 not
165 res = curl_easy_perform(curl);
166
167 /* Check for errors */
168 if (res != CURLE_OK) {
169 LOGD("curl_easy_perform() failed: " << curl_easy_strerror(res));
170 status = FAILURE;
171 }
172
173 /* Free lists. */
174 curl_slist_free_all(recipients);
175 curl_slist_free_all(headers);
176
177 /* curl won't send the QUIT command until you call cleanup, so you should
178 * be able to re-use this connection for additional messages (setting
179 * CURLOPT_MAIL_FROM and CURLOPT_MAIL_RCPT as required, and calling
180 * curl_easy_perform() again. It may not be a good idea to keep the
181 * connection open for a very long time though (more than a few minutes
182 * may result in the server timing out the connection), and you do want to
183 * clean up in the end.
184 */
185 curl_easy_cleanup(curl);
186
187 /* Free multipart message. */
188 curl_mime_free(mime);
189 }
190
191 return status;
192}
void addCcEmailAddr(const std::string &email_addr, const std::string &name="")
Добавляет получателя в скрытую копию.
std::pair< std::string, std::string > m_from
Пара (email, имя отправителя).
std::vector< std::pair< std::string, std::string > > m_ccs
Список получателей копии (email, имя).
int send()
Отправляет письмо через SMTP (libcurl).
std::string m_smtp_url
URL SMTP-сервера (protocol://server:port).
std::vector< std::string > m_attachments
Список прикреплённых файлов.
void addRecvEmailAddr(const std::string &email_addr, const std::string &name="")
Добавляет получателя в список "Кому".
std::vector< std::pair< std::string, std::string > > m_recvs
Список получателей (email, имя).
EmailSender(const std::string &smtp_server, const int smtp_port, const std::string &protocol, const std::string &from_email, const std::string &password, const std::string &from_name="")
Конструктор.
void setEmailContent(const std::string &subject="", const std::string &body="")
Устанавливает тему и тело письма.
void addAttachment(const std::string &filename)
Прикрепляет файл к письму.
std::string m_password
Пароль для аутентификации.
std::string m_email_body
Тело письма.
~EmailSender()
Деструктор. Очищает списки получателей и вложений.
std::string m_email_subject
Тема письма.
#define FAILURE
Definition mailer.cpp:19
#define SUCCESS
Definition mailer.cpp:18