Harden send_mail API and TLS configuration
This commit is contained in:
@@ -2,8 +2,7 @@ INSERT INTO sqlpage_functions (
|
||||
"name",
|
||||
"introduced_in_version",
|
||||
"icon",
|
||||
"description_md",
|
||||
"return_type"
|
||||
"description_md"
|
||||
)
|
||||
VALUES (
|
||||
'send_mail',
|
||||
@@ -11,7 +10,7 @@ VALUES (
|
||||
'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_HOST` contains the relay host name. Set `SMTP_PORT` when the relay does not use the default for the selected encryption mode: 587 for `starttls`, 465 for `tls`, or 25 for `none`.
|
||||
|
||||
`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.
|
||||
|
||||
@@ -19,23 +18,23 @@ If your SMTP server requires authentication, configure `SMTP_USERNAME` and `SMTP
|
||||
|
||||
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>"`.
|
||||
- `to`: 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>`.
|
||||
- `from`: sender address. It may be omitted when `SMTP_FROM` configures a default sender.
|
||||
- `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.
|
||||
The function returns `NULL` after the SMTP relay accepts the message and raises an error if the message cannot be sent. The argument is required; passing `NULL` is an error.
|
||||
|
||||
### Example
|
||||
|
||||
```sql
|
||||
set message = json_object(
|
||||
''recipient'', ''admin@example.com'',
|
||||
''sender'', ''contact@example.com'',
|
||||
''to'', ''admin@example.com'',
|
||||
''from'', ''contact@example.com'',
|
||||
''subject'', ''New contact form message'',
|
||||
''body'', ''Hello from SQLPage!''
|
||||
);
|
||||
@@ -50,7 +49,7 @@ 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'',
|
||||
''to'', ''admin@example.com'',
|
||||
''reply_to'', $email,
|
||||
''subject'', ''Website contact form'',
|
||||
''body'', $message
|
||||
@@ -58,8 +57,7 @@ set mail = json_object(
|
||||
select sqlpage.send_mail($mail)
|
||||
where $message is not null;
|
||||
```
|
||||
',
|
||||
'JSON'
|
||||
'
|
||||
);
|
||||
|
||||
INSERT INTO sqlpage_function_parameters (
|
||||
@@ -73,6 +71,6 @@ 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`.',
|
||||
'A JSON object containing the email to send. Required properties are `to`, `subject`, and `body`. Optional properties are `from` (required unless `SMTP_FROM` is configured) and `reply_to`. Unknown properties are rejected to catch misspellings.',
|
||||
'JSON'
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@ docker compose up
|
||||
|
||||
Open http://localhost:8080 to send an email, then inspect it in the Mailpit inbox at http://localhost:8025.
|
||||
|
||||
The SMTP server is configured in [`docker-compose.yml`](./docker-compose.yml) with `SMTP_HOST=mailpit:1025` and `SMTP_TLS_MODE=none`. Plaintext mode is intended only for trusted local SMTP servers such as Mailpit.
|
||||
The SMTP server is configured in [`docker-compose.yml`](./docker-compose.yml) with `SMTP_HOST=mailpit`, `SMTP_PORT=1025`, and `SMTP_TLS_MODE=none`. Plaintext mode is intended only for trusted local SMTP servers such as Mailpit.
|
||||
|
||||
For a remote SMTP relay, keep the default `SMTP_TLS_MODE=starttls`, or set it to `tls` when the relay requires implicit TLS. Configure `SMTP_USERNAME` and `SMTP_PASSWORD` when authentication is required; SQLPage rejects credentials in plaintext mode.
|
||||
|
||||
@@ -18,14 +18,14 @@ The form handler sends the message with a single function call:
|
||||
|
||||
```sql
|
||||
set message = json_object(
|
||||
'recipient', :recipient,
|
||||
'sender', :sender,
|
||||
'to', :recipient,
|
||||
'from', :sender,
|
||||
'subject', :subject,
|
||||
'body', :body
|
||||
);
|
||||
set sent_message = sqlpage.send_mail($message);
|
||||
set _ = sqlpage.send_mail($message);
|
||||
```
|
||||
|
||||
After the SMTP server accepts the email, `sqlpage.send_mail` returns the message JSON unchanged. It raises an error when delivery to the SMTP server fails.
|
||||
`sqlpage.send_mail` returns `NULL` after the SMTP relay accepts the message. It raises an error when the relay rejects the message or cannot be reached, so statements after the call run only on success.
|
||||
|
||||
Do not expose an unrestricted form like this publicly. In production, authenticate users, restrict recipients, validate input, and add rate limiting to prevent abuse.
|
||||
|
||||
@@ -4,7 +4,8 @@ services:
|
||||
ports:
|
||||
- "8080:8080"
|
||||
environment:
|
||||
SMTP_HOST: mailpit:1025
|
||||
SMTP_HOST: mailpit
|
||||
SMTP_PORT: 1025
|
||||
SMTP_TLS_MODE: none
|
||||
volumes:
|
||||
- .:/var/www
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set message = json_object(
|
||||
'recipient', :recipient,
|
||||
'sender', :sender,
|
||||
'to', :recipient,
|
||||
'from', :sender,
|
||||
'subject', :subject,
|
||||
'body', :body
|
||||
);
|
||||
@@ -9,8 +9,7 @@ set sent_message = sqlpage.send_mail($message);
|
||||
select
|
||||
'alert' as component,
|
||||
'success' as color,
|
||||
'Email sent successfully' as title
|
||||
where $sent_message is not null;
|
||||
'Email sent successfully' as title;
|
||||
|
||||
select 'button' as component;
|
||||
select 'Send another email' as title, 'index.sql' as link;
|
||||
|
||||
Reference in New Issue
Block a user