- Implement PKCE (Proof Key for Code Exchange) with S256 method - Add crypto/pkce module with code verifier and challenge generation - Modify OAuth flow to include code_challenge in authorization requests - Update HandleCallback to validate code_verifier during token exchange - Extend session lifetime from 7 to 30 days - Add comprehensive unit tests for PKCE functions - Maintain backward compatibility with fallback for non-PKCE sessions - Add detailed logging for OAuth flow with PKCE tracking PKCE enhances security by preventing authorization code interception attacks, as recommended by OAuth 2.1 and OIDC standards. feat: add encrypted refresh token storage with automatic cleanup - Add oauth_sessions table for storing encrypted refresh tokens - Implement AES-256-GCM encryption for refresh tokens using cookie secret - Create OAuth session repository with full CRUD operations - Add SessionWorker for automatic cleanup of expired sessions - Configure cleanup to run every 24h for sessions older than 37 days - Modify OAuth flow to store refresh tokens after successful authentication - Track client IP and user agent for session security validation - Link OAuth sessions to user sessions via session ID - Add comprehensive encryption tests with security validations - Integrate SessionWorker into server lifecycle with graceful shutdown This enables persistent OAuth sessions with secure token storage, reducing the need for frequent re-authentication from 7 to 30 days.
7.6 KiB
Email Setup
SMTP configuration for sending email reminders to expected signers.
Overview
Ackify's email service allows sending automatic reminders to users who have not yet signed a document.
Features:
- Multilingual reminder sending (fr, en, es, de, it)
- HTML and plain text templates
- Send history in PostgreSQL
- TLS/STARTTLS support
- Configurable timeout
Note: Email service is optional. If ACKIFY_MAIL_HOST is not defined, emails are disabled.
Basic Configuration
Required Variables
# SMTP server
ACKIFY_MAIL_HOST=smtp.gmail.com
ACKIFY_MAIL_PORT=587
ACKIFY_MAIL_USERNAME=your-email@gmail.com
ACKIFY_MAIL_PASSWORD=your-app-password
# Sender address
ACKIFY_MAIL_FROM=noreply@company.com
Optional Variables
# Displayed sender name (default: ACKIFY_ORGANISATION)
ACKIFY_MAIL_FROM_NAME="Ackify - ACME Corporation"
# Email subject prefix (optional)
ACKIFY_MAIL_SUBJECT_PREFIX="[Ackify]"
# Enable TLS (default: true)
ACKIFY_MAIL_TLS=true
# Enable STARTTLS (default: true)
ACKIFY_MAIL_STARTTLS=true
# Connection timeout (default: 10s)
ACKIFY_MAIL_TIMEOUT=10s
# Email template directory (default: templates/emails)
ACKIFY_MAIL_TEMPLATE_DIR=templates/emails
# Default email language/locale (default: en)
# Supported: en, fr, es, de, it
ACKIFY_MAIL_DEFAULT_LOCALE=en
Popular SMTP Providers
Gmail
Configuration:
ACKIFY_MAIL_HOST=smtp.gmail.com
ACKIFY_MAIL_PORT=587
ACKIFY_MAIL_USERNAME=your-email@gmail.com
ACKIFY_MAIL_PASSWORD=your-app-password
ACKIFY_MAIL_TLS=true
ACKIFY_MAIL_STARTTLS=true
Prerequisites:
- Enable 2-step verification on your Google account
- Generate an "App Password": https://myaccount.google.com/apppasswords
- Use this password in
ACKIFY_MAIL_PASSWORD
SendGrid
ACKIFY_MAIL_HOST=smtp.sendgrid.net
ACKIFY_MAIL_PORT=587
ACKIFY_MAIL_USERNAME=apikey
ACKIFY_MAIL_PASSWORD=your-sendgrid-api-key
ACKIFY_MAIL_FROM=noreply@your-domain.com
ACKIFY_MAIL_TLS=true
Amazon SES
ACKIFY_MAIL_HOST=email-smtp.us-east-1.amazonaws.com
ACKIFY_MAIL_PORT=587
ACKIFY_MAIL_USERNAME=your-smtp-username
ACKIFY_MAIL_PASSWORD=your-smtp-password
ACKIFY_MAIL_FROM=noreply@verified-domain.com
ACKIFY_MAIL_TLS=true
Important: Verify your domain in AWS SES before sending.
Mailgun
ACKIFY_MAIL_HOST=smtp.mailgun.org
ACKIFY_MAIL_PORT=587
ACKIFY_MAIL_USERNAME=postmaster@your-domain.mailgun.org
ACKIFY_MAIL_PASSWORD=your-mailgun-smtp-password
ACKIFY_MAIL_FROM=noreply@your-domain.com
ACKIFY_MAIL_TLS=true
Custom SMTP (Self-hosted)
ACKIFY_MAIL_HOST=mail.company.com
ACKIFY_MAIL_PORT=587
ACKIFY_MAIL_USERNAME=ackify@company.com
ACKIFY_MAIL_PASSWORD=secure_password
ACKIFY_MAIL_FROM=ackify@company.com
ACKIFY_MAIL_TLS=true
ACKIFY_MAIL_STARTTLS=true
Email Templates
Templates are in /backend/templates/emails/ with multilingual support.
Structure
templates/emails/
├── fr/
│ ├── reminder.html # French HTML template
│ └── reminder.txt # French plain text template
├── en/
│ ├── reminder.html # English HTML template
│ └── reminder.txt # English plain text template
└── ...
Available Variables
In templates, you can use:
{{.RecipientName}} // Recipient name
{{.DocumentID}} // Document ID
{{.DocumentTitle}} // Document title
{{.DocumentURL}} // Document URL (if defined in metadata)
{{.SignURL}} // URL to sign
{{.OrganisationName}} // Organization name
{{.SenderName}} // Sender name (admin)
HTML Template Example
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Signature reminder</title>
</head>
<body>
<h1>Hello {{.RecipientName}},</h1>
<p>
You are expected to sign the document
<strong>{{.DocumentTitle}}</strong>.
</p>
<p>
<a href="{{.SignURL}}" style="background: #0066cc; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px;">
Sign now
</a>
</p>
<p>
Best regards,<br>
{{.OrganisationName}}
</p>
</body>
</html>
Customize Templates
To use custom templates:
ACKIFY_MAIL_TEMPLATE_DIR=/custom/path/to/email/templates
Make sure to maintain the same directory structure (locale/reminder.html).
Sending Reminders
Via Admin Dashboard
- Go to
/admin - Select a document
- Click "Expected Signers"
- Select recipients
- Click "Send Reminders"
Via API
curl -X POST http://localhost:8080/api/v1/admin/documents/doc_id/reminders \
-b cookies.txt \
-H "Content-Type: application/json" \
-H "X-CSRF-Token: YOUR_TOKEN" \
-d '{
"emails": ["user1@company.com", "user2@company.com"],
"locale": "fr"
}'
Response:
{
"sent": 2,
"failed": 0,
"errors": []
}
Reminder History
Sends are tracked in the reminder_logs table:
SELECT
recipient_email,
sent_at,
status,
error_message
FROM reminder_logs
WHERE doc_id = 'my_document'
ORDER BY sent_at DESC;
Possible statuses:
sent- Successfully sentfailed- Send failurebounced- Bounced (invalid email)
Testing the Configuration
Manual Test via API
# 1. Login as admin
# 2. Add an expected signer with your email
curl -X POST http://localhost:8080/api/v1/admin/documents/test_doc/signers \
-b cookies.txt \
-H "Content-Type: application/json" \
-H "X-CSRF-Token: YOUR_TOKEN" \
-d '{
"email": "your-email@company.com",
"name": "Test User"
}'
# 3. Send a test reminder
curl -X POST http://localhost:8080/api/v1/admin/documents/test_doc/reminders \
-b cookies.txt \
-H "Content-Type: application/json" \
-H "X-CSRF-Token: YOUR_TOKEN" \
-d '{
"emails": ["your-email@company.com"],
"locale": "en"
}'
Check Logs
docker compose logs -f ackify-ce | grep -i mail
You should see:
INFO Email sent successfully to: your-email@company.com
Troubleshooting
Error "SMTP connection failed"
Verify:
ACKIFY_MAIL_HOSTandACKIFY_MAIL_PORTare correct- Your server allows outgoing connections on the SMTP port
ACKIFY_MAIL_TLS=trueif the server requires TLS
Error "Authentication failed"
Verify:
ACKIFY_MAIL_USERNAMEandACKIFY_MAIL_PASSWORDare correct- For Gmail: use an "App Password", not your main password
- For SendGrid: username must be
apikey
Email not received but status "sent"
Verify:
- Spam/junk folder
- SPF/DKIM/DMARC of your domain (to avoid spam filters)
- The
ACKIFY_MAIL_FROMaddress is verified with your provider
Template not found
Verify:
ACKIFY_MAIL_TEMPLATE_DIRpoints to the correct directory- The structure
{locale}/reminder.htmlexists - Files have the correct permissions (readable)
Timeout during send
Increase timeout:
ACKIFY_MAIL_TIMEOUT=30s
Best Practices
Production
- ✅ Use a dedicated SMTP service (SendGrid, Mailgun, SES)
- ✅ Verify your domain (SPF, DKIM, DMARC)
- ✅ Use a
noreply@address forACKIFY_MAIL_FROM - ✅ Monitor
reminder_logsto detect failures - ✅ Regularly test email sending
Security
- ✅ Never commit
ACKIFY_MAIL_PASSWORDto git - ✅ Use Docker secrets or environment variables
- ✅ Restrict SMTP account permissions
- ✅ Enable TLS/STARTTLS in production
Performance
- Emails are sent synchronously during API call
- For large volumes, consider an asynchronous queue
- Limit number of recipients per batch (recommended: < 100)
Disabling Emails
To completely disable the email service:
# Remove or comment out ACKIFY_MAIL_HOST
# ACKIFY_MAIL_HOST=
The admin dashboard will no longer display reminder sending options.