-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsmtpsend.hpp
More file actions
206 lines (171 loc) · 6.3 KB
/
smtpsend.hpp
File metadata and controls
206 lines (171 loc) · 6.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
// =====================================================================================
//
// Filename: smtpsend.hpp
// Version: 1.0
// Created: 05.12.2012 11:15:58
// Author: selivanov
// =====================================================================================
//
//
// Добавить авторизацию
// Добавить резольвилку MX (отправка без указания сервера)
#pragma once
#include <string>
#include <vector>
#include <stdexcept>
#include <boost/lexical_cast.hpp>
#include <boost/interprocess/detail/atomic.hpp>
#include <ace/SOCK_Stream.h>
namespace transport
{
class temporary_error : public std::runtime_error
{
public:
explicit temporary_error(const std::string& msg)
: std::runtime_error("Temporary error [" + msg + "]")
{
}
};
class permanent_error : public std::runtime_error
{
public:
explicit permanent_error(const std::string& msg)
: std::runtime_error("Permanent error [" + msg + "]")
{
}
explicit permanent_error(const std::string& cmd, const std::string& retmsg)
: std::runtime_error("Permanent error [" + cmd + "] [" + retmsg + "]")
{}
explicit permanent_error(const std::string& cmd, const std::string& arg, const std::string& retmsg)
: std::runtime_error("Permanent error [" + cmd + " " + arg + "] [" + retmsg + "]")
{}
};
class resolve_error : public permanent_error
{
public:
explicit resolve_error(const std::string& msg)
: permanent_error("Resolve error [" + msg + "]")
{
}
explicit resolve_error(const std::string& host, int port)
: permanent_error("Can't resolve " + host + ":"+ boost::lexical_cast<std::string>(port))
{}
};
class connect_exception : public temporary_error
{
public:
explicit connect_exception()
: temporary_error("Connection not established")
{}
explicit connect_exception(const std::string& host, int port)
: temporary_error("Can't connect to " + host + ":"+ boost::lexical_cast<std::string>(port))
{}
};
class transport_error : public temporary_error
{
public:
explicit transport_error(const std::string& msg, const std::string& host, int port)
: temporary_error("Transport error: " + msg + " " + host + ":"+ boost::lexical_cast<std::string>(port))
{}
};
class command_unexpected : public temporary_error
{
public:
explicit command_unexpected(const std::string& retmsg, int expected_retcode)
: temporary_error("Unexpected command reply [" + retmsg + "] expected:" + boost::lexical_cast<std::string>(expected_retcode))
{}
explicit command_unexpected(const std::string& cmd, const std::string& retmsg, int expected_retcode)
: temporary_error("Unexpected command reply [" + cmd + "] [" + retmsg + "] expected:" + boost::lexical_cast<std::string>(expected_retcode))
{}
explicit command_unexpected(const std::string& cmd, const std::string& arg, const std::string& retmsg, int expected_retcode)
: temporary_error("Unexpected command reply [" + cmd + " " + arg + "] [" + retmsg + "] expected:" + boost::lexical_cast<std::string>(expected_retcode))
{}
};
class transient_error : public temporary_error
{
public:
explicit transient_error(const std::string& retmsg)
: temporary_error("Transient error [" + retmsg + "]")
{}
explicit transient_error(const std::string& cmd, const std::string& retmsg)
: temporary_error("Transient error [" + cmd + "] [" + retmsg + "]")
{}
explicit transient_error(const std::string& cmd, const std::string& arg, const std::string& retmsg)
: temporary_error("Transient error [" + cmd + " " + arg + "] [" + retmsg + "]")
{}
};
class protocol_error : public temporary_error
{
public:
explicit protocol_error(const std::string& retmsg)
: temporary_error("Protocol error [" + retmsg + "]")
{}
explicit protocol_error(const std::string& cmd, const std::string& retmsg)
: temporary_error("Protocol error [" + cmd + "] [" + retmsg + "]")
{}
explicit protocol_error(const std::string& cmd, const std::string& arg, const std::string& retmsg)
: temporary_error("Protocol error [" + cmd + " " + arg + "] [" + retmsg + "]")
{}
};
typedef std::vector<std::string> RecipientList;
// Пример использования
//
// transport::SmtpTransport t;
// t.connect(mx_host);
// std::stringstream ss;
// ss<<"From: <test@km.ru>\r\n\r\nMessage body";
// transport::RecipientList rl;
// rl.push_back("support@km.ru");
// t.send_message(ss, "test@km.ru", rl);
//
class SmtpTransport
{
public:
~SmtpTransport();
SmtpTransport(int timeout = 4);
void connect(const std::string& host, int port = 25, std::string helo = "");
void send_message(std::istream& ifs, const std::string& from, const RecipientList& recipient_list);
std::string host() const { return host_; }
int port() const { return port_; }
private:
std::string normalize(const std::string& email);
unsigned int say(const std::string& cmd, unsigned int expected_retcode = 0);
unsigned int say(const std::string& cmd, const std::string& arg, unsigned int expected_retcode = 0);
unsigned int say_data(std::string& buf, unsigned int expected_retcode = 0);
unsigned int get(std::vector<std::string>& response, unsigned int max_len = 4096);
private:
std::string host_;
int port_;
bool connected_;
ACE_SOCK_Stream stream_;
ACE_Time_Value timeout_;
static boost::uint32_t connect_count;
public:
static int get_connection_count();
};
inline bool match_str(const char* b, const char* e, const char* term_str, unsigned int term_len, unsigned int* match_from)
{
unsigned int n = e - b;
if( n >= (term_len - *match_from))
{
n = (term_len - *match_from);
}
unsigned int i;
for(i = 0; i < n; ++i)
{
if( b[i] != term_str[*match_from+i])
{
return false;
}
}
if(*match_from + i == term_len)
{
return true;
}
else
{
*match_from += (i);
return false;
}
}
}