Initial commit: Grav CMS setup with HTML reference material

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-18 23:38:26 +02:00
commit a9be15caf3
2261 changed files with 418989 additions and 0 deletions
@@ -0,0 +1,141 @@
---
title: 'Send Email'
template: api-endpoint
taxonomy:
category: docs
api:
method: POST
path: /email/send
description: 'Send an ad-hoc email. Uses the email plugin''s configured mailer transport (SMTP, Sendmail, etc). The "from" address defaults to the plugin''s configured sender if not specified.'
parameters:
-
name: to
type: string
required: true
description: 'Recipient email address. Supports: "user@example.com", "Name <user@example.com>", or comma-separated for multiple recipients.'
-
name: subject
type: string
required: true
description: 'Email subject line.'
-
name: body
type: string
required: true
description: 'Email body content. Interpreted as HTML by default (see content_type).'
-
name: from
type: string
required: false
description: 'Sender email address. Defaults to the email plugin''s configured "from" address.'
-
name: cc
type: string
required: false
description: 'CC recipient(s). Same format as "to".'
-
name: bcc
type: string
required: false
description: 'BCC recipient(s). Same format as "to".'
-
name: reply_to
type: string
required: false
description: 'Reply-To address.'
-
name: content_type
type: string
required: false
description: 'Content type: "text/html" (default) or "text/plain".'
request_example: "{\n \"to\": \"recipient@example.com\",\n \"subject\": \"Hello from Grav API\",\n \"body\": \"<h1>Hello</h1><p>This email was sent via the Grav API.</p>\",\n \"from\": \"sender@example.com\",\n \"cc\": \"copy@example.com\",\n \"content_type\": \"text/html\"\n}"
response_example: "{\n \"data\": {\n \"message\": \"Email sent successfully.\",\n \"to\": \"recipient@example.com\",\n \"subject\": \"Hello from Grav API\"\n }\n}"
response_codes:
-
code: '200'
description: 'Email sent successfully'
-
code: '401'
description: 'Unauthorized - missing or invalid API key'
-
code: '403'
description: 'Forbidden - missing api.system.write permission'
-
code: '422'
description: 'Validation error - missing required fields (to, subject, body)'
-
code: '500'
description: 'Send failed - mailer transport error'
-
code: '503'
description: 'Email plugin not enabled or configured'
---
## Usage Notes
### Required Headers
```
X-API-Key: grav_your_api_key
X-Grav-Environment: localhost
Content-Type: application/json
```
### Multiple Recipients
Send to multiple recipients by comma-separating addresses:
```json
{
"to": "user1@example.com, user2@example.com",
"subject": "Team Update",
"body": "<p>Hello team!</p>"
}
```
Or use named addresses:
```json
{
"to": "Alice <alice@example.com>, Bob <bob@example.com>"
}
```
### Plain Text Emails
Set `content_type` to send plain text instead of HTML:
```json
{
"to": "user@example.com",
"subject": "Plain text message",
"body": "This is a plain text email.\n\nNo HTML formatting.",
"content_type": "text/plain"
}
```
### Example with cURL
```bash
curl -X POST "https://yoursite.com/api/v1/email/send" \
-H "X-API-Key: grav_your_key" \
-H "X-Grav-Environment: localhost" \
-H "Content-Type: application/json" \
-d '{
"to": "recipient@example.com",
"subject": "Hello from Grav",
"body": "<h1>Hello</h1><p>Sent via the API</p>"
}'
```
### Error Handling
If the email transport fails (e.g., SMTP connection error), the API returns a 500 error with details:
```json
{
"status": 500,
"title": "Internal Server Error",
"detail": "Failed to send email: Connection to smtp.example.com:587 timed out"
}
```
@@ -0,0 +1,65 @@
---
title: 'Test Email'
template: api-endpoint
taxonomy:
category: docs
api:
method: POST
path: /email/test
description: 'Send a test email to verify that the email plugin is correctly configured. Sends a simple HTML email with a timestamp. Useful for validating SMTP settings, DNS, and deliverability.'
parameters:
-
name: to
type: string
required: false
description: 'Recipient email address. Defaults to the email plugin''s configured "to" address.'
request_example: "{\n \"to\": \"admin@example.com\"\n}"
response_example: "{\n \"data\": {\n \"message\": \"Test email sent successfully.\",\n \"to\": \"admin@example.com\"\n }\n}"
response_codes:
-
code: '200'
description: 'Test email sent successfully'
-
code: '401'
description: 'Unauthorized - missing or invalid API key'
-
code: '403'
description: 'Forbidden - missing api.system.write permission'
-
code: '422'
description: 'No recipient - no "to" provided and no default configured'
-
code: '500'
description: 'Send failed - mailer transport error'
-
code: '503'
description: 'Email plugin not enabled or configured'
---
## Usage Notes
### Quick Configuration Check
The simplest way to verify your email setup works end-to-end:
```bash
curl -X POST "https://yoursite.com/api/v1/email/test" \
-H "X-API-Key: grav_your_key" \
-H "X-Grav-Environment: localhost" \
-H "Content-Type: application/json" \
-d '{"to": "your@email.com"}'
```
### Default Recipient
If you omit the `to` field, the test email is sent to the default recipient configured in the email plugin settings (`plugins.email.to`). If neither is set, the endpoint returns a 422 error.
### Test Email Content
The test email contains:
- **Subject**: "Grav API - Test Email"
- **Body**: A simple HTML message with the send timestamp
- **From**: The configured sender address from email plugin settings
This is intentionally simple to isolate transport issues from content/template problems.
+26
View File
@@ -0,0 +1,26 @@
---
title: Email
template: chapter
description: Send emails via the Grav API
taxonomy:
category:
- docs
---
The Email API allows you to send ad-hoc emails and test your email configuration programmatically. These endpoints are registered by the Email plugin via the Grav API plugin's extensibility system.
## Requirements
- [Grav API Plugin](https://github.com/getgrav/grav-plugin-api) must be installed and enabled
- Email plugin must be installed, enabled, and configured with a valid mailer
## Authentication
All email endpoints require the `api.system.write` permission.
## Available Operations
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/email/send` | Send an ad-hoc email |
| POST | `/email/test` | Send a test email to verify configuration |
@@ -0,0 +1,216 @@
{
"info": {
"_postman_id": "grav-email-api-v1",
"name": "Grav Email API",
"description": "API endpoints for the Grav Email plugin.\n\nRequires the Grav CMS API plugin to be installed and enabled.\n\nUses the same environment variables as the core Grav CMS API collection:\n- `base_url` - Your Grav site URL\n- `api_prefix` - API version prefix (default: /api/v1)\n- `api_key` - A valid API key with api.system.write permission\n- `grav_environment` - Grav environment (default: localhost)",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "Send Email",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has success message', () => pm.expect(res.data.message).to.include('successfully'));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"to\": \"recipient@example.com\",\n \"subject\": \"Hello from Grav API\",\n \"body\": \"<h1>Hello</h1><p>This email was sent via the Grav API.</p>\",\n \"content_type\": \"text/html\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/email/send",
"host": ["{{base_url}}{{api_prefix}}"],
"path": ["email", "send"]
},
"description": "Send an ad-hoc email.\n\n**Required fields**: `to`, `subject`, `body`\n\n**Optional fields**: `from` (defaults to plugin config), `cc`, `bcc`, `reply_to`, `content_type` (default: `text/html`)"
}
},
{
"name": "Send Email (Plain Text)",
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"to\": \"recipient@example.com\",\n \"subject\": \"Plain text message\",\n \"body\": \"This is a plain text email.\\n\\nNo HTML formatting.\",\n \"content_type\": \"text/plain\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/email/send",
"host": ["{{base_url}}{{api_prefix}}"],
"path": ["email", "send"]
},
"description": "Send a plain text email by setting content_type to text/plain."
}
},
{
"name": "Send Email (with CC/BCC)",
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"to\": \"recipient@example.com\",\n \"subject\": \"Team Update\",\n \"body\": \"<p>Hello team, here is the latest update.</p>\",\n \"cc\": \"manager@example.com\",\n \"bcc\": \"archive@example.com\",\n \"reply_to\": \"noreply@example.com\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/email/send",
"host": ["{{base_url}}{{api_prefix}}"],
"path": ["email", "send"]
},
"description": "Send an email with CC, BCC, and Reply-To fields."
}
},
{
"name": "Send Email (custom from)",
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"to\": \"recipient@example.com\",\n \"from\": \"Custom Sender <custom@example.com>\",\n \"subject\": \"Custom From Address\",\n \"body\": \"<p>This email has a custom from address.</p>\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/email/send",
"host": ["{{base_url}}{{api_prefix}}"],
"path": ["email", "send"]
},
"description": "Send an email with a custom from address, overriding the plugin's configured default."
}
},
{
"name": "Test Email",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has success message', () => pm.expect(res.data.message).to.include('successfully'));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"to\": \"your@email.com\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/email/test",
"host": ["{{base_url}}{{api_prefix}}"],
"path": ["email", "test"]
},
"description": "Send a test email to verify your email configuration is working. If `to` is omitted, sends to the plugin's configured default recipient."
}
},
{
"name": "Test Email (default recipient)",
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/email/test",
"host": ["{{base_url}}{{api_prefix}}"],
"path": ["email", "test"]
},
"description": "Send a test email to the plugin's configured default recipient. No body fields required."
}
}
]
}