Skip to content

Commit

Permalink
docs: Add example of using Sendgrid client (#404)
Browse files Browse the repository at this point in the history
  • Loading branch information
spencewenski authored Oct 11, 2024
1 parent b3ad334 commit b05100d
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 2 deletions.
3 changes: 2 additions & 1 deletion examples/full/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ default = ["grpc"]
grpc = ["roadster/grpc", "dep:tonic", "dep:tonic-reflection", "dep:prost"]

[dependencies]
roadster = { version = "0.6", path = "../..", features = ["email-smtp"] }
roadster = { version = "0.6", path = "../..", features = ["email-smtp", "email-sendgrid"] }
tokio = { workspace = true }
tokio-util = { workspace = true }
anyhow = { workspace = true }
Expand Down Expand Up @@ -39,6 +39,7 @@ serde = { workspace = true, features = ["derive"] }

# Email
lettre = { workspace = true, features = ["pool"] }
sendgrid = { workspace = true }

[build-dependencies]
tonic-build = { workspace = true }
Expand Down
4 changes: 4 additions & 0 deletions examples/full/config/development/email.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ uri = "smtp://localhost:1025"
#port = 465
#username = "username"
#password = "password"

[email.sendgrid]
api-key = "api-key"
sandbox = true
18 changes: 17 additions & 1 deletion examples/full/src/api/http/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ use roadster::api::http::build_path;
use roadster::error::RoadsterResult;
use roadster::service::worker::sidekiq::app_worker::AppWorker;
use schemars::JsonSchema;
use sendgrid::v3::{Content, Email, Personalization};
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use tracing::instrument;
use tracing::{instrument, warn};

const BASE: &str = "/example";
const TAG: &str = "Example";
Expand All @@ -33,6 +34,7 @@ pub struct ExampleResponse {}
async fn example_get(State(state): State<AppState>) -> RoadsterResult<Json<ExampleResponse>> {
ExampleWorker::enqueue(&state, "Example".to_string()).await?;

// Emails can be sent via SMTP
let email: MessageBuilder = (&state.app_context.config().email).into();
let email = email
.to(Mailbox::from_str("hello@example.com")?)
Expand All @@ -41,6 +43,20 @@ async fn example_get(State(state): State<AppState>) -> RoadsterResult<Json<Examp
.body("Hello, World!".to_string())?;
state.app_context.mailer().send(&email)?;

// Emails can also be sent using Sendgrid
let email: sendgrid::v3::Message = (&state.app_context.config().email).into();
let email = email
.set_subject("Greetings")
.add_content(
Content::new()
.set_content_type("text/plain")
.set_value("Hello, World!"),
)
.add_personalization(Personalization::new(Email::new("hello@example.com")));
if let Err(err) = state.app_context.sendgrid().send(&email).await {
warn!("An error occurred when sending email using Sendgrid. This may be expected in a dev/test environment if a prod API key is not used. Error: {err}");
}

Ok(Json(ExampleResponse {}))
}

Expand Down
11 changes: 11 additions & 0 deletions src/error/email.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ pub enum EmailError {
#[error(transparent)]
LettreError(#[from] lettre::error::Error),

#[cfg(feature = "email-sendgrid")]
#[error(transparent)]
SendgridError(#[from] sendgrid::SendgridError),

#[error(transparent)]
Other(#[from] Box<dyn std::error::Error + Send + Sync>),
}
Expand All @@ -39,3 +43,10 @@ impl From<lettre::error::Error> for Error {
Self::Email(EmailError::from(value))
}
}

#[cfg(feature = "email-sendgrid")]
impl From<sendgrid::SendgridError> for Error {
fn from(value: sendgrid::SendgridError) -> Self {
Self::Email(EmailError::from(value))
}
}

0 comments on commit b05100d

Please sign in to comment.