设为首页 收藏本站
查看: 649|回复: 0

[经验分享] Exchange Custom Field

[复制链接]

尚未签到

发表于 2015-9-11 09:10:17 | 显示全部楼层 |阅读模式
  Frequently Asked Questions
  --------------------------------------------------------------------------------
  This topic covers the most frequently asked questions about programming with Microsoft? Exchange 2000 Server.
  Messaging and CDO for Exchange
Why do I get an 0x80040220 error when using cdoSendUsingPickup?
  What's the difference between the IBodyPart.BodyParts collection and the IMessage.Attachments collection on a Message object?
  Why can't I write text to the Stream object of a newly added BodyPart object using _Stream::WriteText?
  How do I set message headers on Message or BodyPart objects when there aren't properties for them?
  How can CDO objects expose multiple dual interfaces?
  Why do I get an 0x80040220 error when using cdoSendUsingPickup?
When using Exchange 2000 Server SP3 or later, you may encounter the following error when using cdoSendUsingPickup:
  CDO.Message.1 (0x80040220)
The "SendUsing" configuration value is invalid.
In Exchange 2000 Server SP3 and later versions, default read access to the Microsoft Internet Information Services (IIS) metabase is restricted. To avoid getting this error, you need to either specify the pickup directory in your code, or run your application under an account that has read access to the metabase. For more information, see Specifying the Pickup Directory.
  What's the difference between the IBodyPart.BodyParts collection and the IMessage.Attachments collection on a Message object?
Although both the IBodyPart.BodyParts and IMessage.Attachments properties return IBodyParts interfaces on collection objects, the objects contained within each collection normally differ. For messages that are encoded as Multipurpose Internet Mail Extensions (MIME), a good rule of thumb is that all body parts with content-disposition set to "attachment" are returned in the IMessage.Attachments collection. Depending on the complexity of the MIME structure, these body parts can exist deep in the body part hierarchy. The IBodyPart.BodyParts collection, on the other hand, contains only that object's immediate child BodyPart objects.
  For example, a common MIME structure is expressed in the diagram below as a BodyPart hierarchy below the Message object, labeled A. Each object is designated with a letter; appropriate mail header fields are listed in each box representing an object:
  A <--- content-type=&quot;multipart/mixed&quot;
  B <--- content-type=&quot;multipart/related&quot;
    C <--- content-type=&quot;text/plain&quot;
    D <--- content-type=&quot;text/html&quot;
  E <--- content-disposition=&quot;attachment&quot;
  F <--- content-disposition=&quot;attachment&quot;
  Object A is the Message object, which is the root of the hierarchy. All other objects are BodyPart objects. The IMessage.Attachments collection for the Message object would contain BodyPart objects E and F. For each object, its IBodyPart.BodyParts collections would contain only the direct descendants of the object in the hierarchy (remember that instances of the Message COM class expose the IBodyPart interface as well as instances of the BodyPart COM class). For object A (the Message object), this would include objects B, E and F. For object B (a BodyPart object), the collection would contain objects C and D. Objects E and F have empty BodyParts collections because they do not have descendants.
  For Unix-to-Unix encode (UUENCODE) formatted messages, the hierarchy is only one level deep, because all body parts are necessarily deemed attachments. In this case, only the Message object has descendants, and the IMessage.Attachments and IBodyPart.BodyParts collections are the same. For example,
  A
  B <-- UUENCODE attachment
  C <-- ditto
  D <-- ditto
  Why can't I write text to the Stream object of a newly added BodyPart object using _Stream::WriteText?
Microsoft ActiveX? Data Objects (ADO) Stream objects are always one of two types: text or binary. When you first add a BodyPart object to a Message object's body part hierarchy, the content media type defaults to application/octet-stream, rendering a binary decoded content stream (this only applies to the decoded content stream, as the encoded content stream is, by definition, text). The _Stream.WriteText method fails because this method is defined to function only on streams that are of the text type.
  To use the WriteText method, you have to set stream type to text. You can do this in one of two ways:
  Before retrieving the decoded content stream, set the BodyPart object's content media type to a text-based type, such as &quot;text/plain.&quot; You can use either the IBodyPart.ContentMediaType property or the urn:schemas:mailheader:content-type field in the IBodyPart.Fields collection. Once set, the returned content stream will be of the text type.
Manually change the stream type using the _Stream.Type property on the Stream object. Note that in most cases, you will also need to set the content media type after setting and flushing the stream, as shown in the following examples:
Visual Basic
' EXAMPLE for Step 1
'   Assume that you have a BodyPart object reference in the variable Bp1,
'   and that you wish to add a body part that will hold a text-based
'   content stream.
  Dim Bp2 as IBodyPart
Dim Strm as ADODB.Stream
  Set Bp2 = Bp1.AddBodyPart
Bp2.ContentMediaType = &quot;text/plain&quot;
  Set Strm = Bp2.GetDecodedContentStream
Strm.WriteText &quot;this is the text content here&quot;
  'Commit the changes back
Strm.Flush
  ' EXAMPLE for 2
  Dim Bp3 as IBodyPart
