pub struct ClientBuilder { /* private fields */ }Implementations§
Source§impl ClientBuilder
impl ClientBuilder
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates a new ClientBuilder.
Setting the credentials is required to connect to the JMAP API.
Sourcepub fn credentials(self, credentials: impl Into<Credentials>) -> Self
pub fn credentials(self, credentials: impl Into<Credentials>) -> Self
Set up client credentials to connect to the JMAP API.
The JMAP API URL is set using the ClientBuilder.connect() method.
§Bearer authentication
Pass a &str with the API Token.
Client::new().credentials("some-api-token");Or use the longer form by using Credentials::bearer().
let credentials = Credentials::bearer("some-api-token");
Client::new().credentials(credentials);§Basic authentication
Pass a (&str, &str) tuple, with the first position containing a username and the second containing a password.
It is not suggested to use this approach in production; instead, if possible, use Bearer authentication.
Client::new().credentials(("user@domain.com", "password"));Or use the longer form by using Credentials::basic().
let credentials = Credentials::basic("user@domain.com", "password");
Client::new().credentials(credentials);Examples found in repository?
23async fn mailboxes() {
24 // Connect to the JMAP server using Basic authentication
25 let client = Client::new()
26 .credentials(("john@example.org", "secret"))
27 .connect("https://jmap.example.org")
28 .await
29 .unwrap();
30
31 // Create a mailbox
32 let mailbox_id = client
33 .mailbox_create("My Mailbox", None::<String>, Role::None)
34 .await
35 .unwrap()
36 .take_id();
37
38 // Rename a mailbox
39 client
40 .mailbox_rename(&mailbox_id, "My Renamed Mailbox")
41 .await
42 .unwrap();
43
44 // Query mailboxes to obtain Inbox's id
45 let inbox_id = client
46 .mailbox_query(Filter::role(Role::Inbox).into(), None::<Vec<_>>)
47 .await
48 .unwrap()
49 .take_ids()
50 .pop()
51 .unwrap();
52
53 // Print Inbox's details
54 println!(
55 "{:?}",
56 client.mailbox_get(&inbox_id, None::<Vec<_>>).await.unwrap()
57 );
58
59 // Move the newly created mailbox under Inbox
60 client
61 .mailbox_move(&mailbox_id, inbox_id.into())
62 .await
63 .unwrap();
64
65 // Delete the mailbox including any messages
66 client.mailbox_destroy(&mailbox_id, true).await.unwrap();
67}More examples
22async fn event_source() {
23 // Connect to the JMAP server using Basic authentication
24 let client = Client::new()
25 .credentials(("john@example.org", "secret"))
26 .connect("https://jmap.example.org")
27 .await
28 .unwrap();
29
30 // Open EventSource connection
31 let mut stream = client
32 .event_source(
33 [
34 DataType::Email,
35 DataType::EmailDelivery,
36 DataType::Mailbox,
37 DataType::EmailSubmission,
38 DataType::Identity,
39 ]
40 .into(),
41 false,
42 60.into(),
43 None,
44 )
45 .await
46 .unwrap();
47
48 // Consume events
49 while let Some(event) = stream.next().await {
50 use jmap_client::event_source::PushNotification;
51
52 match event.unwrap() {
53 PushNotification::StateChange(changes) => {
54 println!("-> Change id: {:?}", changes.id());
55 for account_id in changes.changed_accounts() {
56 println!(" Account {} has changes:", account_id);
57 if let Some(account_changes) = changes.changes(account_id) {
58 for (type_state, state_id) in account_changes {
59 println!(" Type {:?} has a new state {}.", type_state, state_id);
60 }
61 }
62 }
63 }
64 PushNotification::CalendarAlert(calendar_alert) => {
65 println!(
66 "-> Calendar alert received for event {} (alert id {}).",
67 calendar_alert.calendar_event_id, calendar_alert.alert_id
68 );
69 }
70 }
71 }
72}25async fn websocket() {
26 // Connect to the JMAP server using Basic authentication
27
28 use jmap_client::PushObject;
29
30 let client = Client::new()
31 .credentials(("john@example.org", "secret"))
32 .connect("https://jmap.example.org")
33 .await
34 .unwrap();
35
36 // Connect to the WebSocket endpoint
37 let mut ws_stream = client.connect_ws().await.unwrap();
38
39 // Read WS messages on a separate thread
40 let (stream_tx, mut stream_rx) = mpsc::channel::<WebSocketMessage>(100);
41 tokio::spawn(async move {
42 while let Some(change) = ws_stream.next().await {
43 stream_tx.send(change.unwrap()).await.unwrap();
44 }
45 });
46
47 // Create a mailbox over WS
48 let mut request = client.build();
49 let create_id = request
50 .set_mailbox()
51 .create()
52 .name("WebSocket Test")
53 .create_id()
54 .unwrap();
55 let request_id = request.send_ws().await.unwrap();
56
57 // Read response from WS stream
58 let mailbox_id = if let Some(WebSocketMessage::Response(mut response)) = stream_rx.recv().await
59 {
60 assert_eq!(request_id, response.request_id().unwrap());
61 response
62 .pop_method_response()
63 .unwrap()
64 .unwrap_set_mailbox()
65 .unwrap()
66 .created(&create_id)
67 .unwrap()
68 .take_id()
69 } else {
70 unreachable!()
71 };
72
73 // Enable push notifications over WS
74 client
75 .enable_push_ws(None::<Vec<_>>, None::<&str>)
76 .await
77 .unwrap();
78
79 // Make changes over standard HTTP and expect a push notification via WS
80 client
81 .mailbox_update_sort_order(&mailbox_id, 1)
82 .await
83 .unwrap();
84 if let Some(WebSocketMessage::PushNotification(PushObject::StateChange { changed })) =
85 stream_rx.recv().await
86 {
87 println!("Received changes: {:?}", changed);
88 } else {
89 unreachable!()
90 }
91}33async fn messages() {
34 // Connect to the JMAP server using Basic authentication
35 let client = Client::new()
36 .credentials(("john@example.org", "secret"))
37 .connect("https://jmap.example.org")
38 .await
39 .unwrap();
40
41 // Query mailboxes to obtain Inbox and Trash folder id
42 let inbox_id = client
43 .mailbox_query(
44 mailbox::query::Filter::role(Role::Inbox).into(),
45 None::<Vec<_>>,
46 )
47 .await
48 .unwrap()
49 .take_ids()
50 .pop()
51 .unwrap();
52 let trash_id = client
53 .mailbox_query(
54 mailbox::query::Filter::role(Role::Trash).into(),
55 None::<Vec<_>>,
56 )
57 .await
58 .unwrap()
59 .take_ids()
60 .pop()
61 .unwrap();
62
63 // Import message into inbox
64 client
65 .email_import(TEST_MESSAGE.to_vec(), [&inbox_id], ["$draft"].into(), None)
66 .await
67 .unwrap();
68
69 // Query mailbox
70 let email_id = client
71 .email_query(
72 Filter::and([
73 email::query::Filter::subject("test"),
74 email::query::Filter::in_mailbox(&inbox_id),
75 email::query::Filter::has_keyword("$draft"),
76 ])
77 .into(),
78 [email::query::Comparator::from()].into(),
79 )
80 .await
81 .unwrap()
82 .take_ids()
83 .pop()
84 .unwrap();
85
86 // Fetch message
87 let email = client
88 .email_get(
89 &email_id,
90 [Property::Subject, Property::Preview, Property::Keywords].into(),
91 )
92 .await
93 .unwrap()
94 .unwrap();
95 assert_eq!(email.preview().unwrap(), "This is a test.");
96 assert_eq!(email.subject().unwrap(), "Testing JMAP client");
97 assert_eq!(email.keywords(), ["$draft"]);
98
99 // Remove the $draft keyword
100 client
101 .email_set_keyword(&email_id, "$draft", false)
102 .await
103 .unwrap();
104
105 // Replace all keywords
106 client
107 .email_set_keywords(&email_id, ["$seen", "$important"])
108 .await
109 .unwrap();
110
111 // Move the message to the Trash folder
112 client
113 .email_set_mailboxes(&email_id, [&trash_id])
114 .await
115 .unwrap();
116
117 // Destroy the e-mail
118 client.email_destroy(&email_id).await.unwrap();
119}20async fn result_reference() {
21 // Connect to the JMAP server using Basic authentication
22 let client = Client::new()
23 .credentials(("john@example.org", "secret"))
24 .connect("https://jmap.example.org")
25 .await
26 .unwrap();
27
28 // Delete e-mails matching a filter
29 let mut request = client.build();
30 let result_ref = request
31 .query_email()
32 .filter(query::Filter::and([
33 email::query::Filter::has_keyword("$draft"),
34 email::query::Filter::from("bill"),
35 ]))
36 .result_reference();
37 request.set_email().destroy_ref(result_ref);
38 let _destroyed_ids = request
39 .send()
40 .await
41 .unwrap()
42 .unwrap_method_responses()
43 .pop()
44 .unwrap()
45 .unwrap_set_email()
46 .unwrap()
47 .take_destroyed_ids();
48
49 // Fetch mailboxes matching a filter
50 let mut request = client.build();
51 let query_result = request
52 .query_mailbox()
53 .filter(query::Filter::and([
54 mailbox::query::Filter::has_any_role(false),
55 mailbox::query::Filter::is_subscribed(true),
56 ]))
57 .result_reference();
58 request.get_mailbox().ids_ref(query_result).properties([
59 mailbox::Property::Id,
60 mailbox::Property::Name,
61 mailbox::Property::ParentId,
62 mailbox::Property::TotalEmails,
63 mailbox::Property::UnreadEmails,
64 ]);
65 let _mailboxes = request
66 .send()
67 .await
68 .unwrap()
69 .unwrap_method_responses()
70 .pop()
71 .unwrap()
72 .unwrap_get_mailbox()
73 .unwrap()
74 .take_list();
75
76 // Fetch only the updated properties of all mailboxes that changed
77 // since a state.
78 let mut request = client.build();
79 let changes_request = request.changes_mailbox("n").max_changes(0);
80 let properties_ref = changes_request.updated_properties_reference();
81 let updated_ref = changes_request.updated_reference();
82 request
83 .get_mailbox()
84 .ids_ref(updated_ref)
85 .properties_ref(properties_ref);
86 for mailbox in request
87 .send()
88 .await
89 .unwrap()
90 .unwrap_method_responses()
91 .pop()
92 .unwrap()
93 .unwrap_get_mailbox()
94 .unwrap()
95 .take_list()
96 {
97 println!("Changed mailbox: {:#?}", mailbox);
98 }
99}Sourcepub fn timeout(self, timeout: Duration) -> Self
pub fn timeout(self, timeout: Duration) -> Self
Set a timeout for all the requests to the JMAP API.
The timeout can be changed after the Client has been created by using Client.set_timeout().
By default the timeout is 10 seconds.
Sourcepub fn accept_invalid_certs(self, accept_invalid_certs: bool) -> Self
pub fn accept_invalid_certs(self, accept_invalid_certs: bool) -> Self
Accepts invalid certificates for all the requests to the JMAP API.
By default certificates are validated.
§Warning
It is not suggested to use this approach in production; this method should be used only for testing and as a last resort.
Sourcepub fn follow_redirects(
self,
trusted_hosts: impl IntoIterator<Item = impl Into<String>>,
) -> Self
pub fn follow_redirects( self, trusted_hosts: impl IntoIterator<Item = impl Into<String>>, ) -> Self
Set a list of trusted hosts that will be checked when a redirect is required.
The list can be changed after the Client has been created by using Client.set_follow_redirects().
The client will follow at most 5 redirects.
Sourcepub fn forwarded_for(self, forwarded_for: IpAddr) -> Self
pub fn forwarded_for(self, forwarded_for: IpAddr) -> Self
Set the originating IP address of the client connecting to the JMAP API.
Sourcepub async fn connect(self, url: &str) -> Result<Client>
pub async fn connect(self, url: &str) -> Result<Client>
Connects to the JMAP API Session URL.
Setting up Credentials must be done before calling this function.
Examples found in repository?
23async fn mailboxes() {
24 // Connect to the JMAP server using Basic authentication
25 let client = Client::new()
26 .credentials(("john@example.org", "secret"))
27 .connect("https://jmap.example.org")
28 .await
29 .unwrap();
30
31 // Create a mailbox
32 let mailbox_id = client
33 .mailbox_create("My Mailbox", None::<String>, Role::None)
34 .await
35 .unwrap()
36 .take_id();
37
38 // Rename a mailbox
39 client
40 .mailbox_rename(&mailbox_id, "My Renamed Mailbox")
41 .await
42 .unwrap();
43
44 // Query mailboxes to obtain Inbox's id
45 let inbox_id = client
46 .mailbox_query(Filter::role(Role::Inbox).into(), None::<Vec<_>>)
47 .await
48 .unwrap()
49 .take_ids()
50 .pop()
51 .unwrap();
52
53 // Print Inbox's details
54 println!(
55 "{:?}",
56 client.mailbox_get(&inbox_id, None::<Vec<_>>).await.unwrap()
57 );
58
59 // Move the newly created mailbox under Inbox
60 client
61 .mailbox_move(&mailbox_id, inbox_id.into())
62 .await
63 .unwrap();
64
65 // Delete the mailbox including any messages
66 client.mailbox_destroy(&mailbox_id, true).await.unwrap();
67}More examples
22async fn event_source() {
23 // Connect to the JMAP server using Basic authentication
24 let client = Client::new()
25 .credentials(("john@example.org", "secret"))
26 .connect("https://jmap.example.org")
27 .await
28 .unwrap();
29
30 // Open EventSource connection
31 let mut stream = client
32 .event_source(
33 [
34 DataType::Email,
35 DataType::EmailDelivery,
36 DataType::Mailbox,
37 DataType::EmailSubmission,
38 DataType::Identity,
39 ]
40 .into(),
41 false,
42 60.into(),
43 None,
44 )
45 .await
46 .unwrap();
47
48 // Consume events
49 while let Some(event) = stream.next().await {
50 use jmap_client::event_source::PushNotification;
51
52 match event.unwrap() {
53 PushNotification::StateChange(changes) => {
54 println!("-> Change id: {:?}", changes.id());
55 for account_id in changes.changed_accounts() {
56 println!(" Account {} has changes:", account_id);
57 if let Some(account_changes) = changes.changes(account_id) {
58 for (type_state, state_id) in account_changes {
59 println!(" Type {:?} has a new state {}.", type_state, state_id);
60 }
61 }
62 }
63 }
64 PushNotification::CalendarAlert(calendar_alert) => {
65 println!(
66 "-> Calendar alert received for event {} (alert id {}).",
67 calendar_alert.calendar_event_id, calendar_alert.alert_id
68 );
69 }
70 }
71 }
72}25async fn websocket() {
26 // Connect to the JMAP server using Basic authentication
27
28 use jmap_client::PushObject;
29
30 let client = Client::new()
31 .credentials(("john@example.org", "secret"))
32 .connect("https://jmap.example.org")
33 .await
34 .unwrap();
35
36 // Connect to the WebSocket endpoint
37 let mut ws_stream = client.connect_ws().await.unwrap();
38
39 // Read WS messages on a separate thread
40 let (stream_tx, mut stream_rx) = mpsc::channel::<WebSocketMessage>(100);
41 tokio::spawn(async move {
42 while let Some(change) = ws_stream.next().await {
43 stream_tx.send(change.unwrap()).await.unwrap();
44 }
45 });
46
47 // Create a mailbox over WS
48 let mut request = client.build();
49 let create_id = request
50 .set_mailbox()
51 .create()
52 .name("WebSocket Test")
53 .create_id()
54 .unwrap();
55 let request_id = request.send_ws().await.unwrap();
56
57 // Read response from WS stream
58 let mailbox_id = if let Some(WebSocketMessage::Response(mut response)) = stream_rx.recv().await
59 {
60 assert_eq!(request_id, response.request_id().unwrap());
61 response
62 .pop_method_response()
63 .unwrap()
64 .unwrap_set_mailbox()
65 .unwrap()
66 .created(&create_id)
67 .unwrap()
68 .take_id()
69 } else {
70 unreachable!()
71 };
72
73 // Enable push notifications over WS
74 client
75 .enable_push_ws(None::<Vec<_>>, None::<&str>)
76 .await
77 .unwrap();
78
79 // Make changes over standard HTTP and expect a push notification via WS
80 client
81 .mailbox_update_sort_order(&mailbox_id, 1)
82 .await
83 .unwrap();
84 if let Some(WebSocketMessage::PushNotification(PushObject::StateChange { changed })) =
85 stream_rx.recv().await
86 {
87 println!("Received changes: {:?}", changed);
88 } else {
89 unreachable!()
90 }
91}33async fn messages() {
34 // Connect to the JMAP server using Basic authentication
35 let client = Client::new()
36 .credentials(("john@example.org", "secret"))
37 .connect("https://jmap.example.org")
38 .await
39 .unwrap();
40
41 // Query mailboxes to obtain Inbox and Trash folder id
42 let inbox_id = client
43 .mailbox_query(
44 mailbox::query::Filter::role(Role::Inbox).into(),
45 None::<Vec<_>>,
46 )
47 .await
48 .unwrap()
49 .take_ids()
50 .pop()
51 .unwrap();
52 let trash_id = client
53 .mailbox_query(
54 mailbox::query::Filter::role(Role::Trash).into(),
55 None::<Vec<_>>,
56 )
57 .await
58 .unwrap()
59 .take_ids()
60 .pop()
61 .unwrap();
62
63 // Import message into inbox
64 client
65 .email_import(TEST_MESSAGE.to_vec(), [&inbox_id], ["$draft"].into(), None)
66 .await
67 .unwrap();
68
69 // Query mailbox
70 let email_id = client
71 .email_query(
72 Filter::and([
73 email::query::Filter::subject("test"),
74 email::query::Filter::in_mailbox(&inbox_id),
75 email::query::Filter::has_keyword("$draft"),
76 ])
77 .into(),
78 [email::query::Comparator::from()].into(),
79 )
80 .await
81 .unwrap()
82 .take_ids()
83 .pop()
84 .unwrap();
85
86 // Fetch message
87 let email = client
88 .email_get(
89 &email_id,
90 [Property::Subject, Property::Preview, Property::Keywords].into(),
91 )
92 .await
93 .unwrap()
94 .unwrap();
95 assert_eq!(email.preview().unwrap(), "This is a test.");
96 assert_eq!(email.subject().unwrap(), "Testing JMAP client");
97 assert_eq!(email.keywords(), ["$draft"]);
98
99 // Remove the $draft keyword
100 client
101 .email_set_keyword(&email_id, "$draft", false)
102 .await
103 .unwrap();
104
105 // Replace all keywords
106 client
107 .email_set_keywords(&email_id, ["$seen", "$important"])
108 .await
109 .unwrap();
110
111 // Move the message to the Trash folder
112 client
113 .email_set_mailboxes(&email_id, [&trash_id])
114 .await
115 .unwrap();
116
117 // Destroy the e-mail
118 client.email_destroy(&email_id).await.unwrap();
119}20async fn result_reference() {
21 // Connect to the JMAP server using Basic authentication
22 let client = Client::new()
23 .credentials(("john@example.org", "secret"))
24 .connect("https://jmap.example.org")
25 .await
26 .unwrap();
27
28 // Delete e-mails matching a filter
29 let mut request = client.build();
30 let result_ref = request
31 .query_email()
32 .filter(query::Filter::and([
33 email::query::Filter::has_keyword("$draft"),
34 email::query::Filter::from("bill"),
35 ]))
36 .result_reference();
37 request.set_email().destroy_ref(result_ref);
38 let _destroyed_ids = request
39 .send()
40 .await
41 .unwrap()
42 .unwrap_method_responses()
43 .pop()
44 .unwrap()
45 .unwrap_set_email()
46 .unwrap()
47 .take_destroyed_ids();
48
49 // Fetch mailboxes matching a filter
50 let mut request = client.build();
51 let query_result = request
52 .query_mailbox()
53 .filter(query::Filter::and([
54 mailbox::query::Filter::has_any_role(false),
55 mailbox::query::Filter::is_subscribed(true),
56 ]))
57 .result_reference();
58 request.get_mailbox().ids_ref(query_result).properties([
59 mailbox::Property::Id,
60 mailbox::Property::Name,
61 mailbox::Property::ParentId,
62 mailbox::Property::TotalEmails,
63 mailbox::Property::UnreadEmails,
64 ]);
65 let _mailboxes = request
66 .send()
67 .await
68 .unwrap()
69 .unwrap_method_responses()
70 .pop()
71 .unwrap()
72 .unwrap_get_mailbox()
73 .unwrap()
74 .take_list();
75
76 // Fetch only the updated properties of all mailboxes that changed
77 // since a state.
78 let mut request = client.build();
79 let changes_request = request.changes_mailbox("n").max_changes(0);
80 let properties_ref = changes_request.updated_properties_reference();
81 let updated_ref = changes_request.updated_reference();
82 request
83 .get_mailbox()
84 .ids_ref(updated_ref)
85 .properties_ref(properties_ref);
86 for mailbox in request
87 .send()
88 .await
89 .unwrap()
90 .unwrap_method_responses()
91 .pop()
92 .unwrap()
93 .unwrap_get_mailbox()
94 .unwrap()
95 .take_list()
96 {
97 println!("Changed mailbox: {:#?}", mailbox);
98 }
99}