acl/lib_acl_cpp/include/acl_cpp/smtp/smtp_client.hpp
2017-06-02 14:47:24 +08:00

220 lines
5.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "../acl_cpp_define.hpp"
#include "../stream/socket_stream.hpp"
#include <vector>
struct SMTP_CLIENT;
namespace acl {
class istream;
class polarssl_conf;
class mail_message;
/**
* SMTP 邮件发送客户端类,可以使用此类对象发送邮件,支持身份认证等功能
*/
class ACL_CPP_API smtp_client
{
public:
/**
* 构造函数
* @param addr {const char*} SMTP 邮件服务器地址格式IP:PORT
* 或 domain:port
* @param conn_timeout {int} 连接服务器的超时时间(秒)
* @param rw_timeout {int} 网络 IO 超时时间(秒)
*/
smtp_client(const char* addr, int conn_timeout = 60,
int rw_timeout = 60);
~smtp_client();
/**
* 调用本函数发送邮件数据至邮件服务端,该函数会首先调用 send_envelop
* 发送信封,当 email 或 message.get_email() 非空时,则会调用发送邮件
* 过程;否则(即 email 和 message.get_email() 均为 NULL则只发送
* 信封
* @param message {const mail_messsage&} 邮件相关信息,必须提前构建好
* @param email {const char*} 非空时,优先使用此文件做为邮件体数据发送
* @return {bool} 发送是否成功
* 注:如果 email 为 NULL 同时 messsage.get_email() 也为 NULL则本
* 函数仅发送 SMTP 信封部分,用户还需要调用:
* data_begin-->write|format|vformat|send_file-->data_end
* 过程来发送邮件数据体
*/
bool send(const mail_message& message, const char* email = NULL);
/**
* 在 SMTP 会话阶段仅发送邮件信封部分数据,应用调用此函数成功后,
* 还需要调用:
* 1、data_begin开始发送邮件体指令
* 2、write/format/vformat/send_file发送邮件数据
* 3、data_end表示发送邮件体数据完毕
* @param message {const mail_message&} 发送邮件所构建的邮件消息对象
* @return {bool} 是否成功
* 注:本函数是 open/auth_login/mail_from/rcpt_to 发送信封过程的组合
*/
bool send_envelope(const mail_message& message);
/**
* 设置 SSL 数据传输模式
* @param ssl_conf {polarssl_conf*} 非空时,指定采用 SSL 传输模式
* @return {smtp_client&}
*/
smtp_client& set_ssl(polarssl_conf* ssl_conf);
/**
* 获得上次 SMTP 交互过程服务端返回的状态码
* @return {int}
*/
int get_code() const;
/**
* 获得上次 SMTP 交互过程服务端返回的状态信息
* @return {const char*}
*/
const char* get_status() const;
/////////////////////////////////////////////////////////////////////
/**
* 发送邮件体数据,可以循环调用本函数,但数据内容必须是严格的邮件格式
* @param data {const char*} 邮件内容
* @param len {size_t} data 邮件数据长度
* @return {bool} 命令操作是否成功
* 注:在第一次调用本函数前,必须保证 SMTP 信封已经成功发送
*/
bool write(const char* data, size_t len);
/**
* 发送邮件体数据,可以循环调用本函数,但数据内容必须是严格的邮件格式
* @param fmt {const char*} 变参格式
* @return {bool} 命令操作是否成功
* 注:在第一次调用本函数前,必须保证 SMTP 信封已经成功发送
*/
bool format(const char* fmt, ...);
/**
* 发送邮件体数据,可以循环调用本函数,但数据内容必须是严格的邮件格式
* @param fmt {const char*} 变参格式
* @param ap {va_list}
* @return {bool} 命令操作是否成功
* 注:在第一次调用本函数前,必须保证 SMTP 信封已经成功发送
*/
bool vformat(const char* fmt, va_list ap);
/////////////////////////////////////////////////////////////////////
/**
* 连接远程 SMTP 服务器
* @return {bool} 连接是否成功,若想使用 SSL 方式,则需要在类对象
* 初始化后调用 set_ssl 设置 SSL 通信方式
*/
bool open();
/**
* 主动关闭与 SMTP 服务端的连接
*/
void close();
/**
* 第一次连接成功后需要调用本函数获得 SMTP 服务端的欢迎信息
* @return {bool} 是否成功
*/
bool get_banner();
/**
* 调用 get_banner 成功后调用本函数向 SMTP 服务端发送 HELO/HELO 命令
* @return {bool} 是否成功
*/
bool greet();
/**
* 调用 gree 成功后调用本函数向 SMTP 服务端发送身份认证命令
* @param user {const char*} 用户账号,非空字符串
* @param pass {const char*} 用户账号密码,非空字符串
* @return {bool} 是否成功
*/
bool auth_login(const char* user, const char* pass);
/**
* 调用 auth_login 成功后(如果无身份验证,则可以在 greet 成功后)
* 调用本函数向 SMTP 服务器发送 MAIL FROM 命令
* @param from {const char*} 发件人的邮箱地址
* @return {bool} 是否成功
*/
bool mail_from(const char* from);
/**
* 调用 mail_from 成功后调用本函数向 SMTP 服务端发送 RCPT TO 命令,
* 指明一个收件人,可以多次本函数将邮件发送至多个收件人
* @param to {const char*} 收件人邮箱地址
* @return {bool} 是否成功
*/
bool rcpt_to(const char* to);
/**
* 调用 rcpt_to 或 send_envelope 成功调用本函数向 SMTP 服务端
* DATA 命令,表明开始发送邮件数据
* @return {bool} 命令操作是否成功
* 注:在调用本函数前,必须保证 SMTP 信封已经成功发送
*/
bool data_begin();
/**
* 调用 data_begin 成功调用本函数向 SMTP 服务端发送一封完整的邮件,
* 需要给出邮件存储于磁盘上的路径
* @param filepath {const char*} 邮件文件路径
* @return {bool} 命令操作是否成功
* 注:在调用本函数前,必须保证 SMTP 信封已经成功发送
*/
bool send_email(const char* filepath);
/**
* 邮件发送完毕如调用send_email最后必须调用本函数告诉 SMTP
* 邮件服务器发送数据结束
* @return {bool} 命令操作是否成功
*/
bool data_end();
/**
* 断开与邮件服务器的连接
* @return {bool} 命令操作是否成功
*/
bool quit();
/**
* NOOP 命令
* @return {bool} 命令操作是否成功
*/
bool noop();
/**
* 重置与邮件服务器的连接状态
* @return {bool} 命令操作是否成功
*/
bool reset();
/**
* 获得与 SMTP 服务器之间的连接流对象,该函数只有当 open 成功后才可调用
* @return {socket_stream&}
*/
socket_stream& get_stream(void)
{
return stream_;
}
private:
polarssl_conf* ssl_conf_;
char* addr_;
int conn_timeout_;
int rw_timeout_;
SMTP_CLIENT* client_;
socket_stream stream_;
bool ehlo_;
bool reuse_;
bool to_recipients(const std::vector<rfc822_addr*>& recipients);
};
} // namespace acl