Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

384 lines
12 KiB

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
mail.cpp
Abstract:
Implementation of mail related utility functions
Author:
Eran Yariv (EranY) Feb, 2000
Revision History:
--*/
#include <faxutil.h>
#pragma warning (disable:4146) // unary minus operator applied to unsigned type, result still unsigned
#include "msado15.tlh"
#include "cdosys.tlh"
#include <cdosysstr.h> // String constants in this file
#include <cdosyserr.h> // Error constants in this file
#pragma warning (default:4146) // unary minus operator applied to unsigned type, result still unsigned
#define SMTP_CONN_TIMEOUT (long)10 // Time out (sec) of SMTP connection
HRESULT
SendMail (
LPCTSTR lpctstrFrom,
LPCTSTR lpctstrTo,
LPCTSTR lpctstrSubject,
LPCTSTR lpctstrBody,
LPCTSTR lpctstrHTMLBody,
LPCTSTR lpctstrAttachmentPath,
LPCTSTR lpctstrAttachmentMailFileName,
LPCTSTR lpctstrServer,
DWORD dwPort, // = 25
CDO_AUTH_TYPE AuthType, // = CDO_AUTH_ANONYMOUS
LPCTSTR lpctstrUser, // = NULL
LPCTSTR lpctstrPassword, // = NULL
HANDLE hLoggedOnUserToken // = NULL
)
/*++
Routine name : SendMail
Routine description:
Sends a mail message using SMTP over CDO2.
Author:
Eran Yariv (EranY), Feb, 2000
Arguments:
lpctstrFrom [in] - From address (mandatory)
e.g: [email protected]
lpctstrTo [in] - To address (mandatory)
e.g: [email protected]
lpctstrSubject [in] - Subject (optional)
lpctstrBody [in] - Body text of message (optional).
If NULL, the message will not have a body.
lpctstrHTMLBody [in] - HTML Body text of message (optional).
If NULL, the message will not have a HTML body.
lpctstrAttachmentPath [in] - Full path to file to attach (optional)
If NULL, the message will not include attachments.
lpctstrAttachmentMailFileName [in] - The file name of the attachment as is will appear in the mail message.
lpctstrServer [in] - SMTP server to connect to (mandatory)
e.g: hai-msg-01
dwPort [in] - SMTP port (optional, default = 25)
AuthType [in] - Type of SMTP authentication.
Valid values are CDO_AUTH_ANONYMOUS, CDO_AUTH_BASIC,
and CDO_AUTH_NTLM.
lpctstrUser [in] - User to authenticate
In use only if AuthType is CDO_AUTH_BASIC or CDO_AUTH_NTLM.
lpctstrPassword [in] - Password to authenticate
In use only if AuthType is CDO_AUTH_BASIC or CDO_AUTH_NTLM.
hLoggedOnUserToken [in] - Handle to alogged on user token.
In use only if AuthType is CDO_AUTH_NTLM.
Return Value:
Standard HRESULT code
--*/
{
DEBUG_FUNCTION_NAME(TEXT("SendMail"))
Assert (lpctstrFrom && lpctstrTo && lpctstrServer);
HRESULT hr = NOERROR;
Assert ((CDO_AUTH_ANONYMOUS == AuthType) ||
(CDO_AUTH_BASIC == AuthType) ||
(CDO_AUTH_NTLM == AuthType));
BOOL bImpersonated = FALSE;
hr = CoInitialize(NULL);
if (S_FALSE == hr)
{
//
// Thread's COM already initialized.
// This is not an error and we still have to call CoUninitialize at the end.
//
hr = NOERROR;
}
if (FAILED(hr))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("CoInitialize failed. (hr: 0x%08x)"),
hr);
return hr;
}
try
{
//
// The following code is in a seperate block so that the auto pointers dtors
// get called before CoUninitialize
//
//
// Create a new message instance (can throw exception)
//
IMessagePtr iMsg(__uuidof(Message));
//
// Create a new CDO2 configuration instance (can throw exception)
IConfigurationPtr iConf(__uuidof(Configuration));
//
// Access configuration fields collection
//
FieldsPtr Flds;
Flds = iConf->Fields;
//
// Send the message using the network. (SMTP protocol over the network)
//
Flds->Item[cdoSendUsingMethod]->Value = _variant_t((long)cdoSendUsingPort);
//
// Define SMTP server
//
Flds->Item[cdoSMTPServer]->Value = _variant_t(lpctstrServer);
//
// Define SMTP port
//
Flds->Item[cdoSMTPServerPort]->Value = _variant_t((long)dwPort);
//
// Define SMTP connection timeout (in seconds)
//
Flds->Item[cdoSMTPConnectionTimeout]->Value = _variant_t(SMTP_CONN_TIMEOUT);
//
// Make sure we don't used cached info for attachments
//
Flds->Item[cdoURLGetLatestVersion]->Value = _variant_t(VARIANT_TRUE);
//
// Choose authentication method
//
switch (AuthType)
{
case CDO_AUTH_ANONYMOUS:
Flds->Item[cdoSMTPAuthenticate]->Value = _variant_t((long)cdoAnonymous);
break;
case CDO_AUTH_BASIC:
Flds->Item[cdoSMTPAuthenticate]->Value = _variant_t((long)cdoBasic);
Flds->Item[cdoSendUserName]->Value = _variant_t(lpctstrUser);
Flds->Item[cdoSendPassword]->Value = _variant_t(lpctstrPassword);
break;
case CDO_AUTH_NTLM:
//
// NTLM authentication required the calling client (that's us)
// to impersonate the user
//
Flds->Item[cdoSMTPAuthenticate]->Value = _variant_t((long)cdoNTLM);
break;
default:
ASSERT_FALSE;
}
//
// Update configuration from the fields
//
Flds->Update();
//
// Store configuration in the message
//
iMsg->Configuration = iConf;
//
// Set recipient
//
iMsg->To = lpctstrTo;
//
// Set sender
//
iMsg->From = lpctstrFrom;
//
// Set subject
//
iMsg->Subject = lpctstrSubject;
//
// Set message format to MIME
//
iMsg->MimeFormatted = _variant_t(VARIANT_TRUE);
//
// Set charset to Unicode (UTF-8)
//
iMsg->BodyPart->Charset = "utf-8";
iMsg->BodyPart->ContentTransferEncoding = "base64";
IBodyPartPtr iBp;
//
// Get message body root
//
iBp = iMsg;
//
// Set content type fo mixed to support both body and attachment
//
iBp->ContentMediaType = "multipart/mixed; charset=""utf-8""";
if (lpctstrBody)
{
//
// Add body text
//
IBodyPartPtr iBp2;
_StreamPtr Stm;
//
// Add text body under root
//
iBp2 = iBp->AddBodyPart(-1);
//
// Use text format
//
iBp2->ContentMediaType = "text/plain";
//
// Set charset to Unicode (UTF-8)
//
iBp2->Charset = "utf-8";
iBp2->ContentTransferEncoding = "base64";
//
// Get body text stream
//
Stm = iBp2->GetDecodedContentStream();
//
// Write stream text
//
Stm->WriteText(lpctstrBody, adWriteChar);
Stm->Flush();
}
if (lpctstrHTMLBody)
{
//
// Set content type to alternative to support both plain text body and HTML body
// If an attachment is added afterwards, the ContentMediaType is automatically set
// to mixed and the multipart/alternative is moved to new sub-BodyPart.
//
iBp->ContentMediaType = "multipart/alternative; charset=""utf-8""";
IBodyPartPtr iBp2;
_StreamPtr Stm;
//
// Add html body under root
//
iBp2 = iBp->AddBodyPart(-1);
//
// Use html format
//
iBp2->ContentMediaType = "text/html";
//
// Set charset to Unicode (UTF-8)
//
iBp2->Charset = "utf-8";
iBp2->ContentTransferEncoding = "base64";
//
// Get body html stream
//
Stm = iBp2->GetDecodedContentStream();
//
// Write stream html
//
Stm->WriteText(lpctstrHTMLBody, adWriteChar);
Stm->Flush();
}
if (lpctstrAttachmentPath)
{
//
// Add attachment
//
IBodyPartPtr iBpAttachment;
iBpAttachment = iMsg->AddAttachment(lpctstrAttachmentPath, TEXT(""), TEXT(""));
iBpAttachment->ContentMediaType = "image/tif";
if (lpctstrHTMLBody)
{ // The multipart/alternative section was moved to sub-bodypart and
// the main ContentMediaType was moved with it so now we restore it.
iBp->ContentMediaType = "multipart/mixed; charset=""utf-8""";
}
if (lpctstrAttachmentMailFileName)
{
//
// User wishes to rename attachment in the mail message
//
FieldsPtr Flds = iBpAttachment->Fields;
_bstr_t bstrContentType = iBpAttachment->ContentMediaType +
TEXT("; name=\"") +
lpctstrAttachmentMailFileName +
TEXT("\"");
Flds->Item[cdoContentType]->Value = _variant_t(bstrContentType);
Flds->Update();
Flds->Resync(adResyncAllValues);
}
}
if (CDO_AUTH_NTLM == AuthType)
{
//
// We impersonate the user in the NTLM authentication mode.
// This is the last thing we do just before sending the message.
//
Assert (hLoggedOnUserToken);
if (!ImpersonateLoggedOnUser (hLoggedOnUserToken))
{
hr = HRESULT_FROM_WIN32(GetLastError());
DebugPrintEx(
DEBUG_ERR,
TEXT("ImpersonateLoggedOnUser failed. (hr: 0x%08x)"),
hr);
goto exit;
}
bImpersonated = TRUE;
}
//
// Finally - send the message
//
iMsg->Send();
}
catch (_com_error &er)
{
//
// Error in CDO2
//
hr = er.Error ();
DebugPrintEx(
DEBUG_ERR,
TEXT("CDO2 Error 0x%08x: to:%s, subject:%s")
#ifdef UNICODE
TEXT(" Description:%s")
#endif
,hr,
lpctstrTo,
lpctstrSubject
#ifdef UNICODE
,(LPCTSTR)er.Description()
#endif
);
}
exit:
CoUninitialize();
if (bImpersonated)
{
if (!RevertToSelf ())
{
hr = HRESULT_FROM_WIN32(GetLastError());
DebugPrintEx(
DEBUG_ERR,
TEXT("RevertToSelf failed. (hr: 0x%08x)"),
hr);
}
}
return hr;
} // SendMail