⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mapimessage.cpp

📁 A (hopefully) complete extended MAPI wrapper for WinXP, WinCE, and .NET.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	CString strPath;
	BOOL bResult=FALSE;
	enum { PROP_ATTACH_NUM, PROP_ATTACH_LONG_FILENAME, PROP_ATTACH_FILENAME, ATTACH_COLS };
	static SizedSPropTagArray(ATTACH_COLS,Columns)={ATTACH_COLS, PR_ATTACH_NUM, PR_ATTACH_LONG_FILENAME, PR_ATTACH_FILENAME };
	if(pAttachTable->SetColumns((LPSPropTagArray)&Columns,0)==S_OK) {
		int i=0;
		LPSRowSet pRows=NULL;
		while(TRUE) {
			if(pAttachTable->QueryRows(1,0,&pRows)!=S_OK) MAPIFreeBuffer(pRows);
			else if(!pRows->cRows) FreeProws(pRows);
			else if(i<nIndex) {
				i++;
				continue;
			} else {
				LPATTACH pAttachment;
				if(m_pMessage->OpenAttach(pRows->aRow[0].lpProps[PROP_ATTACH_NUM].Value.bin.cb,NULL,0,&pAttachment)==S_OK) {
					if(CMAPIEx::GetValidString(pRows->aRow[nIndex].lpProps[PROP_ATTACH_LONG_FILENAME])) strPath.Format(_T("%s\\%s"),szFolder,pRows->aRow[0].lpProps[PROP_ATTACH_LONG_FILENAME].Value.LPSZ);
					else if(CMAPIEx::GetValidString(pRows->aRow[nIndex].lpProps[PROP_ATTACH_FILENAME])) strPath.Format(_T("%s\\%s"),szFolder,pRows->aRow[0].lpProps[PROP_ATTACH_FILENAME].Value.LPSZ);
					else strPath.Format(_T("%s\\Attachment.dat"), szFolder);
						
					if(!SaveAttachment(pAttachment,strPath)) {
						pAttachment->Release();
						FreeProws(pRows);
						RELEASE(pAttachTable);
						return FALSE;
					}
					bResult=TRUE;
					pAttachment->Release();
				}

				FreeProws(pRows);
				if(nIndex==-1) continue;
			}
			break;
		}
	}
	RELEASE(pAttachTable);
	return bResult;
}

// use nIndex of -1 to delete all attachments
BOOL CMAPIMessage::DeleteAttachments(int nIndex)
{
	LPMAPITABLE pAttachTable=NULL;
	if(m_pMessage->GetAttachmentTable(0,&pAttachTable)!=S_OK) return FALSE;

	BOOL bResult=FALSE;
	enum { PROP_ATTACH_NUM, ATTACH_COLS };
	static SizedSPropTagArray(ATTACH_COLS,Columns)={ATTACH_COLS, PR_ATTACH_NUM };
	if(pAttachTable->SetColumns((LPSPropTagArray)&Columns,0)==S_OK) {
		int i=0;
		LPSRowSet pRows=NULL;
		while(TRUE) {
			if(pAttachTable->QueryRows(1,0,&pRows)!=S_OK) MAPIFreeBuffer(pRows);
			else if(!pRows->cRows) FreeProws(pRows);
			else if(i<nIndex) {
				i++;
				continue;
			} else {
				if(m_pMessage->DeleteAttach(pRows->aRow[0].lpProps[PROP_ATTACH_NUM].Value.bin.cb,0,NULL,0)!=S_OK) {
					FreeProws(pRows);
					RELEASE(pAttachTable);
					return FALSE;
				}
				bResult=TRUE;
				FreeProws(pRows);
				if(nIndex==-1) continue;
			}
			break;
		}
	}
	RELEASE(pAttachTable);
	if(bResult) m_pMessage->SaveChanges(FORCE_SAVE | KEEP_OPEN_READWRITE);
	return bResult;
}

