Skip to content

Commit

Permalink
Created UpdateItem and added necessary trait implementations (#18)
Browse files Browse the repository at this point in the history
* Created UpdateItem and added necessary trait implementations

* Respond to feedback on UpdateItem, unduplicate MessageDisposition (now as Option<MessageDisposition>) and add Clone for all types

* Also added default trait for ConflictResolution

* Adjusted comment to use a noun phrase for ConflictResolution

* Fixed formatting issues

* Test formatting

* Fix formatting again

* Test broken formatting

* Test broken formatting

* Fix broken formatting

* Update documentation and get rid of serialize-only Message type (#23)

* Add reference to EWS updateitem docs

---------

Co-authored-by: Sean Burke <[email protected]>
  • Loading branch information
tobypilling and leftmostcat authored Oct 31, 2024
1 parent 8918191 commit 3b1d4db
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 73 deletions.
1 change: 1 addition & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ pub mod get_folder;
pub mod get_item;
pub mod sync_folder_hierarchy;
pub mod sync_folder_items;
pub mod update_item;
21 changes: 17 additions & 4 deletions src/types/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,18 @@ pub enum DistinguishedPropertySet {
UnifiedMessaging,
}

/// The action an Exchange server will take upon creating a `Message` item.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/createitem#messagedisposition-attribute>
/// and <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateitem#messagedisposition-attribute>
#[derive(Clone, Copy, Debug, XmlSerialize)]
#[xml_struct(text)]
pub enum MessageDisposition {
SaveOnly,
SendOnly,
SendAndSaveCopy,
}

/// The type of the value of a MAPI property.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/extendedfielduri#propertytype-attribute>
Expand Down Expand Up @@ -407,7 +419,7 @@ pub struct Items {
/// Exchange item.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/items>
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize, XmlSerialize)]
pub enum RealItem {
Message(Message),
}
Expand Down Expand Up @@ -458,13 +470,14 @@ impl XmlSerialize for DateTime {
/// An email message.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/message-ex15websvcsotherref>
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, XmlSerialize)]
#[serde(rename_all = "PascalCase")]
pub struct Message {
/// The MIME content of the item.
pub mime_content: Option<MimeContent>,

/// The item's Exchange identifier.
pub item_id: ItemId,
pub item_id: Option<ItemId>,

/// The identifier for the containing folder.
///
Expand Down Expand Up @@ -605,7 +618,7 @@ pub struct InternetMessageHeaders {
/// A reference to a user or address which can send or receive mail.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/mailbox>
#[derive(Clone, Debug, Default, Deserialize, XmlSerialize, PartialEq)]
#[derive(Clone, Debug, Deserialize, XmlSerialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Mailbox {
/// The name of this mailbox's user.
Expand Down
74 changes: 5 additions & 69 deletions src/types/create_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,11 @@ use serde::Deserialize;
use xml_struct::XmlSerialize;

use crate::{
types::sealed::EnvelopeBodyContents, ArrayOfRecipients, BaseFolderId, ExtendedFieldURI, Items,
MimeContent, Operation, OperationResponse, ResponseClass, ResponseCode, MESSAGES_NS_URI,
types::sealed::EnvelopeBodyContents, BaseFolderId, ExtendedFieldURI, Items, MessageDisposition,
Operation, OperationResponse, RealItem, ResponseClass, ResponseCode, MESSAGES_NS_URI,
};

/// The action an Exchange server will take upon creating a `Message` item.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/createitem#messagedisposition-attribute>
#[derive(Clone, Debug, XmlSerialize)]
#[xml_struct(text)]
pub enum MessageDisposition {
SaveOnly,
SendOnly,
SendAndSaveCopy,
}

/// A request to create (and optionally send) one or more Exchange item(s).
/// A request to create (and optionally send) one or more Exchange items.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/createitem>
#[derive(Clone, Debug, XmlSerialize)]
Expand All @@ -43,64 +32,11 @@ pub struct CreateItem {
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/saveditemfolderid>
///
/// [`SendOnly`]: [`MessageDisposition::SendOnly`]
/// [`SendOnly`]: `MessageDisposition::SendOnly`
pub saved_item_folder_id: Option<BaseFolderId>,

/// The item or items to create.
pub items: Vec<Item>,
}

/// A new item that appears in a CreateItem request.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/items>
// N.B.: Commented-out variants are not yet implemented.
#[non_exhaustive]
#[derive(Clone, Debug, XmlSerialize)]
#[xml_struct(variant_ns_prefix = "t")]
pub enum Item {
// Item(Item),
Message(Message),
// CalendarItem(CalendarItem),
// Contact(Contact),
// Task(Task),
// MeetingMessage(MeetingMessage),
// MeetingRequest(MeetingRequest),
// MeetingResponse(MeetingResponse),
// MeetingCancellation(MeetingCancellation),
}

/// An email message to create.
///
/// This struct follows the same specification to [`common::Message`], but has a
/// few differences that allow the creation of new messages without forcing any
/// tradeoff on strictness when deserializing; for example not making the item
/// ID a required field.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/message-ex15websvcsotherref>
///
/// [`common::message`]: crate::Message
#[derive(Clone, Debug, Default, XmlSerialize)]
pub struct Message {
/// The MIME content of the item.
#[xml_struct(ns_prefix = "t")]
pub mime_content: Option<MimeContent>,

// Whether to request a delivery receipt.
#[xml_struct(ns_prefix = "t")]
pub is_delivery_receipt_requested: Option<bool>,

// The message ID for the message, semantically identical to the Message-ID
// header.
#[xml_struct(ns_prefix = "t")]
pub internet_message_id: Option<String>,

// Recipients to include as Bcc, who won't be included in the MIME content.
#[xml_struct(ns_prefix = "t")]
pub bcc_recipients: Option<ArrayOfRecipients>,

// Extended MAPI properties to set on the message.
#[xml_struct(ns_prefix = "t")]
pub extended_property: Option<Vec<ExtendedProperty>>,
pub items: Vec<RealItem>,
}

/// An extended MAPI property to set on the message.
Expand Down
151 changes: 151 additions & 0 deletions src/types/update_item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use crate::types::common::{BaseItemId, Message, MessageDisposition, PathToElement};
use crate::{
types::sealed::EnvelopeBodyContents, Items, Operation, OperationResponse, ResponseClass,
ResponseCode,
};
use serde::Deserialize;
use xml_struct::XmlSerialize;

/// A request to update properties of one or more Exchange items.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateitem>
#[derive(Clone, Debug, XmlSerialize)]
pub struct UpdateItem {
/// The action the Exchange server will take upon updating this item.
///
/// This field is required for and only applicable to [`Message`] items.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateitem#messagedisposition-attribute>
#[xml_struct(attribute)]
pub message_disposition: Option<MessageDisposition>,

/// The method the Exchange server will use to resolve conflicts between
/// updates.
///
/// If omitted, the server will default to [`AutoResolve`].
///
/// [`AutoResolve`]: `ConflictResolution::AutoResolve`
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateitem#conflictresolution-attribute>
#[xml_struct(attribute)]
pub conflict_resolution: Option<ConflictResolution>,

/// A list of items and their corresponding updates.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/itemchanges>
pub item_changes: ItemChanges,
}

impl Operation for UpdateItem {
type Response = UpdateItemResponse;
}

impl EnvelopeBodyContents for UpdateItem {
fn name() -> &'static str {
"UpdateItem"
}
}

/// A response to an [`UpdateItem`] request.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateitemresponse>
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct UpdateItemResponse {
pub response_messages: ResponseMessages,
}

impl OperationResponse for UpdateItemResponse {}

impl EnvelopeBodyContents for UpdateItemResponse {
fn name() -> &'static str {
"UpdateItemResponse"
}
}

