sendgrid_rs/
lib.rs

1//! This crate is a wrapper around SendGrid's v3 API using builder patterns to construct a payload
2//! to send. This crate does not have batteries included, does not perform any validations, and
3//! makes no assumptions other than what's specified in SendGrid's API documentation. To actually
4//! call the API, you must use some other mechnism for the HTTP connection (such as the reqwest
5//! crate).
6//!
7//! Everything stems from [Message](message/struct.Message.html) which you can construct using a
8//! [MessageBuilder](message/struct.MessageBuilder.html). When you're done with the
9//! `MessageBuilder` call `build()` to get the underlying `Message` and `to_json()` to get the
10//! entire `Message` output as a JSON string.
11//!
12//! # Examples
13//! ```
14//! # use sendgrid_rs::{MessageBuilder, ContactBuilder, PersonalizationBuilder, MailSettingsBuilder};
15//! let api_payload = MessageBuilder::new(
16//!     ContactBuilder::new("from@example.com").name("from").build(),
17//!     "Subject Line!",
18//! )
19//! .template_id("SENDGRID-TEMPLATE-ID")
20//! // Don't Actually send email. If you want to really send the email, delete the line below
21//! .mail_settings(MailSettingsBuilder::default().sandbox_mode().build())
22//! .personalization(
23//!     PersonalizationBuilder::default()
24//!         .to(ContactBuilder::new("to@example.com").name("to").build())
25//!         .build(),
26//! )
27//! .build()
28//! .to_json();
29//! ```
30
31use serde::Serialize;
32
33pub mod attachment;
34pub mod mail_settings;
35pub mod message;
36pub mod personalization;
37pub mod tracking_settings;
38
39pub use crate::attachment::AttachmentBuilder;
40pub use crate::mail_settings::MailSettingsBuilder;
41pub use crate::message::MessageBuilder;
42pub use crate::personalization::PersonalizationBuilder;
43pub use crate::tracking_settings::{GaTrackingSettingBuilder, TrackingSettingsBuilder};
44
45/// Type used for SendGrid's asm fields for managing subscriptions
46/// Use `AsmBuilder` to construct this when adding it to a `Message`
47#[derive(Debug, Serialize)]
48pub struct Asm {
49    group_id: i32,
50    groups_to_display: Vec<i32>,
51}
52
53/// A builder pattern for constructing `Asm`
54/// Make sure you call `build()` to consume the builder and retrieve the underyling `Asm`
55pub struct AsmBuilder {
56    asm: Asm,
57}
58
59impl AsmBuilder {
60    /// Creates the builder. `group_id` is the only required paramteter which is associated
61    /// to the SendGrid group_id for `Asm` subscriptions
62    ///
63    /// # Examples
64    /// ```
65    /// # use sendgrid_rs::AsmBuilder;
66    ///
67    /// let builder = AsmBuilder::new(1);
68    /// ```
69    pub fn new(group_id: i32) -> Self {
70        AsmBuilder {
71            asm: Asm {
72                group_id,
73                groups_to_display: vec![],
74            },
75        }
76    }
77
78    /// Adds a display group to the `Asm`
79    ///
80    /// # Examples
81    /// ```
82    /// # use sendgrid_rs::AsmBuilder;
83    ///
84    /// let builder = AsmBuilder::new(1)
85    ///     .group_to_display(2)
86    ///     .group_to_display(3);
87    /// ```
88    pub fn group_to_display(mut self, group: i32) -> Self {
89        self.asm.groups_to_display.push(group);
90        self
91    }
92
93    /// Consumes the `AsmBuilder` and returns the underlying `Asm`
94    ///
95    /// # Examples
96    /// ```
97    /// # use sendgrid_rs::AsmBuilder;
98    ///
99    /// let asm = AsmBuilder::new(1).build();
100    /// ```
101    pub fn build(self) -> Asm {
102        self.asm
103    }
104}
105
106/// `Content` is the struct used to add content fields on SendGrid's API
107/// This is essentially a key/value store that serializes into the correct format
108#[derive(Debug, Serialize)]
109pub struct Content {
110    #[serde(rename = "type")]
111    c_type: String,
112    value: String,
113}
114
115impl Content {
116    /// Constructs a `Content`, this requires a content type (mime type) and value
117    ///
118    /// # Examples
119    /// ```
120    /// # use sendgrid_rs::Content;
121    ///
122    /// let content = Content::new("text/plain", "Message Content");
123    /// ```
124    pub fn new<S: Into<String>>(c_type: S, value: S) -> Self {
125        Content {
126            c_type: c_type.into(),
127            value: value.into(),
128        }
129    }
130}
131
132/// Struct that holds the data needed for the 'contact' section in the SendGrid API.
133/// Use a `ContactBuilder` to construct this.
134#[derive(Serialize, Debug)]
135pub struct Contact {
136    email: String,
137    name: Option<String>,
138}
139
140impl Contact {
141    fn new(email: impl Into<String>, name: Option<String>) -> Contact {
142        Contact {
143            email: email.into(),
144            name,
145        }
146    }
147}
148
149/// Builder pattern for `Contact`. Make sure you call `build()` when you're done to consume the
150/// builder and return the underlying `Contact`.
151pub struct ContactBuilder {
152    contact: Contact,
153}
154
155impl ContactBuilder {
156    /// Construct a new `ContactBuilder`. Email address is the only required parameter
157    ///
158    /// # Examples
159    /// ```
160    /// # use sendgrid_rs::ContactBuilder;
161    ///
162    /// let builder = ContactBuilder::new("from@example.com");
163    /// ```
164    pub fn new(email: impl Into<String>) -> Self {
165        ContactBuilder {
166            contact: Contact::new(email, None),
167        }
168    }
169
170    /// Set the name of the `Contact`
171    ///
172    /// # Examples
173    /// ```
174    /// # use sendgrid_rs::ContactBuilder;
175    ///
176    /// let builder = ContactBuilder::new("from@example.com")
177    ///               .name("From");
178    /// ```
179    pub fn name(mut self, name: impl Into<String>) -> Self {
180        self.contact.name = Some(name.into());
181        self
182    }
183
184    /// Consume the builder and return the underlying `Contact`
185    ///
186    /// # Examples
187    /// ```
188    /// # use sendgrid_rs::ContactBuilder;
189    ///
190    /// let builder = ContactBuilder::new("from@example.com").build();
191    /// ```
192    pub fn build(self) -> Contact {
193        self.contact
194    }
195}
196
197#[cfg(test)]
198mod tests {
199    use crate::{ContactBuilder, MessageBuilder};
200
201    #[test]
202    fn it_works() {
203        let m = MessageBuilder::new(
204            ContactBuilder::new("from@from.com").name("from").build(),
205            "subject",
206        )
207        .build();
208        println!("{}", m.to_json());
209    }
210}