BOOL CMAPIMessage::Create(CMAPIEx* pMAPI,int nPriority)
{
	if(!pMAPI) return FALSE;
	LPMAPIFOLDER pOutbox=pMAPI->GetFolder();
	if(!pOutbox) pOutbox=pMAPI->OpenOutbox();
	if(!pOutbox || pOutbox->CreateMessage(NULL,0,&m_pMessage)!=S_OK) return FALSE;
	m_pMAPI=pMAPI;

    SPropValue prop;
	prop.ulPropTag=PR_MESSAGE_FLAGS;
	prop.Value.l=MSGFLAG_UNSENT | MSGFLAG_FROMME;
	m_pMessage->SetProps(1,&prop,NULL);

#ifdef _WIN32_WCE
	// the following uses non outlook attachments (no winmail.dat) so other clients can read mail and attachments
	static const GUID ID_USE_TNEF = {0x00062008,0x000,0x0000,{0xc0,0x00,0x0,0x00,0x00,0x00,0x00,0x46 } };
	MAPINAMEID nameid={(GUID*)&ID_USE_TNEF, MNID_ID, 0x8582};
	MAPINAMEID *rgpnameid[1]={&nameid}; 
	_SPropTagArray* lpSPropTags; 
	HRESULT hr=m_pMessage->GetIDsFromNames(1, rgpnameid, MAPI_CREATE, &lpSPropTags);
	unsigned long ulPropTag=lpSPropTags->aulPropTag[0];
	ulPropTag=PROP_TAG(PT_BOOLEAN, PROP_ID(ulPropTag)); 

	prop.ulPropTag=ulPropTag;
	prop.Value.b=FALSE;
	m_pMessage->SetProps(1,&prop,NULL);

	prop.ulPropTag=PR_MESSAGE_CLASS;
	prop.Value.lpszA=(TCHAR*)"IPM.Note";
	m_pMessage->SetProps(1,&prop,NULL);
#endif

	LPSPropValue props=NULL;
	ULONG cValues=0;
	ULONG rgTags[]={ 1, PR_IPM_SENTMAIL_ENTRYID };

	if(m_pMAPI->GetMessageStore()->GetProps((LPSPropTagArray) rgTags, CMAPIEx::cm_nMAPICode, &cValues, &props)==S_OK) {
		prop.ulPropTag=PR_SENTMAIL_ENTRYID;
		prop.Value.bin.cb=props[0].Value.bin.cb;
		prop.Value.bin.lpb=props[0].Value.bin.lpb;
		m_pMessage->SetProps(1,&prop,NULL);
	}

	if(nPriority!=IMPORTANCE_NORMAL) {
		prop.ulPropTag=PR_IMPORTANCE;
		prop.Value.l=nPriority;
		m_pMessage->SetProps(1,&prop,NULL);
	}

#ifdef _WIN32_WCE
	prop.ulPropTag=PR_MSG_STATUS;
	prop.Value.ul=MSGSTATUS_RECTYPE_SMTP;
	m_pMessage->SetProps(1,&prop,NULL);
#endif

	MAPIFreeBuffer(props);
	return TRUE;
}

// used only by WinCE, pass in MSGSTATUS_RECTYPE_SMS to send an SMS 
// (default is set to MSGSTATUS_RECTYPE_SMTP in Create(...) above)
void CMAPIMessage::SetMessageStatus(int nMessageStatus)
{
	SPropValue prop;
	prop.ulPropTag=PR_MSG_STATUS;
	prop.Value.ul=nMessageStatus;
	m_pMessage->SetProps(1,&prop,NULL);
}

void CMAPIMessage::MarkAsRead(BOOL bRead)
{
	ULONG ulFlags=bRead ? 0 : CLEAR_READ_FLAG;
	if(m_pMessage) m_pMessage->SetReadFlag(ulFlags);
}

