Skip to content

Type system is not leveraged to avoid mistakes when building sendgrid requests #67

@Ten0

Description

@Ten0

The library provides lots of way to build Sendgrid queries that have zero chance to succeed:
Examples:

sender.send(&Message::new())?;
sender.send(&Message::new()
			.set_from(self.from.clone())
			.set_subject(subject)
			.add_personalization(Personalization::new().add_to(Email::new().set_email(to_email)))
			.add_content(Content::new().set_value(body)))?;
sender.send(&Message::new()
			.set_subject(subject)
			.add_personalization(Personalization::new().add_to(Email::new().set_email(to_email)))
			.add_content(Content::new().set_content_type("text/html").set_value(body)))?;
sender.send(&Message::new()
			.set_from(self.from.clone())
			.add_personalization(Personalization::new().add_to(Email::new().set_email(to_email)))
			.add_content(Content::new().set_content_type("text/html").set_value(body)))?;
sender.send(&Message::new()
			.set_from(self.from.clone())
			.set_subject(subject)
			.add_content(Content::new().set_content_type("text/html").set_value(body)))?;
sender.send(&Message::new()
			.set_from(self.from.clone())
			.set_subject(subject)
			.add_personalization(Personalization::new().add_to(Email::new().set_email(to_email)))
			.add_content(Content::new().set_content_type("text/htlm").set_value(body)))?;

It's already been several times we've gotten trapped by this, resulting in broken deployed software.

Given the amount of fields that are mandatory/have restricted values, there should only be, as much as possible, constructors that respect the Sendgrid constraints.

e.g.:

sender.send(Message::new(
   "from.someone@somewhere.com",
   "to.someone.else@somewhere.com",
   Content::html("subject", "<strong>body</strong>"),
)

where Content could be:

#[serde(untagged)] // and flattened into the message
pub enum Content<'a> {
    SubjectAndBody {
        subject: &'a str,
        body: Body<'a>,
    }
    Template {
        // If I understand correctly https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/index.html
        // specifying a template id makes subject and body optional
        template_id: &'a str,
        subject: Option<&'a str>,
        body: Option<Body<'a>>,
    }
}

pub struct Body<'a> {
    content_type: ContentType,
    body: &'a str,
}

pub enum ContentType {
    Html,
    PlainText,
}

etc.

I feel like providing typing for an API is be the whole point of this kind of library. Otherwise if I'm going to have to read the Sendgrid spec anyway to figure which fields are mandatory and where I should put them, I almost might as well write my own serde SDK.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions