acl  3.5.3.0
smtp_client.hpp
浏览该文件的文档.
1 #pragma once
2 #include "../acl_cpp_define.hpp"
3 #include "../stdlib/noncopyable.hpp"
4 #include "../stream/socket_stream.hpp"
5 #include <vector>
6 
7 #if !defined(ACL_MIME_DISABLE)
8 
9 struct SMTP_CLIENT;
10 
11 namespace acl {
12 
13 class istream;
14 class sslbase_conf;
15 class mail_message;
16 
17 /**
18  * SMTP 邮件发送客户端类,可以使用此类对象发送邮件,支持身份认证等功能
19  */
21 {
22 public:
23  /**
24  * 构造函数
25  * @param addr {const char*} SMTP 邮件服务器地址,格式:IP:PORT
26  * 或 domain:port
27  * @param conn_timeout {int} 连接服务器的超时时间(秒)
28  * @param rw_timeout {int} 网络 IO 超时时间(秒)
29  */
30  smtp_client(const char* addr, int conn_timeout = 60,
31  int rw_timeout = 60);
32  ~smtp_client();
33 
34  /**
35  * 调用本函数发送邮件数据至邮件服务端,该函数会首先调用 send_envelop
36  * 发送信封,当 email 或 message.get_email() 非空时,则会调用发送邮件
37  * 过程;否则(即 email 和 message.get_email() 均为 NULL)则只发送
38  * 信封
39  * @param message {const mail_messsage&} 邮件相关信息,必须提前构建好
40  * @param email {const char*} 非空时,优先使用此文件做为邮件体数据发送
41  * @return {bool} 发送是否成功
42  * 注:如果 email 为 NULL 同时 messsage.get_email() 也为 NULL,则本
43  * 函数仅发送 SMTP 信封部分,用户还需要调用:
44  * data_begin-->write|format|vformat|send_file-->data_end
45  * 过程来发送邮件数据体
46  */
47  bool send(const mail_message& message, const char* email = NULL);
48 
49  /**
50  * 在 SMTP 会话阶段仅发送邮件信封部分数据,应用调用此函数成功后,
51  * 还需要调用:
52  * 1、data_begin:开始发送邮件体指令
53  * 2、write/format/vformat/send_file:发送邮件数据
54  * 3、data_end:表示发送邮件体数据完毕
55  * @param message {const mail_message&} 发送邮件所构建的邮件消息对象
56  * @return {bool} 是否成功
57  * 注:本函数是 open/auth_login/mail_from/rcpt_to 发送信封过程的组合
58  */
59  bool send_envelope(const mail_message& message);
60 
61  /**
62  * 设置 SSL 数据传输模式
63  * @param ssl_conf {sslbase_conf*} 非空时,指定采用 SSL 传输模式
64  * @return {smtp_client&}
65  */
66  smtp_client& set_ssl(sslbase_conf* ssl_conf);
67 
68  /**
69  * 获得上次 SMTP 交互过程服务端返回的状态码
70  * @return {int}
71  */
72  int get_code() const;
73 
74  /**
75  * 获得上次 SMTP 交互过程服务端返回的状态信息
76  * @return {const char*}
77  */
78  const char* get_status() const;
79 
80  /////////////////////////////////////////////////////////////////////
81 
82  /**
83  * 发送邮件体数据,可以循环调用本函数,但数据内容必须是严格的邮件格式
84  * @param data {const char*} 邮件内容
85  * @param len {size_t} data 邮件数据长度
86  * @return {bool} 命令操作是否成功
87  * 注:在第一次调用本函数前,必须保证 SMTP 信封已经成功发送
88  */
89  bool write(const char* data, size_t len);
90 
91  /**
92  * 发送邮件体数据,可以循环调用本函数,但数据内容必须是严格的邮件格式
93  * @param fmt {const char*} 变参格式
94  * @return {bool} 命令操作是否成功
95  * 注:在第一次调用本函数前,必须保证 SMTP 信封已经成功发送
96  */
97  bool format(const char* fmt, ...);
98 
99  /**
100  * 发送邮件体数据,可以循环调用本函数,但数据内容必须是严格的邮件格式
101  * @param fmt {const char*} 变参格式
102  * @param ap {va_list}
103  * @return {bool} 命令操作是否成功
104  * 注:在第一次调用本函数前,必须保证 SMTP 信封已经成功发送
105  */
106  bool vformat(const char* fmt, va_list ap);
107 
108  /////////////////////////////////////////////////////////////////////
109 
110  /**
111  * 连接远程 SMTP 服务器
112  * @return {bool} 连接是否成功,若想使用 SSL 方式,则需要在类对象
113  * 初始化后调用 set_ssl 设置 SSL 通信方式
114  */
115  bool open();
116 
117  /**
118  * 主动关闭与 SMTP 服务端的连接
119  */
120  void close();
121 
122  /**
123  * 第一次连接成功后需要调用本函数获得 SMTP 服务端的欢迎信息
124  * @return {bool} 是否成功
125  */
126  bool get_banner();
127 
128  /**
129  * 调用 get_banner 成功后调用本函数向 SMTP 服务端发送 HELO/HELO 命令
130  * @return {bool} 是否成功
131  */
132  bool greet();
133 
134  /**
135  * 调用 gree 成功后调用本函数向 SMTP 服务端发送身份认证命令
136  * @param user {const char*} 用户账号,非空字符串
137  * @param pass {const char*} 用户账号密码,非空字符串
138  * @return {bool} 是否成功
139  */
140  bool auth_login(const char* user, const char* pass);
141 
142  /**
143  * 调用 auth_login 成功后(如果无身份验证,则可以在 greet 成功后)
144  * 调用本函数向 SMTP 服务器发送 MAIL FROM 命令
145  * @param from {const char*} 发件人的邮箱地址
146  * @return {bool} 是否成功
147  */
148  bool mail_from(const char* from);
149 
150  /**
151  * 调用 mail_from 成功后调用本函数向 SMTP 服务端发送 RCPT TO 命令,
152  * 指明一个收件人,可以多次本函数将邮件发送至多个收件人
153  * @param to {const char*} 收件人邮箱地址
154  * @return {bool} 是否成功
155  */
156  bool rcpt_to(const char* to);
157 
158  /**
159  * 调用 rcpt_to 或 send_envelope 成功调用本函数向 SMTP 服务端
160  * DATA 命令,表明开始发送邮件数据
161  * @return {bool} 命令操作是否成功
162  * 注:在调用本函数前,必须保证 SMTP 信封已经成功发送
163  */
164  bool data_begin();
165 
166  /**
167  * 调用 data_begin 成功调用本函数向 SMTP 服务端发送一封完整的邮件,
168  * 需要给出邮件存储于磁盘上的路径
169  * @param filepath {const char*} 邮件文件路径
170  * @return {bool} 命令操作是否成功
171  * 注:在调用本函数前,必须保证 SMTP 信封已经成功发送
172  */
173  bool send_email(const char* filepath);
174 
175  /**
176  * 邮件发送完毕(如调用:send_email)后,最后必须调用本函数告诉 SMTP
177  * 邮件服务器发送数据结束
178  * @return {bool} 命令操作是否成功
179  */
180  bool data_end();
181 
182  /**
183  * 断开与邮件服务器的连接
184  * @return {bool} 命令操作是否成功
185  */
186  bool quit();
187 
188  /**
189  * NOOP 命令
190  * @return {bool} 命令操作是否成功
191  */
192  bool noop();
193 
194  /**
195  * 重置与邮件服务器的连接状态
196  * @return {bool} 命令操作是否成功
197  */
198  bool reset();
199 
200  /**
201  * 获得与 SMTP 服务器之间的连接流对象,该函数只有当 open 成功后才可调用
202  * @return {socket_stream&}
203  */
205  {
206  return stream_;
207  }
208 
209 private:
210  sslbase_conf* ssl_conf_;
211  char* addr_;
212  int conn_timeout_;
213  int rw_timeout_;
214  SMTP_CLIENT* client_;
215  socket_stream stream_;
216  bool ehlo_;
217  bool reuse_;
218 
219  bool to_recipients(const std::vector<rfc822_addr*>& recipients);
220 };
221 
222 } // namespace acl
223 
224 #endif // !defined(ACL_MIME_DISABLE)
ACL_API ACL_VSTRING const char * format
Definition: acl_vstring.h:239
socket_stream & get_stream(void)
ACL_API void const char * fmt
Definition: acl_aio.h:771
#define ACL_CPP_API