BOOL CMAPIMessage::AddRecipient(LPCTSTR szEmail,int nType)
{
	if(!m_pMessage || !m_pMAPI) return FALSE;

#ifndef _WIN32_WCE
	LPADRBOOK pAddressBook;
	if(m_pMAPI->GetSession()->OpenAddressBook(0, NULL, AB_NO_DIALOG, &pAddressBook)!=S_OK) return FALSE;
#endif

	int nBufSize=CbNewADRLIST(1);
	LPADRLIST pAddressList=NULL;
	MAPIAllocateBuffer(nBufSize,(LPVOID FAR*)&pAddressList);
	memset(pAddressList,0,nBufSize);

	const int nProperties=2;
	pAddressList->cEntries=1;

	pAddressList->aEntries[0].ulReserved1=0;
	pAddressList->aEntries[0].cValues=nProperties;

	MAPIAllocateBuffer(sizeof(SPropValue)*nProperties,(LPVOID FAR*)&pAddressList->aEntries[0].rgPropVals);
	memset(pAddressList->aEntries[0].rgPropVals, 0, sizeof(SPropValue)*nProperties);

	pAddressList->aEntries[0].rgPropVals[0].ulPropTag=PR_RECIPIENT_TYPE;
	pAddressList->aEntries[0].rgPropVals[0].Value.ul=nType;

#ifdef _WIN32_WCE
	pAddressList->aEntries[0].rgPropVals[1].ulPropTag=PR_EMAIL_ADDRESS;
	pAddressList->aEntries[0].rgPropVals[1].Value.LPSZ=(TCHAR*)szEmail;
#else
	pAddressList->aEntries[0].rgPropVals[1].ulPropTag=PR_DISPLAY_NAME;
	pAddressList->aEntries[0].rgPropVals[1].Value.LPSZ=(TCHAR*)szEmail;
#endif

#ifdef _WIN32_WCE
	HRESULT hr=m_pMessage->ModifyRecipients(MODRECIP_ADD, pAddressList);
#else
	HRESULT hr=E_INVALIDARG;
	if(pAddressBook->ResolveName(0, CMAPIEx::cm_nMAPICode, NULL, pAddressList)==S_OK) hr=m_pMessage->ModifyRecipients(MODRECIP_ADD, pAddressList);
#endif
	MAPIFreeBuffer(pAddressList->aEntries[0].rgPropVals);
	MAPIFreeBuffer(pAddressList);
#ifndef _WIN32_WCE
	RELEASE(pAddressBook);
#endif
	return (hr==S_OK);
}

void CMAPIMessage::SetSubject(LPCTSTR szSubject)
{
	m_strSubject=szSubject;
	if(m_strSubject.GetLength() && m_pMessage) {
		SPropValue prop;
		prop.ulPropTag=PR_SUBJECT;
		prop.Value.LPSZ=(TCHAR*)szSubject;
		m_pMessage->SetProps(1,&prop,NULL);
	}
}

void CMAPIMessage::SetSenderName(LPCTSTR szSenderName)
{
	m_strSenderName=szSenderName;
	if(m_strSenderName.GetLength() && m_pMessage) {
		SPropValue prop;
		prop.ulPropTag=PR_SENDER_NAME;
		prop.Value.LPSZ=(TCHAR*)szSenderName;
		m_pMessage->SetProps(1,&prop,NULL);
	}
}

void CMAPIMessage::SetSenderEmail(LPCTSTR szSenderEmail)
{
	m_strSenderEmail=szSenderEmail;
	if(m_strSenderEmail.GetLength() && m_pMessage) {
		SPropValue prop;
		prop.ulPropTag=PR_SENDER_EMAIL_ADDRESS;
		prop.Value.LPSZ=(TCHAR*)szSenderEmail;
		m_pMessage->SetProps(1,&prop,NULL);
	}
}