Set Bp3        = Bp1.AddBodyPart
Set Strm       = Bp3.GetDecodedContentStream
Strm.Type      = adTypeText
Strm.WriteText &quot;<P>this is some more content</P>&quot;
Strm.Flush
Bp3.ContentMediaType = &quot;text/html&quot;
' ...
  How do I set message headers on Message or BodyPart objects when there aren't properties for them?
All message and body part headers can be accessed through an appropriate Fields collection, for example, IMessage.Fields or IBodyPart.Fields. Each mail header resides in the urn:schemas:mailheader: namespace. For example, the Message-ID mail header is identified with the full name urn:schemas:mailheader:message-id.
  The fields provided in the urn:schemas:mailheader: namespace are the most common headers defined by the Internet community. However, you can add other headers that are not a part of this default set by adding it to the Fields collection in the urn:schemas:mailheader: namespace. For example, 'urn:schemas:mailheader:Some-Header.'
  Dim Msg as New CDO.Message
Dim Flds as ADODB.Fields
  Set Flds = Msg.Fields
With Flds
  .Append(&quot;urn:schemas:mailheader:message-id&quot;) = id
  .Append(&quot;urn:schemas:mailheader:custom&quot;)   = &quot;some value&quot;
  .Update
End With
  How can CDO objects expose multiple dual interfaces?
The short answer is: they can't. By definition, a dual interface is one that both extends the IDispatch interface and provides access to defined methods through the v-table and through the seven methods defined by the IDispatch interface (hence the name dual). Because Component Object Model (COM) uses proxy/stubs to marshal arguments between separate apartments, objects can expose only one IDispatch interface. In addition, you can't trick COM proxy/stubs by returning different addresses depending upon the interface from which you request IDispatch (for more details on this rule, see Advanced ). Therefore, there's one and only one IDispatch interface per object.
  This restriction is no problem for languages such as Microsoft Visual Basic? and Microsoft Visual J++? that support direct binding to OLE Automation&#8211;compatible interfaces. All Collaboration Data Objects (CDO) interfaces use these types, so you can navigate to and use each in the standard way for that language. For example, the CDO Message object exposes the IMessage, IDataSource, and IBodyPart dual interfaces. In Visual Basic, you first add references to the ActiveX Data Objects database (ADODB) and CDO type libraries, then type each interface variable using the types in these type libraries, and finally use the Set keyword to navigate to each interface. With Visual J++, use the jactivex tool to create necessary Microsoft virtual machine&#8211;compatible Java packages, and then import these packages into their .java source files. The following examples illustrate these procedures:
  Visual Basic
Dim iMsg  as CDO.Message
Dim iDsrc as CDO.IDataSource
Dim iBp   as CDO.IBodyPart
Dim iDisp as Object
  Set iBp   = New CDO.Message   ' Have IBodyPart
Set iDsrc = iBp               ' Have IDataSource
Set iMsg  = iBp               ' Have IMessage
Set iDisp = iBp               ' Have IDispatch
  Visual J++
import cdo.*;
  class Main {
  public static void main( String args[] ) {
    IMessage    iMsg  = null;
    IDataSource iDsrc = null;
    IBodyPart   iBp   = null;
    Object      iDisp = null;
  iBp   = (IBodyPart)   new Message(); // IBodyPart
    iDsrc = (IDataSource) iBp;           // IDataSource
    iMsg  = (IMessage)    iBp;           // IMessage
    iDisp = (Object)      iBp;           // IDispatch
    // ...
  }
}
  In both cases, you finish with references to all three CDO interfaces and a reference to the IDispatch interface, each on the same object.
  The situation is different for scripting languages such as Visual Basic Scripting Edition (VBScript), and Microsoft JScript?. With these languages, all interactions with COM objects occur through the object's IDispatch interface. Because each object can have only one IDispatch interface, you need separate objects with different implementations of IDispatch, not separate interfaces. Furthermore, you need a way for these languages to access these other objects. To facilitate this, many CDO interfaces define properties and the GetInterface method that return other objects (rather than interfaces) exposing the appropriate IDispatch implementation. However, this produces the illusion of &quot; interface navigation&quot; because it appears to the scriptwriter that the interface itself is being returned. The following code demonstrates this illusion using the CDO Message object:
  VBScript
Option Explicit
Dim iMsg
Dim iDsrc
Dim iBp
Set iMsg  = CreateObject(&quot;CDO.Message&quot;)      ' IMessage    (IDispatch)
  Set iDsrc = iMsg.DataSource                  ' IDataSource (IDispatch)
Set iDsrc = iMsg.GetInterface(&quot;IDataSource&quot;) ' Again IDataSource (IDispatch)
  Set iBp   = iMsg.BodyPart                    ' IBodyPart (IDispatch)
Set iBp   = iMsg.GetInterface(&quot;IBodyPart&quot;)   ' Again IBodyPart (IDispatch)
  Visual JScript
var iMsg  = null;
var iBp   = null;
var iDsrc = null;
  iMsg  = New ActiveXObject(&quot;CDO.Message&quot;);  // IMessage (IDispatch)
  iBp   = iMsg.BodyPart;                     // IBodyPart (IDispatch)
