Click here to Skip to main content
15,891,253 members
Articles / Desktop Programming / MFC

The Ultimate Toolbox Home Page

Rate me:
Please Sign up or sign in to vote.
4.97/5 (141 votes)
25 Aug 2007CPOL13 min read 3.2M   91.4K   476  
The Ultimate Toolbox is now Open Source
// ==========================================================================
//      Class Implementation : COXSendMail
// ==========================================================================

// Source file : SendMail.cpp

// This software along with its related components, documentation and files ("The Libraries")
// is � 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement").  Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office.  For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.

// //////////////////////////////////////////////////////////////////////////

#include "stdafx.h"  // standard MFC include
#include "OXSendMail.h"

#pragma warning(disable: 4228)
#include <mapi.h>
#include <mapix.h>
#include <mapiwin.h>
#include <mapiutil.h>

#define USES_IID_IMAPIFolder
#define INITGUID
#include <initguid.h>
#include <mapiguid.h>
#pragma warning(default: 4228)

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


COXSendMail::CMessage::CMessage()
{
}

COXSendMail::CMessage::~CMessage()
{
	int i;
	
	for (i=0 ; i<m_recipients.GetSize() ; i++)
		delete m_recipients[i];
	for (i=0 ; i<m_attachments.GetSize() ; i++)
		delete m_attachments[i];
}

void COXSendMail::CMessage::AddRecipient(CString sRecipient, ERecipientType eType)
{
	SRecipient* pRecipient = new SRecipient;
	
	pRecipient->sName = sRecipient;
	pRecipient->eType = eType;
	m_recipients.Add(pRecipient);
}

void COXSendMail::CMessage::AddAttachment(CString sAttachment, EAttachmentType eType, CString sOleDocument /*= _T("")*/)
{
	SAttachment* pAttachment = new SAttachment;
	
	pAttachment->sPath = sAttachment;
	pAttachment->eType = eType;
	pAttachment->sOleDocument = sOleDocument;
	m_attachments.Add(pAttachment);
}


#ifndef OX_MAPI_DIRECT

COXSendMail::COXSendMail()
{
}

COXSendMail::~COXSendMail()
{
	if (IsInitialized())
	Uninitialize();
}


BOOL COXSendMail::Initialize(CString sProfileName, CString sPassword)
{
	ASSERT_VALID(this);

	LPMAPISESSION	pMAPISession;       
	HRESULT			hResult;
	BOOL			bMAPIInitialized = FALSE;
	BOOL			bResult = TRUE;

	TRY
	{
		MAPIINIT_0 MAPIINIT = { 0, MAPI_NT_SERVICE | MAPI_MULTITHREAD_NOTIFICATIONS }; 
		hResult = MAPIInitialize(&MAPIINIT);
		if (FAILED (hResult))
			return FALSE;

		bMAPIInitialized = TRUE;

		hResult = MAPILogonEx(
						(ULONG)NULL,
						sProfileName.GetBuffer(256),
						sPassword.GetBuffer(256),
						MAPI_LOGON_UI | MAPI_NO_MAIL | MAPI_EXTENDED | MAPI_EXPLICIT_PROFILE | MAPI_NEW_SESSION,
						&pMAPISession);

		sProfileName.ReleaseBuffer();
		sPassword.ReleaseBuffer();

		if (FAILED (hResult))
		{
			MAPIUninitialize();
			return FALSE;
		}
		
		if (m_objSession.m_lpDispatch == NULL)
		{
			if (m_objSession.CreateDispatch(_T("MAPI.Session")) == FALSE)
			{
				MAPIUninitialize();
				bResult = FALSE;
			}
		}
		if (bResult)
			m_objSession.SetMapiobject(pMAPISession);
	}
	CATCH_ALL(e)
	{
		if (bMAPIInitialized)
			MAPIUninitialize();
		bResult = FALSE;
	}
	END_CATCH_ALL

	if (bResult)
		m_sMAPIProfile = sProfileName;
	return bResult;
}