void CMAPIMessage::SetBody(LPCTSTR szBody)
{
	m_strBody=szBody;
	if(m_strBody.GetLength() && m_pMessage) {
		LPSTREAM pStream=NULL;
        if(m_pMessage->OpenProperty(PR_BODY, &IID_IStream, 0, MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN*)&pStream)==S_OK) {
	        pStream->Write(szBody,(ULONG)(_tcslen(szBody)+1)*sizeof(TCHAR),NULL);
        }
        RELEASE(pStream);
	}
}

// use this function to set the body of the message to HTML or RTF
void CMAPIMessage::SetRTF(LPCTSTR szRTF)
{
	if(!m_pMessage) return;
	m_strBody=szRTF;

	ULONG ulSupport=m_pMAPI ? m_pMAPI->GetMessageStoreSupport() : 0;
	if(_tcsnccmp(szRTF,_T("<html"),5)==0) {
		// is this HTML?  Does this store support HTML directly?
		if(ulSupport&STORE_HTML_OK) {
			LPSTREAM pStream=NULL;
			if(m_pMessage->OpenProperty(PR_BODY_HTML, &IID_IStream, 0, MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN*)&pStream)==S_OK) {
				pStream->Write(szRTF,(ULONG)(_tcslen(szRTF)+1)*sizeof(TCHAR),NULL);
			}
			RELEASE(pStream);
			return;
		} else {
			// otherwise lets encode it into RTF 
			TCHAR szCodePage[6]=_T("1252"); // default codepage is ANSI - Latin I
			GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE,szCodePage,sizeof(szCodePage));

			m_strRTF.Format(_T("{\\rtf1\\ansi\\ansicpg%s\\fromhtml1 {\\*\\htmltag1 "),szCodePage);
			m_strRTF+=szRTF;
			m_strRTF+=_T(" }}");
		}
	}

	if(m_strRTF.GetLength()) {
		LPSTREAM pStream=NULL;
		if(m_pMessage->OpenProperty(PR_RTF_COMPRESSED, &IID_IStream, STGM_CREATE | STGM_WRITE, MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN*)&pStream)==S_OK) {
			IStream *pUncompressed;
			if(WrapCompressedRTFStream(pStream,MAPI_MODIFY,&pUncompressed)==S_OK) {
				pUncompressed->Write(m_strRTF,(ULONG)m_strRTF.GetLength()*sizeof(TCHAR),NULL);
				if(pUncompressed->Commit(STGC_DEFAULT)==S_OK) pStream->Commit(STGC_DEFAULT);
				RELEASE(pUncompressed);
			}
			RELEASE(pStream);
		}
	}
}

BOOL CMAPIMessage::AddAttachment(LPCTSTR szPath,LPCTSTR szName)
{
	if(!m_pMessage) return FALSE;

	IAttach* pAttachment=NULL;
	ULONG ulAttachmentNum=0;

	CFile file;
	if(!file.Open(szPath,CFile::modeRead)) return FALSE;

	LPTSTR szFileName=(LPTSTR)szName;
	if(!szFileName) {
		szFileName=(LPTSTR)szPath;
		for(int i=(int)_tcsclen(szPath)-1;i>=0;i--) if(szPath[i]=='\\' || szPath[i]=='/') {
			szFileName=(LPTSTR)&szPath[i+1];
			break;
		}
	}

	if(m_pMessage->CreateAttach(NULL,0,&ulAttachmentNum,&pAttachment)!=S_OK) {
		file.Close();
		return FALSE;
	}

	const int nProperties=4;
	SPropValue prop[nProperties];
	memset(prop,0,sizeof(SPropValue)*nProperties);
	prop[0].ulPropTag=PR_ATTACH_METHOD;
	prop[0].Value.ul=ATTACH_BY_VALUE;
	prop[1].ulPropTag=PR_ATTACH_LONG_FILENAME;
	prop[1].Value.LPSZ=(TCHAR*)szFileName;
	prop[2].ulPropTag=PR_ATTACH_FILENAME;
	prop[2].Value.LPSZ=(TCHAR*)szFileName;
	prop[3].ulPropTag=PR_RENDERING_POSITION;
	prop[3].Value.l=-1;
	if(pAttachment->SetProps(nProperties,prop,NULL)==S_OK) {
		LPSTREAM pStream=NULL;
		if(pAttachment->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, 0, MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN*)&pStream)==S_OK) {
			const int BUF_SIZE=4096;
			BYTE pData[BUF_SIZE];
			ULONG ulSize=0,ulRead,ulWritten;

			ulRead=file.Read(pData,BUF_SIZE);
			while(ulRead) {
				pStream->Write(pData,ulRead,&ulWritten);
				ulSize+=ulRead;
				ulRead=file.Read(pData,BUF_SIZE);
			}

			pStream->Commit(STGC_DEFAULT);
			RELEASE(pStream);
			file.Close();

			prop[0].ulPropTag=PR_ATTACH_SIZE;
			prop[0].Value.ul=ulSize;
			pAttachment->SetProps(1, prop, NULL);

			pAttachment->SaveChanges(KEEP_OPEN_READONLY);
			RELEASE(pAttachment);
			m_nAttachments++;
			return TRUE;
		}
	}

	file.Close();
	RELEASE(pAttachment);
	return FALSE;
}

