先上源码
H
/*
* File: CSendMail.h
* Author: jaylong35
*
* Created on January 16, 2012, 6:14 PM
*/
#ifndef CSENDMAIL_H
#define CSENDMAIL_H
#include <string>
#include <list>
#include <vector>
#include <curl/curl.h>
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
class CSendMail {
public:
CSendMail();
CSendMail( //create sendmail object with paremeter;
const std::string & strUser,
const std::string & strPsw,
const std::string & strSmtpServer,
int iPort,
const std::string & strMailFrom
);
CSendMail(const CSendMail& orig);
virtual ~CSendMail();
private:
std::string m_strUser; //邮箱用户名
std::string m_strPsw; //邮箱密码
std::string m_strSmtpServer; //邮箱SMTP服务器
int m_iPort; //邮箱SMTP服务器端口
std::list<std::string> m_RecipientList; //接收者邮件list
std::string m_strMailFrom; //发送者邮箱
std::vector<std::string> m_MailContent; //发送的内容队列,包括头和内容项
int m_iMailContentPos; //用于发送数据时记录发送到第几个content
private:
//发送内容回调函数
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp);
//获取当前时间
static struct timeval tvnow(void);
//两个时间差
static long tvdiff(struct timeval newer, struct timeval older);
//创建邮件内容
bool ConstructHead(const std::string & strSubject/*邮件主题*/, const std::string & strContent/*邮件内容*/);
public:
bool SendMail(const std::string & strSubject, const char * pMailBody, int len);
bool SendMail(const std::string & strSubject, const std::string & strMailBody);
bool SendMail( //create sendmail object with paremeter;
const std::string & strUser,
const std::string & strPsw,
const std::string & strSmtpServer,
int iPort,
std::list<std::string> & recipientList,
const std::string & strMailFrom,
const std::string & strSubject,
const char * pMailBody,
int len
);
bool SendMail( //create sendmail object with paremeter;
const std::string & strUser,
const std::string & strPsw,
const std::string & strSmtpServer,
int iPort,
const std::string & strMailTo,
const std::string & strMailFrom,
const std::string & strSubject,
const char * pMailBody,
int len
);
bool SendMail( //create sendmail object with paremeter;
const std::string & strUser,
const std::string & strPsw,
const std::string & strSmtpServer,
int iPort,
std::list<std::string> & recipientList,
const std::string & strMailFrom,
const std::string & strSubject,
const std::string & strMailBody
);
bool SendMail( //create sendmail object with paremeter;
const std::string & strUser,
const std::string & strPsw,
const std::string & strSmtpServer,
int iPort,
const std::string & strMailTo,
const std::string & strMailFrom,
const std::string & strSubject,
const std::string & strMailBody
);
void SetUser(const std::string & strUser) { m_strUser = strUser; }
std::string & GetUser() { return m_strUser; }
void SetPsw(const std::string & strPsw) { m_strPsw = strPsw; }
std::string & GetPsw() { return m_strPsw; }
void SetSmtpServer(const std::string & strSmtpServer) { m_strSmtpServer = strSmtpServer; }
std::string & GetSmtpServer() { return m_strSmtpServer; }
void SetPort(int iPort) { m_iPort = iPort; }
int GetPort() { return m_iPort; }
void SetMailFrom(const std::string & strMailFrom) { m_strMailFrom = strMailFrom; }
std::string & GetMailFrom() { return m_strMailFrom; }
//添加接收者邮箱
void AddRecipient(const std::string & strMailTo) { m_RecipientList.push_back(strMailTo); }
void AddRecipient(std::list<std::string> recipientList)
{
std::copy(recipientList.begin(), recipientList.end(), m_RecipientList.begin());
}
void ClearRecipient() { m_RecipientList.clear(); }
};
#endif /* CSENDMAIL_H */
cpp
/*
* File: CSendMail.cpp
* Author: root
*
* Created on January 16, 2012, 6:14 PM
*/
#include "CSendMail.h"
CSendMail::CSendMail()
{
m_strUser = "";
m_strPsw = "";
m_strSmtpServer = "";
m_iPort = -1;
m_RecipientList.clear();
m_strMailFrom = "";
m_MailContent.clear();
m_iMailContentPos = 0;
}
CSendMail::CSendMail( //create sendmail object with paremeter;
const std::string & strUser,
const std::string & strPsw,
const std::string & strSmtpServer,
int iPort,
const std::string & strMailFrom
)
{
m_strUser = strUser;
m_strPsw = strPsw;
m_strSmtpServer = strSmtpServer;
m_iPort = iPort;
m_RecipientList.clear();
m_strMailFrom = strMailFrom;
m_MailContent.clear();
m_iMailContentPos = 0;
}
CSendMail::CSendMail(const CSendMail& orig) {
}
CSendMail::~CSendMail() {
}
size_t CSendMail::read_callback(void* ptr, size_t size, size_t nmemb, void* userp)
{
CSendMail * pSm = (CSendMail *)userp;
if(size*nmemb < 1)
return 0;
if(pSm->m_iMailContentPos < pSm->m_MailContent.size())
{
size_t len;
len = pSm->m_MailContent[pSm->m_iMailContentPos].length();
memcpy(ptr, pSm->m_MailContent[pSm->m_iMailContentPos].c_str(), pSm->m_MailContent[pSm->m_iMailContentPos].length());
pSm->m_iMailContentPos++; /* advance pointer */
return len;
}
return 0;
}
struct timeval CSendMail::tvnow()
{
/*
** time() returns the value of time in seconds since the Epoch.
*/
struct timeval now;
now.tv_sec = (long)time(NULL);
now.tv_usec = 0;
return now;
}
long CSendMail::tvdiff(timeval newer, timeval older)
{
return (newer.tv_sec-older.tv_sec)*1000+
(newer.tv_usec-older.tv_usec)/1000;
}
bool CSendMail::ConstructHead(const std::string & strSubject, const std::string & strContent)
{
m_MailContent.push_back("MIME-Versioin: 1.0\n");
std::string strTemp = "To: ";
for(std::list<std::string >::iterator it = m_RecipientList.begin(); it != m_RecipientList.end();)
{
strTemp += *it;
it++;
if(it != m_RecipientList.end())
strTemp += ",";
}
strTemp += "\n";
m_MailContent.push_back(strTemp);
if(strSubject != "")
{
strTemp = "Subject: ";
strTemp += strSubject;
strTemp += "\n";
m_MailContent.push_back(strTemp);
}
m_MailContent.push_back("Content-Transfer-Encoding: 8bit\n");
m_MailContent.push_back("Content-Type: text/html; \n Charset=\"UTF-8\"\n\n");
if(strContent != "")
{
m_MailContent.push_back(strContent);
}
return true;
}
bool CSendMail::SendMail(const std::string& strSubject, const std::string& strMailBody)
{
m_MailContent.clear();
m_iMailContentPos = 0;
ConstructHead(strSubject, strMailBody);
bool bRet = true;
CURL *curl;
CURLM *mcurl;
int still_running = 1;
struct timeval mp_start;
char mp_timedout = 0;
struct curl_slist* rcpt_list = NULL;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (!curl)
{
printf("Init curl failed!\n");
return false;
}
mcurl = curl_multi_init();
if (!mcurl)
{
printf("Init mcurl failed!\n");
return false;
}
for(std::list<std::string >::iterator it = m_RecipientList.begin(); it != m_RecipientList.end();it++)
{
rcpt_list = curl_slist_append(rcpt_list, it->c_str());
}
if(m_strSmtpServer == "" || m_iPort <= 0)
{
printf("smtp server couldn't be empty, or port must be large than 0!\n");
curl_slist_free_all(rcpt_list);
curl_multi_cleanup(mcurl);
curl_easy_cleanup(curl);
curl_global_cleanup();
return false;
}
std::string strUrl = "smtp://" + m_strSmtpServer;
strUrl += ":";
char cPort[10];
memset(cPort, 0, 10);
sprintf(cPort, "%d", m_iPort);
strUrl += cPort;
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
if(m_strUser != "")
{
curl_easy_setopt(curl, CURLOPT_USERNAME, m_strUser.c_str());
}
if(m_strPsw != "")
{
curl_easy_setopt(curl, CURLOPT_PASSWORD, m_strPsw.c_str());
}
curl_easy_setopt(curl, CURLOPT_READFUNCTION, &CSendMail::read_callback);
if(m_strMailFrom == "")
{
printf("Mail from address couldn't be empty!\n");
curl_slist_free_all(rcpt_list);
curl_multi_cleanup(mcurl);
curl_easy_cleanup(curl);
curl_global_cleanup();
return false;
}
curl_easy_setopt(curl, CURLOPT_MAIL_FROM, m_strMailFrom.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, this);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_SSLVERSION, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L);
curl_multi_add_handle(mcurl, curl);
mp_timedout = 0;
mp_start = tvnow();
/* we start some action by calling perform right away */
curl_multi_perform(mcurl, &still_running);
while (still_running) {
struct timeval timeout;
int rc; /* select() return code */
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd = -1;
long curl_timeo = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
/* set a suitable timeout to play around with */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
curl_multi_timeout(mcurl, &curl_timeo);
if (curl_timeo >= 0) {
timeout.tv_sec = curl_timeo / 1000;
if (timeout.tv_sec > 1)
timeout.tv_sec = 1;
else
timeout.tv_usec = (curl_timeo % 1000) * 1000;
}
/* get file descriptors from the transfers */
curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the
function calls. On success, the value of maxfd is guaranteed to be
greater or equal than -1. We call select(maxfd + 1, ...), specially in
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
if (tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
fprintf(stderr, "ABORTING TEST, since it seems "
"that it would have run forever.\n");
bRet = false;
break;
}
switch (rc) {
case -1:
/* select error */
printf("select error\n");
bRet = false;
break;
case 0: /* timeout */
printf("time out, retry again!\n");
curl_multi_perform(mcurl, &still_running);
break;
default: /* action */
curl_multi_perform(mcurl, &still_running);
break;
}
}
curl_multi_remove_handle(mcurl, curl);
curl_slist_free_all(rcpt_list);
curl_multi_cleanup(mcurl);
curl_easy_cleanup(curl);
curl_global_cleanup();
return bRet;
}
bool CSendMail::SendMail(const std::string & strSubject, const char* pMailBody, int len)
{
std::string strMailContent;
strMailContent.append(pMailBody, len);
return SendMail(strSubject, strMailContent);
}
bool CSendMail::SendMail(const std::string& strUser, const std::string& strPsw, const std::string& strSmtpServer, int iPort, std::list<std::string>& recipientList, const std::string& strMailFrom, const std::string& strSubject, const std::string& strMailBody)
{
m_strUser = strUser;
m_strPsw = strPsw;
m_strSmtpServer = strSmtpServer;
m_iPort = iPort;
std::copy(recipientList.begin(), recipientList.end(), m_RecipientList.begin());
m_strMailFrom = strMailFrom;
return SendMail(strSubject, strMailBody);
}
bool CSendMail::SendMail(const std::string& strUser, const std::string& strPsw, const std::string& strSmtpServer, int iPort, std::list<std::string>& recipientList, const std::string& strMailFrom, const std::string& strSubject, const char* pMailBody, int len)
{
std::string strMailContent;
strMailContent.append(pMailBody, len);
return SendMail(strUser, strPsw, strSmtpServer, iPort, recipientList, strMailFrom, strSubject, strMailContent);
}
bool CSendMail::SendMail(const std::string& strUser, const std::string& strPsw, const std::string& strSmtpServer, int iPort, const std::string& strMailTo, const std::string& strMailFrom, const std::string& strSubject, const std::string& strMailBody)
{
std::list<std::string> recipientList;
recipientList.push_back(strMailTo);
return SendMail(strUser, strPsw, strSmtpServer, iPort, recipientList, strMailFrom, strSubject, strMailBody);
}
bool CSendMail::SendMail(const std::string& strUser, const std::string& strPsw, const std::string& strSmtpServer, int iPort, const std::string& strMailTo, const std::string& strMailFrom, const std::string& strSubject, const char* pMailBody, int len)
{
std::string strMailContent;
strMailContent.append(pMailBody, len);
return SendMail(strUser, strPsw, strSmtpServer, iPort, strMailTo, strMailFrom, strSubject, strMailContent);
}
这个是通过libcurl multi接口来做的,所以使用的时候记得要libcurl库的支持。
调用代码示例
/*
* File: main.cpp
* Author:jaylong35
*
* Created on January 16, 2012, 6:14 PM
*/
#include <cstdlib>
#include <iostream>
#include "CSendMail.h"
using namespace std;
#define USERNAME "xx@126.com"
#define PASSWORD "xxxxxx"
#define SMTPSERVER "smtp.126.com"
#define SMTPPORT ":25"
#define RECIPIENT "<kkk@126.com>"
#define MAILFROM "<xx@126.com>"
int main(int argc, char** argv)
{
CSendMail sendMail(USERNAME, PASSWORD, SMTPSERVER, 25, MAILFROM);
sendMail.AddRecipient(RECIPIENT);
sendMail.SendMail("mytestfirst","I hate you");
return 0;
}