Sendgrid
Sendgrid is a popular provider for sending email with a visual email template builder. When the email-sendgrid
feature
is enabled, Roadster will initialize a Sendgrid client via the sendgrid
crate.
Sendgrid also supports sending emails via SMTP. For details on Roadster's SMTP integration, see the previous chapter.
Configure the Sendgrid integration
The Sendgrid connection details can be configured via your app's config files, and via env vars or an
AsyncSource
for
sensitive connection details.
# Note: Hard-coded connection details are used here for demonstration purposes only. In a real application,
# an `AsyncSource` should be used to fetch secrets from an external service, such as AWS or GCS
# secrets manager services.
[email.sendgrid]
api-key = "api-key"
# `sandbox` should not be true in prod (simply omit this field in the prod config)
sandbox = true
Sending an email
With the Sendgrid client, emails are sent by providing a Sendgrid email template ID and the template's parameters. Below is a simple example of using the Sendgrid client. See Sendgrid's docs for more details on the other fields you may want to set when sending emails.
pub struct EmailConfirmationSendgrid {
state: AppContext,
}
impl EmailConfirmationSendgrid {
pub fn new(state: &AppContext) -> Self {
Self {
state: state.clone(),
}
}
}
#[derive(Debug, TypedBuilder, Serialize, Deserialize)]
pub struct EmailConfirmationSendgridArgs {
user_id: Uuid,
}
#[async_trait]
impl Worker<EmailConfirmationSendgridArgs> for EmailConfirmationSendgrid {
#[instrument(skip_all)]
async fn perform(&self, args: EmailConfirmationSendgridArgs) -> sidekiq::Result<()> {
let user = User::find_by_id(&self.state, args.user_id).await?;
send_email(&self.state, &user).await?;
Ok(())
}
}
const TEMPLATE_ID: &str = "template-id";
#[derive(Serialize)]
struct EmailTemplateArgs {
verify_url: String,
}
/// Send the verification email to the user.
async fn send_email(state: &AppContext, user: &User) -> RoadsterResult<()> {
let verify_url = "https://exaple.com?verify=1234".to_string();
let personalization = Personalization::new(Email::new(&user.email))
.set_subject("Please confirm your email address")
.add_dynamic_template_data_json(&EmailTemplateArgs { verify_url })?;
let message = Message::new(Email::new(state.config().email.from.email.to_string()))
.set_template_id(TEMPLATE_ID)
.add_personalization(personalization);
state.sendgrid().send(&message).await?;
info!(user=%user.id, "Email confirmation sent");
Ok(())
}