This commit is contained in:
Mauro D
2022-09-09 09:49:32 +00:00
parent 5e9c4f825e
commit 2e70d350ed
8 changed files with 786 additions and 9 deletions

62
examples/eventsource.rs Normal file
View File

@@ -0,0 +1,62 @@
/*
* Copyright Stalwart Labs Ltd. See the COPYING
* file at the top-level directory of this distribution.
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* file at the top-level directory of this distribution.
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
* option. This file may not be copied, modified, or distributed
* except according to those terms.
*/
use futures_util::StreamExt;
use jmap_client::{client::Client, TypeState};
async fn event_source() {
// Connect to the JMAP server using Basic authentication
let client = Client::new()
.credentials(("john@example.org", "secret"))
.connect("https://jmap.example.org")
.await
.unwrap();
// Open EventSource connection
let mut stream = client
.event_source(
[
TypeState::Email,
TypeState::EmailDelivery,
TypeState::Mailbox,
TypeState::EmailSubmission,
TypeState::Identity,
]
.into(),
false,
60.into(),
None,
)
.await
.unwrap();
// Consume events
while let Some(event) = stream.next().await {
let changes = event.unwrap();
println!("-> Change id: {:?}", changes.id());
for account_id in changes.changed_accounts() {
println!(" Account {} has changes:", account_id);
if let Some(account_changes) = changes.changes(account_id) {
for (type_state, state_id) in account_changes {
println!(" Type {:?} has a new state {}.", type_state, state_id);
}
}
}
}
}
fn main() {
let _c = event_source();
}

69
examples/mailboxes.rs Normal file
View File

@@ -0,0 +1,69 @@
/*
* Copyright Stalwart Labs Ltd. See the COPYING
* file at the top-level directory of this distribution.
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* file at the top-level directory of this distribution.
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
* option. This file may not be copied, modified, or distributed
* except according to those terms.
*/
use jmap_client::{
client::Client,
mailbox::{query::Filter, Role},
};
async fn mailboxes() {
// Connect to the JMAP server using Basic authentication
let client = Client::new()
.credentials(("john@example.org", "secret"))
.connect("https://jmap.example.org")
.await
.unwrap();
// Create a mailbox
let mailbox_id = client
.mailbox_create("My Mailbox", None::<String>, Role::None)
.await
.unwrap()
.take_id();
// Rename a mailbox
client
.mailbox_rename(&mailbox_id, "My Renamed Mailbox")
.await
.unwrap();
// Query mailboxes to obtain Inbox's id
let inbox_id = client
.mailbox_query(Filter::role(Role::Inbox).into(), None::<Vec<_>>)
.await
.unwrap()
.take_ids()
.pop()
.unwrap();
// Print Inbox's details
println!(
"{:?}",
client.mailbox_get(&inbox_id, None::<Vec<_>>).await.unwrap()
);
// Move the newly created mailbox under Inbox
client
.mailbox_move(&mailbox_id, inbox_id.into())
.await
.unwrap();
// Delete the mailbox including any messages
client.mailbox_destroy(&mailbox_id, true).await.unwrap();
}
fn main() {
let _c = mailboxes();
}

120
examples/messages.rs Normal file
View File

