SMTP EnvelopeFields Code Example
SMTP EnvelopeFields Code Example
The following code example can be used only with Simple Mail Transfer Protocol (SMTP) OnArrival event sinks. The IMessage.EnvelopeFields property returns an empty collection in all cases except for a Message object reference passed to a sink during a transport event.
For the purposes of illustration, the example code performs the following tasks:
- Checks the subject of the message. If the subject is equal to ---BAD MESSAGE---, it sets the messagestatus field to cdoStatAbortDelivery to block delivery. It also sets the EventStatus parameter (in the OnArrival event sink) to the event call equal to cdoSkipRemainingSinks, so that the event dispatcher does not notify remaining sinks of the message’s arrival.
- If the recipientlist envelope field is equal to distributionlist@example.com, the recipientlist field is expanded (replaced) with a hypothetical list, namely example@example.com and example2@example.com.
- Writes a log file entry to disk that contains the envelope fields for the message, after the dynamic-link library (DLL) has expanded, along with the message stream, which is retrieved using IMessage.GetStream. This is to allow inspection of the fields and the message stream after the message is sent and to verify that everything is working correctly.
Example
Implements IEventIsCacheable
Implements ISMTPOnArrival
Private Sub IEventIsCacheable_IsCacheable()
' just return S_OK which means do nothing!
' Object will be cached for subsequent use
End Sub
Sub ISMTPOnArrival_OnArrival(ByVal iMsg as CDO.Message, EventStatus as CdoEventStatus)
Dim RecipListFld as ADODB.Field
Dim Fld as ADODB.Field
Dim Flds as ADODB.Fields
Dim strOutPut as String
Set Flds = iMsg.EnvelopeFields
if iMsg.Subject = "---BAD MESSAGE---" Then Flds("https://schemas.microsoft.com/cdo/smtpenvelope/messagestatus") = cdoStatAbortDelivery
Flds.Update ' must call update to commit changes to fields
EventStatus = cdoSkipRemainingSinks
strOutPut = "Aborted delivery of this message:" & vbCrLf
strOutPut = strOutPut & "Envelope Fields: " & vbCrLf
For Each Fld in Flds
strOutPut = strOutPut & "------" & vbCrLf
strOutPut = strOutPut & "Name: " & Fld.Name & vbCrLf
strOutPut = strOutPut & "Value: " & Fld.Value & vbCrLf
Next Fld
strOutPut = "Message was: " & vbCrL
Dim Strm as ADODB.Stream
Set Strm = iMsg.GetStream
strOutPut = strOutPut & Strm.ReadText & vbCrLf & vbCrLf
Else
Dim strRecipList as String
Set RecipListFld = Flds("https://schemas.microsoft.com/cdo/smtpenvelope/recipientlist")
strRecipList = RecipListFld.Value
If strRecipList = "distributionlist@example.com" Then
' Do DL expansion here
strRecipList = "SMTP:example@example.com;SMTP:example2@example.com;"
RecipListFld.Value = strRecipList
Flds.Update ' must call update to commit changes to fields
strOutPut = "Expanded DL distributionlist@example.com" & vbCLf
strOutPut = "Envelope Fields: " & vbCrLf
For Each Fld in Flds
strOutPut = strOutPut & "------" & vbCrLf
strOutPut = strOutPut & "Name: " & Fld.Name & vbCrLf
strOutPut = strOutPut & "Value: " & Fld.Value & vbCrLf
Next Fld
strOutPut = "Message was: " & vbCrLf
Dim Strm as ADODB.Stream
Set Strm = iMsg.GetStream
strOutPut = strOutPut & Strm.ReadText & vbCrLf & vbCrLf
End If
End If
Dim FS as New Scripting.FileSystemObject
Dim File as Scripting.TextStream
Set File = FS.CreateTextFile("c:\envelopefieldlog\fields.log",True,False)
File.Write strOutPut
End Sub
#include "resource.h" // main symbols
#import <msado15.dll> no_namespace raw_interfaces_only
#import <cdosys.dll> no_namespace raw_interfaces_only
#import <seo.dll> no_namespace raw_interfaces_only
/////////////////////////////////////////////////////////////////////////////
// CSink1
class ATL_NO_VTABLE CSink1 :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CSink1, &CLSID_Sink1>,
public IDispatchImpl<ISMTPOnArrival, &__uuidof(ISMTPOnArrival), &LIBID_TRANSSINKEXLib>
{
public:
CSink1()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_SINK1)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CSink1)
COM_INTERFACE_ENTRY(ISMTPOnArrival)
COM_INTERFACE_ENTRY(IEventIsCacheable)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
// ISink1
public:
STDMETHOD(IsCacheable)() { return S_OK;}
STDMETHOD(OnArrival)(IMessage* pMsg,CdoEventStatus* pStat);
};
// these are in cdosysstr.h and cdoexstr.h
const BSTR cdoRecipientList = L"https://schemas.microsoft.com/cdo/smtpenvelope/recipientlist";
const BSTR cdoMessageStatus =L"https://schemas.microsoft.com/cdo/smtpenvelope/messagestatus";
HRESULT CSink1::OnArrival(IMessage* pMsg,CdoEventStatus* pStat) {
CComPtr<Field> pField;
CComPtr<Fields> pFields;
CComPtr<Field> pDL;
HRESULT hr = pMsg->get_EnvelopeFields(&pFields);
CComBSTR bstrSubject;
hr = pMsg->get_Subject(&bstrSubject);
CComBSTR bstrOutPut = "This is a start of an entry here \r\n";
//
// check the subject for ---BAD MESSAGE---
// note that this is for illustration only ;-)
// if we have ---BAD MESSAGE---,
// * set the pStat arg to CdoSkipRemainingSinks
// * set the messagestatus field to cdoStatAbortDeliver
// * write the log entry
//
if(bstrSubject == CComBSTR("---BAD MESSAGE---")){
*pStat = cdoSkipRemainingSinks;
CComPtr<Field> pFldMsgStatus;
pFields->get_Item(CComVariant(CComBSTR(cdoMessageStatus)),&pFldMsgStatus);
pFldMsgStatus->put_Value(CComVariant((long)cdoStatAbortDelivery));
hr = pFields->Update();
if(FAILED(hr))
return hr;
//assert(SUCCEEDED(hr));
bstrOutPut += " got a ---BAD MESSAGE--- here: \r\n";
CComPtr<_Stream> pStrm;
hr = pMsg->GetStream(&pStrm);
if(FAILED(hr))
return hr;
CComBSTR bstrStreamData;
hr = pStrm->ReadText(-1,&bstrStreamData);
if(FAILED(hr))
return hr;
bstrOutPut += bstrStreamData;
}
// check for the address SMTP:distributionlist@example.com
// if this is the recipient list,
// * replace with
// "SMTP:example@example.com;SMTP:example2@example.com;"
// * write log file
//
else {
hr = pFields->get_Item(CComVariant(cdoRecipientList),&pField);
CComVariant varRecipName;
hr = pField->get_Value(&varRecipName);
if(FAILED(hr)) {
bstrOutPut += "error getting value for recipientlist\r\n";
goto writelog;
}
CComBSTR name = varRecipName.bstrVal;
if(name == CComBSTR("SMTP:distributionlist@example.com;")) {
hr = S_OK;
CComVariant varDL = "SMTP:example@example.com;SMTP:example2@example.com;";
hr = pField->put_Value(varDL);
if(FAILED(hr)) {
bstrOutPut += "error putting recpientlist value\r\nhr= ";
bstrOutPut.Append(CComBSTR(hr));
bstrOutPut += "\r\n";
goto writelog;
}
hr = pFields->Update();
bstrOutPut += "Updated distlist: \r\n";
CComPtr<_Stream> pStrm;
hr = pMsg->GetStream(&pStrm);
if(FAILED(hr))
return hr;
CComBSTR bstrStreamData;
hr = pStrm->ReadText(-1,&bstrStreamData);
if(FAILED(hr))
return hr;
bstrOutPut += bstrStreamData;
}
}
writelog:
LPCWSTR szFilename = L"c:\\logs\\events.txt";
HANDLE hFile;
int nBufSize = 0;
ULONG nSizeWritten = 0 ;
BOOL fRC = FALSE;
hFile=CreateFileW(szFilename,
GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE| FILE_SHARE_DELETE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
return E_POINTER;
SetFilePointer(hFile,0,NULL,FILE_END);
nBufSize = lstrlenW(bstrOutPut);
fRC = WriteFile(hFile,bstrOutPut,nBufSize * 2,&nSizeWritten,NULL);
if(fRC == FALSE)
return S_FALSE;
CloseHandle(hFile);
return S_OK;
}