完美支持中文及附件的基于libcur邮件客户端封装类

最近做了一个小项目需要在windows c++ 环境下,发送邮件
在网上查了很多,大部分编译不成功,少部分中文乱码
参考了 libcurl实例及,网友的源码,努力了两天终于得到了比较圆满的结果
从 https://github.com/honeyligo/curlsmtp.git 上修改
话不多说上源码
调用方式

创新互联是专业的双峰网站建设公司,双峰接单;提供成都网站设计、成都网站制作、外贸网站建设,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行双峰网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!

    std::vector to = {
        "43982653@qq.com"
    };
    std::vector cc = {
        "fj1981@126.com"
    };
    std::vector attach = {
        "C:\\Users\\xxx\\Downloads\\Compressed\\curlsmtp-master\\curlsmtp.cpp"
    };
    auto l =L"相信相当数量的人都已经在准备吐槽了,只要看过《编程珠玑》的人都知道这道题的答案和其中极为简单的道理。不过别着急骂街,不管你信不信,这道笔试题我拿到的答案好多都长这样:";
    auto aa = CStdStr::W2UTF(l);
    CurlSmtp* mail = new CurlSmtp("fj1981"
                                  , "*****"
                                  , "smtp.126.com"
                                  , "25");
    mail->set_from("fj1981@126.com");
    mail->set_subject("相信相当数量的人都已经在准备吐槽了");
    mail->set_message(aa);
    mail->set_to(to);
   // mail->set_attach(attach);
    mail->send_mail();
    Sleep(5);

#ifndef __CURL_SMTP_H__
#define __CURL_SMTP_H__

#include 
#include 
#include 
#include 
#include "ustd_string.h"

#define SMTP_SERVER             "smtp.126.com"
#define SMTP_PORT               "25"

class CurlSmtp {
    struct WriteThis {
        int pos;
        int counter;
        std::vector data;
    };

  public:
    CurlSmtp(const std::string& user,
             const std::string& password,
             const std::string& server = SMTP_SERVER,
             const std::string& port = SMTP_PORT);

    ~CurlSmtp();

    void set_from(const std::string& from);
    void set_to(const std::vector& to);
    void set_secret(const std::vector& secret);
    void set_cc(const std::vector& cc);
    void set_attach(const std::vector& attach);
    void set_subject(const std::string& subject);
    void set_message(const std::string& message);
    void set_server(const std::string& server);
    void set_port(const std::string& port);
    void set_user(const std::string& user);
    void set_password(const std::string& password);
    bool send_mail();
    std::string last_error() const;
  private:
    void make_send_message();
    bool attach(const std::string& filename);
    void set_receiver_list();
    void set_curl_option();
    void clear();
    static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp);

    std::string get_boundary();

  private:
    std::vector send_buffer_;
    std::string from_;
    std::vector to_;
    std::vector cc_;
    std::vector secret_;
    std::vector attach_;
    std::string server_;
    std::string port_;
    std::string subject_;
    std::string message_;
    std::string user_;
    std::string password_;
    std::string last_error_;
    std::vector, std::string>> attachment_;

    CURL *curl_ = nullptr;
    struct curl_slist* rcpt_list_;
    struct WriteThis pooh_;

    std::unordered_map typeMap_;
};

#endif // !__CURL_SMTP_H__

#include "stdafx.h"
//#include 
#include "curlsmtp.h"
#include 

#define LEFT_BRACE                    "<"
#define RIGTH_BRACE                   ">"
#define ENTER                       "\r\n"
#define BOUNDARY_FLAG               "--"

#define USER_AGENT                  "User-Agent: Mail Client"
#define MIME_VER                    "MIME-Version: 1.0"
#define HEADER_CONTENT_TYPE         "Content-Type: multipart/mixed;"

#define MSG_CONTENT_TYPE            "Content-Type: text/html; charset=utf-8; format=flowed"
#define MSG_ENCODING                "Content-Transfer-Encoding: 7bit"

#define MULTI_PERFORM_HANG_TIMEOUT  60 * 1000
#define CHUNCK_SIZE                 1024 * 10

