sendgrid_rs/message.rs
1use crate::attachment::Attachment;
2use crate::mail_settings::MailSettings;
3use crate::personalization::Personalization;
4use crate::tracking_settings::TrackingSettings;
5use crate::{Asm, Contact, Content};
6use serde::Serialize;
7use std::collections::HashMap;
8
9/// Message is the wrapper around the entire payload to be sent to SendGrid's API.
10/// Use [MessageBuilder](struct.MessageBuilder.html) to properly construct this. The `to_json`
11/// method is available to turn this struct into the request body to send to SendGrid
12#[derive(Debug, Serialize)]
13pub struct Message {
14 #[serde(skip_serializing_if = "Vec::is_empty")]
15 personalizations: Vec<Personalization>,
16 from: Contact,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 reply_to: Option<Contact>,
19 subject: String,
20 #[serde(skip_serializing_if = "Vec::is_empty")]
21 content: Vec<Content>,
22 #[serde(skip_serializing_if = "Vec::is_empty")]
23 attachments: Vec<Attachment>,
24 #[serde(skip_serializing_if = "Option::is_none")]
25 template_id: Option<String>,
26 #[serde(skip_serializing_if = "HashMap::is_empty")]
27 sections: HashMap<String, String>,
28 #[serde(skip_serializing_if = "HashMap::is_empty")]
29 headers: HashMap<String, String>,
30 #[serde(skip_serializing_if = "Vec::is_empty")]
31 categories: Vec<String>,
32 #[serde(skip_serializing_if = "HashMap::is_empty")]
33 custom_args: HashMap<String, String>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 send_at: Option<i32>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 batch_id: Option<String>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 asm: Option<Asm>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 ip_pool_name: Option<String>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 mail_settings: Option<MailSettings>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 tracking_settings: Option<TrackingSettings>,
46}
47
48impl Message {
49 /// `to_json` serializes the entire message into JSON. The result of this method call
50 /// should contain the entire body for the HTTP POST to SendGrid. This method will
51 /// panic if it is unable to serialize, because it is likely a bug in this crate that
52 /// is causing it.
53 pub fn to_json(&self) -> String {
54 serde_json::to_string(&self).expect("could not properly serialize into JSON")
55 }
56}
57
58/// A `builder pattern` type for constructing `Message`
59///
60/// Use this to construct a Message with the desired data.
61/// Make sure you call the 'build' method at the end to
62/// consume this builder and return the underyling message.
63///
64/// # API Requirements
65/// At least one personalization is required
66/// From is required, but handled in the constructor
67/// Subject is required, but handled in the constructor
68pub struct MessageBuilder {
69 message: Message,
70}
71
72impl MessageBuilder {
73 /// Creates a `MessageBuilder`.
74 ///
75 /// # Parameters
76 /// from: Contact
77 /// subject: impl Into<String>
78 ///
79 /// # Examples
80 ///
81 /// ```
82 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder};
83 ///
84 /// let builder = MessageBuilder::new(
85 /// ContactBuilder::new("from@example.com").build(),
86 /// "Subject Line"
87 /// );
88 /// ```
89 pub fn new(from: Contact, subject: impl Into<String>) -> Self {
90 MessageBuilder {
91 message: Message {
92 personalizations: vec![],
93 from,
94 reply_to: None,
95 subject: subject.into(),
96 content: vec![],
97 attachments: vec![],
98 template_id: None,
99 sections: HashMap::new(),
100 headers: HashMap::new(),
101 categories: vec![],
102 custom_args: HashMap::new(),
103 send_at: None,
104 batch_id: None,
105 asm: None,
106 ip_pool_name: None,
107 mail_settings: None,
108 tracking_settings: None,
109 },
110 }
111 }
112
113 /// Adds a `Personalization` to the `Message`
114 /// At least one is required according to the API specification
115 /// Use a `PersonalizationBuilder` to construct the `Personalization`
116 ///
117 /// # Examples
118 /// ```
119 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder, PersonalizationBuilder};
120 ///
121 /// let builder = MessageBuilder::new(
122 /// ContactBuilder::new("from@example.com").build(),
123 /// "Subject Line"
124 /// )
125 /// .personalization(
126 /// PersonalizationBuilder::default().build()
127 /// );
128 /// ```
129 pub fn personalization(mut self, per: Personalization) -> Self {
130 self.message.personalizations.push(per);
131 self
132 }
133
134 /// Overwrites personalializations with input data.
135 ///
136 /// Use this to assign many personalizations at once.
137 ///
138 /// # Examples
139 /// ```
140 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder, personalization::Personalization};
141 ///
142 /// let personalizations: Vec<Personalization> = Vec::new();
143 /// let builder = MessageBuilder::new(
144 /// ContactBuilder::new("from@example.com").build(),
145 /// "Subject Line"
146 /// )
147 /// .personalizations(personalizations);
148 /// ```
149 pub fn personalizations(mut self, data: Vec<Personalization>) -> Self {
150 self.message.personalizations = data;
151 self
152 }
153
154 /// Adds a reply_to `Contact` to the `Message`
155 /// Use a `ContactBuilder` to construct the `Contact`
156 ///
157 /// # Examples
158 /// ```
159 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder};
160 ///
161 /// let builder = MessageBuilder::new(
162 /// ContactBuilder::new("from@example.com").build(),
163 /// "Subject Line"
164 /// )
165 /// .reply_to(
166 /// ContactBuilder::new("reply_to@example.com").build()
167 /// );
168 /// ```
169 pub fn reply_to(mut self, contact: Contact) -> Self {
170 self.message.reply_to = Some(contact);
171 self
172 }
173
174 /// Adds a `Content` to to the `Message`
175 ///
176 /// # Examples
177 /// ```
178 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder, Content};
179 ///
180 /// let builder = MessageBuilder::new(
181 /// ContactBuilder::new("from@example.com").build(),
182 /// "Subject Line"
183 /// )
184 /// .content(
185 /// Content::new("text/plain", "Email Body")
186 /// );
187 /// ```
188 pub fn content(mut self, content: Content) -> Self {
189 self.message.content.push(content);
190 self
191 }
192
193 /// Adds an `Attachment` to the `Message`
194 /// Use an `AttachmentBuilder` to construct the `Attachment`
195 ///
196 /// # Examples
197 /// ```
198 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder, AttachmentBuilder};
199 ///
200 /// let builder = MessageBuilder::new(
201 /// ContactBuilder::new("from@example.com").build(),
202 /// "Subject Line"
203 /// )
204 /// .attachment(
205 /// AttachmentBuilder::new(
206 /// "SGVsbG8gV29ybGQh",
207 /// "file.txt"
208 /// ).build()
209 /// );
210 /// ```
211 pub fn attachment(mut self, attachment: Attachment) -> Self {
212 self.message.attachments.push(attachment);
213 self
214 }
215
216 /// Sets the template id the `Message` will use.
217 ///
218 /// # Examples
219 /// ```
220 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder};
221 ///
222 /// let builder = MessageBuilder::new(
223 /// ContactBuilder::new("from@example.com").build(),
224 /// "Subject Line"
225 /// )
226 /// .template_id("0001");
227 /// ```
228 pub fn template_id(mut self, id: impl Into<String>) -> Self {
229 self.message.template_id = Some(id.into());
230 self
231 }
232
233 /// Adds a section key/value pair to the `Message`
234 ///
235 /// # Examples
236 /// ```
237 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder};
238 ///
239 /// let builder = MessageBuilder::new(
240 /// ContactBuilder::new("from@example.com").build(),
241 /// "Subject Line"
242 /// )
243 /// .section("Key", "Value");
244 /// ```
245 pub fn section<S: Into<String>>(mut self, key: S, value: S) -> Self {
246 self.message.sections.insert(key.into(), value.into());
247 self
248 }
249
250 /// Adds a header key/value pair to the `Message`
251 ///
252 /// # Examples
253 /// ```
254 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder};
255 ///
256 /// let builder = MessageBuilder::new(
257 /// ContactBuilder::new("from@example.com").build(),
258 /// "Subject Line"
259 /// )
260 /// .header("Key", "Value");
261 /// ```
262 pub fn header<S: Into<String>>(mut self, key: S, value: S) -> Self {
263 self.message.headers.insert(key.into(), value.into());
264 self
265 }
266
267 /// Adds a category to the `Message`
268 ///
269 /// # Examples
270 /// ```
271 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder};
272 ///
273 /// let builder = MessageBuilder::new(
274 /// ContactBuilder::new("from@example.com").build(),
275 /// "Subject Line"
276 /// )
277 /// .category("Marketing");
278 /// ```
279 pub fn category(mut self, category: impl Into<String>) -> Self {
280 self.message.categories.push(category.into());
281 self
282 }
283
284 /// Adds a custom arg to the `Message`
285 ///
286 /// # Examples
287 /// ```
288 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder};
289 ///
290 /// let builder = MessageBuilder::new(
291 /// ContactBuilder::new("from@example.com").build(),
292 /// "Subject Line"
293 /// )
294 /// .custom_arg("arg_name", "arg_value");
295 /// ```
296 pub fn custom_arg<S: Into<String>>(mut self, key: S, value: S) -> Self {
297 self.message.custom_args.insert(key.into(), value.into());
298 self
299 }
300
301 /// Adds a send_at time to the `Message`
302 ///
303 /// # Examples
304 /// ```
305 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder};
306 ///
307 /// let builder = MessageBuilder::new(
308 /// ContactBuilder::new("from@example.com").build(),
309 /// "Subject Line"
310 /// )
311 /// .send_at(3600);
312 /// ```
313 pub fn send_at(mut self, time: i32) -> Self {
314 self.message.send_at = Some(time);
315 self
316 }
317
318 /// Adds a batch_id to the `Message`
319 ///
320 /// # Examples
321 /// ```
322 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder};
323 ///
324 /// let builder = MessageBuilder::new(
325 /// ContactBuilder::new("from@example.com").build(),
326 /// "Subject Line"
327 /// )
328 /// .batch_id("abc123");
329 /// ```
330 pub fn batch_id(mut self, id: impl Into<String>) -> Self {
331 self.message.batch_id = Some(id.into());
332 self
333 }
334
335 /// Adds an `Asm` to the `Message`
336 /// Use `AsmBuilder` to construct the `Asm`
337 ///
338 /// # Examples
339 /// ```
340 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder, AsmBuilder};
341 ///
342 /// let builder = MessageBuilder::new(
343 /// ContactBuilder::new("from@example.com").build(),
344 /// "Subject Line"
345 /// )
346 /// .asm(
347 /// AsmBuilder::new(1)
348 /// .build()
349 /// );
350 /// ```
351 pub fn asm(mut self, asm: Asm) -> Self {
352 self.message.asm = Some(asm);
353 self
354 }
355
356 /// Adds the ip_pool_name to the `Message`
357 ///
358 /// # Examples
359 /// ```
360 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder};
361 ///
362 /// let builder = MessageBuilder::new(
363 /// ContactBuilder::new("from@example.com").build(),
364 /// "Subject Line"
365 /// )
366 /// .ip_pool_name("marketing_pool");
367 /// ```
368 pub fn ip_pool_name(mut self, name: impl Into<String>) -> Self {
369 self.message.ip_pool_name = Some(name.into());
370 self
371 }
372
373 /// Adds `MailSettings` to the `Message`
374 /// Use `MailSettingsBuilder` to construct the `MailSettings`
375 ///
376 /// # Examples
377 /// ```
378 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder, MailSettingsBuilder};
379 ///
380 /// let builder = MessageBuilder::new(
381 /// ContactBuilder::new("from@example.com").build(),
382 /// "Subject Line"
383 /// )
384 /// .mail_settings(
385 /// MailSettingsBuilder::default().build()
386 /// );
387 /// ```
388 pub fn mail_settings(mut self, settings: MailSettings) -> Self {
389 self.message.mail_settings = Some(settings);
390 self
391 }
392
393 /// Adds `TrackingSettings` to the `Message`
394 /// Use `TrackingSettingsBuilder` to construct the `TrackingSettings`
395 ///
396 /// # Examples
397 /// ```
398 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder, TrackingSettingsBuilder};
399 ///
400 /// let builder = MessageBuilder::new(
401 /// ContactBuilder::new("from@example.com").build(),
402 /// "Subject Line"
403 /// )
404 /// .tracking_settings(
405 /// TrackingSettingsBuilder::default().build()
406 /// );
407 /// ```
408 pub fn tracking_settings(mut self, settings: TrackingSettings) -> Self {
409 self.message.tracking_settings = Some(settings);
410 self
411 }
412
413 /// Consumes the `MessageBuilder` and returns the `Message`
414 ///
415 /// # Examples
416 /// ```
417 /// # use sendgrid_rs::{MessageBuilder, ContactBuilder};
418 ///
419 /// let message = MessageBuilder::new(
420 /// ContactBuilder::new("from@example.com").build(),
421 /// "Subject Line"
422 /// )
423 /// .build();
424 /// ```
425 pub fn build(self) -> Message {
426 self.message
427 }
428}