Introduction
I had a project recently that required sending emails with HTML content. I found an article by PJ Naughter on CodeProject that provided a couple of nice classes from Microsoft that are included in the Visual Studio 8.0 (Visual Studio 2005) development package. These classes are CMimeMessage
and CSMTPConnection
. This article explains how to use these classes to easily send email messages.
I looked through the CMimeMessage
class to see if there was a way to use it without modification to send emails with HTML content and didn't see a clear path, but may be wrong. I searched the internet for a while and found that some others were asking the same question. I didn't find an answer.
So I decided to extend the CMimeMessage
class to add a function that would add Text as HMTL to the Mail Message. It turned out to be pretty simple and could be done inline.
The Code
The first thing that I had to do was to extend the CMimeText
class, as it has a function MakeMimeHeader
that is automatically called to generate the email header for the Mime Section that it represents. I named this class CMimeHtml
.
I just simply copied the MakeMimeHeader
function from the existing CMimeText
class. The only modification was to replace the Content-Type: text/plain
with Content-Type: text/html
:
virtual inline BOOL MakeMimeHeader(CStringA& header, LPCSTR szBoundary) throw()
{
char szBegin[256];
if (*szBoundary)
{
Checked::memcpy_s(szBegin, sizeof(szBegin),
ATLMIME_SEPARATOR, sizeof(ATLMIME_SEPARATOR));
Checked::memcpy_s(szBegin+6, sizeof(szBegin)-6, szBoundary,
ATL_MIME_BOUNDARYLEN);
*(szBegin+(ATL_MIME_BOUNDARYLEN+6)) = '\0';
}
else
{
Checked::memcpy_s(szBegin, sizeof(szBegin), ATLMIME_VERSION, sizeof(ATLMIME_VERSION));
}
_ATLTRY
{
header.Format("%s\r\nContent-Type:
text/html;\r\n\tcharset=\"%s\"\r\nContent-Transfer-Encoding:
8bit\r\n\r\n",
szBegin, m_szCharset);
return TRUE;
}
_ATLCATCHALL()
{
return FALSE;
}
}
The next step was to add a function to the CMimeMessage
class to add an HTML Mime section. So I called the function AddHtml
. I copied the code from the AddText
function of the existing CMimeMessage
class. I named this class CExtMimeMessage
.
The only modification here is to replace the CMimeText
class with our extended CMimeHtml
class:
inline BOOL
AddHtml(LPCTSTR szText, int nTextLen = -1, int
nPos = 1, UINT uiCodePage = 0) throw()
{
if (szText == NULL)
return FALSE;
if (nPos < 1)
{
nPos = 1;
}
CAutoPtr<CMimeBodyPart> spNewText;
CExtMimeHtml *pNewText = NULL;
ATLTRY(spNewText.Attach(pNewText = new CExtMimeHtml()));
if (!spNewText ||
!pNewText)
return FALSE;
BOOL bRet = pNewText->Initialize(szText, nTextLen, m_spMultiLanguage,
uiCodePage);
if (bRet)
{
_ATLTRY
{
POSITION currPos = m_BodyParts.FindIndex(nPos-1);
if (!currPos)
{
if
(!m_BodyParts.AddTail(spNewText))
bRet = FALSE;
}
else
{
if
(!m_BodyParts.InsertBefore(currPos, spNewText))
bRet = FALSE;
}
}
_ATLCATCHALL()
{
bRet = FALSE;
}
}
return bRet;
}
All done. All you have to do is copy in the included ExtMimeMessage.h file into your project, include "ExtMimeMessage.h", and use the CExtMimeMessage
class in exactly the same way that you would have used the original CMimeMessage
class.
I haven't seen any errors from using this class, but am open to all comments.
History
- 18th January, 2007: Initial post