BOOL COXSendMail::IsInitialized()
{
	if (m_objSession.m_lpDispatch)
		if (m_objSession.GetMapiobject() != NULL)
			return TRUE;
	return FALSE;
}

void COXSendMail::Uninitialize()
{
	TRY
	{
		ASSERT(m_objSession.m_lpDispatch);
		if (m_objSession.m_lpDispatch)
			m_objSession.Logoff();
	}
	CATCH_ALL(e)
	{
	}
	END_CATCH_ALL
	m_objSession.ReleaseDispatch();
	MAPIUninitialize();
}

CString COXSendMail::GetProfile()
{
	CString sProfile;

	if (IsInitialized())
		sProfile = m_sMAPIProfile;
	return sProfile;
}

BOOL COXSendMail::SendMessage(CMessage& message)
{
    COXMMessage objMessage;
    COXMRecipient objOneRecip;
	COXMAttachment objAttachment;
	ASSERT(m_objSession.m_lpDispatch);

	if (m_objSession.m_lpDispatch == NULL)
		return FALSE;

	TRY
	{
		// create new message and set subject and content
		objMessage = m_objSession.GetOutbox().GetMessages().Add();
		objMessage.SetSubject(message.m_sSubject);
		objMessage.SetText(message.m_sContent);

		// set the recipients
		for (int i=0 ; i<message.m_recipients.GetSize() ; i++)
		{
			objOneRecip = objMessage.GetRecipients().Add();
			objOneRecip.SetName(message.m_recipients[i]->sName);
			switch (message.m_recipients[i]->eType)
			{
			case rtCC:
				objOneRecip.SetType(oxmrtCc);
				break;
			case rtBCC:
				objOneRecip.SetType(oxmrtBcc);
				break;
			default:
				objOneRecip.SetType(oxmrtTo);
			}
		    objOneRecip.Resolve(FALSE);
		}

		// add the attachments
		for (i=0 ; i<message.m_attachments.GetSize() ; i++)
		{
			CString sAttachment;
			TCHAR pszDrive[_MAX_DRIVE];
			TCHAR pszSubdir[_MAX_DIR];
			TCHAR pszBaseName[_MAX_FNAME];
			TCHAR pszExtender[_MAX_EXT];

			sAttachment = message.m_attachments[i]->sPath;
			_tsplitpath(sAttachment, pszDrive, pszSubdir, pszBaseName, pszExtender);
			_tmakepath(sAttachment.GetBuffer(_MAX_PATH), NULL, NULL, pszBaseName, pszExtender);
			sAttachment.ReleaseBuffer();

			objAttachment = objMessage.GetAttachments().Add(sAttachment);
			objAttachment.SetName(sAttachment);
			objAttachment.SetType((EOXMAttachmentType) message.m_attachments[i]->eType);
			objAttachment.ReadFromFile(message.m_attachments[i]->sPath);
		}

		// send the message
		objMessage.Send();
	}
	CATCH_ALL(e)
	{
		return FALSE;
	}
	END_CATCH_ALL

	return TRUE;

}

#endif