size_t CurlSmtp::read_callback(void *ptr, size_t size, size_t nmemb,
                               void *userp) {
    struct WriteThis *pooh = (struct WriteThis *)userp;
    //const char *data;
    if(size * nmemb < 1)
        return 0;
    const std::string& str = pooh->data[pooh->counter];
    if(pooh->counter < (int)pooh->data.size()) {
        size_t len = str.size();
        int size = len - pooh->pos;
        if (len < CHUNCK_SIZE || size <= CHUNCK_SIZE) {
            memcpy(ptr, str.c_str() + pooh->pos, size);
            pooh->counter++; /* advance pointer */
            pooh->pos = 0;
            return size;
        } else {
            memcpy(ptr, str.c_str() + pooh->pos, CHUNCK_SIZE);
            pooh->pos += CHUNCK_SIZE;
            return CHUNCK_SIZE;
        }
    }
    return 0;
}

std::string CurlSmtp::get_boundary() {
    std::string boundary;
    boundary.reserve(16);
    const char hex[] =
        "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    for (int i = 0; i < 16; ++i) {
        int x = rand() % 62;
        boundary.append(1, hex[x]);
    }
    return boundary;
}

CurlSmtp::CurlSmtp(const std::string& user,
                   const std::string& password,
                   const std::string& server,
                   const std::string& port)
    : user_(user)
    , password_(password)
    , server_(server)
    , port_(port)
    , rcpt_list_(NULL)
    , curl_(curl_easy_init()) {
    curl_global_init(CURL_GLOBAL_DEFAULT);
    typeMap_.insert(std::make_pair(".gif", "Content-Type: image/gif;"));
    typeMap_.insert(std::make_pair(".jpg", "Content-Type: image/jpg;"));
    typeMap_.insert(std::make_pair(".jpeg", "Content-Type: image/jpeg;"));
    typeMap_.insert(std::make_pair(".png", "Content-Type: image/png;"));
    typeMap_.insert(std::make_pair(".bmp", "Content-Type: image/bmp;"));
    typeMap_.insert(std::make_pair(".txt", "Content-Type: plain/txt;"));
    typeMap_.insert(std::make_pair(".log", "Content-Type: plain/txt;"));
    typeMap_.insert(std::make_pair(".htm", "Content-Type: plain/htm;"));
    typeMap_.insert(std::make_pair(".html", "Content-Type: plain/htm;"));
    typeMap_.insert(std::make_pair(".exe",
                                   "Content-Type: application/X-exectype-1;"));
}

CurlSmtp::~CurlSmtp() {
    curl_easy_cleanup(curl_);
    curl_global_cleanup();
}

void CurlSmtp::set_from(const std::string& from) {
    from_.assign(from);
}

void CurlSmtp::set_password(const std::string& password) {
    password_.assign(password);
}

void CurlSmtp::set_to(const std::vector& to) {
    to_.resize(to.size());
    to_.assign(to.begin(), to.end());
}

void CurlSmtp::set_secret(const std::vector& secret) {
    secret_.resize(secret.size());
    secret_.assign(secret.begin(), secret.end());
}

void CurlSmtp::set_cc(const std::vector& cc) {
    cc_.resize(cc.size());
    cc_.assign(cc.begin(), cc.end());
}

void CurlSmtp::set_attach(const std::vector& attach) {
    attach_.resize(attach.size());
    attach_.assign(attach.begin(), attach.end());
}

void CurlSmtp::set_subject(const std::string& subject) {
    std::vector outdata;
    ustd::string::base64encode(&subject[0], subject.size(), outdata);
    outdata.push_back(0);
    std::string encode ="=?utf-8?B?";
    encode += &outdata[0];
    encode += "?=";
    subject_= std::move(encode);
}

void CurlSmtp::set_message(const std::string& message) {
    message_.assign(message);
}

void CurlSmtp::set_server(const std::string& server) {
    server_.assign(server);
}

void CurlSmtp::set_port(const std::string& port) {
    port_.assign(port);
}

