📄 mapimessage.cpp
字号:
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 + -