邮件解码---GMIME的使用其实很简单

其实邮件解码很简单,很多人愿意自己解码,但是为什么不用现成的工具呢?给大家推荐一款十分方便的邮件解码源码——Gmime

Gmime从2002年开始做了,到现在已经有了很多版本支持大部分的smtp和HTTP,但是也有他不完美的地方,比方说charset解码的流数据大小不准确,比如说最新版本gmime2.6.20编译编不过去(这个问题确实让我很恶心,我几乎把gmime所有依赖的glib等库全编了一遍,但是还是不好用),我用的版本是gmime-2.6.7。在我们的产品上已经用了一段时间,还是不错的,不过对于Http下使用还得自己改下源代码。

下面进入正题说下GMIME如何用,GMIME有个文档,很详细的介绍了函数功能:gmime-2.6.7\gmime-2.6.7\docs\reference\html 

因为最开始我没看到,所以研究了半天没搞明白所给的实例中代码如何用,使用者请仔细看下他提供的函数接口,并比对着gmime-2.6.7\gmime-2.6.7\examples下的例子仔细看下,打开工程可以在gmime-2.6.7\gmime-2.6.7\build\vs2008 用vs2008打开并全局查找比对例子如何用,当然不是所有函数接口都有案例的。

下面给几个比较关键接口实现,比较简单网上有基本不需要自己改(请仔细阅读gmime提供的文档和案例)

获取body部分,由于获取body时要使用g_mime_stream_read 而这个函数采用的流读取,只能对流中的内容读取一次,每次读取的内容仅限4096(修改源码也没用,就算修改了也没效果,亲身测试),所以要采取循环读取的方法。

以下是这部分的关键代码:

std::string CMailParser::GetBody(){
	
	
	std::string data;
	int iRe=0,ichar=0,iencode =0;
	GMimePart * mime_part =  (GMimePart*)g_mime_message_get_body_ex(this->m_MimeMessage);

	if( NULL==mime_part )
	{
		return "error" ;
	}

	GMimeContentEncoding ReEncoding = g_mime_part_get_content_encoding(mime_part);

	char* szCharset = (char*)g_mime_object_get_content_type_parameter((GMimeObject*)mime_part,"charset");

	GMimeDataWrapper *dataWrap = g_mime_part_get_content_object(mime_part);

	GMimeStream * gmime_stream= g_mime_data_wrapper_get_stream(dataWrap);
	//encoding转码
	GMimeFilter * pAttFilter =  g_mime_filter_basic_new(ReEncoding,FALSE);
	GMimeStream* pFilterStream =  g_mime_stream_filter_new(gmime_stream);

	iencode = g_mime_stream_filter_add (GMIME_STREAM_FILTER (pFilterStream), pAttFilter);
	//charset转码
	gint64 size = g_mime_stream_length(pFilterStream);

	g_object_unref ( pAttFilter );


	if (pFilterStream && size >0)
	{
					
		char* szTemp=NULL;
		szTemp = (char*)malloc( size * 3 );
		char* current =szTemp;
		memset(szTemp,0,size*3);
		while ( (current-szTemp) < size)
		{
			iRe = g_mime_stream_read(pFilterStream,current,size );
			int iLength= strlen(szTemp);

			if(iRe>0)
				current += iRe;
			else 
				break;

		}	
		size = current-szTemp;
		if (size >0)
		{
			if(szCharset != NULL)
			{

				char * pUtf8Buff = NULL;
				pUtf8Buff = GetUtf8String((const byte*)szTemp, size );
				data.assign(pUtf8Buff,strlen(pUtf8Buff));
				if( pUtf8Buff !=NULL )
				{
					free( pUtf8Buff  );
				}		
				if(szTemp != NULL)
				{	
					free(szTemp);
					szTemp = NULL;
				}

			}
			else
			{
				data.assign(szTemp,size);
				if(szTemp != NULL)
				{	
					free(szTemp);
					szTemp = NULL;
				}

			}

			
		}

		g_mime_stream_filter_remove((GMimeStreamFilter*)pFilterStream,ichar);
		g_mime_stream_filter_remove((GMimeStreamFilter*)pFilterStream,iencode);

		g_object_unref (pFilterStream);
		//g_object_unref (gmime_stream);

	}
	else
	{
		g_mime_stream_filter_remove((GMimeStreamFilter*)pFilterStream,ichar);
		g_mime_stream_filter_remove((GMimeStreamFilter*)pFilterStream,iencode);
			g_object_unref (pFilterStream);
		//g_object_unref (gmime_stream);
	
		return "error";
	}

	
	return data;	
}

gmime还有个很关键的点就是计数器,很多东西GMIME会用GLIB生成在内部进行加1,出来的时候要unref一下,这个得自己看代码查,如果unref次数多于ref错误会导致警报,如果ref次数多于unref次数可能导致内存泄露,这就得使用者自己查了~~

(天融信dlp研发工程师)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值