Platform SDK: SMTP Server Events |
[This is preliminary documentation and subject to change.]
This file contains the implementation for all the exposed CSink interfaces.
#include "stdafx.h" #include "ShieldsUp.h" #include "Sink.h" #define DEFAULT_RESPONSE "Please Try Again Later." ///////////////////////////////////////////////////////////////////////////// // CSink /* ** ISmtpInCommandSink */ STDMETHODIMP CSink::OnSmtpInCommand( IUnknown *pServer, IUnknown *pSession, IMailMsgProperties *pMsg, ISmtpInCommandContext *pContext) { HRESULT hr = S_OK; if(pContext == NULL) return E_POINTER; char* pszResponse = NULL; long lResponseLength = strlen(g_szResponseText); pszResponse = (char*) CoTaskMemAlloc(g_dwResponseSize); strcpy(pszResponse,g_szResponseText); pszResponse[g_dwResponseSize-1] = '\0'; hr = pContext->SetResponse(pszResponse, g_dwResponseSize); if(FAILED(hr)) return hr; hr = pContext->SetCommandStatus(EXPE_DROP_SESSION); if(FAILED(hr)) return hr; // Success. // Notify the dispatcher that we have // consummed the event. // No other sinks will run, and // the connection will be dropped. return EXPE_S_CONSUMED; } /* ** IPersistPropertyBag : IPersist */ STDMETHODIMP CSink::GetClassID(CLSID *pClassID) { return S_OK; } STDMETHODIMP CSink::InitNew(void) { return S_OK; } STDMETHODIMP CSink::Load(IPropertyBag* pBag,IErrorLog *pErrorLog) { if(pBag == NULL) return E_POINTER; if(g_fHaveCustomText) return S_OK; ATLASSERT(pBag); HRESULT hr = S_OK; CComVariant varVal; hr = pBag->Read(L"ResponseText",&varVal,pErrorLog); if(FAILED(hr)) return S_OK; // There's no custom text /* ** We have some custom text */ UINT uiResponseLength = SysStringLen(varVal.bstrVal); char* temp = NULL; temp = new char[uiResponseLength + 1]; if(temp == NULL) return E_OUTOFMEMORY; if(wcstombs(temp,varVal.bstrVal,uiResponseLength+1) == NULL) { delete [] temp; return E_OUTOFMEMORY; } if(g_szResponseText != NULL) delete [] g_szResponseText; g_szResponseText = temp; g_szResponseText[uiResponseLength] = '\0'; g_dwResponseSize = uiResponseLength + 1; g_fHaveCustomText = true; return S_OK; } STDMETHODIMP CSink::Save( IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties) { return S_OK; } /* ** Oddly enough, the most involved code for this example ** is where we register and unregister the event sink bindings. ** What's going on is very simple. We have to add a binding ** to the appropriate source in the SEO database. ** SEO is ole-automation compatible, so much of this code ** mirrors much simpler code using vbscript. ** The hierarchy of SEO objects is as follows: ** ** EventManager ** SourceTypes ** SourceType ** Sources ** Source ** Bindings ** Binding <--- Adding another of these ** SinkProperties ** SourceProperties ** */ STDMETHODIMP CSink::RegisterSink(long lInstance, BSTR DisplayName, BSTR BindingGUID, BSTR ResponseText, VARIANT_BOOL fEnabled, BSTR* OutBindingGUID) { IEventManager* pEvtMan = NULL; IEventUtil* pEvtUtil = NULL; IEventSourceTypes* pSrcTypes = NULL; IEventSourceType* pSrcType = NULL; IEventSources* pSrcs = NULL; IEventSource* pSrc = NULL; IEventBindingManager* pBindingMan = NULL; IEventBindings* pBindings = NULL; IEventBinding* pBinding = NULL; IEventPropertyBag* pSourceProps = NULL; IEventPropertyBag* pSinkProps = NULL; HRESULT hr = S_OK; BSTR bstrSourceGUID; hr = CoCreateInstance(__uuidof(CEventUtil), NULL, CLSCTX_INPROC_SERVER, __uuidof(IEventUtil), (void**)&pEvtUtil); // Get the Source GUID for the SMTP Server Instance hr = pEvtUtil->GetIndexedGUID(CComBSTR(g_szGuidSmtpSvcSource),lInstance,&bstrSourceGUID); if(FAILED(hr)) { pEvtUtil->Release(); return hr; } // Use the EventManager to create the binding hr = CoCreateInstance(__uuidof(CEventManager), NULL, CLSCTX_INPROC_SERVER, __uuidof(IEventManager), (void**)&pEvtMan); if(FAILED(hr)) return hr; hr = E_FAIL; if(SUCCEEDED(pEvtMan->get_SourceTypes(&pSrcTypes))) { if(SUCCEEDED(pSrcTypes->Item(&CComVariant(g_szGuidSmtpSourceType),&pSrcType))) { if(SUCCEEDED(pSrcType->get_Sources(&pSrcs))) { if(SUCCEEDED(pSrcs->Item(&CComVariant(bstrSourceGUID),&pSrc))) { if(SUCCEEDED(pSrc->GetBindingManager(&pBindingMan))) { if(SUCCEEDED(pBindingMan->get_Bindings(CComBSTR(g_szcatidSmtpOnInboundCommand),&pBindings))) { // BindingGUID was passed by the caller hr = pBindings->Add(BindingGUID,&pBinding); if(SUCCEEDED(hr)) { // error checking is omitted for clarity. // each result _should_ be checked // but these work most of the time pBinding->put_SinkClass(CComBSTR("ShieldsUp.Sink")); pBinding->put_DisplayName(DisplayName); pBinding->put_Enabled(fEnabled); // Source Properties pBinding->get_SourceProperties(&pSourceProps); // Rule is: EHLO command (all) pSourceProps->Add(CComBSTR("Rule"),&CComVariant("ehlo")); // highest prio pSourceProps->Add(CComBSTR("Priority"),&CComVariant((long) 0)); pSourceProps->Release(); // Sink Properties pBinding->get_SinkProperties(&pSinkProps); pSinkProps->Add(CComBSTR("ResponseText"),&CComVariant(ResponseText)); hr = pBinding->Save(); // If the caller did not specify a GUID, we return it. // If they did, we return it anyway hr = pBinding->get_ID(OutBindingGUID); pSinkProps->Release(); pBinding->Release(); } pBindings->Release(); } pBindingMan->Release(); } pSrc->Release(); } pSrcs->Release(); } pSrcType->Release(); } pSrcTypes->Release(); } pEvtMan->Release(); ATLASSERT(SUCCEEDED(hr)); return S_OK; } STDMETHODIMP CSink::UnRegisterSink(long lInstance, BSTR BindingGUID) { IEventManager* pEvtMan = NULL; IEventUtil* pEvtUtil = NULL; IEventSourceTypes* pSrcTypes = NULL; IEventSourceType* pSrcType = NULL; IEventSources* pSrcs = NULL; IEventSource* pSrc = NULL; IEventBindingManager* pBindingMan = NULL; IEventBindings* pBindings = NULL; IEventBinding* pBinding = NULL; HRESULT hr = S_OK; BSTR bstrSourceGUID; hr = CoCreateInstance(__uuidof(CEventUtil), NULL, CLSCTX_INPROC_SERVER, __uuidof(IEventUtil), (void**)&pEvtUtil); // Get the Source GUID for the SMTP Server Instance hr = pEvtUtil->GetIndexedGUID(CComBSTR(g_szGuidSmtpSvcSource),lInstance,&bstrSourceGUID); if(FAILED(hr)) { pEvtUtil->Release(); return hr; } pEvtUtil->Release(); // Use the EventManager to create the binding hr = CoCreateInstance(__uuidof(CEventManager), NULL, CLSCTX_INPROC_SERVER, __uuidof(IEventManager), (void**)&pEvtMan); if(FAILED(hr)) return hr; hr = E_FAIL; if(SUCCEEDED(pEvtMan->get_SourceTypes(&pSrcTypes))) { if(SUCCEEDED(pSrcTypes->Item(&CComVariant(g_szGuidSmtpSourceType),&pSrcType))) { if(SUCCEEDED(pSrcType->get_Sources(&pSrcs))) { if(SUCCEEDED(pSrcs->Item(&CComVariant(bstrSourceGUID),&pSrc))) { if(SUCCEEDED(pSrc->GetBindingManager(&pBindingMan))) { if(SUCCEEDED(pBindingMan->get_Bindings(CComBSTR(g_szcatidSmtpOnInboundCommand),&pBindings))) { hr = pBindings->Remove(&CComVariant(BindingGUID)); pBindings->Release(); } pBindingMan->Release(); } pSrc->Release(); } pSrcs->Release(); } pSrcType->Release(); } pSrcTypes->Release(); } pEvtMan->Release(); return hr; }