Skip to content

Commit 04831d4

Browse files
committed
working demo
1 parent 8bbb222 commit 04831d4

12 files changed

Lines changed: 275 additions & 74 deletions

File tree

example/main.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <brewtils/env.h>
22

33
#include <bloomail/clients/gmail.h>
4+
#include <bloomail/version.h>
45

56
int main(int argc, char **argv) {
67
brewtils::env::init("../.env");
@@ -10,5 +11,17 @@ int main(int argc, char **argv) {
1011
bloomail::Client::Gmail gmail = bloomail::Client::Gmail(true);
1112
gmail.login(emailUsername, emailPassword);
1213

14+
logger::success("Logged in successfully for " + emailUsername + "!");
15+
16+
std::string version = "v" + std::to_string(BLOOMAIL_VERSION_MAJOR) + "." +
17+
std::to_string(BLOOMAIL_VERSION_MINOR) + "." +
18+
std::to_string(BLOOMAIL_VERSION_PATCH);
19+
20+
gmail.addToRecipient("[email protected]");
21+
gmail.setSubject("[Bloomail] Test message");
22+
gmail.setMessage("Hi!\n\nThis is a test message sent using bloomail " +
23+
version + "\n\nThanks!");
24+
gmail.sendEmail();
25+
1326
return EXIT_SUCCESS;
1427
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#pragma once
2+
3+
#include <set>
4+
5+
#include <brewtils/string.h>
6+
#include <logger/log.h>
7+
8+
namespace bloomail {
9+
10+
namespace BaseClient {
11+
12+
class IBaseClient {
13+
protected:
14+
bool debug;
15+
bool isLoggedIn;
16+
17+
std::string username;
18+
std::string rawUsername;
19+
std::string password;
20+
std::string subject;
21+
std::string message;
22+
23+
std::set<std::string> toRecipients;
24+
std::set<std::string> ccRecipients;
25+
std::set<std::string> bccRecipients;
26+
27+
virtual void send(const std::string &cmd) = 0;
28+
virtual std::string recv() = 0;
29+
virtual void authenticate() = 0;
30+
virtual void quit() = 0;
31+
32+
void clear();
33+
void validate();
34+
35+
public:
36+
IBaseClient(bool debug = false);
37+
~IBaseClient();
38+
39+
virtual void sendEmail() = 0;
40+
41+
void addToRecipient(const std::string &recipient);
42+
void addCcRecipient(const std::string &recipient);
43+
void addBccRecipient(const std::string &recipient);
44+
45+
void setSubject(const std::string &subject);
46+
void setMessage(const std::string &message);
47+
};
48+
49+
} // namespace BaseClient
50+
51+
} // namespace bloomail

include/bloomail/base_clients/smtp_client.h renamed to include/bloomail/base_clients/smtp.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,35 @@
11
#pragma once
22

3+
#include <set>
4+
35
#include <brewtils/base64.h>
46

5-
#include <bloomail/helper_clients/tls_client.h>
7+
#include <bloomail/base_clients/i_base_client.h>
8+
#include <bloomail/helper_clients/tls.h>
69

710
namespace bloomail {
811

912
namespace BaseClient {
1013

11-
class Smtp {
14+
class Smtp : public IBaseClient {
1215
private:
13-
bool debug;
1416
bool tlsConnected;
15-
std::string username;
16-
std::string password;
1717

1818
bloomail::HelperClient::Tcp tcp;
1919
bloomail::HelperClient::Tls tls;
2020

21-
void send(const std::string &cmd);
22-
std::string recv();
21+
void send(const std::string &cmd) override;
22+
std::string recv() override;
2323
void startTls();
24-
void authenticate();
25-
void quit();
24+
void authenticate() override;
25+
void quit() override;
2626

2727
public:
2828
Smtp(const std::string &host, int port, bool debug = false);
2929
~Smtp();
3030

3131
void login(const std::string &username, const std::string &password);
32+
void sendEmail() override;
3233
};
3334

3435
} // namespace BaseClient

include/bloomail/clients/gmail.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#pragma once
22

3-
#include <bloomail/base_clients/smtp_client.h>
3+
#include <bloomail/base_clients/smtp.h>
44

55
namespace bloomail {
66

File renamed without changes.

include/bloomail/helper_clients/tls_client.h renamed to include/bloomail/helper_clients/tls.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#pragma once
22

3+
#include <openssl/err.h>
34
#include <openssl/ssl.h>
45

5-
#include <bloomail/helper_clients/tcp_client.h>
6+
#include <bloomail/helper_clients/tcp.h>
67

78
namespace bloomail {
89

include/bloomail/version.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#pragma once
2+
3+
#define BLOOMAIL_VERSION_MAJOR 0
4+
#define BLOOMAIL_VERSION_MINOR 1
5+
#define BLOOMAIL_VERSION_PATCH 0

src/base_clients/i_base_client.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#include <bloomail/base_clients/i_base_client.h>
2+
3+
bloomail::BaseClient::IBaseClient::IBaseClient(bool debug) : debug(debug) {
4+
return;
5+
}
6+
7+
bloomail::BaseClient::IBaseClient::~IBaseClient() { return; }
8+
9+
void bloomail::BaseClient::IBaseClient::addToRecipient(
10+
const std::string &recipient) {
11+
this->toRecipients.insert(recipient);
12+
}
13+
14+
void bloomail::BaseClient::IBaseClient::addCcRecipient(
15+
const std::string &recipient) {
16+
this->ccRecipients.insert(recipient);
17+
}
18+
19+
void bloomail::BaseClient::IBaseClient::addBccRecipient(
20+
const std::string &recipient) {
21+
this->bccRecipients.insert(recipient);
22+
}
23+
24+
void bloomail::BaseClient::IBaseClient::setSubject(const std::string &subject) {
25+
this->subject = subject;
26+
}
27+
28+
void bloomail::BaseClient::IBaseClient::setMessage(const std::string &message) {
29+
this->message = message;
30+
}
31+
32+
void bloomail::BaseClient::IBaseClient::clear() {
33+
this->subject.clear();
34+
this->message.clear();
35+
this->toRecipients.clear();
36+
this->ccRecipients.clear();
37+
this->bccRecipients.clear();
38+
}
39+
40+
void bloomail::BaseClient::IBaseClient::validate() {
41+
if (!this->isLoggedIn) {
42+
logger::error("You need to be authenticated before sending an email",
43+
"void bloomail::BaseClient::IBaseClient::validate()");
44+
}
45+
46+
if (this->toRecipients.empty()) {
47+
logger::error("Empty TO recipients",
48+
"void bloomail::BaseClient::IBaseClient::validate()");
49+
}
50+
51+
if (this->subject.empty()) {
52+
logger::error("Empty subject line",
53+
"void bloomail::BaseClient::IBaseClient::validate()");
54+
}
55+
56+
if (this->message.empty()) {
57+
logger::error("Empty message",
58+
"void bloomail::BaseClient::IBaseClient::validate()");
59+
}
60+
}

src/base_clients/smtp.cpp

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#include <bloomail/base_clients/smtp.h>
2+
3+
bloomail::BaseClient::Smtp::Smtp(const std::string &host, int port, bool debug)
4+
: tcp(host, port), tls(tcp), bloomail::BaseClient::IBaseClient(debug),
5+
tlsConnected(false) {
6+
this->recv();
7+
this->send("EHLO localhost");
8+
this->recv();
9+
return;
10+
}
11+
12+
bloomail::BaseClient::Smtp::~Smtp() {
13+
this->quit();
14+
return;
15+
}
16+
17+
void bloomail::BaseClient::Smtp::login(const std::string &username,
18+
const std::string &password) {
19+
if (this->isLoggedIn) {
20+
logger::error("Already logged in with " + this->rawUsername +
21+
". Attempt to login with " + this->username,
22+
"void bloomail::BaseClient::Smtp::login(const std::string "
23+
"&username, const std::string &password)");
24+
}
25+
26+
this->rawUsername = username;
27+
this->username = brewtils::base64::encode(username);
28+
this->password = brewtils::base64::encode(password);
29+
this->startTls();
30+
this->authenticate();
31+
this->isLoggedIn = true;
32+
}
33+
34+
void bloomail::BaseClient::Smtp::send(const std::string &cmd) {
35+
if (this->debug) {
36+
logger::debug((this->tlsConnected ? "[TLS] " : "[TCP] ") + cmd);
37+
}
38+
if (this->tlsConnected) {
39+
this->tls.write(cmd + "\r\n");
40+
} else {
41+
this->tcp.write(cmd + "\r\n");
42+
}
43+
}
44+
45+
std::string bloomail::BaseClient::Smtp::recv() {
46+
std::string response =
47+
this->tlsConnected ? this->tls.read() : this->tcp.read();
48+
if (this->debug) {
49+
logger::debug((this->tlsConnected ? "[TLS] " : "[TCP] ") + response);
50+
}
51+
return response;
52+
}
53+
54+
void bloomail::BaseClient::Smtp::startTls() {
55+
this->send("STARTTLS");
56+
this->recv();
57+
this->tls.connect();
58+
this->tlsConnected = true;
59+
this->send("EHLO localhost");
60+
this->recv();
61+
}
62+
63+
void bloomail::BaseClient::Smtp::authenticate() {
64+
this->send("AUTH LOGIN");
65+
this->recv();
66+
this->send(this->username);
67+
this->recv();
68+
this->send(this->password);
69+
this->recv();
70+
}
71+
72+
void bloomail::BaseClient::Smtp::quit() {
73+
this->send("QUIT");
74+
this->recv();
75+
}
76+
77+
void bloomail::BaseClient::Smtp::sendEmail() {
78+
this->validate();
79+
80+
this->send("MAIL FROM:<" + this->rawUsername + ">");
81+
this->recv();
82+
83+
for (const auto &recipient : this->toRecipients) {
84+
this->send("RCPT TO:<" + recipient + ">");
85+
this->recv();
86+
}
87+
for (const auto &recipient : this->ccRecipients) {
88+
this->send("RCPT TO:<" + recipient + ">");
89+
this->recv();
90+
}
91+
for (const auto &recipient : this->bccRecipients) {
92+
this->send("RCPT TO:<" + recipient + ">");
93+
this->recv();
94+
}
95+
96+
this->send("DATA");
97+
this->recv();
98+
99+
std::string header = "Subject: " + this->subject + "\r\n";
100+
101+
header += "To: ";
102+
bool first = true;
103+
for (const auto &r : this->toRecipients) {
104+
if (!first)
105+
header += ", ";
106+
header += "<" + r + ">";
107+
first = false;
108+
}
109+
header += "\r\n";
110+
111+
if (!this->ccRecipients.empty()) {
112+
header += "Cc: ";
113+
first = true;
114+
for (const auto &r : this->ccRecipients) {
115+
if (!first)
116+
header += ", ";
117+
header += "<" + r + ">";
118+
first = false;
119+
}
120+
header += "\r\n";
121+
}
122+
123+
header += "Content-Type: text/plain; charset=UTF-8\r\n";
124+
header += "\r\n";
125+
this->send(header + brewtils::string::replace(message, "\n", "\r\n") +
126+
"\r\n.");
127+
this->recv();
128+
129+
return this->clear();
130+
}

0 commit comments

Comments
 (0)