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