void CurlSmtp::set_user(const std::string& user) {
    user_.assign(user_);
}

bool CurlSmtp::send_mail() {
    last_error_.clear();
    set_receiver_list();
    make_send_message();
    set_curl_option();
    auto  res = curl_easy_perform(curl_);
    /* Check for errors */
    if (res != CURLE_OK) {
        char buff[MAX_PATH] = {};
        sprintf(buff, "failed: %s\n",
                curl_easy_strerror(res));
        last_error_ = buff;
    }
    clear();
    return res == CURLE_OK;
}

std::string CurlSmtp::last_error() const {
    return last_error_;
}

bool CurlSmtp::attach(const std::string& filename) {
    if (!filename.length()) // do silly checks.
        return false;
    std::ifstream file(filename.c_str(), std::ios::binary | std::ios::in);
    if (!file)
        return false;
    std::vector filedata;
    char c = file.get();
    for (; file.good(); c = file.get()) {
        if (file.bad())
            break;
        filedata.push_back(c);
    }
    std::vector outdata;
    ustd::string::base64encode(&filedata[0], filedata.size(), outdata);
    std::string fn(filename);
    std::string::size_type p = fn.find_last_of('/');
    if (p == std::string::npos)
        p = fn.find_last_of('\\');
    if (p != std::string::npos) {
        p += 1; // get past folder delimeter
        fn = fn.substr(p, fn.length() - p);
    }
    attachment_.push_back(std::make_pair(outdata, fn));
    return true;
}

void CurlSmtp::set_receiver_list() {
    for (int i = 0; i < (int)to_.size(); i++) {
        rcpt_list_ = curl_slist_append(rcpt_list_,
                                       std::string(LEFT_BRACE + to_[i] + RIGTH_BRACE).c_str());
    }
    for (int i = 0; i < (int)cc_.size(); i++) {
        rcpt_list_ = curl_slist_append(rcpt_list_,
                                       std::string(LEFT_BRACE + cc_[i] + RIGTH_BRACE).c_str());
    }
    for (int i = 0; i < (int)secret_.size(); i++) {
        rcpt_list_ = curl_slist_append(rcpt_list_,
                                       std::string(LEFT_BRACE + secret_[i] + RIGTH_BRACE).c_str());
    }
}

void CurlSmtp::set_curl_option() {
    pooh_.pos = 0;
    pooh_.counter = 0;
    pooh_.data.resize(send_buffer_.size() + 1);
    pooh_.data.insert(pooh_.data.begin(), send_buffer_.begin(), send_buffer_.end());
    curl_easy_setopt(curl_, CURLOPT_URL,
                     std::string("smtp://" + server_ + ":" + port_).c_str());
    curl_easy_setopt(curl_, CURLOPT_USERNAME, user_.c_str());
    curl_easy_setopt(curl_, CURLOPT_PASSWORD, password_.c_str());
    curl_easy_setopt(curl_, CURLOPT_READFUNCTION, read_callback);
    curl_easy_setopt(curl_, CURLOPT_MAIL_FROM, from_.c_str());
    curl_easy_setopt(curl_, CURLOPT_MAIL_RCPT, rcpt_list_);
    curl_easy_setopt(curl_, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
    curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0L);
    curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0L);
    curl_easy_setopt(curl_, CURLOPT_READDATA, &pooh_);
    curl_easy_setopt(curl_, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(curl_, CURLOPT_SSLVERSION, 0L);
    curl_easy_setopt(curl_, CURLOPT_SSL_SESSIONID_CACHE, 0L);
    curl_easy_setopt(curl_, CURLOPT_UPLOAD, 1L);
}

void CurlSmtp::clear() {
    from_.clear();
    password_.clear();
    to_.clear();
    cc_.clear();
    secret_.clear();
    attach_.clear();
    attachment_.clear();
    subject_.clear();
    message_.clear();
    server_.clear();
    port_.clear();
    if (rcpt_list_ != NULL) {
        curl_slist_free_all(rcpt_list_);
        rcpt_list_ = NULL;
    }
}

