azure_functions/send_grid/
message_builder.rs

1use crate::{
2    bindings::SendGridMessage,
3    send_grid::{Attachment, Content, EmailAddress, Personalization},
4};
5use serde_json::Value;
6
7/// Represents a builder for SendGrid messages.
8#[derive(Default)]
9pub struct MessageBuilder(SendGridMessage);
10
11impl MessageBuilder {
12    /// Creates a new message builder.
13    pub fn new() -> MessageBuilder {
14        MessageBuilder(SendGridMessage::default())
15    }
16
17    /// Appends the given "to" email address to the first personalization of the message.
18    ///
19    /// # Examples
20    ///
21    /// ```rust
22    /// # use azure_functions::send_grid::MessageBuilder;
23    ///
24    /// let message = MessageBuilder::new().to("foo@example.com").finish();
25    ///
26    /// assert_eq!(message.personalizations[0].to[0].email, "foo@example.com");
27    /// assert_eq!(message.personalizations[0].to[0].name, None);
28    /// ```
29    pub fn to<T>(mut self, email: T) -> MessageBuilder
30    where
31        T: Into<String>,
32    {
33        self.append_to(EmailAddress::new(email));
34        self
35    }
36
37    /// Appends the given "to" email address to the first personalization of the message.
38    ///
39    /// # Examples
40    ///
41    /// ```rust
42    /// # use azure_functions::send_grid::MessageBuilder;
43    ///
44    /// let message = MessageBuilder::new().to_with_name("foo@example.com", "Peter").finish();
45    ///
46    /// assert_eq!(message.personalizations[0].to[0].email, "foo@example.com");
47    /// assert_eq!(message.personalizations[0].to[0].name, Some("Peter".to_owned()));
48    /// ```
49    #[allow(clippy::wrong_self_convention)]
50    pub fn to_with_name<T, U>(mut self, email: T, name: U) -> MessageBuilder
51    where
52        T: Into<String>,
53        U: Into<String>,
54    {
55        self.append_to(EmailAddress::new_with_name(email, name));
56        self
57    }
58
59    /// Appends the given "to" email addresses to the first personalization of the message.
60    ///
61    /// # Examples
62    ///
63    /// ```rust
64    /// # use azure_functions::send_grid::MessageBuilder;
65    /// # use azure_functions::send_grid::EmailAddress;
66    ///
67    /// let message = MessageBuilder::new().tos(
68    ///     vec![
69    ///         EmailAddress::new("foo@example.com"),
70    ///         EmailAddress::new_with_name("bar@example.com", "Peter"),
71    ///     ]).finish();
72    ///
73    /// assert_eq!(message.personalizations[0].to[0].email, "foo@example.com");
74    /// assert_eq!(message.personalizations[0].to[0].name, None);
75    /// assert_eq!(message.personalizations[0].to[1].email, "bar@example.com");
76    /// assert_eq!(message.personalizations[0].to[1].name, Some("Peter".to_owned()));
77    /// ```
78    pub fn tos<T>(mut self, addresses: T) -> MessageBuilder
79    where
80        T: IntoIterator<Item = EmailAddress>,
81    {
82        self.initialize_personalization();
83        self.0.personalizations[0].to.extend(addresses);
84        self
85    }
86
87    /// Appends the given "cc" email address to the first personalization of the message.
88    ///
89    /// # Examples
90    ///
91    /// ```rust
92    /// # use azure_functions::send_grid::MessageBuilder;
93    ///
94    /// let message = MessageBuilder::new().cc("foo@example.com").finish();
95    ///
96    /// assert_eq!(message.personalizations[0].cc[0].email, "foo@example.com");
97    /// assert_eq!(message.personalizations[0].cc[0].name, None);
98    /// ```
99    pub fn cc<T>(mut self, email: T) -> MessageBuilder
100    where
101        T: Into<String>,
102    {
103        self.append_cc(EmailAddress::new(email));
104        self
105    }
106
107    /// Appends the given "cc" email address to the first personalization of the message.
108    ///
109    /// # Examples
110    ///
111    /// ```rust
112    /// # use azure_functions::send_grid::MessageBuilder;
113    ///
114    /// let message = MessageBuilder::new().cc_with_name("foo@example.com", "Peter").finish();
115    ///
116    /// assert_eq!(message.personalizations[0].cc[0].email, "foo@example.com");
117    /// assert_eq!(message.personalizations[0].cc[0].name, Some("Peter".to_owned()));
118    /// ```
119    pub fn cc_with_name<T, U>(mut self, email: T, name: U) -> MessageBuilder
120    where
121        T: Into<String>,
122        U: Into<String>,
123    {
124        self.append_cc(EmailAddress::new_with_name(email, name));
125        self
126    }
127
128    /// Appends the given "cc" email addresses to the first personalization of the message.
129    ///
130    /// # Examples
131    ///
132    /// ```rust
133    /// # use azure_functions::send_grid::MessageBuilder;
134    /// # use azure_functions::send_grid::EmailAddress;
135    ///
136    /// let message = MessageBuilder::new().ccs(
137    ///     vec![
138    ///         EmailAddress::new("foo@example.com"),
139    ///         EmailAddress::new_with_name("bar@example.com", "Peter"),
140    ///     ]).finish();
141    ///
142    /// assert_eq!(message.personalizations[0].cc[0].email, "foo@example.com");
143    /// assert_eq!(message.personalizations[0].cc[0].name, None);
144    /// assert_eq!(message.personalizations[0].cc[1].email, "bar@example.com");
145    /// assert_eq!(message.personalizations[0].cc[1].name, Some("Peter".to_owned()));
146    /// ```
147    pub fn ccs<T>(mut self, addresses: T) -> MessageBuilder
148    where
149        T: IntoIterator<Item = EmailAddress>,
150    {
151        self.initialize_personalization();
152        self.0.personalizations[0].cc.extend(addresses);
153        self
154    }
155
156    /// Appends the given "bcc" email address to the first personalization of the message.
157    ///
158    /// # Examples
159    ///
160    /// ```rust
161    /// # use azure_functions::send_grid::MessageBuilder;
162    ///
163    /// let message = MessageBuilder::new().bcc("foo@example.com").finish();
164    ///
165    /// assert_eq!(message.personalizations[0].bcc[0].email, "foo@example.com");
166    /// assert_eq!(message.personalizations[0].bcc[0].name, None);
167    /// ```
168    pub fn bcc<T>(mut self, email: T) -> MessageBuilder
169    where
170        T: Into<String>,
171    {
172        self.append_bcc(EmailAddress::new(email));
173        self
174    }
175
176    /// Appends the given "bcc" email address to the first personalization of the message.
177    ///
178    /// # Examples
179    ///
180    /// ```rust
181    /// # use azure_functions::send_grid::MessageBuilder;
182    ///
183    /// let message = MessageBuilder::new().bcc_with_name("foo@example.com", "Peter").finish();
184    ///
185    /// assert_eq!(message.personalizations[0].bcc[0].email, "foo@example.com");
186    /// assert_eq!(message.personalizations[0].bcc[0].name, Some("Peter".to_owned()));
187    /// ```
188    pub fn bcc_with_name<T, U>(mut self, email: T, name: U) -> MessageBuilder
189    where
190        T: Into<String>,
191        U: Into<String>,
192    {
193        self.append_bcc(EmailAddress::new_with_name(email, name));
194        self
195    }
196
197    /// Appends the given "bcc" email addresses to the first personalization of the message.
198    ///
199    /// # Examples
200    ///
201    /// ```rust
202    /// # use azure_functions::send_grid::MessageBuilder;
203    /// # use azure_functions::send_grid::EmailAddress;
204    ///
205    /// let message = MessageBuilder::new().bccs(
206    ///     vec![
207    ///         EmailAddress::new("foo@example.com"),
208    ///         EmailAddress::new_with_name("bar@example.com", "Peter"),
209    ///     ]).finish();
210    ///
211    /// assert_eq!(message.personalizations[0].bcc[0].email, "foo@example.com");
212    /// assert_eq!(message.personalizations[0].bcc[0].name, None);
213    /// assert_eq!(message.personalizations[0].bcc[1].email, "bar@example.com");
214    /// assert_eq!(message.personalizations[0].bcc[1].name, Some("Peter".to_owned()));
215    /// ```
216    pub fn bccs<T>(mut self, addresses: T) -> MessageBuilder
217    where
218        T: IntoIterator<Item = EmailAddress>,
219    {
220        self.initialize_personalization();
221        self.0.personalizations[0].bcc.extend(addresses);
222        self
223    }
224
225    /// Sets the subject for the first personalization of the message.
226    ///
227    /// # Examples
228    ///
229    /// ```rust
230    /// # use azure_functions::send_grid::MessageBuilder;
231    ///
232    /// let message = MessageBuilder::new().subject("hello world!").finish();
233    ///
234    /// assert_eq!(message.personalizations[0].subject, Some("hello world!".to_owned()));
235    /// ```
236    pub fn subject<T>(mut self, subject: T) -> MessageBuilder
237    where
238        T: Into<String>,
239    {
240        self.initialize_personalization();
241        self.0.personalizations[0].subject = Some(subject.into());
242        self
243    }
244
245    /// Appends a header to the first personalization of the message.
246    ///
247    /// # Examples
248    ///
249    /// ```rust
250    /// # use azure_functions::send_grid::MessageBuilder;
251    ///
252    /// let message = MessageBuilder::new().header("foo", "bar").finish();
253    ///
254    /// assert_eq!(message.personalizations[0].headers.get("foo").map(String::as_str), Some("bar"));
255    /// ```
256    pub fn header<T, U>(mut self, key: T, value: U) -> MessageBuilder
257    where
258        T: Into<String>,
259        U: Into<String>,
260    {
261        self.initialize_personalization();
262        self.0.personalizations[0]
263            .headers
264            .insert(key.into(), value.into());
265        self
266    }
267
268    /// Appends multiple headers to the first personalization of the message.
269    ///
270    /// # Examples
271    ///
272    /// ```rust
273    /// # use azure_functions::send_grid::MessageBuilder;
274    /// # use std::collections::HashMap;
275    ///
276    /// let mut headers = HashMap::new();
277    /// headers.insert("foo".to_owned(), "bar".to_owned());
278    /// headers.insert("bar".to_owned(), "baz".to_owned());
279    ///
280    /// let message = MessageBuilder::new().headers(headers).finish();
281    ///
282    /// assert_eq!(message.personalizations[0].headers.get("foo").map(String::as_str), Some("bar"));
283    /// assert_eq!(message.personalizations[0].headers.get("bar").map(String::as_str), Some("baz"));
284    /// ```
285    pub fn headers<T>(mut self, headers: T) -> MessageBuilder
286    where
287        T: IntoIterator<Item = (String, String)>,
288    {
289        self.initialize_personalization();
290        self.0.personalizations[0].headers.extend(headers);
291        self
292    }
293
294    /// Appends a substitution to the first personalization of the message.
295    ///
296    /// # Examples
297    ///
298    /// ```rust
299    /// # use azure_functions::send_grid::MessageBuilder;
300    ///
301    /// let message = MessageBuilder::new().substitution("foo", "bar").finish();
302    ///
303    /// assert_eq!(message.personalizations[0].substitutions.get("foo").map(String::as_str), Some("bar"));
304    /// ```
305    pub fn substitution<T, U>(mut self, key: T, value: U) -> MessageBuilder
306    where
307        T: Into<String>,
308        U: Into<String>,
309    {
310        self.initialize_personalization();
311        self.0.personalizations[0]
312            .substitutions
313            .insert(key.into(), value.into());
314        self
315    }
316
317    /// Appends multiple substitutions to the first personalization of the message.
318    ///
319    /// # Examples
320    ///
321    /// ```rust
322    /// # use azure_functions::send_grid::MessageBuilder;
323    /// # use std::collections::HashMap;
324    ///
325    /// let mut substitutions = HashMap::new();
326    /// substitutions.insert("foo".to_owned(), "bar".to_owned());
327    /// substitutions.insert("bar".to_owned(), "baz".to_owned());
328    ///
329    /// let message = MessageBuilder::new().substitutions(substitutions).finish();
330    ///
331    /// assert_eq!(message.personalizations[0].substitutions.get("foo").map(String::as_str), Some("bar"));
332    /// assert_eq!(message.personalizations[0].substitutions.get("bar").map(String::as_str), Some("baz"));
333    /// ```
334    pub fn substitutions<T>(mut self, substitutions: T) -> MessageBuilder
335    where
336        T: IntoIterator<Item = (String, String)>,
337    {
338        self.initialize_personalization();
339        self.0.personalizations[0]
340            .substitutions
341            .extend(substitutions);
342        self
343    }
344
345    /// Sets the template data for the first personalization of the message.
346    ///
347    /// # Examples
348    ///
349    /// ```rust
350    /// # use azure_functions::send_grid::MessageBuilder;
351    /// # use serde_json::{json, to_string};
352    ///
353    /// let message = MessageBuilder::new().template_data(json!({ "foo": "bar" })).finish();
354    ///
355    /// assert_eq!(to_string(message.personalizations[0].template_data.as_ref().unwrap()).unwrap(), r#"{"foo":"bar"}"#);
356    /// ```
357    pub fn template_data(mut self, data: Value) -> MessageBuilder {
358        if let Value::Object(map) = data {
359            self.initialize_personalization();
360            self.0.personalizations[0].template_data = Some(map);
361        } else {
362            panic!("template data must be a JSON object");
363        }
364
365        self
366    }
367
368    /// Appends a custom argument to the first personalization of the message.
369    ///
370    /// # Examples
371    ///
372    /// ```rust
373    /// # use azure_functions::send_grid::MessageBuilder;
374    ///
375    /// let message = MessageBuilder::new().custom_arg("foo", "bar").finish();
376    ///
377    /// assert_eq!(message.personalizations[0].custom_args.get("foo").map(String::as_str), Some("bar"));
378    /// ```
379    pub fn custom_arg<T, U>(mut self, key: T, value: U) -> MessageBuilder
380    where
381        T: Into<String>,
382        U: Into<String>,
383    {
384        self.initialize_personalization();
385        self.0.personalizations[0]
386            .custom_args
387            .insert(key.into(), value.into());
388        self
389    }
390
391    /// Appends multiple custom arguments to the first personalization of the message.
392    ///
393    /// # Examples
394    ///
395    /// ```rust
396    /// # use azure_functions::send_grid::MessageBuilder;
397    /// # use std::collections::HashMap;
398    ///
399    /// let mut args = HashMap::new();
400    /// args.insert("foo".to_owned(), "bar".to_owned());
401    /// args.insert("bar".to_owned(), "baz".to_owned());
402    ///
403    /// let message = MessageBuilder::new().custom_args(args).finish();
404    ///
405    /// assert_eq!(message.personalizations[0].custom_args.get("foo").map(String::as_str), Some("bar"));
406    /// assert_eq!(message.personalizations[0].custom_args.get("bar").map(String::as_str), Some("baz"));
407    /// ```
408    pub fn custom_args<T>(mut self, args: T) -> MessageBuilder
409    where
410        T: IntoIterator<Item = (String, String)>,
411    {
412        self.initialize_personalization();
413        self.0.personalizations[0].custom_args.extend(args);
414        self
415    }
416
417    /// Sets the "send at" timestamp for the first personalization of the message.
418    ///
419    /// > Note:
420    /// > This trait uses a Unix timestamp. A handy Unix timestamp converter can be found at [unixtimestamp.com/](https://www.unixtimestamp.com/)
421    ///
422    /// # Examples
423    ///
424    /// ```rust
425    /// # use azure_functions::send_grid::MessageBuilder;
426    ///
427    /// let message = MessageBuilder::new().send_at(1555890183).finish();
428    ///
429    /// assert_eq!(message.personalizations[0].send_at, Some(1555890183));
430    /// ```
431    pub fn send_at(mut self, timestamp: i64) -> MessageBuilder {
432        self.initialize_personalization();
433        self.0.personalizations[0].send_at = Some(timestamp);
434        self
435    }
436
437    /// Sets the "from" email address for the message.
438    ///
439    /// # Examples
440    ///
441    /// ```rust
442    /// # use azure_functions::send_grid::MessageBuilder;
443    ///
444    /// let message = MessageBuilder::new().from("foo@example.com").finish();
445    ///
446    /// assert_eq!(message.from.as_ref().unwrap().email, "foo@example.com");
447    /// assert_eq!(message.from.as_ref().unwrap().name, None);
448    /// ```
449    pub fn from<T>(mut self, email: T) -> MessageBuilder
450    where
451        T: Into<String>,
452    {
453        self.0.from = Some(EmailAddress::new(email));
454        self
455    }
456
457    /// Sets the "from" email address for the message.
458    ///
459    /// # Examples
460    ///
461    /// ```rust
462    /// # use azure_functions::send_grid::MessageBuilder;
463    ///
464    /// let message = MessageBuilder::new().from_with_name("foo@example.com", "Peter").finish();
465    ///
466    /// assert_eq!(message.from.as_ref().unwrap().email, "foo@example.com");
467    /// assert_eq!(message.from.as_ref().unwrap().name, Some("Peter".to_owned()));
468    /// ```
469    #[allow(clippy::wrong_self_convention)]
470    pub fn from_with_name<T, U>(mut self, email: T, name: U) -> MessageBuilder
471    where
472        T: Into<String>,
473        U: Into<String>,
474    {
475        self.0.from = Some(EmailAddress::new_with_name(email, name));
476        self
477    }
478
479    /// Sets the default global subject for all personalizations of the message.
480    ///
481    /// # Examples
482    ///
483    /// ```rust
484    /// # use azure_functions::send_grid::MessageBuilder;
485    ///
486    /// let message = MessageBuilder::new().global_subject("hello world").finish();
487    ///
488    /// assert_eq!(message.subject, Some("hello world".to_owned()));
489    /// ```
490    pub fn global_subject<T>(mut self, subject: T) -> MessageBuilder
491    where
492        T: Into<String>,
493    {
494        self.0.subject = Some(subject.into());
495        self
496    }
497
498    /// Adds a text content (with MIME type "text/plain") to the message.
499    ///
500    /// # Examples
501    ///
502    /// ```rust
503    /// # use azure_functions::send_grid::MessageBuilder;
504    ///
505    /// let message = MessageBuilder::new().content("hello world").finish();
506    ///
507    /// assert_eq!(message.contents[0].mime_type, "text/plain");
508    /// assert_eq!(message.contents[0].value, "hello world");
509    /// ```
510    pub fn content<T>(mut self, text: T) -> MessageBuilder
511    where
512        T: Into<String>,
513    {
514        self.0.contents.push(Content {
515            mime_type: "text/plain".to_owned(),
516            value: text.into(),
517        });
518
519        self
520    }
521
522    /// Adds a content with the given MIME type to the message.
523    ///
524    /// # Examples
525    ///
526    /// ```rust
527    /// # use azure_functions::send_grid::MessageBuilder;
528    ///
529    /// let message = MessageBuilder::new().content_with_type("hello world", "text/plain").finish();
530    ///
531    /// assert_eq!(message.contents[0].mime_type, "text/plain");
532    /// assert_eq!(message.contents[0].value, "hello world");
533    /// ```
534    pub fn content_with_type<T, U>(mut self, content: T, mime_type: U) -> MessageBuilder
535    where
536        T: Into<String>,
537        U: Into<String>,
538    {
539        self.0.contents.push(Content {
540            mime_type: mime_type.into(),
541            value: content.into(),
542        });
543
544        self
545    }
546
547    /// Adds the given content to the message.
548    ///
549    /// # Examples
550    ///
551    /// ```rust
552    /// # use azure_functions::send_grid::MessageBuilder;
553    /// # use azure_functions::send_grid::Content;
554    ///
555    /// let message = MessageBuilder::new()
556    ///     .contents(
557    ///         vec![
558    ///             Content{ mime_type: "text/plain".to_owned(), value: "hello world".to_owned() }
559    ///         ])
560    ///     .finish();
561    ///
562    /// assert_eq!(message.contents[0].mime_type, "text/plain");
563    /// assert_eq!(message.contents[0].value, "hello world");
564    /// ```
565    pub fn contents<T>(mut self, contents: T) -> MessageBuilder
566    where
567        T: IntoIterator<Item = Content>,
568    {
569        self.0.contents.extend(contents);
570        self
571    }
572
573    /// Adds an attachment to the message.
574    ///
575    /// > SendGrid expects the `content` argument to be Base 64 encoded.
576    /// > In this example, "hello world" is encoded as "aGVsbG8gd29ybGQ="
577    ///
578    /// # Examples
579    ///
580    /// ```rust
581    /// # use azure_functions::send_grid::MessageBuilder;
582    ///
583    /// let message = MessageBuilder::new().attachment("hello.txt", "text/plain", "aGVsbG8gd29ybGQ=").finish();
584    ///
585    /// assert_eq!(message.attachments[0].filename, "hello.txt");
586    /// assert_eq!(message.attachments[0].mime_type, "text/plain");
587    /// assert_eq!(message.attachments[0].content, "aGVsbG8gd29ybGQ=");
588    /// ```
589    pub fn attachment<T, U, V>(mut self, filename: T, mime_type: U, content: V) -> MessageBuilder
590    where
591        T: Into<String>,
592        U: Into<String>,
593        V: Into<String>,
594    {
595        self.0.attachments.push(Attachment {
596            filename: filename.into(),
597            mime_type: mime_type.into(),
598            content: content.into(),
599            ..Default::default()
600        });
601        self
602    }
603
604    /// Adds an attachment to the message.
605    ///
606    /// > SendGrid expects the `content` argument to be Base 64 encoded.
607    /// > In this example, "hello world" is encoded as "aGVsbG8gd29ybGQ="
608    ///
609    /// # Examples
610    ///
611    /// ```rust
612    /// # use azure_functions::send_grid::MessageBuilder;
613    ///
614    /// let message = MessageBuilder::new().inline_attachment("hello.jpg", "image/jpeg", "aGVsbG8gd29ybGQ=", "img_139db99fdb5c3704").finish();
615    ///
616    /// assert_eq!(message.attachments[0].filename, "hello.jpg");
617    /// assert_eq!(message.attachments[0].mime_type, "image/jpeg");
618    /// assert_eq!(message.attachments[0].content, "aGVsbG8gd29ybGQ=");
619    /// assert_eq!(message.attachments[0].disposition, Some("inline".to_owned()));
620    /// assert_eq!(message.attachments[0].content_id, Some("img_139db99fdb5c3704".to_owned()));
621    /// ```
622    pub fn inline_attachment<T, U, V, W>(
623        mut self,
624        filename: T,
625        mime_type: U,
626        content: V,
627        content_id: W,
628    ) -> MessageBuilder
629    where
630        T: Into<String>,
631        U: Into<String>,
632        V: Into<String>,
633        W: Into<String>,
634    {
635        self.0.attachments.push(Attachment {
636            filename: filename.into(),
637            mime_type: mime_type.into(),
638            content: content.into(),
639            disposition: Some("inline".to_owned()),
640            content_id: Some(content_id.into()),
641        });
642        self
643    }
644
645    /// Adds multiple attachments to the message.
646    ///
647    /// > SendGrid expects the `content` argument to be Base 64 encoded.
648    /// > In this example, "hello world" is encoded as "aGVsbG8gd29ybGQ="
649    ///
650    /// # Examples
651    ///
652    /// ```rust
653    /// # use azure_functions::send_grid::MessageBuilder;
654    /// use azure_functions::send_grid::Attachment;
655    ///
656    /// let message = MessageBuilder::new()
657    ///     .attachments(
658    ///         vec![
659    ///             Attachment{ filename: "hello.txt".to_owned(), mime_type: "text/plain".to_owned(), content: "aGVsbG8gd29ybGQ=".to_owned(), ..Default::default() }
660    ///         ])
661    ///     .finish();
662    ///
663    /// assert_eq!(message.attachments[0].filename, "hello.txt");
664    /// assert_eq!(message.attachments[0].mime_type, "text/plain");
665    /// assert_eq!(message.attachments[0].content, "aGVsbG8gd29ybGQ=");
666    /// ```
667    pub fn attachments<T>(mut self, attachments: T) -> MessageBuilder
668    where
669        T: IntoIterator<Item = Attachment>,
670    {
671        self.0.attachments.extend(attachments);
672        self
673    }
674
675    /// Sets the template id for the message.
676    ///
677    /// # Examples
678    /// ```rust
679    /// # use azure_functions::send_grid::MessageBuilder;
680    /// use azure_functions::send_grid::Attachment;
681    ///
682    /// let message = MessageBuilder::new().template_id("id").finish();
683    ///
684    /// assert_eq!(message.template_id, Some("id".to_owned()));
685    /// ```
686    pub fn template_id<T>(mut self, id: T) -> MessageBuilder
687    where
688        T: Into<String>,
689    {
690        self.0.template_id = Some(id.into());
691        self
692    }
693
694    /// Appends a section substitution to the message.
695    ///
696    /// # Examples
697    ///
698    /// ```rust
699    /// # use azure_functions::send_grid::MessageBuilder;
700    ///
701    /// let message = MessageBuilder::new().section("foo", "bar").finish();
702    ///
703    /// assert_eq!(message.sections.get("foo").map(String::as_str), Some("bar"));
704    /// ```
705    pub fn section<T, U>(mut self, key: T, value: U) -> MessageBuilder
706    where
707        T: Into<String>,
708        U: Into<String>,
709    {
710        self.0.sections.insert(key.into(), value.into());
711        self
712    }
713
714    /// Appends multiple sections to the message.
715    ///
716    /// # Examples
717    ///
718    /// ```rust
719    /// # use azure_functions::send_grid::MessageBuilder;
720    /// use std::collections::HashMap;
721    ///
722    /// let mut sections = HashMap::new();
723    /// sections.insert("foo".to_owned(), "bar".to_owned());
724    /// sections.insert("bar".to_owned(), "baz".to_owned());
725    ///
726    /// let message = MessageBuilder::new().sections(sections).finish();
727    ///
728    /// assert_eq!(message.sections.get("foo").map(String::as_str), Some("bar"));
729    /// assert_eq!(message.sections.get("bar").map(String::as_str), Some("baz"));
730    /// ```
731    pub fn sections<T>(mut self, sections: T) -> MessageBuilder
732    where
733        T: IntoIterator<Item = (String, String)>,
734    {
735        self.0.sections.extend(sections);
736        self
737    }
738
739    /// Appends a category to the message.
740    ///
741    /// # Examples
742    ///
743    /// ```rust
744    /// # use azure_functions::send_grid::MessageBuilder;
745    ///
746    /// let message = MessageBuilder::new().category("foo").finish();
747    ///
748    /// assert_eq!(message.categories[0], "foo");
749    /// ```
750    pub fn category<T>(mut self, category: T) -> MessageBuilder
751    where
752        T: Into<String>,
753    {
754        self.0.categories.push(category.into());
755        self
756    }
757
758    /// Appends multiple categories to the message.
759    ///
760    /// # Examples
761    ///
762    /// ```rust
763    /// # use azure_functions::send_grid::MessageBuilder;
764    ///
765    /// let message = MessageBuilder::new().categories(vec!["foo".to_owned(), "bar".to_owned(), "baz".to_owned()]).finish();
766    ///
767    /// assert_eq!(message.categories[0], "foo");
768    /// assert_eq!(message.categories[1], "bar");
769    /// assert_eq!(message.categories[2], "baz");
770    /// ```
771    pub fn categories<T>(mut self, categories: T) -> MessageBuilder
772    where
773        T: IntoIterator<Item = String>,
774    {
775        self.0.categories.extend(categories);
776        self
777    }
778
779    /// Appends a global header for all personalizations of the message.
780    ///
781    /// # Examples
782    ///
783    /// ```rust
784    /// # use azure_functions::send_grid::MessageBuilder;
785    ///
786    /// let message = MessageBuilder::new().global_header("foo", "bar").finish();
787    ///
788    /// assert_eq!(message.headers.get("foo").map(String::as_str), Some("bar"));
789    /// ```
790    pub fn global_header<T, U>(mut self, key: T, value: U) -> MessageBuilder
791    where
792        T: Into<String>,
793        U: Into<String>,
794    {
795        self.0.headers.insert(key.into(), value.into());
796        self
797    }
798
799    /// Appends multiple global headers for all personalizations of the message.
800    ///
801    /// # Examples
802    ///
803    /// ```rust
804    /// # use azure_functions::send_grid::MessageBuilder;
805    /// use std::collections::HashMap;
806    ///
807    /// let mut headers = HashMap::new();
808    /// headers.insert("foo".to_owned(), "bar".to_owned());
809    /// headers.insert("bar".to_owned(), "baz".to_owned());
810    ///
811    /// let message = MessageBuilder::new().global_headers(headers).finish();
812    ///
813    /// assert_eq!(message.headers.get("foo").map(String::as_str), Some("bar"));
814    /// assert_eq!(message.headers.get("bar").map(String::as_str), Some("baz"));
815    /// ```
816    pub fn global_headers<T>(mut self, headers: T) -> MessageBuilder
817    where
818        T: IntoIterator<Item = (String, String)>,
819    {
820        self.0.headers.extend(headers);
821        self
822    }
823
824    /// Appends a global custom argument for all personalizations of the message.
825    ///
826    /// # Examples
827    ///
828    /// ```rust
829    /// # use azure_functions::send_grid::MessageBuilder;
830    ///
831    /// let message = MessageBuilder::new().global_custom_arg("foo", "bar").finish();
832    ///
833    /// assert_eq!(message.custom_args.get("foo").map(String::as_str), Some("bar"));
834    /// ```
835    pub fn global_custom_arg<T, U>(mut self, key: T, value: U) -> MessageBuilder
836    where
837        T: Into<String>,
838        U: Into<String>,
839    {
840        self.initialize_personalization();
841        self.0.custom_args.insert(key.into(), value.into());
842        self
843    }
844
845    /// Appends multiple global custom arguments for all personalizations of the message.
846    ///
847    /// # Examples
848    ///
849    /// ```rust
850    /// # use azure_functions::send_grid::MessageBuilder;
851    /// use std::collections::HashMap;
852    ///
853    /// let mut args = HashMap::new();
854    /// args.insert("foo".to_owned(), "bar".to_owned());
855    /// args.insert("bar".to_owned(), "baz".to_owned());
856    ///
857    /// let message = MessageBuilder::new().global_custom_args(args).finish();
858    ///
859    /// assert_eq!(message.custom_args.get("foo").map(String::as_str), Some("bar"));
860    /// assert_eq!(message.custom_args.get("bar").map(String::as_str), Some("baz"));
861    /// ```
862    pub fn global_custom_args<T>(mut self, args: T) -> MessageBuilder
863    where
864        T: IntoIterator<Item = (String, String)>,
865    {
866        self.initialize_personalization();
867        self.0.custom_args.extend(args);
868        self
869    }
870
871    /// Sets the global "send at" timestamp for all personalizations of the message.
872    ///
873    /// > Note:
874    /// > This trait uses a Unix timestamp. A handy Unix timestamp converter can be found at [unixtimestamp.com](https://www.unixtimestamp.com/)
875    ///
876    /// # Examples
877    ///
878    /// ```rust
879    /// # use azure_functions::send_grid::MessageBuilder;
880    ///
881    /// let message = MessageBuilder::new().global_send_at(1555890183).finish();
882    ///
883    /// assert_eq!(message.send_at, Some(1555890183));
884    /// ```
885    pub fn global_send_at(mut self, timestamp: i64) -> MessageBuilder {
886        self.initialize_personalization();
887        self.0.send_at = Some(timestamp);
888        self
889    }
890
891    /// Sets the batch id for the message.
892    ///
893    /// # Examples
894    ///
895    /// ```rust
896    /// # use azure_functions::send_grid::MessageBuilder;
897    ///
898    /// let message = MessageBuilder::new().batch_id("HkJ5yLYULb7Rj8GKSx7u025ouWVlMgAi").finish();
899    ///
900    /// assert_eq!(message.batch_id.unwrap(), "HkJ5yLYULb7Rj8GKSx7u025ouWVlMgAi");
901    /// ```
902    pub fn batch_id<T>(mut self, id: T) -> MessageBuilder
903    where
904        T: Into<String>,
905    {
906        self.0.batch_id = Some(id.into());
907        self
908    }
909
910    /// Consumes the builder and returns the SendGrid message.
911    pub fn finish(self) -> SendGridMessage {
912        self.0
913    }
914
915    fn append_to(&mut self, address: EmailAddress) {
916        self.initialize_personalization();
917        self.0.personalizations[0].to.push(address);
918    }
919
920    fn append_cc(&mut self, address: EmailAddress) {
921        self.initialize_personalization();
922        self.0.personalizations[0].cc.push(address);
923    }
924
925    fn append_bcc(&mut self, address: EmailAddress) {
926        self.initialize_personalization();
927        self.0.personalizations[0].bcc.push(address);
928    }
929
930    fn initialize_personalization(&mut self) {
931        if self.0.personalizations.is_empty() {
932            self.0.personalizations.push(Personalization {
933                ..Default::default()
934            });
935        }
936    }
937}