chore: SMTP is a simple implementation, recommand local server to have a spool
This commit is contained in:
@@ -185,6 +185,26 @@ Used by the magic-link invitation flow and the login-via-email flow. When `OXICL
|
||||
| `OXICLOUD_SMTP_FROM` | — | `From:` mailbox; bare address or RFC 5322 name-address (`OxiCloud <noreply@example.com>`) |
|
||||
| `OXICLOUD_SMTP_TLS` | `starttls` | Transport encryption: `starttls`, `tls`, or `none` (emits startup WARN) |
|
||||
|
||||
### Reliability and retries
|
||||
|
||||
OxiCloud does **not** spool mail. Each `send()` is a single attempt: if the remote SMTP server is unreachable, slow, or temporarily refusing the message, the send fails and the error is logged — there is no in-process retry, queue, or dead-letter handling. This keeps the HTTP path fast and the binary small at the cost of durability guarantees during a relay outage.
|
||||
|
||||
For production deployments where you cannot afford to drop invitation mail during a brief relay outage, **point OxiCloud at a local MTA configured as a smarthost** (Postfix, OpenSMTPD, exim, or `msmtp-mta`/`nullmailer` for minimal setups). The local MTA owns the durable queue: it accepts the message from OxiCloud in milliseconds over the loopback, then retries with its own exponential backoff against your real upstream relay until the message is delivered or the queue lifetime expires.
|
||||
|
||||
Typical local-relay config:
|
||||
|
||||
```env
|
||||
OXICLOUD_SMTP_HOST=127.0.0.1
|
||||
OXICLOUD_SMTP_PORT=25
|
||||
OXICLOUD_SMTP_TLS=none # loopback only — never over the network
|
||||
OXICLOUD_SMTP_FROM=OxiCloud <noreply@example.com>
|
||||
# OXICLOUD_SMTP_USER / _PASS unset — local MTA accepts loopback unauthenticated
|
||||
```
|
||||
|
||||
Then configure the local MTA's smarthost / relayhost to your upstream provider (SendGrid, Amazon SES, your corporate relay, etc.). Verify durability by stopping the upstream relay, sending an invitation, restarting the relay, and confirming the mail eventually arrives.
|
||||
|
||||
If you point `OXICLOUD_SMTP_HOST` directly at a remote SMTP server, treat the absence of retries as a documented constraint: a brief network glitch during invitation flow is a lost invite, and the recipient will need to be re-invited.
|
||||
|
||||
## Magic-Link Authentication
|
||||
|
||||
Configures the invite-by-email and login-via-email flows. Both require SMTP to be configured above.
|
||||
|
||||
@@ -318,6 +318,12 @@ OXICLOUD_WOPI_ENABLED=false
|
||||
# Used by the magic-link invitation flow (sharing with someone by email) and
|
||||
# the login-via-email flow. When HOST is empty (the default), the feature is
|
||||
# disabled and any endpoint that needs email returns 503.
|
||||
#
|
||||
# OxiCloud does NOT spool mail or retry failed sends — each delivery is a
|
||||
# single attempt. For durability against brief upstream outages, point this
|
||||
# at a local MTA (Postfix, OpenSMTPD, msmtp-mta, …) configured as a
|
||||
# smarthost. The local MTA owns the queue and retries against your real
|
||||
# relay. See docs/config/env.md → "Reliability and retries" for the recipe.
|
||||
|
||||
# SMTP server hostname or IP. Empty = feature disabled.
|
||||
#OXICLOUD_SMTP_HOST=smtp.example.com
|
||||
|
||||
@@ -8,6 +8,19 @@
|
||||
//! On startup the `From:` mailbox is parsed once and cached. Bad config
|
||||
//! (unparseable `from`, missing `host`) is reported during construction
|
||||
//! so the server fails fast rather than at first send.
|
||||
//!
|
||||
//! # No retry / no spool — by design
|
||||
//!
|
||||
//! `send()` makes a single attempt against the configured relay. If the
|
||||
//! relay is unreachable, slow, or returns a transient error, the call
|
||||
//! returns `Err` and the message is gone. There is no in-process queue,
|
||||
//! no exponential backoff, no dead-letter handling.
|
||||
//!
|
||||
//! Operators who need durability across upstream relay outages should
|
||||
//! point `OXICLOUD_SMTP_HOST` at a local MTA (Postfix, OpenSMTPD,
|
||||
//! msmtp-mta, …) configured as a smarthost — the local MTA owns the
|
||||
//! retry queue. See `docs/config/env.md` → "Reliability and retries"
|
||||
//! for the recipe.
|
||||
|
||||
use async_trait::async_trait;
|
||||
use lettre::message::{Mailbox, MultiPart, SinglePart, header::ContentType};
|
||||
|
||||
Reference in New Issue
Block a user