// request a Read Receipt sent to szReceiverEmail 
void CMAPIMessage::SetReadReceipt(BOOL bSet,LPCTSTR szReceiverEmail)
{
	if(!m_pMessage) return;

	SPropValue prop;
	prop.ulPropTag=PR_READ_RECEIPT_REQUESTED;
	prop.Value.b=(unsigned short)bSet;
	m_pMessage->SetProps(1,&prop,NULL);

	if(bSet && szReceiverEmail && _tcslen(szReceiverEmail)>0) {
		prop.ulPropTag=PR_READ_RECEIPT_SEARCH_KEY;
		prop.Value.LPSZ=(TCHAR*)szReceiverEmail;
		m_pMessage->SetProps(1,&prop,NULL);
	}
}

BOOL CMAPIMessage::Send()
{
	if(m_pMessage && m_pMessage->SubmitMessage(0)==S_OK) {
		Close();
		return TRUE;
	}
	return FALSE;
}

// shallow copy only, no message pointer
CMAPIMessage& CMAPIMessage::operator=(CMAPIMessage& message)
{
	m_strSenderName=message.m_strSenderName;
	m_strSenderEmail=message.m_strSenderEmail;
	m_strSubject=message.m_strSubject;
	m_strBody=message.m_strBody;
	m_strRTF=message.m_strRTF;

	m_dwMessageFlags=message.m_dwMessageFlags;
	m_tmReceived=message.m_tmReceived;
	SetEntryID(message.GetEntryID());
	return *this;
}

// limited compare, compares entry IDs and subject to determine if two emails are equal
BOOL CMAPIMessage::operator==(CMAPIMessage& message)
{
	if(!m_entry.cb || !message.m_entry.cb || m_entry.cb!=message.m_entry.cb) return FALSE;
	if(memcmp(&m_entry.lpb,&message.m_entry.lpb,m_entry.cb)) return FALSE;
	return (!m_strSubject.Compare(message.m_strSubject));
}

// Novell GroupWise customization by jcadmin
#ifndef GROUPWISE
void CMAPIMessage::MarkAsPrivate() {}
#else
#include GWMAPI.h
//(from Novell Developer Kit)
#define SEND_OPTIONS_MARK_PRIVATE 0x00080000L

void CMAPIMessage::MarkAsPrivate() 
{
	SPropValue prop;
	prop.ulPropTag=PR_NGW_SEND_OPTIONS;
	prop.Value.l=NGW_SEND_OPTIONS_MARK_PRIVATE;
	m_pMessage->SetProps(1,&prop,NULL);
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -