resend_rs/
client.rs

1use std::sync::Arc;
2use std::{env, fmt};
3
4#[cfg(not(feature = "blocking"))]
5use reqwest::Client as ReqwestClient;
6#[cfg(feature = "blocking")]
7use reqwest::blocking::Client as ReqwestClient;
8
9use crate::{batch::BatchSvc, config::Config, services::ReceivingSvc, webhooks::WebhookSvc};
10use crate::{
11    services::{
12        ApiKeysSvc, BroadcastsSvc, ContactsSvc, DomainsSvc, EmailsSvc, SegmentsSvc, TemplateSvc,
13    },
14    topics::TopicsSvc,
15};
16
17#[cfg(doc)]
18use crate::ConfigBuilder;
19
20/// The [Resend](https://resend.com) client.
21#[must_use]
22#[derive(Clone)]
23pub struct Resend {
24    /// `Resend` APIs for `/emails` endpoints.
25    pub emails: EmailsSvc,
26    /// `Resend` APIs for the batch `/emails` endpoints.
27    pub batch: BatchSvc,
28    /// `Resend` APIs for `/api-keys` endpoints.
29    pub api_keys: ApiKeysSvc,
30    /// `Resend` APIs for `/audiences` endpoints.
31    pub segments: SegmentsSvc,
32    /// `Resend` APIs for `/audiences/:id/contacts` endpoints.
33    pub contacts: ContactsSvc,
34    /// `Resend` APIs for `/domains` endpoints.
35    pub domains: DomainsSvc,
36    /// `Resend` APIs for `/broadcasts` endpoints.
37    pub broadcasts: BroadcastsSvc,
38    /// `Resend` APIs for `/templates` endpoints.
39    pub templates: TemplateSvc,
40    /// `Resend` APIs for `/topics` endpoints.
41    pub topics: TopicsSvc,
42    /// `Resend` APIs for `/emails/receiving` endpoints.
43    pub receiving: ReceivingSvc,
44    /// `Resend` APIs for `/webhooks` endpoints.
45    pub webhooks: WebhookSvc,
46}
47
48impl Resend {
49    /// Creates a new [`Resend`] client.
50    ///
51    /// ### Panics
52    ///
53    /// - Panics if the environment variable `RESEND_BASE_URL` is set but is not a valid `URL`.
54    ///
55    /// [`Resend`]: https://resend.com
56    pub fn new(api_key: &str) -> Self {
57        Self::with_client(api_key, ReqwestClient::default())
58    }
59
60    /// Creates a new [`Resend`] client with a provided [`reqwest::Client`].
61    ///
62    /// ### Panics
63    ///
64    /// - Panics if the environment variable `RESEND_BASE_URL` is set but is not a valid `URL`.
65    ///
66    /// [`Resend`]: https://resend.com
67    /// [`reqwest::Client`]: ReqwestClient
68    pub fn with_client(api_key: &str, client: ReqwestClient) -> Self {
69        let config = Config::new(api_key.to_owned(), client, None);
70        Self::with_config(config)
71    }
72
73    /// Creates a new [`Resend`] client with a provided [`Config`].
74    ///
75    /// Use [`ConfigBuilder::new`] to construct a [`Config`] instance.
76    ///
77    /// ### Panics
78    ///
79    /// -   Panics if the base url has not been set with [`ConfigBuilder::base_url`]
80    ///     and the environment variable `RESEND_BASE_URL` _is_ set but is not a valid `URL`.
81    ///
82    /// [`Resend`]: https://resend.com
83    /// [`reqwest::Client`]: ReqwestClient
84    pub fn with_config(config: Config) -> Self {
85        let inner = Arc::new(config);
86        Self {
87            api_keys: ApiKeysSvc(Arc::clone(&inner)),
88            segments: SegmentsSvc(Arc::clone(&inner)),
89            contacts: ContactsSvc(Arc::clone(&inner)),
90            domains: DomainsSvc(Arc::clone(&inner)),
91            emails: EmailsSvc(Arc::clone(&inner)),
92            batch: BatchSvc(Arc::clone(&inner)),
93            broadcasts: BroadcastsSvc(Arc::clone(&inner)),
94            templates: TemplateSvc(Arc::clone(&inner)),
95            topics: TopicsSvc(Arc::clone(&inner)),
96            receiving: ReceivingSvc(Arc::clone(&inner)),
97            webhooks: WebhookSvc(inner),
98        }
99    }
100
101    /// Returns the reference to the used `User-Agent` header value.
102    #[inline]
103    #[must_use]
104    pub fn user_agent(&self) -> &str {
105        self.config().user_agent.as_str()
106    }
107
108    /// Returns the reference to the provided `API key`.
109    #[inline]
110    #[must_use]
111    pub fn api_key(&self) -> &str {
112        self.config().api_key.as_ref()
113    }
114
115    /// Returns the reference to the used `base URL`.
116    ///
117    /// ### Notes
118    ///
119    /// Use the `RESEND_BASE_URL` environment variable to override.
120    #[inline]
121    #[must_use]
122    pub fn base_url(&self) -> &str {
123        self.config().base_url.as_str()
124    }
125
126    /// Returns the underlying [`reqwest::Client`].
127    ///
128    /// [`reqwest::Client`]: ReqwestClient
129    #[inline]
130    #[must_use]
131    pub fn client(&self) -> ReqwestClient {
132        self.config().client.clone()
133    }
134
135    #[allow(clippy::missing_const_for_fn)]
136    /// Returns the reference to the inner [`Config`].
137    #[inline]
138    fn config(&self) -> &Config {
139        &self.emails.0
140    }
141}
142
143impl Default for Resend {
144    /// Creates a new [`Resend`] client from the `RESEND_API_KEY` environment variable .
145    ///
146    /// ### Panics
147    ///
148    /// - Panics if the environment variable `RESEND_API_KEY` is not set.
149    /// - Panics if the environment variable `RESEND_BASE_URL` is set but is not a valid `URL`.
150    fn default() -> Self {
151        let api_key = env::var("RESEND_API_KEY")
152            .expect("env variable `RESEND_API_KEY` should be a valid API key");
153
154        Self::new(api_key.as_str())
155    }
156}
157
158impl fmt::Debug for Resend {
159    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160        fmt::Debug::fmt(&self.emails, f)
161    }
162}