天天看点

使用vmime收取邮件

vmime对邮件格式和邮件协议做了很好的封装,使用起来还是非常方便的。

vmime对于邮件协议都封装在vmime::net名字空间中,主要要用到的对象,有:

vmime::net::session,主要用于维护和服务器之间的连接

vmime::net::store,表示一个邮件存储,这是一个基类,没种邮件协议都有自己的store(如pop3store,imapstore)

vmime::net::folder,表示邮件存储上的文件夹,和store一样,每种邮件协议,都有自己的folder实现

vmime::net::message,表示一封网络邮件,和vmime::message不同,vmime::net::message可能只有邮件的一部分,如邮件头等信息(由使用的邮件协议决定)。

vmime会根据session中设置的邮件协议,创建对应的store。

一些常用操作的实现(pop3协议):

连接邮箱:

vmime::utility::ref<vmime::net::session> session = vmime::create<vmime::net::session>(); //创建session

vmime::utility::ref<vmime::net::store> store = session->getstore(vmine_url); //获得store

store->connect();//连接

vmime::utility::ref<vmime::net::folder>folder = store->getdefaultfolder();//创建folder,路径是默认路径(inbox)

folder->open(vmime::net::folder::mode_read_write);//以读写的形式打开

获取邮件:

std::vector<vmime::utility::ref<vmime::net::message> > allmessages = folder->getmessages();

folder->fetchmessages(allmessages, vmime::net::folder::fetch_envelope); //获取所有邮件的头部信息,包含sender, recipients, date, subject

vmime::string mailcontent;

vmime::utility::outputstreamstringadapter out(mailcontent);

resultmsg->extract(out); //找到需要的邮件后,下载到本地,保存到string中,这里vmime::string是std::string的typedef

删除邮件:

folder->deletemessage(resultmsg->getnumber()); //执行删除指令

folder->close(true);//关闭文件夹,真正对邮件进行删除

使用当中出现的问题:

按照vmime-book中的例子,在获取邮件的时候,增加了vmime::net::folder::fetch_flags标签后,会抛出异常,提示不支持该操作。

还有执行了folder->deletemessage函数之后,邮件没有真正删除。通过抓包和查看源代码后发现,deletemessage函数是对邮件服务器发送了dele指令,但是邮件服务器不会立即执行,需要quit之后才会真正的删除。而在folder的析构函数中,调用的是folder->close(false)函数来关闭文件夹的,这样在发送quit命令之前,会向邮件服务器发送一个rset命令,将已经被标记为删除的邮件状态充值,所以不会真正的删除邮件。目前只有在执行了删除命令后,显式执行close(true)函数,确保马上发送quit命令,让服务器删除邮件。

上述命令真正执行的pop3命令为:

#连接

user xxx #用户名

pass xxx #密码

stat #查询邮件数量和大小

top 1 0 #查看序号为1的邮件的头部

retr 1 #接受第一封邮件的所有内容

dele 1 #删除第一封邮件

quit #退出,服务器执行删除操作

转载自:https://coolex.info/blog/108.html