本文共 13024 字,大约阅读时间需要 43 分钟。
原文地址:
使用CURL发送不带附件的例子,在CURL的官方范例simplesmtp.cpp和smtp_tls.cpp中,认真看看,使用不难。而发送附件的例子则没有了,需要了解MIME协议,将邮件按照MIME编码,在CURLOPT_READFUNCTION发送出去即可。直接用字符串拼凑MIME有点麻烦,可以结合MIME C++ library完成这项工作。MIME C++ library的下载地址http://www.codesink.org/mimetic_mime_library.html。
- #include "stdafx.h"
- #include <string>
- #include <iostream>
- #include <mimetic/mimetic.h>
- #include <sstream>
- #include <iterator>
- #include <stdio.h>
- #include <fstream>
-
- int _tmain(int argc, _TCHAR* argv[])
- {
-
- mimetic::MimeEntity me;
- me.header().from("me <me@domain.com>");
- me.header().to("you <you@domain.com>");
- me.header().subject("my first mimetic msg");
- me.body().assign("hello there!");
- std::cout << me <<std::endl;
- return 0;
- }
显示如下:
From: me <me@domain.com> //From:简称<邮箱地址>
To: you <you@domain.com>
//To:简称<邮箱地址> Subject: my first mimetic msg
//邮件标题 hello there!
//正文内容 这是一个最简单的MIME 流了。如果是带附件的 那么:
- #include "stdafx.h"
- #include <string>
- #include <iostream>
- #include <mimetic/mimetic.h>
- #include <sstream>
- #include <iterator>
- #include <stdio.h>
- #include <fstream>
-
- int _tmain(int argc, _TCHAR* argv[])
- {
-
- mimetic::MultipartMixed head;
-
- head.header().from("<me@sina.com.cn>");
-
- head.header().to("<you@sina.com.cn>");
-
- head.header().cc("<he@sina.com.cn>;<she@sina.com.cn>;");
-
- head.header().subject("my first mimetic msg");
-
- head.header().push_back(mimetic::Field("Mime-Version","1.0"));
-
- head.body().assign("hello there!");
-
-
- mimetic::MimeEntity* pMe = new mimetic::MimeEntity;
-
-
-
-
-
- pMe->header().push_back(mimetic::Field("Content-Type: application/octet-stream; name=readme.txt"));
-
- pMe->header().push_back(mimetic::Field("Content-Disposition : attachment; filename=readme.txt"));
-
- pMe->header().push_back(mimetic::Field("Content-Transfer-Encoding","base64"));
-
-
- FILE *pfile = fopen(".\\readme.txt","rb");
- char buffer[4096];
- uint32_t totalreadbytes = 0;
- while (!feof(pfile))
- {
-
- uint32_t readbytes = fread(buffer, 1, 4028, pfile);
- if (ferror(pfile) || readbytes == 0)
- {
- break;
- }
- totalreadbytes += readbytes;
- mimetic::Base64::Encoder b64;
- std::stringstream temp;
- std::ostreambuf_iterator<char> out(temp);
-
- mimetic::code(buffer, buffer + readbytes, b64, out);
- std::string str = temp.str();
- std::cout<<str;
-
-
-
- pMe->load(str.begin(), str.end(), mimetic::imNone);
- }
-
- std::cout<<head;
- return 0;
- }
显示的MIME流如下:
Content-Type: multipart/mixed;
boundary="----lrsJRnnv8qrhVhSN0z5KGo2eQwzHwv_LA_MGCzpaJN87zTe1=_2_"
From: me@sina.com.cn
To: you@sina.com.cn
CC: <he@sina.com.cn>;<she@sina.com.cn>;
Subject: my first mimetic msg
Mime-Version: 1.0
------lrsJRnnv8qrhVhSN0z5KGo2eQwzHwv_LA_MGCzpaJN87zTe1=_2_
Content-Type: application/octet-stream; name="readme.txt"
Content-Disposition : attachment; filename=readme.txt
Content-Transfer-Encoding: base64
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09DQogICAgQ09OU09MRSBBUFBMSUNBVElPTiA6IHRlc3RfbWltZXRpYyBQ
cm9qZWN0IE92ZXJ2aWV3DQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KQXBwV2l6YXJkIGhhcyBjcmVhdGVk
IHRoaXMgdGVzdF9taW1ldGljIGFwcGxpY2F0aW9uIGZvciB5b3UuDQoNClRoaXMgZmlsZSBjb250
YWlucyBhIHN1bW1hcnkgb2Ygd2hhdCB5b3Ugd2lsbCBmaW5kIGluIGVhY2ggb2YgdGhlIGZpbGVz
IHRoYXQNCm1ha2UgdXAgeW91ciB0ZXN0X21pbWV0aWMgYXBwbGljYXRpb24uDQoNCg0KdGVzdF9t
aW1ldGljLnZjeHByb2oNCiAgICBUaGlzIGlzIHRoZSBtYWluIHByb2plY3QgZmlsZSBmb3IgVkMr
KyBwcm9qZWN0cyBnZW5lcmF0ZWQgdXNpbmcgYW4gQXBwbGljYXRpb24gV2l6YXJkLg0KICAgIEl0
IGNvbnRhaW5zIGluZm9ybWF0aW9uIGFib3V0IHRoZSB2ZXJzaW9uIG9mIFZpc3VhbCBDKysgdGhh
dCBnZW5lcmF0ZWQgdGhlIGZpbGUsIGFuZA0KICAgIGluZm9ybWF0aW9uIGFib3V0IHRoZSBwbGF0
Zm9ybXMsIGNvbmZpZ3VyYXRpb25zLCBhbmQgcHJvamVjdCBmZWF0dXJlcyBzZWxlY3RlZCB3aXRo
IHRoZQ0KICAgIEFwcGxpY2F0aW9uIFdpemFyZC4NCg0KdGVzdF9taW1ldGljLnZjeHByb2ouZmls
dGVycw0KICAgIFRoaXMgaXMgdGhlIGZpbHRlcnMgZmlsZSBmb3IgVkMrKyBwcm9qZWN0cyBnZW5l
cmF0ZWQgdXNpbmcgYW4gQXBwbGljYXRpb24gV2l6YXJkLiANCiAgICBJdCBjb250YWlucyBpbmZv
cm1hdGlvbiBhYm91dCB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiB0aGUgZmlsZXMgaW4geW91ciBw
cm9qZWN0IA0KICAgIGFuZCB0aGUgZmlsdGVycy4gVGhpcyBhc3NvY2lhdGlvbiBpcyB1c2VkIGlu
IHRoZSBJREUgdG8gc2hvdyBncm91cGluZyBvZiBmaWxlcyB3aXRoDQogICAgc2ltaWxhciBleHRl
bnNpb25zIHVuZGVyIGEgc3BlY2lmaWMgbm9kZSAoZm9yIGUuZy4gIi5jcHAiIGZpbGVzIGFyZSBh
c3NvY2lhdGVkIHdpdGggdGhlDQogICAgIlNvdXJjZSBGaWxlcyIgZmlsdGVyKS4NCg0KdGVzdF9t
aW1ldGljLmNwcA0KICAgIFRoaXMgaXMgdGhlIG1haW4gYXBwbGljYXRpb24gc291cmNlIGZpbGUu
DQoNCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v
Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vDQpPdGhlciBzdGFuZGFyZCBmaWxlczoNCg0KU3RkQWZ4
LmgsIFN0ZEFmeC5jcHANCiAgICBUaGVzZSBmaWxlcyBhcmUgdXNlZCB0byBidWlsZCBhIHByZWNv
bXBpbGVkIGhlYWRlciAoUENIKSBmaWxlDQogICAgbmFtZWQgdGVzdF9taW1ldGljLnBjaCBhbmQg
YSBwcmVjb21waWxlZCB0eXBlcyBmaWxlIG5hbWVkIFN0ZEFmeC5vYmouDQoNCi8vLy8vLy8vLy8v
Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v
Ly8vLy8vLy8vDQpPdGhlciBub3RlczoNCg0KQXBwV2l6YXJkIHVzZXMgIlRPRE86IiBjb21tZW50
cyB0byBpbmRpY2F0ZSBwYXJ0cyBvZiB0aGUgc291cmNlIGNvZGUgeW91DQpzaG91bGQgYWRkIHRv
IG9yIGN1c3RvbWl6ZS4NCg0KLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v
Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCg==
------lrsJRnnv8qrhVhSN0z5KGo2eQwzHwv_LA_MGCzpaJN87zTe1=_2_--
在这里值得一说的是Content-Type: multipart/mixed;
boundary="----lrsJRnnv8qrhVhSN0z5KGo2eQwzHwv_LA_MGCzpaJN87zTe1=_2_"这里说明了邮件有多块,以----lrsJRnnv8qrhVhSN0z5KGo2eQwzHwv_LA_MGCzpaJN87zTe1=_2_为分割标识符。如果想给邮件中添加新的一个块,比如说,除了附件还需要个正文那么需要再new mimetic::MimeEntity* pMe
-
- mimetic::MimeEntity* pMe2 = new mimetic::MimeEntity;
-
- pMe2->header().push_back(mimetic::Field("Content-Type: text/plain; charset=GB2312"));
- pMe2->header().push_back(mimetic::Field("Content-Transfer-Encoding","base64"));
-
- head.body().parts().push_back(pMe2);
到此为止所需要的流已经生成了,剩下的就是在CURL中发送出去。
-
-
-
- #include "stdafx.h"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #include <stdio.h>
- #include <mimetic/mimetic.h>
- #include <curl/curl.h>
- #include <string.h>
- #include <iostream>
- #include <sstream>
- #include <stdio.h>
-
-
-
-
-
- #define FROM "<me@test.com.cn>"
- #define TO "<you@test.com.cn>"
- #define CC "<he@test.com.cn>"
-
- #define BUFFERR_SIZE 4096
-
- struct UserData
- {
- std::stringstream ss;
- size_t total;
- UserData()
- :total(0)
- {
-
- }
- };
-
-
- static size_t my_read(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())
- {
-
-
- std::cout<<(pstream->total - before)<<std::endl;
- return pstream->total - before;
- }
- std::cout<<(after - before)<<std::endl;
- return after - before;
- }
-
-
-
- int main(void)
- {
- CURL *curl;
- CURLcode res;
- struct curl_slist *recipients = NULL;
-
- mimetic::MultipartMixed head;
- head.header().from("<me@test.com.cn>");
- head.header().to("<you@<span style="font-family: Arial, Helvetica, sans-serif;">test</span>.com.cn>");
- head.header().cc("<he@test.com.cn>");
- head.header().subject("my first mimetic msg");
- head.header().push_back(mimetic::Field("Mime-Version","1.0"));
- head.header().push_back(mimetic::Field("Message-ID","<dcd7cb36-11db-487a-9f3a-e652a9458efd@rfcpedant.example.org>"));
- head.body().assign("hello there!");
-
- mimetic::MimeEntity* pMe = new mimetic::MimeEntity;
-
- pMe->header().push_back(mimetic::Field("Content-Type: application/octet-stream; name=<span style="font-family: Arial, Helvetica, sans-serif;">readme.txt</span>"));
- pMe->header().push_back(mimetic::Field("Content-Disposition : attachment; filename=readme.txt"));
- pMe->header().push_back(mimetic::Field("Content-Transfer-Encoding","base64"));
- FILE *pfile = fopen(".\\readme.txt","rb");
- char buffer[BUFFERR_SIZE];
- uint32_t totalreadbytes = 0;
- while (!feof(pfile))
- {
- uint32_t readbytes = fread(buffer, 1, BUFFERR_SIZE - 1, pfile);
- if (ferror(pfile) || readbytes == 0)
- {
- break;
- }
- totalreadbytes += readbytes;
- mimetic::Base64::Encoder b64;
- std::stringstream temp;
- std::ostreambuf_iterator<char> out(temp);
- buffer[readbytes] = '\0';
- mimetic::code(buffer, buffer + readbytes, b64, out);
- std::string str = temp.str();
- pMe->load(str.begin(), str.end(), mimetic::imNone);
- }
- 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_easy_init();
- if (curl) {
-
-
-
-
- curl_easy_setopt(curl, CURLOPT_URL, "smtp://mainserver.example.net:25");//"smtp://mainserver.example.net:25");
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- curl_easy_setopt(curl, CURLOPT_USERNAME, "test@test.com");
- curl_easy_setopt(curl, CURLOPT_PASSWORD, "*****");
-
-
- curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);
-
-
-
- recipients = curl_slist_append(recipients, TO);
- recipients = curl_slist_append(recipients, CC);
- curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
-
-
-
-
-
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, my_read);
- curl_easy_setopt(curl, CURLOPT_READDATA, &ud);
-
-
-
-
-
-
-
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
-
-
- res = curl_easy_perform(curl);
-
-
- curl_slist_free_all(recipients);
- curl_easy_cleanup(curl);
- }
- return 0;
- }
需要注意的是MIME C++ library构造邮件流的时候是将所有内容加载至内存中的,对于大的附件还得自己拼凑MIME流,不过通过对MIME C++ library学习了MIME协议这应该不是太难的问题了。
转载地址:http://mweab.baihongyu.com/