CString COXSendMail::GetReturnMsg(int nErr)
{
	CString sErrorMsg;
	switch(nErr)
	{
		case SUCCESS_SUCCESS:
			sErrorMsg = _T("Sending of Mail was succesful");
			break;
		case MAPI_E_USER_ABORT:
			sErrorMsg = _T("Sending of Mail has been aborted by user");
			break;
		case MAPI_E_FAILURE:
			sErrorMsg = _T("Sending of Mail was not succesful");
			break;
		case MAPI_E_LOGIN_FAILURE:
			sErrorMsg = _T("login failure");
			break;
		case MAPI_E_DISK_FULL:
			sErrorMsg = _T("Disk full");
			break;
		case MAPI_E_INSUFFICIENT_MEMORY:
			sErrorMsg = _T("not enough memory");
			break;
		case MAPI_E_ACCESS_DENIED:
			sErrorMsg = _T("access denied");
			break;
		case MAPI_E_TOO_MANY_SESSIONS:
			sErrorMsg = _T("too many sessions open");
			break;
		case MAPI_E_TOO_MANY_FILES:
			sErrorMsg = _T("too many open files");
			break;
		case MAPI_E_TOO_MANY_RECIPIENTS:
			sErrorMsg = _T("too many recipients specified");
			break;
		case MAPI_E_ATTACHMENT_NOT_FOUND:
			sErrorMsg = _T("attachment not found");
			break;
		case MAPI_E_ATTACHMENT_OPEN_FAILURE:
			sErrorMsg = _T("could not open attachment");
			break;
		case MAPI_E_ATTACHMENT_WRITE_FAILURE:
			sErrorMsg = _T("could not write attachment");
			break;
		case MAPI_E_UNKNOWN_RECIPIENT:
			sErrorMsg = _T("unknown recipient");
			break;
		case MAPI_E_BAD_RECIPTYPE:
			sErrorMsg = _T("unknown reciptype");
			break;
		case MAPI_E_NO_MESSAGES:
			sErrorMsg = _T("no messages");
			break;
		case MAPI_E_INVALID_MESSAGE:
			sErrorMsg = _T("invalid message");
			break;
		case MAPI_E_TEXT_TOO_LARGE:
			sErrorMsg = _T("text too large");
			break;
		case MAPI_E_INVALID_SESSION:
			sErrorMsg = _T("invalid session");
			break;
		case MAPI_E_TYPE_NOT_SUPPORTED:
			sErrorMsg = _T("type not supported");
			break;
		case MAPI_E_AMBIG_RECIP:
			sErrorMsg = _T("ambiguous recipiebt");
			break;
		case MAPI_E_MESSAGE_IN_USE:
			sErrorMsg = _T("message in use");
			break;
		case MAPI_E_NETWORK_FAILURE:
			sErrorMsg = _T("network failure");
			break;
		case MAPI_E_INVALID_EDITFIELDS:
			sErrorMsg = _T("invalid editfields");
			break;
		case MAPI_E_INVALID_RECIPS:
			sErrorMsg = _T("invalid recipients");
			break;
		case MAPI_E_NOT_SUPPORTED:
			sErrorMsg = _T("not supported request");
			break;
		default:
			sErrorMsg = _T("unknown error");
			break;
	}
	
	return sErrorMsg;
}






/////////////////////////////////////////////////////////////////////////////
// The Extended MAPI alternative



#ifdef OX_MAPI_DIRECT
/////////////////////////////////////////////////////////////////////////////
// MAPI implementation helpers and globals

#define _countof(array)  (sizeof(array)/sizeof(array[0]))

static BOOL IsMailAvail = (BOOL)-1;    // start out not determined

// _AFX_MAIL_STATE

class OX_CLASS_DECL _AFX_MAIL_STATE : public CNoTrackObject
{
public:
	HINSTANCE m_hInstMail;      // handle to MAPI32.DLL
	virtual ~_AFX_MAIL_STATE();
};

_AFX_MAIL_STATE::~_AFX_MAIL_STATE()
{
	if (m_hInstMail != NULL)
		::FreeLibrary(m_hInstMail);
}

_AFX_MAIL_STATE* _afxMailState;
int nCount = 0;



COXSendMail::COXSendMail() :
	m_pMAPISession(NULL),
	m_pAddressBook(NULL),
	m_peidDefaultMDB(NULL),
	m_cbeidDefaultMDB(0),
	m_pDefaultMDB(NULL),
	m_pRootFolder(NULL),
	m_szRecipient(NULL),
	m_uLogoffFlags(LOGOFF_ORDERLY),
	m_szAttachData(NULL)
{
	if (nCount==0)
		_afxMailState = new _AFX_MAIL_STATE;
	nCount++;
}


