Skip to content

Commit

Permalink
feat: Allow specifying the smtp port via config (#395)
Browse files Browse the repository at this point in the history
Also, update READMEs to add instructions for how to start a local smtp
server for dev/testing.

Also, don't run pre-push checks against entire workspace, just roadster
  • Loading branch information
spencewenski authored Oct 9, 2024
1 parent c94e291 commit 9f1b19b
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 16 deletions.
16 changes: 8 additions & 8 deletions .cargo-husky/hooks/pre-push
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ cargo clippy --all-targets -- -D warnings
# With all features
echo "### build --all-features ###"
cargo build --all-features
echo "### nextest run --all-features --workspace ###"
cargo nextest run --all-features --no-fail-fast --workspace
echo "### nextest run --all-features ###"
cargo nextest run --all-features --no-fail-fast
# Nextest doesn't support doc tests, run those separately
echo "### test --doc --all-features --workspace ###"
cargo test --doc --all-features --no-fail-fast --workspace
echo "### check --all-features --workspace ###"
cargo check --all-features --workspace
echo "### clippy --workspace --all-targets --all-features -- -D warnings ###"
cargo clippy --workspace --all-targets --all-features -- -D warnings
echo "### test --doc --all-features ###"
cargo test --doc --all-features --no-fail-fast
echo "### check --all-features ###"
cargo check --all-features
echo "### clippy --all-targets --all-features -- -D warnings ###"
cargo clippy --all-targets --all-features -- -D warnings

echo "### cargo doc --all-features --no-deps ###"
RUSTDOCFLAGS="-D rustdoc::all -A rustdoc::private_intra_doc_links" cargo doc --all-features --no-deps
Expand Down
28 changes: 21 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ and [Poem](https://github.com/poem-web/poem).
the `db-sql` feature)
- Built-in support for [Sidekiq.rs](https://crates.io/crates/rusty-sidekiq) for running async/background jobs (requires
the `sidekiq` feature)
- Built-in support for sending emails via SMTP (requires the `email-smtp` feature)
- Structured logs/traces using tokio's [tracing](https://docs.rs/tracing/latest/tracing/) crate. Export traces/metrics
using OpenTelemetry (requires the `otel` feature).
- Health checks to ensure the app's external dependencies are healthy
Expand All @@ -50,20 +51,20 @@ and [Poem](https://github.com/poem-web/poem).
## Start local DB

```shell
# Replace `example_dev` with your app name, e.g., `myapp_dev` (unless you're using our `full` example, as demonstrated below)
# Dev
# Replace `example_dev` with your app name, e.g., `myapp_dev`
docker run -d -p 5432:5432 -e POSTGRES_USER=roadster -e POSTGRES_DB=example_dev -e POSTGRES_PASSWORD=roadster postgres:15.3-alpine
# Test
docker run -d -p 5433:5432 -e POSTGRES_USER=roadster -e POSTGRES_DB=example_test -e POSTGRES_PASSWORD=roadster postgres:15.3-alpine
```

## Start local Redis instance (for [Sidekiq.rs](https://crates.io/crates/rusty-sidekiq))

```shell
# Dev
docker run -d -p 6379:6379 redis:7.2-alpine
# Test
docker run -d -p 6380:6379 redis:7.2-alpine
```

## Start local SMTP server instance (example: [maildev](https://github.com/maildev/maildev))

```shell
docker run -d -p 1080:1080 -p 1025:1025 maildev/maildev
```

## Create your app
Expand All @@ -90,6 +91,10 @@ echo ROADSTER__ENVIRONMENT=development >> .env
cargo run
```

## Explore the API

Navigate to http://localhost:3000/api/_docs to explore the app's OpenAPI playground

# Add a UI

Currently, Roadster is focused on back-end API development with Rust. We leave it to the consumer to decide how they
Expand All @@ -106,6 +111,15 @@ framework ([Leptos](https://github.com/leptos-rs/leptos) / [Yew](https://github.
|-----------------------------------------------|-------------------------------------------------------------------------------------|
| [Leptos](https://github.com/leptos-rs/leptos) | [leptos-ssr](https://github.com/roadster-rs/roadster/tree/main/examples/leptos-ssr) |

# Email

## Local testing of sending emails via SMTP

If you're using our SMTP integration to send emails, you can test locally using a mock SMTP server. Some options:

- [maildev](https://github.com/maildev/maildev)
- [smtp4dev](https://github.com/rnwood/smtp4dev)

# Tracing + OpenTelemetry

Roadster allows reporting traces and metrics using the `tracing` and `opentelemetry_rust` integrations. Provide the URL
Expand Down
2 changes: 2 additions & 0 deletions examples/full/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export ROADSTER__ENVIRONMENT=development
# Start the database and redis (for sidekiq). Note: change the credentials when deploying to prod
docker run -d -p 5432:5432 -e POSTGRES_USER=roadster -e POSTGRES_DB=example_dev -e POSTGRES_PASSWORD=roadster postgres:15.3-alpine
docker run -d -p 6379:6379 redis:7.2-alpine
# Start a local smtp server, such as https://github.com/maildev/maildev
docker run -d -p 1080:1080 -p 1025:1025 maildev/maildev
# Start the app
cargo run
```
6 changes: 6 additions & 0 deletions examples/full/config/development/email.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,10 @@
from = "[email protected]"

[email.smtp.connection]
# The `smtps` scheme should be used in production
uri = "smtp://localhost:1025"
# Alternatively, provide connection details as individual fields
#host = "smtp.example.com"
#port = 465
#username = "username"
#password = "password"
22 changes: 21 additions & 1 deletion src/config/email/smtp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ impl Validate for SmtpConnection {
#[non_exhaustive]
pub struct SmtpConnectionFields {
pub host: String,
pub port: Option<u16>,
pub username: String,
pub password: String,
}
Expand Down Expand Up @@ -69,7 +70,15 @@ impl TryFrom<&SmtpConnection> for SmtpTransportBuilder {
SmtpConnection::Fields(fields) => {
let credentials =
Credentials::new(fields.username.clone(), fields.password.clone());
SmtpTransport::relay(&fields.host).map(|builder| builder.credentials(credentials))
SmtpTransport::relay(&fields.host)
.map(|builder| {
if let Some(port) = fields.port {
builder.port(port)
} else {
builder
}
})
.map(|builder| builder.credentials(credentials))
}
SmtpConnection::Uri(fields) => SmtpTransport::from_url(fields.uri.as_ref()),
}
Expand Down Expand Up @@ -153,6 +162,17 @@ mod tests {
uri = "smtps://username:[email protected]:425"
"#
)]
#[case(
r#"
from = "[email protected]"
[smtp.connection]
host = "smtp.example.com"
port = 465
username = "username"
password = "password"
"#
)]
#[cfg_attr(coverage_nightly, coverage(off))]
fn serialization(_case: TestCase, #[case] config: &str) {
let email: Email = toml::from_str(config).unwrap();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
source: src/config/email/smtp.rs
expression: email
---
from = '[email protected]'
[smtp.connection]
host = 'smtp.example.com'
port = 465
username = 'username'
password = 'password'

0 comments on commit 9f1b19b

Please sign in to comment.