ClientBuilder

Struct ClientBuilder 

Source
pub struct ClientBuilder { /* private fields */ }

Implementations§

Source§

impl ClientBuilder

Source

pub fn new() -> Self

Creates a new ClientBuilder.

Setting the credentials is required to connect to the JMAP API.

Source

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?
examples/mailboxes.rs (line 26)
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
Hide additional examples
examples/eventsource.rs (line 25)
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                TypeState::Email,
35                TypeState::EmailDelivery,
36                TypeState::Mailbox,
37                TypeState::EmailSubmission,
38                TypeState::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        let changes = event.unwrap();
51        println!("-> Change id: {:?}", changes.id());
52        for account_id in changes.changed_accounts() {
53            println!(" Account {} has changes:", account_id);
54            if let Some(account_changes) = changes.changes(account_id) {
55                for (type_state, state_id) in account_changes {
56                    println!("   Type {:?} has a new state {}.", type_state, state_id);
57                }
58            }
59        }
60    }
61}
examples/websocket.rs (line 28)
25async fn websocket() {
26    // Connect to the JMAP server using Basic authentication
27    let client = Client::new()
28        .credentials(("john@example.org", "secret"))
29        .connect("https://jmap.example.org")
30        .await
31        .unwrap();
32
33    // Connect to the WebSocket endpoint
34    let mut ws_stream = client.connect_ws().await.unwrap();
35
36    // Read WS messages on a separate thread
37    let (stream_tx, mut stream_rx) = mpsc::channel::<WebSocketMessage>(100);
38    tokio::spawn(async move {
39        while let Some(change) = ws_stream.next().await {
40            stream_tx.send(change.unwrap()).await.unwrap();
41        }
42    });
43
44    // Create a mailbox over WS
45    let mut request = client.build();
46    let create_id = request
47        .set_mailbox()
48        .create()
49        .name("WebSocket Test")
50        .create_id()
51        .unwrap();
52    let request_id = request.send_ws().await.unwrap();
53
54    // Read response from WS stream
55    let mailbox_id = if let Some(WebSocketMessage::Response(mut response)) = stream_rx.recv().await
56    {
57        assert_eq!(request_id, response.request_id().unwrap());
58        response
59            .pop_method_response()
60            .unwrap()
61            .unwrap_set_mailbox()
62            .unwrap()
63            .created(&create_id)
64            .unwrap()
65            .take_id()
66    } else {
67        unreachable!()
68    };
69
70    // Enable push notifications over WS
71    client
72        .enable_push_ws(None::<Vec<_>>, None::<&str>)
73        .await
74        .unwrap();
75
76    // Make changes over standard HTTP and expect a push notification via WS
77    client
78        .mailbox_update_sort_order(&mailbox_id, 1)
79        .await
80        .unwrap();
81    if let Some(WebSocketMessage::StateChange(changes)) = stream_rx.recv().await {
82        println!("Received changes: {:?}", changes);
83    } else {
84        unreachable!()
85    }
86}
examples/messages.rs (line 36)
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}
examples/result_reference.rs (line 23)
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}
Source

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.

Source

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.

Read more in the reqwest docs

Source

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.

Source

pub fn forwarded_for(self, forwarded_for: IpAddr) -> Self

Set the originating IP address of the client connecting to the JMAP API.

Source

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?
examples/mailboxes.rs (line 27)
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
Hide additional examples
examples/eventsource.rs (line 26)
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                TypeState::Email,
35                TypeState::EmailDelivery,
36                TypeState::Mailbox,
37                TypeState::EmailSubmission,
38                TypeState::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        let changes = event.unwrap();
51        println!("-> Change id: {:?}", changes.id());
52        for account_id in changes.changed_accounts() {
53            println!(" Account {} has changes:", account_id);
54            if let Some(account_changes) = changes.changes(account_id) {
55                for (type_state, state_id) in account_changes {
56                    println!("   Type {:?} has a new state {}.", type_state, state_id);
57                }
58            }
59        }
60    }
61}
examples/websocket.rs (line 29)
25async fn websocket() {
26    // Connect to the JMAP server using Basic authentication
27    let client = Client::new()
28        .credentials(("john@example.org", "secret"))
29        .connect("https://jmap.example.org")
30        .await
31        .unwrap();
32
33    // Connect to the WebSocket endpoint
34    let mut ws_stream = client.connect_ws().await.unwrap();
35
36    // Read WS messages on a separate thread
37    let (stream_tx, mut stream_rx) = mpsc::channel::<WebSocketMessage>(100);
38    tokio::spawn(async move {
39        while let Some(change) = ws_stream.next().await {
40            stream_tx.send(change.unwrap()).await.unwrap();
41        }
42    });
43
44    // Create a mailbox over WS
45    let mut request = client.build();
46    let create_id = request
47        .set_mailbox()
48        .create()
49        .name("WebSocket Test")
50        .create_id()
51        .unwrap();
52    let request_id = request.send_ws().await.unwrap();
53
54    // Read response from WS stream
55    let mailbox_id = if let Some(WebSocketMessage::Response(mut response)) = stream_rx.recv().await
56    {
57        assert_eq!(request_id, response.request_id().unwrap());
58        response
59            .pop_method_response()
60            .unwrap()
61            .unwrap_set_mailbox()
62            .unwrap()
63            .created(&create_id)
64            .unwrap()
65            .take_id()
66    } else {
67        unreachable!()
68    };
69
70    // Enable push notifications over WS
71    client
72        .enable_push_ws(None::<Vec<_>>, None::<&str>)
73        .await
74        .unwrap();
75
76    // Make changes over standard HTTP and expect a push notification via WS
77    client
78        .mailbox_update_sort_order(&mailbox_id, 1)
79        .await
80        .unwrap();
81    if let Some(WebSocketMessage::StateChange(changes)) = stream_rx.recv().await {
82        println!("Received changes: {:?}", changes);
83    } else {
84        unreachable!()
85    }
86}
examples/messages.rs (line 37)
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}
examples/result_reference.rs (line 24)
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}

Trait Implementations§

Source§

impl Default for ClientBuilder

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,