1#![allow(clippy::derive_partial_eq_without_eq)]
60#![allow(clippy::too_many_arguments)]
61#![allow(clippy::nonstandard_macro_braces)]
62#![allow(clippy::large_enum_variant)]
63#![allow(clippy::tabs_in_doc_comments)]
64#![allow(missing_docs)]
65#![cfg_attr(docsrs, feature(doc_cfg))]
66
67pub mod alerts;
68pub mod api_key_permissions;
69pub mod api_keys;
70pub mod blocks_api;
71pub mod bounces_api;
72pub mod campaigns_api;
73pub mod cancel_scheduled_sends;
74pub mod categories;
75pub mod certificates;
76pub mod contacts;
77pub mod contacts_api_custom_fields;
78pub mod contacts_api_lists;
79pub mod contacts_api_recipients;
80pub mod contacts_api_segments;
81pub mod csv_ui_only;
82pub mod custom_fields;
83pub mod designs_api;
84pub mod domain_authentication;
85pub mod email_address_validation;
86pub mod email_cname_records;
87pub mod invalid_emails_api;
88pub mod ip_access_management;
89pub mod ip_addresses;
90pub mod ip_pools;
91pub mod ip_warmup;
92pub mod link_branding;
93pub mod lists;
94pub mod mail_send;
95pub mod marketing_campaigns_stats;
96pub mod query;
97pub mod reverse_dns;
98pub mod segmenting_contacts;
99pub mod segmenting_contacts_beta;
100pub mod send_test_email;
101pub mod sender_identities_api;
102pub mod sender_verification;
103pub mod senders;
104pub mod settings_enforced_tls;
105pub mod settings_inbound_parse;
106pub mod settings_mail;
107pub mod settings_partner;
108pub mod settings_tracking;
109pub mod single_sends;
110pub mod single_sign_on_settings;
111pub mod single_sign_on_teammates;
112pub mod spam_reports_api;
113pub mod stats;
114pub mod subuser_monitor_settings;
115pub mod subuser_statistics;
116pub mod subusers_api;
117pub mod suppressions;
118pub mod suppressions_global;
119pub mod suppressions_unsubscribe_groups;
120pub mod teammates;
121pub mod traits;
122pub mod transactional_templates;
123pub mod transactional_templates_versions;
124pub mod types;
125pub mod users_api;
126#[doc(hidden)]
127pub mod utils;
128pub mod webhooks;
129
130pub use reqwest::{header::HeaderMap, StatusCode};
131
132#[derive(Debug)]
133pub struct Response<T> {
134 pub status: reqwest::StatusCode,
135 pub headers: reqwest::header::HeaderMap,
136 pub body: T,
137}
138
139impl<T> Response<T> {
140 pub fn new(status: reqwest::StatusCode, headers: reqwest::header::HeaderMap, body: T) -> Self {
141 Self {
142 status,
143 headers,
144 body,
145 }
146 }
147}
148
149type ClientResult<T> = Result<T, ClientError>;
150
151use thiserror::Error;
152
153#[derive(Debug, Error)]
155pub enum ClientError {
156 #[error(transparent)]
158 FromUtf8Error(#[from] std::string::FromUtf8Error),
159 #[error(transparent)]
161 UrlParserError(#[from] url::ParseError),
162 #[error(transparent)]
164 SerdeJsonError(#[from] serde_json::Error),
165 #[error(transparent)]
167 ReqwestError(#[from] reqwest::Error),
168 #[error(transparent)]
170 InvalidHeaderValue(#[from] reqwest::header::InvalidHeaderValue),
171 #[error(transparent)]
173 ReqwestMiddleWareError(#[from] reqwest_middleware::Error),
174 #[error("HTTP Error. Code: {status}, message: {error}")]
176 HttpError {
177 status: http::StatusCode,
178 headers: reqwest::header::HeaderMap,
179 error: String,
180 },
181}
182
183pub const FALLBACK_HOST: &str = "https://api.sendgrid.com/v3";
184
185mod progenitor_support {
186 use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
187
188 const PATH_SET: &AsciiSet = &CONTROLS
189 .add(b' ')
190 .add(b'"')
191 .add(b'#')
192 .add(b'<')
193 .add(b'>')
194 .add(b'?')
195 .add(b'`')
196 .add(b'{')
197 .add(b'}');
198
199 #[allow(dead_code)]
200 pub(crate) fn encode_path(pc: &str) -> String {
201 utf8_percent_encode(pc, PATH_SET).to_string()
202 }
203}
204
205#[derive(Debug, Default)]
206pub(crate) struct Message {
207 pub body: Option<reqwest::Body>,
208 pub content_type: Option<String>,
209}
210
211use std::env;
212
213#[derive(Debug, Default, Clone)]
214pub struct RootDefaultServer {}
215
216impl RootDefaultServer {
217 pub fn default_url(&self) -> &str {
218 "https://api.sendgrid.com/v3"
219 }
220}
221
222#[derive(Clone)]
224pub struct Client {
225 host: String,
226 host_override: Option<String>,
227 token: String,
228
229 client: reqwest_middleware::ClientWithMiddleware,
230}
231
232impl Client {
233 pub fn new<T>(token: T) -> Self
239 where
240 T: ToString,
241 {
242 let client = reqwest::Client::builder()
243 .redirect(reqwest::redirect::Policy::none())
244 .build();
245 let retry_policy =
246 reqwest_retry::policies::ExponentialBackoff::builder().build_with_max_retries(3);
247 match client {
248 Ok(c) => {
249 let client = reqwest_middleware::ClientBuilder::new(c)
250 .with(reqwest_tracing::TracingMiddleware::default())
252 .with(reqwest_conditional_middleware::ConditionalMiddleware::new(
254 reqwest_retry::RetryTransientMiddleware::new_with_policy(retry_policy),
255 |req: &reqwest::Request| req.try_clone().is_some(),
256 ))
257 .build();
258
259 let host = RootDefaultServer::default().default_url().to_string();
260
261 Client {
262 host,
263 host_override: None,
264 token: token.to_string(),
265
266 client,
267 }
268 }
269 Err(e) => panic!("creating reqwest client failed: {:?}", e),
270 }
271 }
272
273 pub fn with_host_override<H>(&mut self, host: H) -> &mut Self
275 where
276 H: ToString,
277 {
278 self.host_override = Some(host.to_string());
279 self
280 }
281
282 pub fn remove_host_override(&mut self) -> &mut Self {
284 self.host_override = None;
285 self
286 }
287
288 pub fn get_host_override(&self) -> Option<&str> {
289 self.host_override.as_deref()
290 }
291
292 pub(crate) fn url(&self, path: &str, host: Option<&str>) -> String {
293 format!(
294 "{}{}",
295 self.get_host_override()
296 .or(host)
297 .unwrap_or(self.host.as_str()),
298 path
299 )
300 }
301
302 pub fn new_from_env() -> Self {
311 let token = env::var("SENDGRID_API_KEY").expect("must set SENDGRID_API_KEY");
312
313 Client::new(token)
314 }
315
316 async fn url_and_auth(&self, uri: &str) -> ClientResult<(reqwest::Url, Option<String>)> {
317 let parsed_url = uri.parse::<reqwest::Url>()?;
318 let auth = format!("Bearer {}", self.token);
319 Ok((parsed_url, Some(auth)))
320 }
321
322 async fn request_raw(
323 &self,
324 method: reqwest::Method,
325 uri: &str,
326 message: Message,
327 ) -> ClientResult<reqwest::Response> {
328 let (url, auth) = self.url_and_auth(uri).await?;
329 let instance = <&Client>::clone(&self);
330 let mut req = instance.client.request(method.clone(), url);
331 req = req.header(
333 reqwest::header::ACCEPT,
334 reqwest::header::HeaderValue::from_static("application/json"),
335 );
336
337 if let Some(content_type) = &message.content_type {
338 req = req.header(
339 reqwest::header::CONTENT_TYPE,
340 reqwest::header::HeaderValue::from_str(content_type).unwrap(),
341 );
342 } else {
343 req = req.header(
344 reqwest::header::CONTENT_TYPE,
345 reqwest::header::HeaderValue::from_static("application/json"),
346 );
347 }
348
349 if let Some(auth_str) = auth {
350 req = req.header(http::header::AUTHORIZATION, &*auth_str);
351 }
352 if let Some(body) = message.body {
353 req = req.body(body);
354 }
355 Ok(req.send().await?)
356 }
357
358 async fn request<Out>(
359 &self,
360 method: reqwest::Method,
361 uri: &str,
362 message: Message,
363 ) -> ClientResult<crate::Response<Out>>
364 where
365 Out: serde::de::DeserializeOwned + 'static + Send,
366 {
367 let response = self.request_raw(method, uri, message).await?;
368
369 let status = response.status();
370 let headers = response.headers().clone();
371
372 let response_body = response.bytes().await?;
373
374 if status.is_success() {
375 log::debug!("Received successful response. Read payload.");
376 let parsed_response = if status == http::StatusCode::NO_CONTENT
377 || std::any::TypeId::of::<Out>() == std::any::TypeId::of::<()>()
378 {
379 serde_json::from_str("null")?
380 } else {
381 serde_json::from_slice::<Out>(&response_body)?
382 };
383 Ok(crate::Response::new(status, headers, parsed_response))
384 } else {
385 let error = if response_body.is_empty() {
386 ClientError::HttpError {
387 status,
388 headers,
389 error: "empty response".into(),
390 }
391 } else {
392 ClientError::HttpError {
393 status,
394 headers,
395 error: String::from_utf8_lossy(&response_body).into(),
396 }
397 };
398
399 Err(error)
400 }
401 }
402
403 async fn request_with_links<Out>(
404 &self,
405 method: http::Method,
406 uri: &str,
407 message: Message,
408 ) -> ClientResult<(Option<crate::utils::NextLink>, crate::Response<Out>)>
409 where
410 Out: serde::de::DeserializeOwned + 'static + Send,
411 {
412 let response = self.request_raw(method, uri, message).await?;
413
414 let status = response.status();
415 let headers = response.headers().clone();
416 let link = response
417 .headers()
418 .get(http::header::LINK)
419 .and_then(|l| l.to_str().ok())
420 .and_then(|l| parse_link_header::parse(l).ok())
421 .as_ref()
422 .and_then(crate::utils::next_link);
423
424 let response_body = response.bytes().await?;
425
426 if status.is_success() {
427 log::debug!("Received successful response. Read payload.");
428
429 let parsed_response = if status == http::StatusCode::NO_CONTENT
430 || std::any::TypeId::of::<Out>() == std::any::TypeId::of::<()>()
431 {
432 serde_json::from_str("null")?
433 } else {
434 serde_json::from_slice::<Out>(&response_body)?
435 };
436 Ok((link, crate::Response::new(status, headers, parsed_response)))
437 } else {
438 let error = if response_body.is_empty() {
439 ClientError::HttpError {
440 status,
441 headers,
442 error: "empty response".into(),
443 }
444 } else {
445 ClientError::HttpError {
446 status,
447 headers,
448 error: String::from_utf8_lossy(&response_body).into(),
449 }
450 };
451 Err(error)
452 }
453 }
454
455 #[allow(dead_code)]
457 async fn post_form<Out>(
458 &self,
459 uri: &str,
460 form: reqwest::multipart::Form,
461 ) -> ClientResult<crate::Response<Out>>
462 where
463 Out: serde::de::DeserializeOwned + 'static + Send,
464 {
465 let (url, auth) = self.url_and_auth(uri).await?;
466
467 let instance = <&Client>::clone(&self);
468
469 let mut req = instance.client.request(http::Method::POST, url);
470
471 req = req.header(
473 reqwest::header::ACCEPT,
474 reqwest::header::HeaderValue::from_static("application/json"),
475 );
476
477 if let Some(auth_str) = auth {
478 req = req.header(http::header::AUTHORIZATION, &*auth_str);
479 }
480
481 req = req.multipart(form);
482
483 let response = req.send().await?;
484
485 let status = response.status();
486 let headers = response.headers().clone();
487
488 let response_body = response.bytes().await?;
489
490 if status.is_success() {
491 log::debug!("Received successful response. Read payload.");
492 let parsed_response = if status == http::StatusCode::NO_CONTENT
493 || std::any::TypeId::of::<Out>() == std::any::TypeId::of::<()>()
494 {
495 serde_json::from_str("null")?
496 } else if std::any::TypeId::of::<Out>() == std::any::TypeId::of::<String>() {
497 let s = String::from_utf8(response_body.to_vec())?;
499 serde_json::from_value(serde_json::json!(&s))?
500 } else {
501 serde_json::from_slice::<Out>(&response_body)?
502 };
503 Ok(crate::Response::new(status, headers, parsed_response))
504 } else {
505 let error = if response_body.is_empty() {
506 ClientError::HttpError {
507 status,
508 headers,
509 error: "empty response".into(),
510 }
511 } else {
512 ClientError::HttpError {
513 status,
514 headers,
515 error: String::from_utf8_lossy(&response_body).into(),
516 }
517 };
518
519 Err(error)
520 }
521 }
522
523 #[allow(dead_code)]
525 async fn request_with_accept_mime<Out>(
526 &self,
527 method: reqwest::Method,
528 uri: &str,
529 accept_mime_type: &str,
530 ) -> ClientResult<crate::Response<Out>>
531 where
532 Out: serde::de::DeserializeOwned + 'static + Send,
533 {
534 let (url, auth) = self.url_and_auth(uri).await?;
535
536 let instance = <&Client>::clone(&self);
537
538 let mut req = instance.client.request(method, url);
539
540 req = req.header(
542 reqwest::header::ACCEPT,
543 reqwest::header::HeaderValue::from_str(accept_mime_type)?,
544 );
545
546 if let Some(auth_str) = auth {
547 req = req.header(http::header::AUTHORIZATION, &*auth_str);
548 }
549
550 let response = req.send().await?;
551
552 let status = response.status();
553 let headers = response.headers().clone();
554
555 let response_body = response.bytes().await?;
556
557 if status.is_success() {
558 log::debug!("Received successful response. Read payload.");
559 let parsed_response = if status == http::StatusCode::NO_CONTENT
560 || std::any::TypeId::of::<Out>() == std::any::TypeId::of::<()>()
561 {
562 serde_json::from_str("null")?
563 } else if std::any::TypeId::of::<Out>() == std::any::TypeId::of::<String>() {
564 let s = String::from_utf8(response_body.to_vec())?;
566 serde_json::from_value(serde_json::json!(&s))?
567 } else {
568 serde_json::from_slice::<Out>(&response_body)?
569 };
570 Ok(crate::Response::new(status, headers, parsed_response))
571 } else {
572 let error = if response_body.is_empty() {
573 ClientError::HttpError {
574 status,
575 headers,
576 error: "empty response".into(),
577 }
578 } else {
579 ClientError::HttpError {
580 status,
581 headers,
582 error: String::from_utf8_lossy(&response_body).into(),
583 }
584 };
585
586 Err(error)
587 }
588 }
589
590 #[allow(dead_code)]
592 async fn request_with_mime<Out>(
593 &self,
594 method: reqwest::Method,
595 uri: &str,
596 content: &[u8],
597 mime_type: &str,
598 ) -> ClientResult<crate::Response<Out>>
599 where
600 Out: serde::de::DeserializeOwned + 'static + Send,
601 {
602 let (url, auth) = self.url_and_auth(uri).await?;
603
604 let instance = <&Client>::clone(&self);
605
606 let mut req = instance.client.request(method, url);
607
608 req = req.header(
610 reqwest::header::ACCEPT,
611 reqwest::header::HeaderValue::from_static("application/json"),
612 );
613 req = req.header(
614 reqwest::header::CONTENT_TYPE,
615 reqwest::header::HeaderValue::from_bytes(mime_type.as_bytes()).unwrap(),
616 );
617 req = req.header(
619 reqwest::header::HeaderName::from_static("x-upload-content-type"),
620 reqwest::header::HeaderValue::from_static("application/octet-stream"),
621 );
622 req = req.header(
623 reqwest::header::HeaderName::from_static("x-upload-content-length"),
624 reqwest::header::HeaderValue::from_bytes(format!("{}", content.len()).as_bytes())
625 .unwrap(),
626 );
627
628 if let Some(auth_str) = auth {
629 req = req.header(http::header::AUTHORIZATION, &*auth_str);
630 }
631
632 if content.len() > 1 {
633 let b = bytes::Bytes::copy_from_slice(content);
634 req = req.body(b);
636 }
637
638 let response = req.send().await?;
639
640 let status = response.status();
641 let headers = response.headers().clone();
642
643 let response_body = response.bytes().await?;
644
645 if status.is_success() {
646 log::debug!("Received successful response. Read payload.");
647 let parsed_response = if status == http::StatusCode::NO_CONTENT
648 || std::any::TypeId::of::<Out>() == std::any::TypeId::of::<()>()
649 {
650 serde_json::from_str("null")?
651 } else {
652 serde_json::from_slice::<Out>(&response_body)?
653 };
654 Ok(crate::Response::new(status, headers, parsed_response))
655 } else {
656 let error = if response_body.is_empty() {
657 ClientError::HttpError {
658 status,
659 headers,
660 error: "empty response".into(),
661 }
662 } else {
663 ClientError::HttpError {
664 status,
665 headers,
666 error: String::from_utf8_lossy(&response_body).into(),
667 }
668 };
669
670 Err(error)
671 }
672 }
673
674 async fn request_entity<D>(
675 &self,
676 method: http::Method,
677 uri: &str,
678 message: Message,
679 ) -> ClientResult<crate::Response<D>>
680 where
681 D: serde::de::DeserializeOwned + 'static + Send,
682 {
683 let r = self.request(method, uri, message).await?;
684 Ok(r)
685 }
686
687 #[allow(dead_code)]
688 async fn get<D>(&self, uri: &str, message: Message) -> ClientResult<crate::Response<D>>
689 where
690 D: serde::de::DeserializeOwned + 'static + Send,
691 {
692 self.request_entity(http::Method::GET, uri, message).await
693 }
694
695 #[allow(dead_code)]
696 async fn get_all_pages<D>(&self, uri: &str, _message: Message) -> ClientResult<Response<Vec<D>>>
697 where
698 D: serde::de::DeserializeOwned + 'static + Send,
699 {
700 self.unfold(uri).await
702 }
703
704 #[allow(dead_code)]
706 async fn unfold<D>(&self, uri: &str) -> ClientResult<crate::Response<Vec<D>>>
707 where
708 D: serde::de::DeserializeOwned + 'static + Send,
709 {
710 let mut global_items = Vec::new();
711 let (new_link, mut response) = self.get_pages(uri).await?;
712 let mut link = new_link;
713 while !response.body.is_empty() {
714 global_items.append(&mut response.body);
715 if let Some(url) = &link {
717 let url = reqwest::Url::parse(&url.0)?;
718 let (new_link, new_response) = self.get_pages_url(&url).await?;
719 link = new_link;
720 response = new_response;
721 }
722 }
723
724 Ok(Response::new(
725 response.status,
726 response.headers,
727 global_items,
728 ))
729 }
730
731 #[allow(dead_code)]
732 async fn get_pages<D>(
733 &self,
734 uri: &str,
735 ) -> ClientResult<(Option<crate::utils::NextLink>, crate::Response<Vec<D>>)>
736 where
737 D: serde::de::DeserializeOwned + 'static + Send,
738 {
739 self.request_with_links(http::Method::GET, uri, Message::default())
740 .await
741 }
742
743 #[allow(dead_code)]
744 async fn get_pages_url<D>(
745 &self,
746 url: &reqwest::Url,
747 ) -> ClientResult<(Option<crate::utils::NextLink>, crate::Response<Vec<D>>)>
748 where
749 D: serde::de::DeserializeOwned + 'static + Send,
750 {
751 self.request_with_links(http::Method::GET, url.as_str(), Message::default())
752 .await
753 }
754
755 #[allow(dead_code)]
756 async fn post<D>(&self, uri: &str, message: Message) -> ClientResult<crate::Response<D>>
757 where
758 D: serde::de::DeserializeOwned + 'static + Send,
759 {
760 self.request_entity(http::Method::POST, uri, message).await
761 }
762
763 #[allow(dead_code)]
764 async fn patch<D>(&self, uri: &str, message: Message) -> ClientResult<crate::Response<D>>
765 where
766 D: serde::de::DeserializeOwned + 'static + Send,
767 {
768 self.request_entity(http::Method::PATCH, uri, message).await
769 }
770
771 #[allow(dead_code)]
772 async fn put<D>(&self, uri: &str, message: Message) -> ClientResult<crate::Response<D>>
773 where
774 D: serde::de::DeserializeOwned + 'static + Send,
775 {
776 self.request_entity(http::Method::PUT, uri, message).await
777 }
778
779 #[allow(dead_code)]
780 async fn delete<D>(&self, uri: &str, message: Message) -> ClientResult<crate::Response<D>>
781 where
782 D: serde::de::DeserializeOwned + 'static + Send,
783 {
784 self.request_entity(http::Method::DELETE, uri, message)
785 .await
786 }
787
788 pub fn alerts(&self) -> alerts::Alerts {
789 alerts::Alerts::new(self.clone())
790 }
791
792 pub fn api_key_permissions(&self) -> api_key_permissions::ApiKeyPermissions {
793 api_key_permissions::ApiKeyPermissions::new(self.clone())
794 }
795
796 pub fn api_keys(&self) -> api_keys::ApiKeys {
797 api_keys::ApiKeys::new(self.clone())
798 }
799
800 pub fn blocks_api(&self) -> blocks_api::BlocksApi {
801 blocks_api::BlocksApi::new(self.clone())
802 }
803
804 pub fn bounces_api(&self) -> bounces_api::BouncesApi {
805 bounces_api::BouncesApi::new(self.clone())
806 }
807
808 pub fn campaigns_api(&self) -> campaigns_api::CampaignsApi {
809 campaigns_api::CampaignsApi::new(self.clone())
810 }
811
812 pub fn cancel_scheduled_sends(&self) -> cancel_scheduled_sends::CancelScheduledSends {
813 cancel_scheduled_sends::CancelScheduledSends::new(self.clone())
814 }
815
816 pub fn categories(&self) -> categories::Categories {
817 categories::Categories::new(self.clone())
818 }
819
820 pub fn certificates(&self) -> certificates::Certificates {
821 certificates::Certificates::new(self.clone())
822 }
823
824 pub fn contacts(&self) -> contacts::Contacts {
825 contacts::Contacts::new(self.clone())
826 }
827
828 pub fn contacts_api_custom_fields(
829 &self,
830 ) -> contacts_api_custom_fields::ContactsApiCustomFields {
831 contacts_api_custom_fields::ContactsApiCustomFields::new(self.clone())
832 }
833
834 pub fn contacts_api_lists(&self) -> contacts_api_lists::ContactsApiLists {
835 contacts_api_lists::ContactsApiLists::new(self.clone())
836 }
837
838 pub fn contacts_api_recipients(&self) -> contacts_api_recipients::ContactsApiRecipients {
839 contacts_api_recipients::ContactsApiRecipients::new(self.clone())
840 }
841
842 pub fn contacts_api_segments(&self) -> contacts_api_segments::ContactsApiSegments {
843 contacts_api_segments::ContactsApiSegments::new(self.clone())
844 }
845
846 pub fn csv_ui_only(&self) -> csv_ui_only::CsvUiOnly {
847 csv_ui_only::CsvUiOnly::new(self.clone())
848 }
849
850 pub fn custom_fields(&self) -> custom_fields::CustomFields {
851 custom_fields::CustomFields::new(self.clone())
852 }
853
854 pub fn designs_api(&self) -> designs_api::DesignsApi {
855 designs_api::DesignsApi::new(self.clone())
856 }
857
858 pub fn domain_authentication(&self) -> domain_authentication::DomainAuthentication {
859 domain_authentication::DomainAuthentication::new(self.clone())
860 }
861
862 pub fn email_address_validation(&self) -> email_address_validation::EmailAddressValidation {
863 email_address_validation::EmailAddressValidation::new(self.clone())
864 }
865
866 pub fn email_cname_records(&self) -> email_cname_records::EmailCnameRecords {
867 email_cname_records::EmailCnameRecords::new(self.clone())
868 }
869
870 pub fn invalid_emails_api(&self) -> invalid_emails_api::InvalidEmailsApi {
871 invalid_emails_api::InvalidEmailsApi::new(self.clone())
872 }
873
874 pub fn ip_access_management(&self) -> ip_access_management::IpAccessManagement {
875 ip_access_management::IpAccessManagement::new(self.clone())
876 }
877
878 pub fn ip_addresses(&self) -> ip_addresses::IpAddresses {
879 ip_addresses::IpAddresses::new(self.clone())
880 }
881
882 pub fn ip_pools(&self) -> ip_pools::IpPools {
883 ip_pools::IpPools::new(self.clone())
884 }
885
886 pub fn ip_warmup(&self) -> ip_warmup::IpWarmup {
887 ip_warmup::IpWarmup::new(self.clone())
888 }
889
890 pub fn link_branding(&self) -> link_branding::LinkBranding {
891 link_branding::LinkBranding::new(self.clone())
892 }
893
894 pub fn lists(&self) -> lists::Lists {
895 lists::Lists::new(self.clone())
896 }
897
898 pub fn mail_send(&self) -> mail_send::MailSend {
899 mail_send::MailSend::new(self.clone())
900 }
901
902 pub fn marketing_campaigns_stats(&self) -> marketing_campaigns_stats::MarketingCampaignsStats {
903 marketing_campaigns_stats::MarketingCampaignsStats::new(self.clone())
904 }
905
906 pub fn query(&self) -> query::Query {
907 query::Query::new(self.clone())
908 }
909
910 pub fn reverse_dns(&self) -> reverse_dns::ReverseDns {
911 reverse_dns::ReverseDns::new(self.clone())
912 }
913
914 pub fn segmenting_contacts(&self) -> segmenting_contacts::SegmentingContacts {
915 segmenting_contacts::SegmentingContacts::new(self.clone())
916 }
917
918 pub fn segmenting_contacts_beta(&self) -> segmenting_contacts_beta::SegmentingContactsBeta {
919 segmenting_contacts_beta::SegmentingContactsBeta::new(self.clone())
920 }
921
922 pub fn send_test_email(&self) -> send_test_email::SendTestEmail {
923 send_test_email::SendTestEmail::new(self.clone())
924 }
925
926 pub fn sender_identities_api(&self) -> sender_identities_api::SenderIdentitiesApi {
927 sender_identities_api::SenderIdentitiesApi::new(self.clone())
928 }
929
930 pub fn sender_verification(&self) -> sender_verification::SenderVerification {
931 sender_verification::SenderVerification::new(self.clone())
932 }
933
934 pub fn senders(&self) -> senders::Senders {
935 senders::Senders::new(self.clone())
936 }
937
938 pub fn settings_enforced_tls(&self) -> settings_enforced_tls::SettingsEnforcedTls {
939 settings_enforced_tls::SettingsEnforcedTls::new(self.clone())
940 }
941
942 pub fn settings_inbound_parse(&self) -> settings_inbound_parse::SettingsInboundParse {
943 settings_inbound_parse::SettingsInboundParse::new(self.clone())
944 }
945
946 pub fn settings_mail(&self) -> settings_mail::SettingsMail {
947 settings_mail::SettingsMail::new(self.clone())
948 }
949
950 pub fn settings_partner(&self) -> settings_partner::SettingsPartner {
951 settings_partner::SettingsPartner::new(self.clone())
952 }
953
954 pub fn settings_tracking(&self) -> settings_tracking::SettingsTracking {
955 settings_tracking::SettingsTracking::new(self.clone())
956 }
957
958 pub fn single_sends(&self) -> single_sends::SingleSends {
959 single_sends::SingleSends::new(self.clone())
960 }
961
962 pub fn single_sign_on_settings(&self) -> single_sign_on_settings::SingleSignOnSettings {
963 single_sign_on_settings::SingleSignOnSettings::new(self.clone())
964 }
965
966 pub fn single_sign_on_teammates(&self) -> single_sign_on_teammates::SingleSignOnTeammates {
967 single_sign_on_teammates::SingleSignOnTeammates::new(self.clone())
968 }
969
970 pub fn spam_reports_api(&self) -> spam_reports_api::SpamReportsApi {
971 spam_reports_api::SpamReportsApi::new(self.clone())
972 }
973
974 pub fn stats(&self) -> stats::Stats {
975 stats::Stats::new(self.clone())
976 }
977
978 pub fn subuser_monitor_settings(&self) -> subuser_monitor_settings::SubuserMonitorSettings {
979 subuser_monitor_settings::SubuserMonitorSettings::new(self.clone())
980 }
981
982 pub fn subuser_statistics(&self) -> subuser_statistics::SubuserStatistics {
983 subuser_statistics::SubuserStatistics::new(self.clone())
984 }
985
986 pub fn subusers_api(&self) -> subusers_api::SubusersApi {
987 subusers_api::SubusersApi::new(self.clone())
988 }
989
990 pub fn suppressions(&self) -> suppressions::Suppressions {
991 suppressions::Suppressions::new(self.clone())
992 }
993
994 pub fn suppressions_global(&self) -> suppressions_global::SuppressionsGlobal {
995 suppressions_global::SuppressionsGlobal::new(self.clone())
996 }
997
998 pub fn suppressions_unsubscribe_groups(
999 &self,
1000 ) -> suppressions_unsubscribe_groups::SuppressionsUnsubscribeGroups {
1001 suppressions_unsubscribe_groups::SuppressionsUnsubscribeGroups::new(self.clone())
1002 }
1003
1004 pub fn teammates(&self) -> teammates::Teammates {
1005 teammates::Teammates::new(self.clone())
1006 }
1007
1008 pub fn transactional_templates(&self) -> transactional_templates::TransactionalTemplates {
1009 transactional_templates::TransactionalTemplates::new(self.clone())
1010 }
1011
1012 pub fn transactional_templates_versions(
1013 &self,
1014 ) -> transactional_templates_versions::TransactionalTemplatesVersions {
1015 transactional_templates_versions::TransactionalTemplatesVersions::new(self.clone())
1016 }
1017
1018 pub fn users_api(&self) -> users_api::UsersApi {
1019 users_api::UsersApi::new(self.clone())
1020 }
1021
1022 pub fn webhooks(&self) -> webhooks::Webhooks {
1023 webhooks::Webhooks::new(self.clone())
1024 }
1025}