Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 143 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ openidconnect = { version = "4.0.0", default-features = false, features = ["acce
encoding_rs = "0.8.35"
odbc-sys = { version = "0", optional = true }
regex = "1"
lettre = { version = "0.11", default-features = false, features = ["builder", "smtp-transport", "tokio1", "tokio1-native-tls"] }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use a TLS backend Docker images can build and run

In the Docker build path I checked, scripts/setup-cross-compilation.sh only installs/stages gcc, libgcc and make, and the Dockerfile only copies /tmp/sqlpage-libs/* into the busybox runtime image. Enabling lettre's tokio1-native-tls feature here pulls native-tls/openssl-sys, so the Linux Docker builds now need OpenSSL headers/pkg-config at build time and libssl/libcrypto plus trust roots at runtime; without adding those for each target, the published minimal/duckdb images can fail to build or start. Prefer lettre's rustls backend or add the OpenSSL build/runtime dependencies explicitly.

Useful? React with 👍 / 👎.


# OpenTelemetry / tracing
tracing = "0.1"
Expand Down
4 changes: 4 additions & 0 deletions configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ Here are the available configuration options and their default values:
| `environment` | development | The environment in which SQLPage is running. Can be either `development` or `production`. In `production` mode, SQLPage will hide error messages and stack traces from the user, and will cache sql files in memory to avoid reloading them from disk. |
| `cache_stale_duration_ms` | 1000 (prod), 0 (dev) | The duration in milliseconds that a file can be cached before its freshness is checked against the filesystem. Defaults to 1000ms (1 second) in production and 0ms in development. |
| `content_security_policy` | `script-src 'self' 'nonce-{NONCE}'` | The [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) to set in the HTTP headers. If you get CSP errors in the browser console, you can set this to the empty string to disable CSP. If you want a custom CSP that contains a nonce, include the `'nonce-{NONCE}'` directive in your configuration string and it will be populated with a random value per request. |
| `smtp_host` | | SMTP server used by the `sqlpage.send_mail` function. Accepts only a host name or `host:port`; if no port is provided, SQLPage uses port 25. Set with `SMTP_HOST` in the environment. |
| `smtp_username` | | Optional SMTP user name for `sqlpage.send_mail`. When set, SQLPage authenticates to `SMTP_HOST` using this user name and `smtp_password`. Credentials require `smtp_tls_mode` to be `starttls` or `tls`. |
| `smtp_password` | | Optional SMTP password for `sqlpage.send_mail` when `smtp_username` is set. |
| `smtp_tls_mode` | `starttls` | Encryption mode for `sqlpage.send_mail`: `starttls` requires a STARTTLS upgrade, `tls` uses TLS from connection start, and `none` permits plaintext only without credentials for trusted local SMTP servers. |
| `system_root_ca_certificates` | false | Whether to use the system root CA certificates to validate SSL certificates when making http requests with `sqlpage.fetch`. If set to false, SQLPage will use its own set of root CA certificates. If the `SSL_CERT_FILE` or `SSL_CERT_DIR` environment variables are set, they will be used instead of the system root CA certificates. |
| `max_recursion_depth` | 10 | Maximum depth of recursion allowed in the `run_sql` function. Maximum value is 255. |
| `markdown_allow_dangerous_html` | false | Whether to allow raw HTML in markdown content. Only enable this if the markdown content is fully trusted (not user generated). |
Expand Down
78 changes: 78 additions & 0 deletions examples/official-site/sqlpage/migrations/75_send_mail.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
INSERT INTO sqlpage_functions (
"name",
"introduced_in_version",
"icon",
"description_md",
"return_type"
)
VALUES (
'send_mail',
'0.45.0',
'mail',
'Sends an email using the SMTP server configured with `SMTP_HOST`.

`SMTP_HOST` must contain only a host name or `host:port`; URL schemes and paths are rejected. When no port is specified, SQLPage uses port 25.

`SMTP_TLS_MODE` defaults to `starttls`, which requires a STARTTLS upgrade before sending email or credentials. Set it to `tls` for implicit TLS, commonly used on port 465. Plaintext mode (`none`) is allowed only without credentials and should be used only for trusted local SMTP servers.

If your SMTP server requires authentication, configure `SMTP_USERNAME` and `SMTP_PASSWORD` as well.

The function accepts a single JSON object argument. The required properties are:

- `recipient`: email address to send to, optionally including a display name such as `"Jane Doe <jane@example.com>"`.
- `subject`: email subject.
- `body`: plain text email body.

Optional properties:

- `sender`: sender address. Defaults to `SQLPage <sqlpage@localhost>`.
- `reply_to`: reply-to address.

After the SMTP server accepts the message, the function returns its JSON argument unchanged. It returns `NULL` when passed `NULL`, and raises an error if the message cannot be sent.

### Example

```sql
set message = json_object(
''recipient'', ''admin@example.com'',
''sender'', ''contact@example.com'',
''subject'', ''New contact form message'',
''body'', ''Hello from SQLPage!''
);
select sqlpage.send_mail($message);
```

### Contact form example

```sql
select ''form'' as component, ''post'' as method;
select ''email'' as name, ''email'' as type, true as required;
select ''message'' as name, ''textarea'' as type, true as required;

set mail = json_object(
''recipient'', ''admin@example.com'',
''reply_to'', $email,
''subject'', ''Website contact form'',
''body'', $message

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use POST variables in the contact-form example

For this POST form, the submitted fields need to be read with :email and :message; in the current evaluator $email/$message read SET/URL variables instead. On a normal form submission without same-named query parameters, the mail body/reply-to and the later WHERE $message guard are NULL, so the documented contact form never sends an email.

Useful? React with 👍 / 👎.

);
select sqlpage.send_mail($mail)
where $message is not null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Alias the guarded send_mail call

In this contact-form example, the unaliased sqlpage.send_mail($mail) is evaluated as a function parameter before the SQL statement runs, so the WHERE clause does not guard the call. On the initial GET/empty-message case the mail JSON contains null fields and the page errors before the predicate can filter it out, and other false predicates would still allow the send attempt; add an alias such as as sent so SQLPage delays the top-level function until after the row passes the WHERE, or otherwise move the condition outside the call.

Useful? React with 👍 / 👎.

```
',
'JSON'
);

INSERT INTO sqlpage_function_parameters (
"function",
"index",
"name",
"description_md",
"type"
)
VALUES (
'send_mail',
1,
'message',
'A JSON object containing the email to send. Required properties are `recipient`, `subject`, and `body`. Optional properties are `sender` and `reply_to`.',
'JSON'
);
Loading
Loading