void CurlSmtp::make_send_message() {
    send_buffer_.clear();
    // from
    send_buffer_.push_back("From: " LEFT_BRACE + from_ + RIGTH_BRACE);
    // to
    for (int i = 0; i < (int)to_.size(); ++i) {
        send_buffer_.push_back("To: " LEFT_BRACE + to_[i] + RIGTH_BRACE);
    }
    // cc
    for (int i = 0; i < (int)cc_.size(); ++i) {
        send_buffer_.push_back("Cc: " LEFT_BRACE + cc_[i] + RIGTH_BRACE);
    }
    // subject
    send_buffer_.push_back("Subject: " + subject_);
    if (attach_.empty() && 0) {
        // split body
        send_buffer_.push_back(ENTER);
        // message
        send_buffer_.push_back(message_ + ENTER);
    } else {
        // user agent
        send_buffer_.push_back(USER_AGENT);
        send_buffer_.push_back(MIME_VER);
        send_buffer_.push_back(HEADER_CONTENT_TYPE);
        std::string boundary(get_boundary());
        // set boundary
        send_buffer_.push_back(" boundary=\"" + boundary + "\"" ENTER);
        // first part of body, boundary header and message
        send_buffer_.push_back(BOUNDARY_FLAG + boundary);
        send_buffer_.push_back(MSG_CONTENT_TYPE);
        send_buffer_.push_back(MSG_ENCODING);
        // split body
        send_buffer_.push_back(ENTER);
        send_buffer_.push_back(message_ + ENTER);
        send_buffer_.push_back(BOUNDARY_FLAG + boundary);
        // attachment
        for (int i = 0; i < (int)attach_.size(); ++i) {
            attach(attach_[i]);
        }
        for (std::vector, std::string>>::iterator it1 =
                    attachment_.begin();
                it1 != attachment_.end(); ++it1) {
            if (it1->second.length() > 3) {
                // long enough for an extension
                std::string typ(it1->second.substr(it1->second.length() - 4, 4));
                if (typeMap_.count(typ) > 0) {
                    send_buffer_.push_back(typeMap_[typ]);
                } else {
                    // add other types
                    // everything else
                    send_buffer_.push_back("Content-Type: application/X-other-1;");
                }
            } else {
                // default to don't know
                send_buffer_.push_back("Content-Type: application/X-other-1;");
            }
            send_buffer_.push_back(" name=\"" + it1->second + "\"");
            send_buffer_.push_back("Content-Transfer-Encoding: base64");
            send_buffer_.push_back("Content-Disposition: attachment; filename=\"" +
                                   it1->second + "\"");
            // split body
            send_buffer_.push_back(ENTER);
            send_buffer_.push_back(std::string(it1->first.begin(), it1->first.end()));
            // terminate the message with the boundary + "--"
            if ((it1 + 1) == attachment_.end())
                send_buffer_.push_back(BOUNDARY_FLAG + boundary + BOUNDARY_FLAG);
            else
                send_buffer_.push_back(BOUNDARY_FLAG + boundary);
        }
    }
    // add \r\n to each item
    for (int i = 0; i < (int)send_buffer_.size(); ++i) {
        send_buffer_[i] += ENTER;
    }
}

#ifndef __USTD_STRING_H__
#define __USTD_STRING_H__

#include 
#include 
#include 
#include 
#include 
#include 
#include 

