Qt + CURL + mimetic 发送邮件(带附件)
使用了大名鼎鼎的CURL 开源库,以及mimetic开源库。
CURL支持N多协议。功能超强,但是不能直接发邮件附件,需要自己拼mime。太麻烦,于是乎~~
mimetic主要用于构造邮件mimetic格式数据。
CURL:http://curl.haxx.se/
mimetic:http://www.codesink.org/mimetic_mime_library.html
源码:http://download.csdn.net/detail/kfbyj/6566431
m_Email.SetUserInfo("你的邮箱帐号", "你的邮箱密码"); m_Email.SetHost("smtp://smtp.163.com"); //你的邮箱smtp服务器地址 m_Email.AddReceiver("<XXXX@163.com>"); //添加一个接受邮件者 m_Email.AddAttach("附件绝对路径"); //添加一个附件 m_Email.SetSend("邮件主题", "邮件内容", "联系方式"); m_Email.start(); //开始发送,,线程
/************************************************************************/ /* author : 狂风暴雨 * date : 2013年11月14日 14:11:49 * desc : 一份邮件的线程 * */ /************************************************************************/ #ifndef EMAIL_H #define EMAIL_H #include "third_party/curl/curl.h" #include <QStringList> #include <QObject> #include <QThread> class Email : public QThread { Q_OBJECT public: Email(QObject *parent); ~Email(); //发送一封右键 void run(); void SetSend(const QString& subject, const QString& content, const QString& contact); //设置服务器地址 void SetHost(const QString& host) { m_smtpServer = host;} QString Host() {return m_smtpServer;} //设置用户密码 void SetUserName(const QString& name); QString UserName() { return m_userName;} void SetPassword(const QString& password); QString Password() { return m_passWord;} void SetUserInfo(const QString& name, const QString& password); //添加收信人,返回收信人数目 int AddReceiver(const QString& receiver); QStringList Receiver() { return m_receiverList;} //附件 int AddAttach(const QString& attachPath); QStringList Attachs() { return m_attachsList;} void RemoveAttach(int index); int Result() {return m_res;} //重置 void Reset(); signals: void signalSendResult(int); private: CURLcode m_res; //主题 QString m_subject; QString m_content; QString m_contact; //用户密码 QString m_userName; QString m_passWord; //stmp 服务器 QString m_smtpServer; //接受人列表 QStringList m_receiverList; //附件列表 QStringList m_attachsList; static int ReadData(void* ptr, size_t size, size_t nmemb, void* userp); }; #endif // EMAIL_H
==============================================================================================================================
==============================================================================================================================
#include "email.h" #include "third_party/mimetic/mimetic.h" #include "utils/utils.h" struct UserData { std::stringstream ss; size_t total; UserData() : total(0), ss() {} }; Email::Email(QObject *parent) : QThread(parent) { m_receiverList.clear(); m_attachsList.clear(); } Email::~Email() { } void Email::run() { mimetic::MultipartMixed head; head.header().from(utils::QStringToUtf8String(m_userName)); head.header().subject(utils::QStringToUtf8String(m_subject)); head.header().push_back(mimetic::Field("Mime-Version","1.0")); struct curl_slist *slist = NULL; for (int i = 0; i < m_receiverList.size(); ++i) { slist = curl_slist_append(slist, utils::QStringToUtf8String(m_receiverList.at(i)).c_str()); head.header().to(utils::QStringToUtf8String(m_receiverList.at(i)).c_str()); } //添加邮件内容 mimetic::MimeEntity* pMeContent = new mimetic::MimeEntity; pMeContent->body().assign(utils::QStringToUtf8String(m_content + tr("\nContact Info:") + m_contact)); head.body().parts().push_back(pMeContent); //如果有附件添加附件 for (int i = 0; i < m_attachsList.size(); ++i) { mimetic::MimeEntity* pMe = new mimetic::MimeEntity; pMe->header().push_back(mimetic::Field("Content-Transfer-Encoding","base64")); FILE *pfile = fopen(utils::QStringToUtf8String(m_attachsList.at(i)).c_str(), "rb"); char buffer[4096]; uint32_t totalreadbytes = 0; while (!feof(pfile)) { uint32_t readbytes = fread(buffer, 1, 4096, pfile); if (ferror(pfile) || readbytes == 0) break; totalreadbytes += readbytes; mimetic::Base64::Encoder b64; std::stringstream temp; std::ostreambuf_iterator<char> out(temp); //转为BASE64编码,目标存放至std::stringstream中 mimetic::code(buffer, buffer + readbytes, b64, out); std::string str = temp.str(); std::cout<<str; pMe->load(str.begin(), str.end(), mimetic::imNone); } fclose(pfile); QString fileName = utils::PathFindFileName(m_attachsList.at(i)); pMe->header().push_back(mimetic::Field( utils::QStringToUtf8String("Content-Type: application/octet-stream; name=" + fileName))); pMe->header().push_back(mimetic::Field(utils::QStringToUtf8String("Content-Disposition : attachment; filename=" + fileName))); head.body().parts().push_back(pMe); } struct UserData ud; ud.ss<<head; ud.ss.seekg(0, std::ios::end); ud.total = ud.ss.tellg(); ud.ss.seekg(0, std::ios::beg); CURL *curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, utils::QStringToUtf8String(m_smtpServer).c_str()); curl_easy_setopt(curl, CURLOPT_USERNAME, utils::QStringToUtf8String(m_userName).c_str()); curl_easy_setopt(curl, CURLOPT_PASSWORD, utils::QStringToUtf8String(m_passWord).c_str()); curl_easy_setopt(curl, CURLOPT_MAIL_FROM, utils::QStringToUtf8String(m_userName).c_str()); //发送者 curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, slist); curl_easy_setopt(curl, CURLOPT_READDATA, &ud); curl_easy_setopt(curl, CURLOPT_READFUNCTION, ReadData); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); } m_res = curl_easy_perform(curl); curl_slist_free_all(slist); curl_easy_cleanup(curl); } void Email::SetSend(const QString& subject, const QString& content, const QString& contact) { m_subject = subject; m_contact = contact; m_content = content; } void Email::Reset() { m_userName.clear(); m_passWord.clear(); m_smtpServer.clear(); m_receiverList.clear(); m_attachsList.clear(); } void Email::SetUserName(const QString& name) { m_userName = name; } void Email::SetPassword(const QString& password) { m_passWord = password; } void Email::SetUserInfo(const QString& name, const QString& password) { m_userName = name; m_passWord = password; } int Email::AddReceiver(const QString& receiver) { m_receiverList.append(receiver); return m_receiverList.size(); } int Email::AddAttach(const QString& attachPath) { m_attachsList.append(attachPath); return m_attachsList.size(); } void Email::RemoveAttach(int index) { m_attachsList.removeAt(index); } int Email::ReadData(void* ptr, size_t size, size_t nmemb, void* userp) { struct UserData * pstream = static_cast<struct UserData *>(userp); if (pstream->ss.eof()) return 0; size_t before = pstream->ss.tellg(); pstream->ss.read((char*)ptr, size*nmemb); size_t after = pstream->ss.tellg(); if (pstream->ss.eof()) return pstream->total - before; return after - before; }