#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct ResponseMessages {
pub update_item_response_message: Vec<UpdateItemResponseMessage>,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct UpdateItemResponseMessage {
/// The status of the corresponding request, i.e. whether it succeeded or
/// resulted in an error.
pub response_class: ResponseClass,

pub response_code: Option<ResponseCode>,

pub message_text: Option<String>,

pub items: Items,
}

/// The method used by the Exchange server to resolve conflicts between item
/// updates.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateitem#conflictresolution-attribute>
#[derive(Clone, Copy, Debug, Default, XmlSerialize)]
#[xml_struct(text)]
pub enum ConflictResolution {
/// Conflicts will cause the update to fail and return an error.
NeverOverwrite,

/// The Exchange server will attempt to resolve any conflicts automatically.
#[default]
AutoResolve,

/// Conflicting fields will be overwritten with the contents of the update.
AlwaysOverwrite,
}

/// A list of updates to items, with each element representing a single item.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/itemchanges>
#[derive(Clone, Debug, XmlSerialize)]
pub struct ItemChanges {
pub item_changes: Vec<ItemChange>,
}

/// One or more updates to a single item.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/itemchange>
#[derive(Clone, Debug, XmlSerialize)]
pub struct ItemChange {
/// The ID of the item to be updated.
pub item_id: BaseItemId,

/// The changes to make to the item, including appending, setting, or
/// deleting fields.
pub updates: Updates,
}

/// A list of changes to fields, with each element representing a single change.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/updates-item>
#[derive(Clone, Debug, XmlSerialize)]
pub struct Updates {
#[xml_struct(flatten)]
pub inner: Vec<ItemChangeDescription>,
}

/// An individual change to a single field.
#[derive(Clone, Debug, XmlSerialize)]
pub enum ItemChangeDescription {
/// An update setting the value of a single field.
///
/// See <https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/setitemfield>
SetItemField {
/// The field to be updated.
field_uri: PathToElement,

/// The new value of the specified field.
message: Message,
},
}

0 comments on commit 3b1d4db

Please sign in to comment.