2017-06-29 117 views
0

我试图通过Microsoft Exchange 2010服务器从C++应用程序发送电子邮件。为此,我使用EWS协议,使用库ews-cpp通过EWS发送邮件:架构验证:无效的子元素“Body”

下面简单的例子,基于一个从https://github.com/otris/ews-cpp/blob/master/examples/send_message.cpp,失败(从我的实际代码剥离邮件地址和凭证):

#include <iostream> 
#include <ews/ews.hpp> 

struct { 
    std::string domain = "mailserver"; 
    std::string username = "..."; 
    std::string password = "..."; 
    std::string server_uri = "https://mailserver/EWS/Exchange.asmx"; 
} env; 

int main() 
{ 
    ews::set_up(); 

    try 
    { 
     auto service = ews::service(env.server_uri, env.domain, env.username, 
            env.password); 
     service.set_request_server_version(ews::server_version::exchange_2010_sp2); 

     auto message = ews::message(); 

     message.set_subject("Test mail from outer space"); 
     std::vector<ews::mailbox> recipients; 

     recipients.push_back(ews::mailbox("...")); 
     message.set_to_recipients(recipients); 

     auto text = ews::body("This is a test."); 
     message.set_body(text); 

     service.create_item(message, 
          ews::message_disposition::send_and_save_copy); 
    } 
    catch (ews::schema_validation_error& exc) 
    { 
     std::cout << exc.what() << std::endl; 
     std::cout << exc.violation() << std::endl; 
    } 

    ews::tear_down(); 
    return 0; 
} 

原始SOAP请求如下(由我添加的压痕) :

<m:CreateItem MessageDisposition="SendAndSaveCopy"> 
    <m:Items> 
    <t:Message> 
     <t:Subject>Test mail from outer space</t:Subject> 
     <t:ToRecipients> 
     <t:Mailbox> 
      <t:EmailAddress>...</t:EmailAddress> 
     </t:Mailbox> 
     </t:ToRecipients> 
     <t:Body BodyType="Text">This is a test.</t:Body> 
    </t:Message> 
    </m:Items> 
</m:CreateItem> 

功能create_item抛出ews::schema_validation_error它被捕获在上述代码中,印刷:

The request failed schema validation 
The element 'Message' in namespace ‘http://schemas.microsoft.com/exchange/services/2006/types’ has invalid child element 'Body' in namespace 'http://schemas.microsoft.com/exchange/services/2006/types'. List of possible elements expected: 'CcRecipients, BccRecipients, IsReadReceiptRequested, IsDeliveryReceiptRequested, ConversationIndex, ConversationTopic, From, InternetMessageId, IsRead, IsResponseRequested, References, ReplyTo, ReceivedBy, ReceivedRepresenting' in Namespace 'http://schemas.microsoft.com/exchange/services/2006/types'. 

换句话说,EWS不希望<t:Body><t:Message>之内。

因此,当在SOAP请求中注销该元素(注释掉message.set_body(text))时,邮件会顺利发送。但是,没有身体的邮件没有多大意义,是吗?

我认为这个问题可能是因为ews-cpp是为Exchange 2013编写的(并且在这方面2010年和2013年之间的架构发生了变化)。所以我深入到架构中,每个Exchange服务器在/ews/types.xsd服务,以查看架构是否允许这样一个子元素。

在架构定义文件,我发现型MessageType的定义(这是Message元素,我们正在谈论的类型):

<xs:complexType name="MessageType"> 
    <xs:complexContent> 
    <xs:extension base="t:ItemType"> 
     <xs:sequence> 
     <xs:element name="Sender" minOccurs="0" type="t:SingleRecipientType"/> 
     <xs:element name="ToRecipients" type="t:ArrayOfRecipientsType" minOccurs="0"/> 
     <xs:element name="CcRecipients" type="t:ArrayOfRecipientsType" minOccurs="0"/> 
     <xs:element name="BccRecipients" type="t:ArrayOfRecipientsType" minOccurs="0"/> 
     <xs:element name="IsReadReceiptRequested" type="xs:boolean" minOccurs="0"/> 
     <xs:element name="IsDeliveryReceiptRequested" type="xs:boolean" minOccurs="0"/> 
     <xs:element name="ConversationIndex" type="xs:base64Binary" minOccurs="0"/> 
     <xs:element name="ConversationTopic" type="xs:string" minOccurs="0"/> 
     <xs:element name="From" type="t:SingleRecipientType" minOccurs="0"/> 
     <xs:element name="InternetMessageId" type="xs:string" minOccurs="0"/> 
     <xs:element name="IsRead" type="xs:boolean" minOccurs="0"/> 
     <xs:element name="IsResponseRequested" type="xs:boolean" minOccurs="0"/> 
     <xs:element name="References" type="xs:string" minOccurs="0"/> 
     <xs:element name="ReplyTo" type="t:ArrayOfRecipientsType" minOccurs="0"/> 
     <xs:element name="ReceivedBy" type="t:SingleRecipientType" minOccurs="0"/> 
     <xs:element name="ReceivedRepresenting" type="t:SingleRecipientType" minOccurs="0"/> 
     </xs:sequence> 
    </xs:extension> 
    </xs:complexContent> 
</xs:complexType> 

正如你所看到的,有没有Body孩子元素,但MessageType是基于ItemType,其定义如下(节选):

<xs:complexType name="ItemType"> 
<xs:sequence> 
    <xs:element name="MimeContent" type="t:MimeContentType" minOccurs="0"/> 
    <xs:element name="ItemId" type="t:ItemIdType" minOccurs="0"/> 
    <xs:element name="ParentFolderId" type="t:FolderIdType" minOccurs="0"/> 
    <xs:element name="ItemClass" type="t:ItemClassType" minOccurs="0"/> 
    <xs:element name="Subject" type="xs:string" minOccurs="0"/> 
    <xs:element name="Sensitivity" type="t:SensitivityChoicesType" minOccurs="0"/> 
    <xs:element name="Body" type="t:BodyType" minOccurs="0"/> 
    <xs:element name="Attachments" type="t:NonEmptyArrayOfAttachmentsType" minOccurs="0"/> 
    [...] 
    </xs:sequence> 
</xs:complexType> 

正如你所看到的,它接受Body元素作为孩子。

请注意,Subject元素也在ItemType中定义,而不是在MessageType中定义,并且EWS在上述代码段中接受该元素。

这个奇怪的验证失败的原因是什么?

回答

0

实测溶液自己:

对于元件Message,其根据所述模式定义基于Item,EWS第一预计,Item所有子元素,其次是Message特异性子元素。

这听起来很疯狂(对我来说),但在<t:Message>元素中交换<t:ToRecipients><t:Body>确实解决了这个问题。

我不希望这在我的代码交换两个对应的setter方法:

auto message = ews::message(); 


    // First, set properties of the general "item": 

    message.set_subject("Test mail from outer space"); 

    auto text = ews::body("This is a test."); 
    message.set_body(text); 


    // Then, set properties of the concrete "message": 

    std::vector<ews::mailbox> recipients; 
    recipients.push_back(ews::mailbox("...")); 
    message.set_to_recipients(recipients); 

我不知道这是否是一个错误ews-cpp,在EWS/Exchange服务器,或在EWS模式定义。