Posts 1 - 10 of 11
First | Prev. | 1 2 | Next | Last
|
|
Brad Smith
Posts: 49
Joined: 2005-11-22
|
I've been away from the forums for a while, and realized with horror that I'd failed to send in the code fragments I promised earlier covering how to add an SMTP X-Header to an outgoing message. The following is going to be a bit disjointed but hopefully can be "converted" to real code.
This is C++ code, with a few bits stripped out. Apologies in advance for formatting problems below:
// Undocumented "magic" GUID that lets us set X-Header values in outgoing SMTP headers
// Supported in OL2000 and above
GUID CLSID_X_Headers = { 0x00020386, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
SCODE CMsgHelper::SetSMTPXHeader(LPMESSAGE pMessage, LPCSTR szHeaderName, LPCSTR szValue)
{
MAPINAMEID NamedProp;
NamedProp.ulKind = MNID_STRING;
MAPINAMEID* pNamedProp = &NamedProp;
LPSPropTagArray lpTags = 0;
// The name needs to be a wide character, so do a simple conversion
wchar_t* pcwPropName = new wchar_t[(strlen(szHeaderName)+1)*2];
memset(pcwPropName, 0, sizeof(pcwPropName));
mbstowcs(pcwPropName, szHeaderName, strlen(szHeaderName)+1);
// Get/Create our named properly, then set the value
// Since this is going in a mail header, we want to make it a human-readable
// string value, but something that can easily be parsed on receipt.
NamedProp.lpguid = (LPGUID)&CLSID_X_Headers;
NamedProp.Kind.lpwstrName = pcwPropName;
hr = ((LPMAPIPROP)(IUnknown*)pMessage)->GetIDsFromNames( 1, &pNamedProp, MAPI_CREATE, &lpTags);
delete [] pcwPropName;
if(S_OK == hr && NULL != lpTags )
{
ULONG ulPropTag = lpTags->aulPropTag[0];
SPropValue prop;
prop.ulPropTag = PROP_TAG(PT_STRING8,PROP_ID(ulPropTag));
prop.Value.LPSZ = (LPSTR)szValue;
hr = HrSetOneProp((LPMAPIPROP)(IUnknown*)pMessage, &prop );
MAPIFreeBuffer(lpTags);
}
return hr;
}
You'd call this something like:
red
This sets a "magic" named property which, when Outlook or Exchange formats the message for SMTP transit, adds a line like:
x-my-header=My String
Note that the name is lowercased. This is a known bug/limitation. Since SMTP headers are expected to be case-insensitive, this isn't much of an issue.
Also note that Outlook/Exchange does absolutely *no* syntax checking. So if' you're not careful, you can render the message unreadable.
More to follow...
|
|
Posted 20 Apr, 2006 11:31:53
|
|
Top
|
|
Brad Smith
Posts: 49
Joined: 2005-11-22
|
Within an Exchange environment (ie. not sent via the Internet), you can read back this named property using MAPI again:
std::string CMsgHelper::GetSMTPXHeader(LPMESSAGE pMessage, LPCSTR szHeaderName)
{
std::string strTmp;
std::string strValue;
// Attempt to get direct from MAPI first. If that fails, then we'll have
// to parse the SMTP headers.
MAPINAMEID NamedProp;
NamedProp.ulKind = MNID_STRING;
MAPINAMEID* pNamedProp = &NamedProp;
LPSPropTagArray lpTags = 0;
// The name needs to be a wide character, so do a simple conversion
wchar_t* pcwPropName = new wchar_t[(strlen(szHeaderName)+1)*2];
memset(pcwPropName, 0, sizeof(pcwPropName));
mbstowcs(pcwPropName, szHeaderName, strlen(szHeaderName)+1);
NamedProp.lpguid = (LPGUID)&CLSID_X_Headers;
NamedProp.Kind.lpwstrName = pcwPropName;
HRESULT hr = ((LPMAPIPROP)(IUnknown*)pMessage)->GetIDsFromNames( 1, &pNamedProp, 0, &lpTags);
delete [] pcwPropName;
if(S_OK == hr && NULL != lpTags )
{
// and now the value
ULONG ulPropTag = lpTags->aulPropTag[0];
SPropValue* pProp = NULL;
hr = HrGetOneProp((LPMAPIPROP)(IUnknown*)pMessage, PROP_TAG(PT_STRING8, PROP_ID(ulPropTag)), &pProp );
if(SUCCEEDED(hr) && PROP_TYPE(pProp->ulPropTag) == PT_STRING8)
{
strValue = pProp->Value.LPSZ;
}
MAPIFreeBuffer(lpTags);
}
return strValue;
}
If the above doesn't return anything, then you reset to grabbing the PR_TRANSPORT_MESSAGE_HEADERS MAPI property, which returns the entire SMTP header blob, and parse out your desired header line (remember, case-insensitive).
I hope this helps, and humble apologies for the delay in getting this out. Now I just get to sit back and wait for somebody to port to C# for me. :-)
Brad. |
|
Posted 20 Apr, 2006 11:42:53
|
|
Top
|
|
Sergey Grischenko
Add-in Express team
Posts: 7233
Joined: 2004-07-05
|
Hi Brad.
Thank you very much for the code. I will try to rewrite it in C#. |
|
Posted 20 Apr, 2006 12:04:32
|
|
Top
|
|
nistech
Posts: 30
Joined: 2005-09-04
|
Thanks! I look forward to the conversion Sergey. |
|
Posted 22 Apr, 2006 01:26:01
|
|
Top
|
|
Sergey Grischenko
Add-in Express team
Posts: 7233
Joined: 2004-07-05
|
|
Posted 26 Apr, 2006 11:33:46
|
|
Top
|
|
nistech
Posts: 30
Joined: 2005-09-04
|
Thanks! I'll take a look. |
|
Posted 26 Apr, 2006 12:26:13
|
|
Top
|
|
Esteban Astudillo
Guest
|
This is great!!
Thank you Brad and Sergey!
I will post here later my results using this code.
|
|
Posted 26 Apr, 2006 13:52:49
|
|
Top
|
|
Jim Kimbrough
Posts: 17
Joined: 2006-02-13
|
Regarding the sample code posted above:
When this code calls SetHeader()...
Outlook._MailItem mitem = item as Outlook._MailItem;
mitem.Save();
SetHeader(mitem.MAPIOBJECT,"x-xyz-header","xyz-xyz");
In the function SetHeader...
private void SetHeader(object itemObj, string headerName, string _value)
{
IMAPIProp mail = null
mail = itemObj as IMAPIProp;
if (mail != null)
.
.
.
ItemObj receives an object argument, but "mail" is always null after itemObj is assigned as IMAPIProp.
What do I need to do to get a successful object assignment to "mail"?
Thank you.
|
|
Posted 05 May, 2006 11:18:48
|
|
Top
|
|
Sergey Grischenko
Add-in Express team
Posts: 7233
Joined: 2004-07-05
|
Hi Jim.
It is very strange. The fact is that the mitem.MAPIOBJECT always returns IMAPIProp interface if the mitem field is an Outlook item.
Didn't you change the code of the example?
|
|
Posted 05 May, 2006 11:53:25
|
|
Top
|
|
Jim Kimbrough
Posts: 17
Joined: 2006-02-13
|
Yes, I moved the relevant portions of your sample code, and your references, with new GUIDs, into another project for x-header testing.
It builds. It runs. But this argument always goes to null when assigned to the IMAPIProp mail object. Maybe an interop or duplicate reference problem. I will experiment with alternate references and see if I can raise some other symptom.
Any thoughts about which reference might be at issue? Seems odd since the IMAPIProp interface is specified right in the code.
Thank you, Sergey.
Jim
|
|
Posted 05 May, 2006 13:38:18
|
|
Top
|
|
Posts 1 - 10 of 11
First | Prev. | 1 2 | Next | Last
|