namespace ustd
{
namespace string
{

static std::string sprintf(const char *format, ...);
static size_t base64encode(const char *data, const int &len, std::vector &dest);
static size_t base64decode(const char *data, const int &len, std::vector &dest);
static size_t split(const std::string &src, const std::string &delim, std::vector &dst);
static std::string ltrim(const std::string &src, const std::string &key = " ");
static std::string rtrim(const std::string &src, const std::string &key = " ");
static std::string trim(const std::string &src, const std::string &key = " ");
static int replace(std::string &base, const std::string &src, const std::string &dst = "");
static std::string url_encode(const std::string &url_text);
static std::string url_base64encode(const std::string &url);
static std::string url_decode(const std::string &url_text);
static std::string url_base64decode(const std::string &url);
static std::string tolower(const std::string &src_text);
static std::string toupper(const std::string &src_text);
static size_t args_parse(const std::string &args, std::unordered_map &args_map, const std::string &delim = "&");

std::string url_base64encode(const std::string &url)
{
    std::string url_text(url);

    std::vector buffer;
    if (ustd::string::base64encode(url_text.c_str(), url_text.size(), buffer) > 0)
    {
        url_text.assign(&buffer[0], buffer.size());
        ustd::string::replace(url_text, "+", "-");
        ustd::string::replace(url_text, "/", "_");

        return url_text;
    }

    return "";
}

std::string url_base64decode(const std::string &url)
{
    std::string url_text(url);
    ustd::string::replace(url_text, "-", "+");
    ustd::string::replace(url_text, "_", "/");

    std::vector buffer;
    if (ustd::string::base64decode(url_text.c_str(), url_text.size(), buffer) > 0)
    {
        return (std::string(&buffer[0], buffer.size()));
    }

    return "";
}

std::string sprintf(const char *format, ...)
{
    char buffer[10240] = {0x00};

    va_list arg_ptr;
    va_start(arg_ptr, format);
    vsprintf(buffer, format, arg_ptr);
    va_end(arg_ptr);

    return (buffer);
}

size_t base64encode(const char *data, const int &len, std::vector &dest)
{
    static const char encodedict[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    int div = len / 3;
    int mod = len % 3;
    int size = div * 4 + ((mod == 0) ? 0 : 4);

    dest.clear();
    dest.reserve(size);

    for (int i = 0; i < div; ++i)
    {
        unsigned char c1 = *data++;
        unsigned char c2 = *data++;
        unsigned char c3 = *data++;

        dest.push_back(encodedict[c1 >> 2]);
        dest.push_back(encodedict[((c1 << 4) | (c2 >> 4)) & 0x3f]);
        dest.push_back(encodedict[((c2 << 2) | (c3 >> 6)) & 0x3f]);
        dest.push_back(encodedict[c3 & 0x3f]);
    }

    switch (mod)
    {
    case 1:
        {
            unsigned char c1 = *data++;
            dest.push_back(encodedict[(c1 & 0xfc) >> 2]);
            dest.push_back(encodedict[((c1 & 0x03) << 4)]);
            dest.push_back('=');
            dest.push_back('=');

            break;
        }

    case 2:
        {
            unsigned char c1 = *data++;
            unsigned char c2 = *data++;
            dest.push_back(encodedict[(c1 & 0xfc) >> 2]);
            dest.push_back(encodedict[((c1 & 0x03) << 4) | ((c2 & 0xf0) >> 4)]);
            dest.push_back(encodedict[((c2 & 0x0f) << 2)]);
            dest.push_back('=');

            break;
        }

    default:
        {
            break;
        }
    }

    return dest.size();
}

size_t base64decode(const char *data, const int &len, std::vector &dest)
{
    static const char decodedict[256] = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        62,        // '+'
        0, 0, 0,
        63,        // '/'
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61,                     // '0'-'9'
        0, 0, 0, 0, 0, 0, 0,
        0, 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,         // 'A'-'Z'
        0, 0, 0, 0, 0, 0,
        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          // 'a'-'z'
    };

    dest.clear();
    if (len % 4 != 0)
    {
        return dest.size();
    }

    int div = len / 4;
    int size = div * 3;
    dest.reserve(size);

    unsigned char *udata = (unsigned char *)data;
    for (int i = 0; i < div; ++i)
    {
        int key = decodedict[*udata++] << 18;
        key += decodedict[*udata++] << 12;
        dest.push_back((char)((key & 0x00ff0000) >> 16));

        if (*udata != '=')
        {
            key += decodedict[*udata++] << 6;
            dest.push_back((char)((key & 0x0000ff00) >> 8));

            if (*udata != '=')
            {
                key += decodedict[*udata++];
                dest.push_back((char)(key & 0x000000ff));
            }
        }
    }

    return dest.size();
}

size_t split(const std::string &src, const std::string &delim, std::vector &dst)
{
    dst.clear();
    size_t idx = 0;
    size_t pos = src.find(delim, idx);
    while (pos != std::string::npos)
    {
        dst.push_back(src.substr(idx, pos - idx));
        idx = pos + delim.length();
        pos = src.find(delim, idx);
    }

    dst.push_back(src.substr(idx));
    return dst.size();
}

std::string ltrim(const std::string &src, const std::string &key)
{
    size_t pos = src.find_first_not_of(key);
    if (pos != std::string::npos)
    {
        return src.substr(pos);
    }

    return ("");
}

std::string rtrim(const std::string &src, const std::string &key)
{
    size_t pos = src.find_last_not_of(key);
    if (pos != std::string::npos)
    {
        return src.substr(0, pos + 1);
    }

    return ("");
}

std::string trim(const std::string &src, const std::string &key)
{
    return ltrim(rtrim(src, key), key);
}

int replace(std::string &base, const std::string &src, const std::string &dst)
{
    int count = 0;
    size_t src_len = src.length();
    size_t dst_len = dst.length();

    size_t pos = base.find(src, 0);
    while (pos != std::string::npos)
    {
        count += 1;
        base.replace(pos, src_len, dst);
        pos = base.find(src, pos + dst_len);
    }

    return count;
}

std::string url_encode(const std::string &url_text)
{
    size_t idx = 0;
    std::string encode_text;
    char hex[] = "0123456789abcdef";

    size_t str_size = url_text.size();

    while (idx < str_size)
    {
        unsigned char ch = url_text[idx++];

        //0-9 a-z A-Z
        //- _ . ! ~ * ( ) \'
        //: ; ? @ & =

        if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '-' || ch == '_' || ch == '.')
        {
            encode_text += ch;
        }
        else
        {
            encode_text += "%";
            encode_text += hex[ch / 16];
            encode_text += hex[ch % 16];
        }
    }