iBp   = iMsg.GetInterface(&quot;IBodyPart&quot;);    // Again IBodyPart (IDispatch)
  iDsrc = iMsg.DataSource;                   // IDataSource (IDispatch)
iDsrc = iMsg.GetInterface(&quot;IDataSource&quot;);  // Again IDataSource (IDispatch)
  In each case, the script actually interacts with separate objects (object identities), each of which exposes an appropriate implementation of IDispatch; no interface navigation per se is occurring. Instead, object navigation is occurring. The scriptwriter need not be concerned with such details, however; the CDO objects handle all the details internally. Most importantly, the CDO object behaves in the same manner, regardless of which object is used.
  Note to C/C++ Programmers (Advanced)
If you write code that depends upon object identity (the physical address of the IUnknown interface), you should be aware of the behavior outlined above. If you use interface properties such as IMessage::get_DataSource or IMessage::get_BodyPart, or if you use the GetInterface method to retrieve interfaces, you're actually getting a different object identity. Consider the following code:
  C++, IDL
#include <iostream.h>
#include &quot;cdoex.h&quot;
#include &quot;cdoex_i.c&quot;
  void main() {
  CoInitialize(NULL);
  IMessage*    pMsg  = NULL;
  IDataSource* pDsrc = NULL;
  IUnknown*    pUnk  = NULL;
  IUnknown*    pUnk2 = NULL;
  /*
  ** Create an instance of the Message CoClass
  */
  CoCreateInstance(CLSID_Message,
                   NULL,
                   CLSCTX_INPROC_SERVER,
                   IID_IUnknown,
                   (void**)&pUnk);
  /*
  **  have IUnknown (controlling) for Message object
  ** Get the IMessage interface on the object
  */
  pUnk->QueryInterface(IID_IMessage,(void**)&pMsg);
  /*
  ** Get IDataSource interface using property.
  */
  pMsg->get_DataSource(&pDsrc);
  /*
  ** Navigate back to IUnknown interface using new IDataSource prop.
  */
  pDsrc->QueryInterface(IID_IUnknown,(void**)&pUnk2);
  
  /*
  ** Check if these are the same address
** You know the answer...they're different, but let's
** be scientific about it...
  */
  if(pUnk == pUnk2)
    cout << &quot;pUnk == pUnk2&quot; << endl;
  else
    cout << &quot;pUnk != pUnk2!&quot; << endl;
  pUnk->Release();
  pUnk2->Release();
  pDsrc->Release();
  pMsg->Release();
  CoUninitialize();
}
  If you compiled and executed this code, the program would emit
  pUnk != pUnk2
  In fact, this is the correct behavior; a separate object identity (and hence a different IUnknown address) is returned when an interface is retrieved through a property on the interface or with GetInterface. This time, the IDispatch interface covers the implementation of the requested interface (IDataSource), essentially &quot;shifting&quot; from the previous.
  You can think of it this way: Microsoft Visual C++?, Visual Basic, and Visual J++ can use multiple Automation interfaces on the same object. Scripting languages, however, require an object model with a one-to-one correspondence between object and IDispatch interface. The answer is to provide both: CDO objects conform to both models, exposing multiple Automation-compatible interfaces on the object for use by Visual C++, Visual Basic, and Visual J++, and spawning separate objects (one for each type of interface) to accommodate scripting languages. For each spawned object, the IDispatch implementation covers the functionality of the target dual interface in &quot;round-robin&quot; fashion.
  You may wonder why all of this is needed. It may appear at first glance that with a clever enough implementation of the IUnknown methods for each interface, you could trick the client into using separate IDispatch implementations by returning the appropriate interface address through an interface property or GetInterface. However, this only works when the CDO object resides in the same apartment as the caller. If the client calls from a separate COM apartment (or process, or even machine process), COM silently provides a proxy and stub manager to remote the calls. The client is then invoking methods through interfaces aggregated on the proxy object, not directly on the object itself. The proxy rigorously enforces the COM object identity laws and additionally assumes that there is only one address for each interface exposed by the object. Being unaware of the devious attempt to return &quot;appropriate&quot; IDispatch physical addresses in round-robin fashion to the client, it instead preempts us, always returning the first IDispatch address retrieved by the client, and regardless of how this interface is subsequently requested. To circumvent this behavior, we are forced to return interfaces exposed on different object identities (and, therefore, through different proxy objects) to get the new IDispatch address (through the new proxy object) to the client in the other apartment. The price paid for this approach is one interface (v-table) duplicate for each exposed interface per IDispatch &quot;shift.&quot;
  It is essential that you understand this behavior if you intend to aggregate CDO interfaces on your objects.
  
--------------------------------------------------------------------------------
  Send us your feedback about the Exchange SDK.
  Build: September 2002 (2002.903.1)
  ? 2000-2002 Microsoft Corporation. All rights reserved. Terms of use.

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-112150-1-1.html 上篇帖子: Dialog Data Exchange 下篇帖子: POP3、SMTP、IMAP、Exchange
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表