|
|
/*++
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: erany@microsoft.com lpctstrTo [in] - To address (mandatory) e.g: erany@microsoft.com 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
|