The email blog platform includes robust security features to prevent unauthorized posting and email spoofing. This guide explains how to configure and use these security features.
Configure the ALLOWED_EMAIL_ADDRESSES
environment variable with a comma-separated list of email addresses that are allowed to publish posts:
ALLOWED_EMAIL_ADDRESSES=user1@example.com,user2@example.com,admin@myblog.com
Important Notes:
- Email addresses are case-insensitive
- Whitespace around commas is automatically trimmed
- If this variable is not set, no emails will be allowed
- Only exact email matches are allowed (no wildcards or domains)
Set your blog's base URL for verification links:
BASE_URL=https://your-blog.web.val.run
If not set, the system will auto-detect the URL from incoming requests.
When an email is received:
- The sender's email address is checked against
ALLOWED_EMAIL_ADDRESSES
- If not allowed, the email is ignored (logged but not processed)
- If allowed, the process continues to verification
For allowed emails:
- Post content is extracted from the email
- A draft post is created (not published yet)
- A unique verification token is generated
- The draft expires after 24 hours if not verified
- An automated verification email is sent to the original sender
- The email contains a secure verification link
- The link expires after 24 hours for security
When the sender clicks the verification link:
- The token is validated and checked for expiration
- The email verification is marked as complete
- The draft post is converted to a published post
- External services are notified (RSS, ActivityPub, etc.)
- The draft and verification records are cleaned up
- Email confirmation required: Even if someone spoofs your email address, they can't access your email to click the verification link
- Time-limited tokens: Verification links expire after 24 hours
- One-time use: Each verification token can only be used once
- Allowlist-based: Only pre-approved email addresses can publish
- No wildcards: Exact email matching prevents subdomain attacks
- Easy management: Add/remove allowed emails via environment variable
- Expired drafts: Unverified drafts are automatically deleted after 24 hours
- Token cleanup: Used and expired verification tokens are removed
- Database efficiency: Regular cleanup prevents database bloat
The system sends a professional verification email with:
- Clear subject line indicating verification needed
- HTML and plain text versions
- Secure verification link
- Expiration warning (24 hours)
- Instructions for non-senders to ignore
Subject: Verify your blog post: My Amazing Blog Post
Hello,
We received a blog post submission with the title "My Amazing Blog Post" from this email address.
To confirm that you sent this post and publish it to the blog, please click the verification link below:
[Verify and Publish Post]
Important: This verification link will expire in 24 hours for security reasons.
If you did not send this blog post, please ignore this email.
- Check allowlist: Ensure sender email is in
ALLOWED_EMAIL_ADDRESSES
- Check logs: Look for "Email from X is not in the allowed list" messages
- Verify format: Ensure environment variable is properly formatted
- Check expiration: Links expire after 24 hours
- Check BASE_URL: Ensure it's set correctly or auto-detection is working
- One-time use: Each link can only be used once
- Click verification link: Posts remain as drafts until verified
- Check email delivery: Ensure verification emails aren't in spam
- Check token validity: Tokens expire after 24 hours
- Use dedicated email addresses for blog posting
- Keep the allowlist minimal (only trusted users)
- Regularly review who has posting access
- Monitor logs for unauthorized posting attempts
- Review verification patterns for unusual activity
- Keep environment variables secure
- Regular database backups include draft posts
- Consider notification systems for failed verifications
- Document your allowed email addresses
- URL:
GET /verify-email?token=<verification_token>
- Purpose: Handles email verification and post publishing
- Responses:
200
: Successful verification and publishing400
: Missing or invalid token404
: Token not found410
: Token expired500
: Server error during publishing
All verification pages include:
- Proper HTML escaping to prevent XSS
- Responsive design for mobile verification
- Clear success/error messaging
- Links back to the main blog
If upgrading from a version without security:
- Set environment variables before receiving new emails
- Existing posts remain published (not affected)
- New emails will require verification from the first email received
- Test thoroughly with a test email before going live
Security is enabled by default. Configure ALLOWED_EMAIL_ADDRESSES
to start receiving posts!