# Add repository
echo "deb [trusted=yes] https://foxzi.github.io/sendry/apt stable main" | sudo tee /etc/apt/sources.list.d/sendry.list
# Install
sudo apt update
sudo apt install sendry# Add repository
sudo tee /etc/yum.repos.d/sendry.repo << 'EOF'
[sendry]
name=Sendry Repository
baseurl=https://foxzi.github.io/sendry/rpm/stable/$basearch/
enabled=1
gpgcheck=0
EOF
# Install
sudo dnf install sendry# Download and install
wget https://github.com/foxzi/sendry/releases/latest/download/sendry_0.4.18-r1_x86_64.apk
apk add --allow-untrusted sendry_*.apk# Download latest release
curl -LO https://github.com/foxzi/sendry/releases/latest/download/sendry-linux-amd64
chmod +x sendry-linux-amd64
sudo mv sendry-linux-amd64 /usr/local/bin/sendrygit clone https://github.com/foxzi/sendry.git
cd sendry
make build
sudo cp build/sendry /usr/local/bin/docker pull ghcr.io/foxzi/sendry:latestThe easiest way to create a configuration is using the init command:
# Interactive mode - prompts for values
sendry init
# Non-interactive with flags
sendry init --domain example.com --hostname mail.example.com --dkim
# Quick sandbox setup for testing
sendry init --domain test.local --mode sandbox -o test.yamlThe wizard will:
- Generate a complete configuration file
- Optionally create DKIM keys
- Show all DNS records you need to add (SPF, DKIM, DMARC)
- Generate secure API key and SMTP password
Create a test config test.yaml:
server:
hostname: "localhost"
smtp:
listen_addr: ":2525"
submission_addr: ":2587"
domain: "test.local"
auth:
required: false
domains:
test.local:
mode: sandbox
api:
listen_addr: ":8080"
api_key: "test-api-key"
queue:
workers: 2
storage:
path: "./data/queue.db"
logging:
level: "debug"
format: "text"Run the server:
mkdir -p data
sendry serve -c test.yaml# Send test email through local server
sendry test send -c config.yaml --to user@example.com
# With custom subject and body
sendry test send -c config.yaml --to user@example.com --subject "Test" --body "Hello!"
# Skip TLS for local testing without certificates
sendry test send -c config.yaml --to user@example.com --no-tls
# Use specific port
sendry test send -c config.yaml --to user@example.com --port 2525# Using netcat
echo -e "EHLO test\nMAIL FROM:<test@test.local>\nRCPT TO:<user@example.com>\nDATA\nSubject: Test\n\nHello World\n.\nQUIT" | nc localhost 2525
# Using swaks (if installed)
swaks --to user@example.com --from test@test.local --server localhost:2525curl -X POST http://localhost:8080/api/v1/send \
-H "X-API-Key: test-api-key" \
-H "Content-Type: application/json" \
-d '{
"from": "api@test.local",
"to": ["user@example.com"],
"subject": "Test Email",
"body": "Hello from Sendry!"
}'# Via CLI
sendry template create -c config.yaml --name welcome --subject "Hello {{.Name}}" --text welcome.txt
# Via API
curl -X POST http://localhost:8080/api/v1/templates \
-H "X-API-Key: test-api-key" \
-H "Content-Type: application/json" \
-d '{
"name": "welcome",
"subject": "Hello {{.Name}}",
"text": "Welcome {{.Name}}!\nYour order #{{.OrderID}} is confirmed.",
"html": "<p>Welcome <b>{{.Name}}</b>!</p>"
}'# Via CLI
sendry template preview -c config.yaml welcome --data '{"Name":"John","OrderID":"12345"}'
# Via API
curl -X POST http://localhost:8080/api/v1/templates/{id}/preview \
-H "X-API-Key: test-api-key" \
-H "Content-Type: application/json" \
-d '{"data":{"Name":"John","OrderID":"12345"}}'curl -X POST http://localhost:8080/api/v1/send/template \
-H "X-API-Key: test-api-key" \
-H "Content-Type: application/json" \
-d '{
"template_id": "{id}",
"from": "noreply@example.com",
"to": ["user@example.com"],
"data": {"Name": "John", "OrderID": "12345"}
}'See Templates Guide for more details.
Sendry Web is a web interface for managing email campaigns, templates, and recipient lists.
# Using binary
sendry-web serve --config /etc/sendry/web.yaml
# Using Docker Compose
docker compose up -dAccess the panel at http://localhost:8088 (default credentials depend on your setup).
Edit web.yaml to add your Sendry MTA server:
sendry:
servers:
- name: "mta-1"
base_url: "http://localhost:8080"
api_key: "your-api-key"
env: "prod"- Go to Templates → New Template
- Fill in:
- Name: e.g., "Welcome Email"
- Subject: e.g., "Welcome, {{name}}!"
- Content: HTML body with variables like
{{name}},{{email}}
- Choose editor mode:
- Visual (Quill) - WYSIWYG editing
- Blocks (Editor.js) - block-based editing
- Code (CodeMirror) - raw HTML
- Click Save
- Click Deploy to send template to MTA server
- Go to Recipients → New List
- Enter list name (e.g., "Newsletter Subscribers")
- Click Create
- Add recipients:
- Manual: Click Add Recipient, enter email and variables
- CSV Import: Click Import, upload CSV file
CSV format example:
email,name,company
john@example.com,John Doe,Acme Inc
jane@example.com,Jane Smith,Tech Corp- Go to Campaigns → New Campaign
- Fill in:
- Name: e.g., "January Newsletter"
- From: sender email (e.g.,
newsletter@example.com) - Template: select your template
- Recipient List: select your list
- Click Create
- (Optional) Add Variables for the campaign (available in templates as
{{var_name}}) - (Optional) Create Variants for A/B testing
- Open the campaign → Click Send
- Configure send options:
- Server: select MTA server
- Schedule: send now or schedule for later
- Dry Run: test without actually sending (sandbox mode)
- Batch Size: emails per batch
- Delay: pause between batches
- Click Start Job
- Go to Jobs to see all jobs
- Click on a job to view:
- Progress (sent/failed/pending)
- Individual item status
- Error messages
- Actions available:
- Pause / Resume - pause/resume sending
- Cancel - stop the job
- Retry Failed - retry failed items
- Go to Servers → select server → DKIM Keys
- Click New DKIM Key
- Enter:
- Domain: e.g.,
example.com - Selector: e.g.,
sendry
- Domain: e.g.,
- Check Deploy to server after creation
- Click Generate Key
- Add the displayed DNS TXT record to your domain
- Go to Servers → select server → Domains
- Click New Domain
- Configure:
- Domain: e.g.,
example.com - Mode: production/sandbox/redirect/bcc
- DKIM: enable and select key
- Rate Limits: messages per hour/day
- Domain: e.g.,
- Click Create
# List all messages
curl -H "X-API-Key: test-api-key" http://localhost:8080/api/v1/sandbox/messages
# Get specific message
curl -H "X-API-Key: test-api-key" http://localhost:8080/api/v1/sandbox/messages/{id}
# Get statistics
curl -H "X-API-Key: test-api-key" http://localhost:8080/api/v1/sandbox/statscurl http://localhost:8080/health# Full production setup with DKIM and Let's Encrypt
sendry init --domain example.com --dkim --acme --acme-email admin@example.com
# Or interactive mode
sendry initFor manual configuration, see full configuration example.
Key steps for production:
- Configure TLS certificates or enable ACME
- Set up DKIM signing
- Enable authentication
- Configure proper rate limits
- Set domain mode to
production
sendry dkim generate --domain example.com --selector sendry --out /var/lib/sendry/dkim/Add the DNS TXT record shown in the output.
Before going to production, check if your server IP is blacklisted:
sendry ip check <your-server-ip>| Port | Service | Description |
|---|---|---|
| 25 | SMTP | Server-to-server mail transfer |
| 587 | Submission | Client mail submission (STARTTLS) |
| 465 | SMTPS | Client mail submission (implicit TLS) |
| 8080 | HTTP API | REST API for sending and management |
| Mode | Description |
|---|---|
production |
Normal delivery to recipients |
sandbox |
Capture emails locally (for testing) |
redirect |
Redirect all emails to specified addresses |
bcc |
Normal delivery + copy to archive |