COXSendMail::~COXSendMail()
{
	if (IsInitialized())
		Uninitialize();

	nCount--;
	if (nCount==0)
		delete _afxMailState;
}

BOOL COXSendMail::Initialize(CString sProfileName, CString sPassword)
{
	ASSERT_VALID(this);

	HRESULT hResult;

	if (IsInitialized())
		Uninitialize();
	
	// Initialize the MAPI libraries before calling ANY MAPI function
	MAPIINIT_0 MAPIINIT = { 0, MAPI_NT_SERVICE | MAPI_MULTITHREAD_NOTIFICATIONS }; 
	hResult = MAPIInitialize(&MAPIINIT);
	if (!FAILED (hResult))
	{
		// Logon onto the message subsystem. We are going to ask the user to
		// select a profile to log into. The UI for this will be provided by MAPI.
		hResult = MAPILogonEx((ULONG)NULL,
			sProfileName.GetBuffer(256),
			sPassword.GetBuffer(256),
			MAPI_NO_MAIL | MAPI_EXTENDED | MAPI_EXPLICIT_PROFILE /*| MAPI_USE_DEFAULT */| MAPI_NEW_SESSION,
			&m_pMAPISession);
		
		sProfileName.ReleaseBuffer();
		sPassword.ReleaseBuffer();

		if (!FAILED (hResult))
		{
			// get the address book
			// be sure to have the correct address book set as the default
			// see the Addressing tab in the profile config control panel applet
			hResult = m_pMAPISession->OpenAddressBook(NULL, NULL, 0, &m_pAddressBook);
			if (!FAILED(hResult))
			{
				if (InitializeMessageStore())
				{
					// get the root folder
					ULONG uObjType;
					hResult = m_pDefaultMDB->OpenEntry(0, 
													 NULL, 
													 (LPIID)&IID_IMAPIFolder, 
													 MAPI_MODIFY, 
													 &uObjType, 
													 (LPUNKNOWN *)&m_pRootFolder);
	
					if (!FAILED(hResult))
					{
						m_sMAPIProfile = sProfileName;
						return TRUE;
					}
				}
			}
		}
		Uninitialize();
	}
	else
		MAPIUninitialize();
	return FALSE;
}

BOOL COXSendMail::IsInitialized()
{
	return (m_pMAPISession!=NULL);
}

void COXSendMail::Uninitialize()
{
	if (m_pRootFolder != NULL)
	{
		m_pRootFolder->Release();
		m_pRootFolder = NULL;
	}
	
	if (m_pDefaultMDB != NULL)
	{
		m_pDefaultMDB->StoreLogoff(&m_uLogoffFlags);
		m_pDefaultMDB->Release();
		m_pDefaultMDB = NULL;
	}
	
	if (m_peidDefaultMDB != NULL)
	{
		MAPIFreeBuffer(m_peidDefaultMDB);
		m_peidDefaultMDB = NULL;
	}
	
	if (m_pAddressBook != NULL)
	{
		m_pAddressBook->Release();
		m_pAddressBook = NULL;
	}
	
	if (m_pMAPISession!=NULL)
	{
		ULONG ulUIParam = (ULONG)NULL;   // null window handle
		ULONG ulFlags =    0;
		ULONG ulReserved = 0;

		m_pMAPISession->Logoff(ulUIParam, ulFlags, ulReserved);
		m_pMAPISession->Release();
		m_pMAPISession = NULL;
		MAPIUninitialize();
	}
}

CString COXSendMail::GetProfile()
{
	CString sProfile;

	if (IsInitialized())
		sProfile = m_sMAPIProfile;
	return sProfile;
}