@@ -0,0 +1,120 @@
/*
* Copyright Stalwart Labs Ltd. See the COPYING
* file at the top-level directory of this distribution.
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* file at the top-level directory of this distribution.
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
* option. This file may not be copied, modified, or distributed
* except according to those terms.
*/
use jmap_client::{
client::Client,
core::query::Filter,
email::{self, Property},
mailbox::{self, Role},
};
const TEST_MESSAGE: &[u8; 90] = br#"From: john@example.org
To: jane@example.org
Subject: Testing JMAP client
This is a test.
"#;
async fn messages() {
// Connect to the JMAP server using Basic authentication
let client = Client::new()
.credentials(("john@example.org", "secret"))
.connect("https://jmap.example.org")
.await
.unwrap();
// Query mailboxes to obtain Inbox and Trash folder id
let inbox_id = client
.mailbox_query(
mailbox::query::Filter::role(Role::Inbox).into(),
None::<Vec<_>>,
)
.await
.unwrap()
.take_ids()
.pop()
.unwrap();
let trash_id = client
.mailbox_query(
mailbox::query::Filter::role(Role::Trash).into(),
None::<Vec<_>>,
)
.await
.unwrap()
.take_ids()
.pop()
.unwrap();
// Import message into inbox
client
.email_import(TEST_MESSAGE.to_vec(), [&inbox_id], ["$draft"].into(), None)
.await
.unwrap();
// Query mailbox
let email_id = client
.email_query(
Filter::and([
email::query::Filter::subject("test"),
email::query::Filter::in_mailbox(&inbox_id),
email::query::Filter::has_keyword("$draft"),
])
.into(),
[email::query::Comparator::from()].into(),
)
.await
.unwrap()
.take_ids()
.pop()
.unwrap();
// Fetch message
let email = client
.email_get(
&email_id,
[Property::Subject, Property::Preview, Property::Keywords].into(),
)
.await
.unwrap()
.unwrap();
assert_eq!(email.preview().unwrap(), "This is a test.");
assert_eq!(email.subject().unwrap(), "Testing JMAP client");
assert_eq!(email.keywords(), ["$draft"]);
// Remove the $draft keyword
client
.email_set_keyword(&email_id, "$draft", false)
.await
.unwrap();
// Replace all keywords
client
.email_set_keywords(&email_id, ["$seen", "$important"])
.await
.unwrap();
// Move the message to the Trash folder
client
.email_set_mailboxes(&email_id, [&trash_id])
.await
.unwrap();
// Destroy the e-mail
client.email_destroy(&email_id).await.unwrap();
}
fn main() {
let _c = messages();
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright Stalwart Labs Ltd. See the COPYING
* file at the top-level directory of this distribution.
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* file at the top-level directory of this distribution.
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
* option. This file may not be copied, modified, or distributed
* except according to those terms.
*/
use jmap_client::{client::Client, core::query, email, mailbox};
async fn result_reference() {
// Connect to the JMAP server using Basic authentication
let client = Client::new()
.credentials(("john@example.org", "secret"))
.connect("https://jmap.example.org")
.await
.unwrap();
// Delete e-mails matching a filter
let mut request = client.build();
let result_ref = request
.query_email()
.filter(query::Filter::and([
email::query::Filter::has_keyword("$draft"),
email::query::Filter::from("bill"),
]))
.result_reference();
request.set_email().destroy_ref(result_ref);
let _destroyed_ids = request
.send()
.await
.unwrap()
.unwrap_method_responses()
.pop()
.unwrap()
.unwrap_set_email()
.unwrap()
.take_destroyed_ids();
// Fetch mailboxes matching a filter
let mut request = client.build();
let query_result = request
.query_mailbox()
.filter(query::Filter::and([
mailbox::query::Filter::has_any_role(false),
mailbox::query::Filter::is_subscribed(true),
]))
.result_reference();
request.get_mailbox().ids_ref(query_result).properties([
mailbox::Property::Id,
mailbox::Property::Name,
mailbox::Property::ParentId,
mailbox::Property::TotalEmails,
mailbox::Property::UnreadEmails,
]);
let _mailboxes = request
.send()
.await
.unwrap()
.unwrap_method_responses()
.pop()
.unwrap()
.unwrap_get_mailbox()
.unwrap()
.take_list();
// Fetch only the updated properties of all mailboxes that changed
// since a state.
let mut request = client.build();
let changes_request = request.changes_mailbox("n").max_changes(0);
let properties_ref = changes_request.updated_properties_reference();
let updated_ref = changes_request.updated_reference();
request
.get_mailbox()
.ids_ref(updated_ref)
.properties_ref(properties_ref);
for mailbox in request
.send()
.await
.unwrap()
.unwrap_method_responses()
.pop()
.unwrap()
.unwrap_get_mailbox()
.unwrap()
.take_list()
{
println!("Changed mailbox: {:#?}", mailbox);
}
}
fn main() {
let _c = result_reference();
}

86
examples/websocket.rs Normal file
View File

@@ -0,0 +1,86 @@
/*
* Copyright Stalwart Labs Ltd. See the COPYING
* file at the top-level directory of this distribution.
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* file at the top-level directory of this distribution.
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
* option. This file may not be copied, modified, or distributed
* except according to those terms.
*/
use futures_util::StreamExt;
use jmap_client::{client::Client, client_ws::WebSocketMessage, core::set::SetObject};
use tokio::sync::mpsc;
// Make sure the "websockets" feature is enabled!
async fn websocket() {
// Connect to the JMAP server using Basic authentication
let client = Client::new()
.credentials(("john@example.org", "secret"))
.connect("https://jmap.example.org")
.await
.unwrap();
// Connect to the WebSocket endpoint
let mut ws_stream = client.connect_ws().await.unwrap();
// Read WS messages on a separate thread
let (stream_tx, mut stream_rx) = mpsc::channel::<WebSocketMessage>(100);
tokio::spawn(async move {
while let Some(change) = ws_stream.next().await {
stream_tx.send(change.unwrap()).await.unwrap();
}
});
// Create a mailbox over WS
let mut request = client.build();
let create_id = request
.set_mailbox()
.create()
.name("WebSocket Test")
.create_id()
.unwrap();
let request_id = request.send_ws().await.unwrap();
// Read response from WS stream
let mailbox_id = if let Some(WebSocketMessage::Response(mut response)) = stream_rx.recv().await
{
assert_eq!(request_id, response.request_id().unwrap());
response
.pop_method_response()
.unwrap()
.unwrap_set_mailbox()
.unwrap()
.created(&create_id)
.unwrap()
.take_id()
} else {
unreachable!()
};
// Enable push notifications over WS
client
.enable_push_ws(None::<Vec<_>>, None::<&str>)
.await
.unwrap();
// Make changes over standard HTTP and expect a push notification via WS
client
.mailbox_update_sort_order(&mailbox_id, 1)
.await
.unwrap();
if let Some(WebSocketMessage::StateChange(changes)) = stream_rx.recv().await {
println!("Received changes: {:?}", changes);
} else {
unreachable!()
}
}
fn main() {
let _c = websocket();
}