    return encode_text;
}

std::string url_decode(const std::string &url_text)
{
    size_t idx = 0;
    std::string decode_text;
    size_t str_size = url_text.size();

    while (idx < str_size)
    {
        char ch = url_text[idx++];

        switch (ch)
        {
        case '%':
            {
                std::string str = url_text.substr(idx, 2);
                decode_text += static_cast(strtol(str.c_str(), NULL, 16));
                idx += 2;
            }

            break;

        case '+':
            {
                decode_text += ' ';
            }

            break;

        default:
            {
                decode_text += ch;
            }

            break;
        }
    }

    return decode_text;
}

std::string tolower(const std::string &src_text)
{
    std::string lower_text = src_text;
    transform(lower_text.begin(), lower_text.end(), lower_text.begin(), (int (*)(int))::tolower);
    return lower_text;
}

std::string toupper(const std::string &src_text)
{
    std::string upper_text = src_text;
    transform(upper_text.begin(), upper_text.end(), upper_text.begin(), (int (*)(int))::toupper);
    return upper_text;
}

size_t args_parse(const std::string &args, std::unordered_map &args_map, const std::string &delim)
{
    args_map.clear();
    size_t args_count = 0;
    std::string args_text = args;
    size_t idx = args.find("?");

    if (idx != std::string::npos)
    {
        args_text = args.substr(idx + 1);
    }

    std::vector tokens;
    if (ustd::string::split(args_text, delim, tokens) > 0)
    {
        for (size_t i = 0; i < tokens.size(); ++i)
        {
            size_t pos = tokens[i].find("=");
            if (pos != std::string::npos)
            {
                std::string key = ustd::string::tolower(ustd::string::trim(tokens[i].substr(0, pos)));
                std::string value = ustd::string::trim(tokens[i].substr(pos + 1));
                if (!key.empty() && args_map.find(key) == args_map.end())
                {
                    args_map.insert(std::make_pair(key, value));
                    args_count += 1;
                }
            }
        }
    }

    return args_count;
}

}
}

#endif

本文题目:完美支持中文及附件的基于libcur邮件客户端封装类
URL链接:http://myzitong.com/article/jhoigp.html