BOOL COXSendMail::SendMessage(CMessage& message)
{
	LPMESSAGE	pMessage;
	HRESULT		hResult;
	
	pMessage = ComposeMessage(message);
	if (pMessage == NULL)
		return FALSE;	
	
	hResult = pMessage->SubmitMessage(FORCE_SUBMIT);
		
	if (pMessage != NULL)
		pMessage->Release();

	if (FAILED(hResult))
		return FALSE;
	return TRUE;
}


// protected functions


BOOL COXSendMail::InitializeMessageStore()
{
	LPSRowSet		pRow = NULL;
	ULONG			ulRow;
	ULONG			uRowCount;
	HRESULT			hResult;
	LPMAPITABLE		pStoresTable;
	LPSPropValue	pProps;
	BOOL			bFound;
	

// The order for this enumaration must match the order of the properties
// in the tag array below
	enum
	{
		DEFAULT_STORE,    
		STORE_EID,
		MSG_STORES_TABLE_PROPS        // number columns in the proptagarray
	};
	
	SizedSPropTagArray (MSG_STORES_TABLE_PROPS, sptMsgStores) =
	{
		MSG_STORES_TABLE_PROPS,
		{
			PR_DEFAULT_STORE,
			PR_ENTRYID,
		}
	};
	
///// end of local declarations
	
	m_cbeidDefaultMDB = 0;
	m_peidDefaultMDB = NULL;
	
	
// first get a table of the message stores available
	hResult = m_pMAPISession->GetMsgStoresTable (0, &pStoresTable);
	if (FAILED(hResult))
		return FALSE;	
	
	
// we only want the default store flag and the entry id
	hResult = pStoresTable->SetColumns((LPSPropTagArray)&sptMsgStores, 0);
	if (FAILED(hResult))
		return FALSE;
	
	pStoresTable->GetRowCount(0, &uRowCount);   // one row corresponds to one MDB provider
// typically no one should have more than
// 6 or 7 MDB providers.
	
// Get row(s) from the message stores table
	hResult = pStoresTable->QueryRows(uRowCount, 0, &pRow);
	if (FAILED(hResult))
		return FALSE;
	
	bFound = FALSE;
// loop through each row -- each row represents the properties of a message store
	for (ulRow=0; ulRow<pRow->cRows; ulRow++)
	{
		pProps = pRow->aRow[ulRow].lpProps;
		
		if (pProps[DEFAULT_STORE].Value.b == 1)    // we found it!
		{
			
			m_cbeidDefaultMDB = pProps[STORE_EID].Value.bin.cb;
			hResult = MAPIAllocateBuffer(m_cbeidDefaultMDB, (LPVOID *)&m_peidDefaultMDB);
			if (FAILED(hResult))
				return FALSE;
			
			memcpy(m_peidDefaultMDB, pProps[STORE_EID].Value.bin.lpb, m_cbeidDefaultMDB);
			
			bFound = TRUE;
		}
/// else ignore the non-defaults    
	}
	
	if (bFound)
		hResult = S_OK;
	else
		hResult = MAPI_E_NOT_FOUND;
	
	
	
// clean up if neccessary
	if (pRow != NULL)
		FreeProws(pRow);
	
	if (pStoresTable != NULL)
		pStoresTable->Release();


	if (FAILED(hResult))   // there was an error
		return FALSE;	
	
// open the default message store
	m_pDefaultMDB = NULL;
	hResult = m_pMAPISession->OpenMsgStore ((ULONG)NULL,
		m_cbeidDefaultMDB,
		m_peidDefaultMDB,
		NULL,
		MDB_WRITE,
		&m_pDefaultMDB);
	if (FAILED(hResult))
		return FALSE;	
	
	return TRUE;
}

