Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / ATL

Send HTML Via SMTP By Extending CMimeMessage

3.18/5 (6 votes)
18 Jan 2007CPOL2 min read 1   299  
Extending the CMimeMessage class to send HTML messages

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:

C++
// This function is a copy of the CMimeText::MakeMimeHeader function. It has been
// updated to change the Content-Type text/html rather than text/plain.
//
// Make the MIME header
virtual inline BOOL MakeMimeHeader(CStringA& header, LPCSTR szBoundary) throw()
{
char szBegin[256];
if (*szBoundary)
{
// this is not the only body part

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
{
// this is the only body part, so output the full MIME header
Checked::memcpy_s(szBegin, sizeof(szBegin), ATLMIME_VERSION, sizeof(ATLMIME_VERSION));
}
_ATLTRY
{
// Here you can see that the Content-Type is text/html instead of text/plain. This is
// the only thing that makes the email message come out as text or html is this
// Content-Type marker that is written in the section header.
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:

C++
// Pretty much taken from the Microsoft CMimeMessage::AddText function.
// The only difference is that we add a CMimeHtml class to the BodyParts
// list instead of a CMimeText class.
//
// Add some text to the message at position nPos in the body parts list
// szText - the text
// nTextLen - the size of the text in bytes 
// (optional - if not specified a _tcslen will be done)
// nPos - the position in the message at which to insert the text (optional)
// uiCodePage - the codepage (optional)

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;
// Note that we are simply using the CExteMimeHtml Class (Extended CMimeText)
// The extended part is that the MakeMimeHeader function makes the Content-Type
// text/html instead of text/plain

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

License

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