add smtp client class in lib_acl_cpp

This commit is contained in:
ubuntu14 2015-09-16 06:03:02 -07:00
parent 4031cd00ff
commit a631725ba5
31 changed files with 626 additions and 169 deletions

View File

@ -2,7 +2,7 @@
#include "http_servlet.h"
#include "master_service.h"
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// ÅäÖÃÄÚÈÝÏî
char *var_cfg_str;
@ -33,7 +33,7 @@ acl::master_int64_tbl var_conf_int64_tab[] = {
{ 0, 0 , 0 , 0, 0 }
};
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
master_service::master_service()
{
@ -52,7 +52,9 @@ void master_service::on_accept(acl::socket_stream* conn)
acl::memcache_session session("127.0.0.1:11211");
http_servlet servlet;
servlet.setLocalCharset("utf-8"); // charset: big5, gb2312, gb18030, gbk, utf-8
// charset: big5, gb2312, gb18030, gbk, utf-8
servlet.setLocalCharset("utf-8");
while (true)
{
if (servlet.doRun(session, conn) == false)

View File

@ -2,7 +2,7 @@
#include "http_servlet.h"
#include "master_service.h"
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// ÅäÖÃÄÚÈÝÏî
char *var_cfg_redis_addrs;
@ -36,7 +36,7 @@ acl::master_int64_tbl var_conf_int64_tab[] = {
{ 0, 0 , 0 , 0, 0 }
};
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
master_service::master_service()
{

View File

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "master_service.h"
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// 配置内容项
char *var_cfg_str;
@ -32,7 +32,7 @@ acl::master_int64_tbl var_conf_int64_tab[] = {
{ 0, 0 , 0 , 0, 0 }
};
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// acl::aio_callback 虚类的子类定义
class io_callback : public acl::aio_callback
@ -58,7 +58,7 @@ protected:
{
if (strncmp(data, "quit", 4) == 0)
{
// 可以显式调用异步流的关闭过程,也可以直接返回 false
// 可以显式调用异步流的关闭过程,也可以直接返回 false
// 通知异步框架自动关闭该异步流
// client_->close();
return false;
@ -99,7 +99,7 @@ private:
acl::aio_socket_stream* client_;
};
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
master_service::master_service()
{

View File

@ -1,6 +1,6 @@
#pragma once
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// ÅäÖÃÄÚÈÝÏî
extern char *var_cfg_str;
@ -15,7 +15,7 @@ extern acl::master_int_tbl var_conf_int_tab[];
extern long long int var_cfg_int64;
extern acl::master_int64_tbl var_conf_int64_tab[];
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//class acl::aio_socket_stream;

View File

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "master_service.h"
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// ÅäÖÃÄÚÈÝÏî
char *var_cfg_str;
@ -32,7 +32,7 @@ acl::master_int64_tbl var_conf_int64_tab[] = {
{ 0, 0 , 0 , 0, 0 }
};
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
master_service::master_service()
{

View File

@ -1,6 +1,6 @@
#pragma once
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// ÅäÖÃÄÚÈÝÏî
extern char *var_cfg_str;
@ -15,7 +15,7 @@ extern acl::master_int_tbl var_conf_int_tab[];
extern long long int var_cfg_int64;
extern acl::master_int64_tbl var_conf_int64_tab[];
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//class acl::socket_stream;

View File

@ -2,7 +2,7 @@
#include "rpc_manager.h"
#include "master_service.h"
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// 配置内容项
char *var_cfg_str;
@ -35,7 +35,7 @@ acl::master_int64_tbl var_conf_int64_tab[] = {
{ 0, 0 , 0 , 0, 0 }
};
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
class request_rpc : public acl::rpc_request
{
@ -76,9 +76,9 @@ protected:
// 开始处理该请求
handle_conn(stream);
// 将 ACL_VSTREAM 与阻塞流对象解绑定,这样才能保证当释放阻塞流对象时
// 不会关闭与请求者的连接,因为该连接本身是属于非阻塞流对象的,需要采
// 用异步流关闭方式进行关闭
// 将 ACL_VSTREAM 与阻塞流对象解绑定,这样才能保证当释放阻塞
// 流对象时不会关闭与请求者的连接,因为该连接本身是属于非阻塞
// 流对象的,需要采用异步流关闭方式进行关闭
stream.unbind();
}
@ -127,7 +127,7 @@ private:
}
};
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// acl::aio_callback 虚类的子类定义
class io_callback : public acl::aio_callback
@ -153,7 +153,7 @@ protected:
{
if (strncmp(data, "quit", len) == 0)
{
// 可以显式调用异步流的关闭过程,也可以直接返回 false
// 可以显式调用异步流的关闭过程,也可以直接返回 false
// 通知异步框架自动关闭该异步流
// client_->close();
return false;
@ -209,7 +209,7 @@ private:
acl::aio_socket_stream* client_;
};
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
master_service::master_service()
{
@ -249,9 +249,11 @@ void master_service::proc_on_init()
{
// 获得异步框架的事件引擎句柄
acl::aio_handle* handle = get_handle();
if (handle == NULL)
logger_fatal("aio handle null!");
// 初始化 rpc 服务对象
rpc_manager::get_instance().init(handle, var_cfg_thread_pool_limit);
rpc_manager::get_instance().init(*handle, var_cfg_thread_pool_limit);
}
void master_service::proc_on_exit()

View File

@ -1,6 +1,6 @@
#pragma once
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// ÅäÖÃÄÚÈÝÏî
extern char *var_cfg_str;
@ -15,7 +15,7 @@ extern acl::master_int_tbl var_conf_int_tab[];
extern long long int var_cfg_int64;
extern acl::master_int64_tbl var_conf_int64_tab[];
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//class acl::aio_socket_stream;

View File

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "master_service.h"
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// ÅäÖÃÄÚÈÝÏî
char *var_cfg_str;
@ -32,7 +32,7 @@ acl::master_int64_tbl var_conf_int64_tab[] = {
{ 0, 0 , 0 , 0, 0 }
};
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
master_service::master_service()
{

View File

@ -1,6 +1,6 @@
#pragma once
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// 配置内容项
extern char *var_cfg_str;
@ -15,7 +15,7 @@ extern acl::master_int_tbl var_conf_int_tab[];
extern long long int var_cfg_int64;
extern acl::master_int64_tbl var_conf_int64_tab[];
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//class acl::socket_stream;
@ -44,8 +44,8 @@ protected:
virtual bool thread_on_accept(acl::socket_stream* stream);
/**
* IO true
*
* IO true
*
* @param stream {socket_stream*}
* @return {bool} false
* thread_main

View File

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "master_service.h"
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// ÅäÖÃÄÚÈÝÏî
char *var_cfg_str;
@ -32,7 +32,7 @@ acl::master_int64_tbl var_conf_int64_tab[] = {
{ 0, 0 , 0 , 0, 0 }
};
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
master_service::master_service()
{

View File

@ -1,6 +1,6 @@
#pragma once
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// ÅäÖÃÄÚÈÝÏî
extern char *var_cfg_str;
@ -15,7 +15,7 @@ extern acl::master_int_tbl var_conf_int_tab[];
extern long long int var_cfg_int64;
extern acl::master_int64_tbl var_conf_int64_tab[];
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
class master_service : public acl::master_trigger
{

View File

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "master_service.h"
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// ÅäÖÃÄÚÈÝÏî
char *var_cfg_str;
@ -32,7 +32,7 @@ acl::master_int64_tbl var_conf_int64_tab[] = {
{ 0, 0 , 0 , 0, 0 }
};
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
master_service::master_service()
{

View File

@ -1,6 +1,6 @@
#pragma once
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// ÅäÖÃÄÚÈÝÏî
extern char *var_cfg_str;
@ -15,7 +15,7 @@ extern acl::master_int_tbl var_conf_int_tab[];
extern long long int var_cfg_int64;
extern acl::master_int64_tbl var_conf_int64_tab[];
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//class acl::socket_stream;

View File

@ -11,40 +11,23 @@ rpc_manager::~rpc_manager()
{
delete service_;
if (handle_ != NULL)
{
handle_->check();
if (internal_handle_)
delete handle_;
}
logger("rpc service destroy ok!");
}
void rpc_manager::init(acl::aio_handle* handle, int max_threads /* = 10 */,
acl::aio_handle_type type /* = acl::ENGINE_SELECT */,
void rpc_manager::init(acl::aio_handle& handle, int max_threads /* = 10 */,
const char* addr /* = NULL */)
{
// 因为本类实例是单例,会在程序 main 之前被调用,
// 所以需要在此类中打开日志
// 创建非阻塞框架句柄
if (handle == NULL)
{
logger("create new handle, max_threads: %d", max_threads);
handle_ = new acl::aio_handle(type);
internal_handle_ = true;
}
else
{
logger("use input handle, max_threads: %d", max_threads);
handle_ = handle;
internal_handle_ = false;
}
handle_ = &handle;
// 创建 rpc 服务对象
service_ = new acl::rpc_service(max_threads);
// 打开消息服务
if (service_->open(handle_, addr && *addr ? addr : NULL) == false)
logger_fatal("open service error: %s", acl::last_serror());
else
logger("open service ok, listening: %s!", service_->get_addr());
logger("open service ok, listen: %s", service_->get_addr());
}
void rpc_manager::fork(acl::rpc_request* req)

View File

@ -11,15 +11,12 @@ public:
/**
*
* @param handle {acl::aio_handle*}
*
* @param handle {acl::aio_handle&}
* @param max_threads {int} 线线
* @param type {acl::aio_handle_type}
* handle
*
* @param addr {const char*} rpc
* 127.0.0.1:PORT
*/
void init(acl::aio_handle* handle, int max_threads = 10,
acl::aio_handle_type type = acl::ENGINE_SELECT,
void init(acl::aio_handle& handle, int max_threads = 10,
const char* addr = NULL);
/**
@ -31,7 +28,7 @@ public:
private:
// 异步消息句柄
acl::aio_handle* handle_;
bool internal_handle_;
// 异步 RPC 通信服务句柄
acl::rpc_service* service_;
};

View File

@ -1,6 +1,10 @@
修改历史列表:
------------------------------------------------------------------------
355) 2015.9.9
355.1) feature: smtp_client 类已经可以非常方便地发送邮件
355.2) samples/smtp_client: 测试邮件发送过程
354) 2015.9.7
354.1) bugfix: geo_member::set_coordinate 中设置经纬度的参数有误
354.2) bugfix: db_row::field_int64 之前使用的将字符串转为64位整数的方法在32位

View File

@ -7,37 +7,87 @@ namespace acl {
class mime_code;
class ostream;
/**
*
*/
class ACL_CPP_API mail_attach
{
public:
/**
*
* @param filepath {const char*}
* @param content_type {const char*}
* @param charset {const char*}
*/
mail_attach(const char* filepath, const char* content_type,
const char* charset);
~mail_attach();
/**
* multipart/relative
* html cid
* @param id {const char*} cid
* @return {mail_attach&}
*/
mail_attach& set_content_id(const char* id);
/**
*
* @return {const char*}
*/
const char* get_filepath() const
{
return filepath_.c_str();
}
/**
* rfc2047
* @return {const char*}
*/
const char* get_filename() const
{
return filename_.c_str();
}
/**
*
* @return {const char*}
*/
const char* get_content_type() const
{
return ctype_.c_str();
}
/**
* set_content_id cid
* @return {const char*}
*/
const char* get_content_id() const
{
return cid_.c_str();
}
/**
*
* @param coder {mime_code*} base64/qp等
* @param out {string&} append
* @return {bool}
*/
bool save_to(mime_code* coder, string& out);
/**
*
* @param coder {mime_code*} base64/qp等
* @param out {out&}
* @return {bool}
*/
bool save_to(mime_code* coder, ostream& out);
/**
* MIME
* @param transfer_encoding {const char*}
* @param out {string&} append
*/
void build_header(const char* transfer_encoding, string& out);
private:

View File

@ -9,53 +9,171 @@ namespace acl {
class mime_code;
class mail_attach;
/**
*
*/
class ACL_CPP_API mail_body
{
public:
/**
*
* @param charset {const char*}
* @param encoding {const char*}
*/
mail_body(const char* charset = "utf-8",
const char* encoding = "base64");
~mail_body();
/**
*
* @return {const string&}
*/
const string& get_content_type() const
{
return content_type_;
}
/**
*
* @return {const http_ctype&}
*/
const http_ctype& get_ctype() const
{
return ctype_;
}
/**
* HTML
* @param html {const char*} HTML
* @param len {size_t} html ( html
* strlen )
* @return {mail_body&}
*/
mail_body& set_html(const char* html, size_t len);
/**
* TEXT
* @param text {const char*} TEXT
* @param len {size_t} text ( text
* strlen )
* @return {mail_body&}
*/
mail_body& set_text(const char* text, size_t len);
/**
* multipart/alternative
*
* @param html {const char*} HTML ()
* @param hlen {size_t} html (>0)
* @param text {const char*} TEXT ()
* @param tlen {size_t} text (>0)
* @return {mail_body&}
*/
mail_body& set_alternative(const char* html, size_t hlen,
const char* text, size_t tlen);
/**
* multipart/relative
* @param html {const char*} HTML ()
* @param hlen {size_t} html (>0)
* @param text {const char*} TEXT ()
* @param tlen {size_t} text (>0)
* @param attachments {const std::vector<mail_attach*>&}
* html cid
* @return {mail_body&}
*/
mail_body& set_relative(const char* html, size_t hlen,
const char* text, size_t tlen,
const std::vector<mail_attach*>& attachments);
/**
* set_html html
* @param len {size_t}
* @return {const char*}
*/
const char* get_html(size_t& len) const
{
len = hlen_;
return html_;
}
/**
* set_text text
* @param len {size_t}
* @return {const char*}
*/
const char* get_text(size_t& len) const
{
len = tlen_;
return text_;
}
/**
* set_attachments
* @return {const std::vector<mail_attach*>*}
*/
const std::vector<mail_attach*>* get_attachments() const
{
return attachments_;
}
/**
*
* @param out {ostream&}
* @return {bool}
*/
bool save_to(ostream& out) const;
/**
*
* @param out {string&}
* @return {bool}
*/
bool save_to(string& out) const;
/**
* text/html
* @param in {const char*} html
* @param len {size_t} in
* @param out {string&}
* @return {bool}
*/
bool save_html(const char* in, size_t len, string& out) const;
/**
* text/plain
* @param in {const char*} plain
* @param len {size_t} in
* @param out {string&}
* @return {bool}
*/
bool save_text(const char* in, size_t len, string& out) const;
/**
* multipart/relative
* @param html {const char*} html
* @param hlen {size_t} html
* @param text {const char*} TEXT ()
* @param tlen {size_t} text (>0)
* @param attachments {const std::vector<mail_attach*>&}
* html cid
* @param out {string&}
* @return {bool}
*/
bool save_relative(const char* html, size_t hlen,
const char* text, size_t tlen,
const std::vector<mail_attach*>& attachments,
string& out) const;
/**
* multipart/alternative
* @param html {const char*} html
* @param hlen {size_t} html
* @param text {const char*} TEXT ()
* @param tlen {size_t} text (>0)
* @param out {string&}
* @return {bool}
*/
bool save_alternative(const char* html, size_t hlen,
const char* text, size_t tlen, string& out) const;

View File

@ -11,67 +11,203 @@ class mail_attach;
class mail_body;
class ofstream;
/**
* SMTP
*
*/
class ACL_CPP_API mail_message
{
public:
/**
*
* @param charset {const char*}
*/
mail_message(const char* charset = "utf-8");
~mail_message();
/**
* SMTP
* @param user {const char*}
* @param pass {const char*}
* @return {mail_message&}
*/
mail_message& set_auth(const char* user, const char* pass);
/**
* SMTP MAIL FROM
* From
* @param from {const char*}
* @param name {const char*}
* @return {mail_message&}
*/
mail_message& set_from(const char* from, const char* name = NULL);
mail_message& set_sender(const char* sender, const char* name = NULL);
/**
* Reply-To
* @param reply_to {const char*} Reply-To
* @param name {const char*} Reply-To
* @return {mail_message&}
*/
mail_message& set_reply_to(const char* reply_to, const char* name = NULL);
/**
* Return-Path
* @param return_path {const char*} Return-Path
* @return {mail_message&}
*/
mail_message& set_return_path(const char* return_path);
/**
* Delivered-To
* @param delivered_to {const char*} Delivered-To
* @return {mail_message&}
*/
mail_message& set_delivered_to(const char* delivered_to);
/**
*
* @param recipients {const char*} RFC822
* @return {mail_message&}
*/
mail_message& add_recipients(const char* recipients);
/**
* To
* @param to {const char*} RFC822
* @return {mail_message&}
*/
mail_message& add_to(const char* to);
/**
* Cc
* @param cc {const char*} RFC822
* @return {mail_message&}
*/
mail_message& add_cc(const char* cc);
/**
*
* @param bcc {const char*} RFC822
* @return {mail_message&}
*/
mail_message& add_bcc(const char* bcc);
/**
* rfc2047
*
* @param subject {const char*}
* @return {mail_message&}
*/
mail_message& set_subject(const char* subject);
/**
*
* @param name {const char*}
* @param value {const char*}
* @return {mail_message&}
*/
mail_message& add_header(const char* name, const char* value);
mail_message& set_body(const mail_body* body);
/**
*
* @param body {const mail_body&}
* @return {mail_message&}
*/
mail_message& set_body(const mail_body& body);
/**
*
* @param filepath {const char*}
* @param content_type {const char*}
* @return {mail_message&}
*/
mail_message& add_attachment(const char* filepath,
const char* content_type);
/**
*
*
* @param filepath {const char*}
* @return {bool}
*/
bool save_to(const char* filepath);
/**
*
* @param out {string&}
* @return {bool}
*/
bool build_header(string& out);
/**
* save_to
* @return {const char*}
*/
const char* get_email() const
{
return filepath_;
}
/**
* SMTP
* @return {const char*}
*/
const char* get_auth_user() const
{
return auth_user_;
}
/**
* SMTP
* @return {const char*}
*/
const char* get_auth_pass() const
{
return auth_pass_;
}
/**
* set_from
* @return {const rfc822_addr*}
*/
const rfc822_addr* get_from() const
{
return from_;
}
/**
* set_sender
* @return {const rfc822_addr*}
*/
const rfc822_addr* get_sender() const
{
return sender_;
}
/**
* set_reply_to
* @return {const rfc822_addr*}
*/
const rfc822_addr* get_reply_to() const
{
return reply_to_;
}
/**
* set_return_path
* @return {const rfc822_addr*}
*/
const rfc822_addr* get_return_path() const
{
return return_path_;
}
/**
* set_delivered_to
* @return {const rfc822_addr*}
*/
const rfc822_addr* get_delivered_to() const
{
return delivered_to_;
@ -82,28 +218,45 @@ public:
return to_list_;
}
/**
* set_cc
* @return {const std::vector<rfc822_addr*>&}
*/
const std::vector<rfc822_addr*>& get_cc() const
{
return cc_list_;
}
/**
* set_bcc
* @return {const std::vector<rfc822_addr*>&}
*/
const std::vector<rfc822_addr*>& get_bcc() const
{
return bcc_list_;
}
/**
*
* @return {const std::vector<rfc822_addr*>&}
*/
const std::vector<rfc822_addr*>& get_recipients() const
{
return recipients_;
}
/**
*
* @param name {const char*}
* @return {const char*}
*/
const char* get_header_value(const char* name) const;
const char* get_filepath() const
{
return filepath_;
}
/**
* MIME
* @param id {const char*} ID
* @param out {string&}
*/
static void create_boundary(const char* id, string& out);
private:

View File

@ -11,20 +11,50 @@ class istream;
class polarssl_conf;
class mail_message;
/**
* SMTP 使
*/
class ACL_CPP_API smtp_client
{
public:
smtp_client(const char* addr, int conn_timeout, int rw_timeout);
/**
*
* @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
* :
* 1data_begin
* 2write/format/vformat/send_file
* 3data_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
@ -44,11 +74,14 @@ public:
*/
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);
@ -56,6 +89,7 @@ public:
*
* @param fmt {const char*}
* @return {bool}
* SMTP
*/
bool format(const char* fmt, ...);
@ -64,33 +98,80 @@ public:
* @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);
/**
* :DATA
* @return {bool}
*/
bool data_begin();
/**
*
* send_email SMTP
*
* @return {bool}
*/
bool data_end();
@ -121,6 +202,7 @@ private:
SMTP_CLIENT* client_;
socket_stream stream_;
bool ehlo_;
bool reuse_;
bool to_recipients(const std::vector<rfc822_addr*>& recipients);
};

View File

@ -18,8 +18,6 @@ public:
istream() {}
virtual ~istream() {}
int read();
/**
*
* @param buf {void*}
@ -140,7 +138,8 @@ public:
/**
*
* @return {int} ASCII
* @return {int} ASCII -1
*
*/
int getch(void);

View File

@ -18,7 +18,7 @@ static void build_html(void)
const char* html = "<html><body>中国人民银行 HTML 格式</body></html>";
acl::mail_body body("gbk");
body.set_html(html, strlen(html));
message.set_body(&body);
message.set_body(body);
const char* filepath = "./html.eml";
if (message.save_to(filepath) == false)
@ -41,7 +41,7 @@ static void build_text(void)
const char* text = "中国人民银行 TEXT 格式";
acl::mail_body body("gbk");
body.set_text(text, strlen(text));
message.set_body(&body);
message.set_body(body);
const char* filepath = "./text.eml";
if (message.save_to(filepath) == false)
@ -67,7 +67,7 @@ static void build_alternative(void)
const char* html = "<html><body>中国人民银行 HTML 格式</body></html>";
acl::mail_body body("gbk");
body.set_alternative(html, strlen(html), text, strlen(text));
message.set_body(&body);
message.set_body(body);
const char* filepath = "./alternative.eml";
if (message.save_to(filepath) == false)
@ -182,7 +182,7 @@ static void build_relative(void)
acl::mail_body body("gbk");
body.set_relative(html.c_str(), html.size(),
text.c_str(), text.size(), attachments);
message.set_body(&body);
message.set_body(body);
const char* filepath = "./relative.eml";
if (message.save_to(filepath) == false)

View File

@ -8,67 +8,100 @@ static acl::polarssl_conf ssl_conf;
static bool send_mail(const char* addr, const char* sender, const char* pass,
const char* recipients, bool use_ssl)
{
acl::smtp_client conn(addr, 60, 60);
if (use_ssl)
conn.set_ssl(&ssl_conf);
conn.set_auth(sender, pass)
acl::mail_message message("gbk");
message.set_auth(sender, pass)
.set_from(sender)
.add_recipients(recipients);
if (conn.send_envelope() == false)
acl::smtp_client conn(addr, 60, 60);
// 设置是否采用 SSL 通信方式
if (use_ssl)
conn.set_ssl(&ssl_conf);
// 发送信封
if (conn.send_envelope(message) == false)
{
printf("send envelope error: %d, %s\r\n",
conn.get_smtp_code(), conn.get_smtp_status());
conn.get_code(), conn.get_status());
return false;
}
// 开始发送邮件体数据
if (conn.data_begin() == false)
{
printf("send data begin error: %d, %s\r\n",
conn.get_smtp_code(), conn.get_smtp_status());
conn.get_code(), conn.get_status());
}
const char* data = "From: <zsxxsz@263.net>\r\n"
"To: zsxxsz@263.net\r\n"
"Subject: hello, world!\r\n"
const char* data = "From: \"郑树新1\" <zsxxsz@263.net>\r\n"
"To: \"郑树新2\" <zsxxsz@263.net>\r\n"
"Subject: 您好,hello, world!\r\n"
"\r\n"
"hello world!\r\n";
// 发送邮件体数据
if (conn.write(data, strlen(data)) == false)
{
printf("send data error: %d, %s\r\n",
conn.get_smtp_code(), conn.get_smtp_status());
conn.get_code(), conn.get_status());
return false;
}
// 发送完毕
if (conn.data_end() == false)
{
printf("send data end error: %d, %s\r\n",
conn.get_smtp_code(), conn.get_smtp_status());
conn.get_code(), conn.get_status());
return false;
}
printf("sendmail ok, from: %s, to: %s, code: %d, status: %s\r\n",
sender, recipients, conn.get_smtp_code(),
conn.get_smtp_status());
sender, recipients, conn.get_code(),
conn.get_status());
// 发送 QUIT 命令
if (conn.quit() == false)
{
printf("send quit error: %d, %s\r\n",
conn.get_smtp_code(), conn.get_smtp_status());
conn.get_code(), conn.get_status());
return false;
}
return true;
}
static bool send_mail(const char* addr, const char* sender, const char* pass,
const char* recipients, const acl::string& email_path, bool use_ssl)
{
acl::mail_message message("utf-8");
message.set_auth(sender, pass)
.set_from(sender)
.add_recipients(recipients);
acl::smtp_client conn(addr, 60, 60);
// 设置是否采用 SSL 通信方式
if (use_ssl)
conn.set_ssl(&ssl_conf);
if (conn.send(message, email_path) == false)
{
printf("send email %s to %s error\r\n",
email_path.c_str(), addr);
return false;
}
printf("send email %s to %s ok\r\n", email_path.c_str(), addr);
return true;
}
static void usage(const char* procname)
{
printf("usage: %s -h[help]\r\n"
"\t-s smtp_server_addr\r\n"
"\t-e [if use ssl]\r\n"
"\t-f email_path\r\n"
"\t-u sender\r\n"
"\t-p sender_pass\r\n"
"\t-t recipients[sample: to1@xxx.com; to2@xxx.com\r\n",
@ -79,13 +112,13 @@ int main(int argc, char* argv[])
{
int ch;
bool use_ssl = false;
acl::string addr("smtp.263.net:25");
acl::string addr("smtp.263.net:25"), email_path;
acl::string sender("zsxxsz@263.net"), pass, recipients;
acl::acl_cpp_init();
acl::log::stdout_open(true);
while ((ch = getopt(argc, argv, "hs:u:p:t:e")) > 0)
while ((ch = getopt(argc, argv, "hs:u:p:t:ef:")) > 0)
{
switch (ch)
{
@ -107,6 +140,9 @@ int main(int argc, char* argv[])
case 'e':
use_ssl = true;
break;
case 'f':
email_path = optarg;
break;
default:
break;
}
@ -118,9 +154,12 @@ int main(int argc, char* argv[])
return 1;
}
(void) send_mail(addr.c_str(), sender.c_str(), pass.c_str(),
recipients.c_str(), use_ssl);
if (email_path.empty())
(void) send_mail(addr.c_str(), sender.c_str(), pass.c_str(),
recipients.c_str(), use_ssl);
else
(void) send_mail(addr.c_str(), sender.c_str(), pass.c_str(),
recipients.c_str(), email_path, use_ssl);
#if defined(_WIN32) || defined(_WIN64)
getchar();

View File

@ -1,6 +0,0 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.9~svn20110310 //

View File

@ -36,7 +36,7 @@ int main(int argc, char* argv[])
printf("after set sendbuf's size: %d, readbuf's size: %d\r\n",
client->get_tcp_sendbuf(), client->get_tcp_recvbuf());
if (client->write("hello world\r\n") == false)
if (client->write("hello world\r\n") == -1)
{
printf("write error\r\n");
delete client;

View File

@ -28,9 +28,7 @@ memcache_pool& memcache_pool::set_timeout(int conn_timeout /* = 30 */,
connect_client* memcache_pool::create_connect()
{
memcache* conn = NEW memcache(addr_, conn_timeout_,
rw_timeout_);
return conn;
return NEW memcache(addr_, conn_timeout_, rw_timeout_);
}
} // namespace acl

View File

@ -43,7 +43,7 @@ bool mail_attach::save_to(mime_code* coder, string& out)
if (coder)
build_header(coder->get_encoding_type(), out);
else
build_header("base64", out);
build_header(NULL, out);
string buf;
if (ifstream::load(filepath_.c_str(), &buf) == false)
@ -72,7 +72,7 @@ bool mail_attach::save_to(mime_code* coder, ostream& out)
if (coder)
build_header(coder->get_encoding_type(), header);
else
build_header("base64", header);
build_header(NULL, header);
if (out.write(header) == -1)
{
@ -140,8 +140,10 @@ void mail_attach::build_header(const char* transfer_encoding, string& out)
{
out.format_append("Content-Type: %s;\r\n", ctype_.c_str());
out.format_append("\tname=\"%s\"\r\n", filename_.c_str());
out.format_append("Content-Transfer-Encoding: %s\r\n",
transfer_encoding);
if (transfer_encoding && *transfer_encoding)
out.format_append("Content-Transfer-Encoding: %s\r\n",
transfer_encoding);
if (cid_.empty())
out.format_append("Content-Disposition: attachment;\r\n"

View File

@ -118,8 +118,8 @@ bool mail_body::save_to(string& out) const
void mail_body::set_content_type(const char* content_type)
{
content_type_.format(content_type);
ctype_.parse(content_type_);
content_type_ = content_type;
ctype_.parse(content_type);
}
bool mail_body::save_html(const char* html, size_t len, string& out) const

View File

@ -202,9 +202,9 @@ const char* mail_message::get_header_value(const char* name) const
return NULL;
}
mail_message& mail_message::set_body(const mail_body* body)
mail_message& mail_message::set_body(const mail_body& body)
{
body_ = body;
body_ = &body;
return *this;
}

View File

@ -10,7 +10,8 @@
namespace acl {
smtp_client::smtp_client(const char* addr, int conn_timeout, int rw_timeout)
smtp_client::smtp_client(const char* addr, int conn_timeout /* = 60 */,
int rw_timeout /* = 60 */)
{
addr_ = acl_mystrdup(addr);
conn_timeout_ = conn_timeout;
@ -18,24 +19,14 @@ smtp_client::smtp_client(const char* addr, int conn_timeout, int rw_timeout)
client_ = NULL;
ehlo_ = true;
reuse_ = false;
ssl_conf_ = NULL;
}
smtp_client::~smtp_client()
{
acl_myfree(addr_);
if (client_)
{
// 将 SMTP_CLIENT 对象的流置空,以避免内部再次释放,
// 因为该流对象会在下面 stream_.close() 时被释放
client_->conn = NULL;
smtp_close(client_);
}
// 当 socket 流对象打开着,则关闭之,同时将依附于其的 SSL 对象释放
if (stream_.opened())
stream_.close();
close();
}
smtp_client& smtp_client::set_ssl(polarssl_conf* ssl_conf)
@ -56,6 +47,32 @@ const char* smtp_client::get_status() const
bool smtp_client::send(const mail_message& message,
const char* email /* = NULL */)
{
// 发送 SMTP 邮件信封过程
if (send_envelope(message) == false)
return false;
// 优先使用参数给出的邮件文件,然后才是 message 中自动生成的邮件文件
if (email == NULL)
email = message.get_email();
// 如果没有可发送的邮件文件,则认为调用者想通过 write 等接口直接发送数据
if (email == NULL)
return true;
// 发送 DATA 命令
if (data_begin() == false)
return false;
// 发送邮件
if (send_email(email) == false)
return false;
// 发送 DATA 结束符
return data_end();
}
bool smtp_client::send_envelope(const mail_message& message)
{
if (open() == false)
return false;
@ -63,31 +80,21 @@ bool smtp_client::send(const mail_message& message,
return false;
if (greet() == false)
return false;
if (!auth_login(message.get_auth_user(), message.get_auth_pass()))
const char* user = message.get_auth_user();
const char* pass = message.get_auth_pass();
if (user && pass && auth_login(user, pass) == false)
return false;
const rfc822_addr* from = message.get_from();
if (from == NULL || from->addr == NULL)
if (from == NULL)
{
logger_error("from null");
return false;
}
if (mail_from(from->addr) == false)
return false;
if (to_recipients(message.get_recipients()) == false)
return false;
if (email != NULL)
{
if (send_email(email) == false)
return false;
return true;
}
email = message.get_email();
if (email != NULL)
{
if (send_email(email) == false)
return false;
return true;
}
return true;
return to_recipients(message.get_recipients());
}
bool smtp_client::open()
@ -96,9 +103,12 @@ bool smtp_client::open()
{
acl_assert(client_ != NULL);
acl_assert(client_->conn == stream_.get_vstream());
reuse_ = true;
return true;
}
reuse_ = false;
client_ = smtp_open(addr_, conn_timeout_, rw_timeout_, 1024);
if (client_ == NULL)
{
@ -106,9 +116,10 @@ bool smtp_client::open()
return false;
}
// 打开流对象
// 打开流对象,只所以使用 stream_ 主要为了使用 SSL 通信
stream_.open(client_->conn);
// 如果设置了 SSL 通信方式,则需要打开 SSL 通信接口
if (ssl_conf_)
{
polarssl_io* ssl = new polarssl_io(*ssl_conf_, false);
@ -119,11 +130,34 @@ bool smtp_client::open()
return false;
}
}
return true;
}
void smtp_client::close()
{
if (client_)
{
// 将 SMTP_CLIENT 对象的流置空,以避免内部再次释放,
// 因为该流对象会在下面 stream_.close() 时被释放
client_->conn = NULL;
smtp_close(client_);
client_ = NULL;
}
// 当 socket 流对象打开着,则关闭之,同时将依附于其的 SSL 对象释放
if (stream_.opened())
stream_.close();
// 重置连接是否被重用的状态
reuse_ = false;
}
bool smtp_client::get_banner()
{
// 如果是同一个连接被使用,则不必再获得服务端的欢迎信息
if (reuse_)
return true;
return smtp_get_banner(client_) == 0 ? true : false;
}
@ -173,7 +207,7 @@ bool smtp_client::to_recipients(const std::vector<rfc822_addr*>& recipients)
std::vector<rfc822_addr*>::const_iterator cit;
for (cit = recipients.begin(); cit != recipients.end(); ++cit)
{
if ((*cit)->addr && rcpt_to((*cit)->addr) != 0)
if ((*cit)->addr && rcpt_to((*cit)->addr) == false)
return false;
}
return true;