LPMESSAGE COXSendMail::ComposeMessage(CMessage& message)
{
	HRESULT		hrRet = 0;
	LPMESSAGE	pMessage = NULL;
	SPropValue	pMessageProps[5];
	LPSPropProblemArray pPropProblems;
	
	// create the message
	hrRet = m_pRootFolder->CreateMessage(NULL, 0, &pMessage);
	if (FAILED(hrRet))
		return NULL;	
	
	// setup the properties
	pMessageProps[0].ulPropTag = PR_MESSAGE_CLASS;
	pMessageProps[1].ulPropTag = PR_PRIORITY;
	pMessageProps[2].ulPropTag = PR_SUBJECT;
	pMessageProps[3].ulPropTag = PR_BODY;
	pMessageProps[4].ulPropTag = PR_CLIENT_SUBMIT_TIME;

	pMessageProps[0].Value.lpszA = "IPM.NOTE";
	pMessageProps[1].Value.l = PRIO_NORMAL;
#ifdef _UNICODE
	pMessageProps[2].Value.lpszW = message.m_sSubject.GetBuffer(message.m_sSubject.GetLength());
	pMessageProps[3].Value.lpszW = message.m_sContent.GetBuffer(message.m_sContent.GetLength());
#else
	pMessageProps[2].Value.lpszA = message.m_sSubject.GetBuffer(message.m_sSubject.GetLength());
	pMessageProps[3].Value.lpszA = message.m_sContent.GetBuffer(message.m_sContent.GetLength());
#endif
	message.m_sSubject.ReleaseBuffer();
	message.m_sContent.ReleaseBuffer();
	
	// set the message submission time
	SYSTEMTIME	tSysTime;
	FILETIME	tSubmitTime;
	GetSystemTime(&tSysTime);
	SystemTimeToFileTime(&tSysTime, &tSubmitTime);  // convert to file time
	pMessageProps[4].Value.ft = tSubmitTime;
	
	
	// set the properties
	hrRet = pMessage->SetProps(5, pMessageProps, &pPropProblems);
	if (!FAILED(hrRet))
	{
		hrRet = AddRecipients(pMessage, message.m_recipients);
		if (!FAILED(hrRet))
		{
			// Create the attachment
			AddAttachments(pMessage, message.m_attachments);
			hrRet = pMessage->SaveChanges(KEEP_OPEN_READWRITE);
		}

		if (!FAILED(hrRet))
			return pMessage;	
	}

	if (pMessage != NULL)
		pMessage->Release();

	return NULL;
}


HRESULT COXSendMail::AddRecipients(LPMESSAGE pMessage, CRecipientArray& recipients)
{
	HRESULT		hrRet;
	LPADRLIST	pAddressList;
	
// allocate address list for one recipient
	MAPIAllocateBuffer(sizeof(ADRLIST) + sizeof(ADRENTRY) * recipients.GetSize(),
		(LPVOID *) &pAddressList);
	
// set properties for address list  
	pAddressList->cEntries = recipients.GetSize();
	for (int i=0 ; i<recipients.GetSize() ; i++)
	{
		// allocate space for properties
		MAPIAllocateBuffer(sizeof(SPropValue) * 2, 
		(LPVOID *) &(pAddressList->aEntries[i].rgPropVals) );

		pAddressList->aEntries[i].cValues = 2;
		pAddressList->aEntries[i].rgPropVals[0].ulPropTag = PR_DISPLAY_NAME;
		pAddressList->aEntries[i].rgPropVals[0].Value.lpszA = recipients[i]->sName.GetBuffer(recipients[i]->sName.GetLength());
		pAddressList->aEntries[i].rgPropVals[1].ulPropTag = PR_RECIPIENT_TYPE;
		recipients[i]->sName.ReleaseBuffer();
		switch (recipients[i]->eType)
		{
		case rtTO:
			pAddressList->aEntries[i].rgPropVals[1].Value.l = MAPI_TO;
			break;
		case rtCC:
			pAddressList->aEntries[i].rgPropVals[1].Value.l = MAPI_CC;
			break;
		case rtBCC:
			pAddressList->aEntries[i].rgPropVals[1].Value.l = MAPI_BCC;
			break;
		}
	}
	
// resolve the address
	hrRet = m_pAddressBook->ResolveName(0, 0, NULL, pAddressList);
	if (!FAILED(hrRet))
	{
		// set the recipients to the message
		hrRet = pMessage->ModifyRecipients(MODRECIP_ADD, pAddressList);
	}

	for (i=0 ; i<recipients.GetSize() ; i++)
		MAPIFreeBuffer(pAddressList->aEntries[i].rgPropVals);

	MAPIFreeBuffer(pAddressList);

	return hrRet;	
}

HRESULT COXSendMail::AddAttachments(LPMESSAGE pMessage, CAttachmentArray& attachments)
{
	HRESULT hrRet;
	UINT idx;
	LPTSTR szAttachment;
	
// if there are no attachments, just return
	if (attachments.GetSize() == 0)
		return 0;
	
	enum
	{ 
		REND_POS,
		PATH_NAME,
		ATT_METHOD,
		DISP_NAME,
		ATT_FILENAME,
		ATT_DIM
	};
	
	SizedSPropTagArray(ATT_DIM , sptAttachTags) =
	{ 
		ATT_DIM,
		{ 
			PR_RENDERING_POSITION, 
			PR_ATTACH_PATHNAME,
			PR_ATTACH_METHOD, 
			PR_DISPLAY_NAME, 
			PR_ATTACH_FILENAME 
		}
	};
	SPropValue spvAttachProps[ATT_DIM];
	
	
	CString sAttachment;

	for (int i=0 ; i<attachments.GetSize() ; i++)
	{
		sAttachment = attachments[i]->sPath;
		
		LPATTACH lpAttach = NULL;
		ULONG ulAttachNum = 0;
		
		hrRet = pMessage->CreateAttach(NULL, 0, &ulAttachNum, &lpAttach);
		if (FAILED(hrRet))
			return hrRet;
		
		for(idx = 0; idx < ATT_DIM; ++idx)
		{
			spvAttachProps[idx].ulPropTag = sptAttachTags.aulPropTag[idx];
			spvAttachProps[idx].dwAlignPad = 0;
		}
		
		
// Split the path of the attachment, so we can extract the filename
// to display under the attachment
		TCHAR pszDrive[_MAX_DRIVE];
		TCHAR pszSubdir[_MAX_DIR];
		TCHAR pszBaseName[_MAX_FNAME];
		TCHAR pszExtender[_MAX_EXT];
		TCHAR pszFileName[_MAX_FNAME + _MAX_EXT];
		
		szAttachment = sAttachment.GetBuffer(_MAX_PATH);

		_tsplitpath(szAttachment, pszDrive, pszSubdir, pszBaseName, pszExtender);
		_tmakepath(pszFileName, NULL, NULL, pszBaseName, pszExtender);
		
		spvAttachProps[REND_POS].Value.l = -1;
		spvAttachProps[PATH_NAME].Value.LPSZ = szAttachment;
		spvAttachProps[ATT_METHOD].Value.l = ATTACH_BY_REF_RESOLVE;
//		spvAttachProps[ATT_METHOD].Value.l = ATTACH_BY_VALUE;
		spvAttachProps[DISP_NAME].Value.LPSZ = pszFileName;
		spvAttachProps[ATT_FILENAME].Value.LPSZ = pszFileName;
		
		hrRet = lpAttach->SetProps(ATT_DIM, spvAttachProps, NULL);
		if (FAILED(hrRet))
		{
			sAttachment.ReleaseBuffer();
			return hrRet;
		}
		
		hrRet = lpAttach->SaveChanges(KEEP_OPEN_READWRITE);

		sAttachment.ReleaseBuffer();
		if (FAILED(hrRet))
			return hrRet;
		
		szAttachment = NULL;
		UlRelease(lpAttach);
	}
	
	return hrRet;
}

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.

Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
This is a Organisation

476 members

Comments and Discussions