Skip to content

TechbirdIT/mailbird

Repository files navigation

Mailbird

A Frappe v16 app that handles contact-form enquiries from multiple client websites. Each website gets its own Website Master record that controls email routing, captcha validation, CORS, and email templates, all managed from the Frappe desk.


Features

  • Multi-site: one Frappe instance serves any number of client websites, each with independent configuration
  • Async email: enquiries are queued via Frappe Email Queue; no SMTP latency on the API response
  • Delivery tracking: Website Enquiry status advances automatically (New -> Email Queued -> Sent / Email Failed) as the Email Queue processes
  • Retry scheduler: failed emails are retried every 15 minutes up to the configured Max Retry Count
  • Dynamic sender: sender name and address are read from the linked Frappe Email Account record, not hardcoded
  • Multi-recipient: admin notifications can go to multiple addresses (comma-separated); each Website Master also supports CC, BCC, a Jinja custom subject, and a default file attachment
  • Email templates: default Mailbird templates ship as fixtures; any Website Master can override with a custom Frappe Email Template using Jinja variables; all outgoing emails carry a "Powered by Techbird" footer
  • Captcha: Cloudflare Turnstile and Google reCAPTCHA v2/v3 supported; type chosen per Website Master
  • CORS sync: allowed_domains on a Website Master are written to site_config.json automatically on save; removals and deactivation are also reflected
  • Domain validation: wildcards, non-HTTP schemes, paths, and out-of-range ports are rejected before save
  • Webhook delivery: form submissions can be POSTed as JSON to any URL (Slack, Zapier, CRM, etc.)
  • Honeypot: hidden field website_url silently drops bot submissions
  • App settings: retry count, message length, webhook timeout, and data retention are configurable from the desk via Mailbird Settings (Single DocType)
  • Error logging: Mailbird-specific errors are captured automatically into a dedicated Mailbird Error Log DocType for triage without searching the global error log

Installation

cd $PATH_TO_YOUR_BENCH
bench get-app $URL_OF_THIS_REPO --branch version-16
bench install-app mailbird
bench --site <your-site> migrate

DocTypes

Website Master

One record per client website. Fields:

Field Description
Website Name Display name, used as the autoname key
Domain Name Bare domain (e.g. example.in), matched against the site form field
Client Name Internal label
Recipient Email(s) Comma-separated email addresses that receive admin notifications
CC Email(s) Comma-separated addresses to CC on every admin notification
BCC Email(s) Comma-separated addresses to BCC on every admin notification
Custom Email Subject Jinja template for the admin email subject (variables: visitor_name, visitor_email, subject, website_name, site). Leave blank to use the default
Default Attachment File attached to every admin notification email (e.g. a brochure or rate card)
Email Account Frappe Email Account used as the sender; name and address are read dynamically
Admin Notification Template Frappe Email Template for the admin email. Leave blank to use the default Mailbird template
Auto Reply Enabled Toggle visitor auto-reply on/off
Auto Reply Template Frappe Email Template for the visitor receipt. Leave blank to use the default Mailbird template
Active Inactive sites are ignored by the API and removed from allow_cors
Configuration Status Manual status indicator (Pending / Configured / Validated / Failed)
Allowed Domains One origin per line (e.g. https://example.in). Written to site_config.json on save. Plain hostnames have https:// prepended automatically
Captcha Type Turnstile (default) or reCAPTCHA
Turnstile Site Key / Secret Key Cloudflare Turnstile credentials (shown when Captcha Type is Turnstile)
reCAPTCHA Site Key / Secret Key Google reCAPTCHA credentials (shown when Captcha Type is reCAPTCHA)
Webhook URL POST destination for each new enquiry payload
Notes Free-text internal notes

Website Enquiry

Audit record created for each form submission. Fields: visitor_name, visitor_email, visitor_phone, enquiry_subject, message, ip_address, submitted_at, status, retry_count, webhook_delivered, honeypot_triggered.

Status flow:

New -> Email Queued -> Sent
                   -> Email Failed  (retried per Max Retry Count in Mailbird Settings)

Status is synced automatically every minute by the sync_enquiry_statuses scheduler task.


API

POST /api/method/mailbird.api.send_website_enquiry

Guest-accessible. Rate-limited to 5 requests per minute per IP.

Form fields:

Field Required Description
site Yes Domain name matching a Website Master domain_name
name Yes Visitor name
email Yes Visitor email
message Yes Enquiry message
phone No Visitor phone
subject No Enquiry subject (defaults to Default Enquiry Subject in Mailbird Settings)
cf_turnstile_response Conditional Turnstile challenge token (when captcha type is Turnstile)
g_recaptcha_response Conditional reCAPTCHA token (when captcha type is reCAPTCHA)
website_url N/A Honeypot field; must be empty

Success response:

{"message": {"success": true, "message": "Thank you! Your enquiry has been sent."}}

Error response:

{"message": {"success": false, "error": "..."}}

Email Templates

Two default templates are shipped as fixtures and synced on every bench migrate:

Template Name Used for
Mailbird - Admin Notification Admin notification email
Mailbird - Auto Reply Visitor receipt email

Available Jinja variables

{{ visitor_name }}  : visitor's full name
{{ visitor_email }} : visitor's email address
{{ visitor_phone }} : visitor's phone (empty string if not provided)
{{ subject }}       : enquiry subject
{{ message }}       : enquiry message body
{{ website_name }}  : Website Master display name
{{ site }}          : domain name (e.g. example.in)
{{ initial }}       : first letter of visitor_name (for monogram use)

Creating a custom template

  1. In the Frappe desk, open Email Template and click New (or duplicate an existing Mailbird template)
  2. Name it anything that does not start with Mailbird - (e.g. MyClient - Admin Notification) so migrations do not overwrite it
  3. Write the subject and HTML body using the variables above
  4. On the Website Master for that site, set Admin Notification Template or Auto Reply Template to the new template name

If a template field is left blank, the corresponding built-in template from api.py is used as the fallback.


CORS Management

When allowed_domains is saved on a Website Master, a background job rebuilds allow_cors in site_config.json:

  • Add a domain: appears in allow_cors within seconds
  • Remove a domain: removed from allow_cors on next save; other sites' domains are untouched
  • Deactivate a Website Master: its domains are removed automatically
  • Manually added entries: any domain in allow_cors that was not written by Mailbird (tracked via _mailbird_cors) is preserved permanently

Domain validation rules (enforced before save):

  • Must be a valid hostname, IPv4, or localhost, with optional port
  • https:// or http:// scheme allowed; all other schemes rejected
  • No wildcards (*.example.com)
  • No paths, query strings, or fragments
  • Port must be 1-65535
  • Max 260 characters per line
  • Duplicates are deduplicated automatically

Scheduler Tasks

Task Frequency Purpose
sync_enquiry_statuses Every ~1 min (all) Advances Website Enquiry status based on Email Queue outcomes
retry_failed_enquiries Every 15 min Re-queues admin emails that failed delivery (up to Max Retry Count)
purge_old_records Daily Deletes old error logs and enquiry records per Mailbird Settings retention values

Mailbird Settings

A Single DocType (one record per site) for app-wide configuration. Open it from the MailBird workspace sidebar.

Email Delivery

Setting Default Description
Max Retry Count 3 Times a failed admin notification email is retried before being marked permanent failure

Enquiry Form

Setting Default Description
Max Message Length 3000 Characters accepted in the message field; longer input is silently truncated
Default Enquiry Subject "General Enquiry" Subject used when the visitor does not supply one

Webhook

Setting Default Description
Webhook Timeout (seconds) 10 Seconds to wait for a webhook endpoint before timing out

Maintenance

Setting Default Description
Auto-purge Mailbird Error Logs On Delete Mailbird Error Log records older than the retention period (runs daily)
Error Log Retention (days) 30 Age at which error log records are deleted
Auto-purge Website Enquiries Off Delete Website Enquiry records older than the retention period (for GDPR compliance)
Enquiry Retention (days) 90 Age at which enquiry records are deleted

Error Logging

Mailbird captures a filtered copy of every Frappe Error Log entry that originates from Mailbird code into a dedicated Mailbird Error Log DocType. This keeps Mailbird errors separate from framework noise so they are easier to triage from the desk.

An error is captured when any of the following is true:

  • The log title matches a known Mailbird title (e.g. ADMIN EMAIL QUEUE FAILED, WEBHOOK DELIVERY FAILED)
  • The title contains CAPTCHA or CORS
  • The traceback file path contains /apps/mailbird/

Mailbird Error Log fields

Field Description
Error Title Title passed to frappe.log_error
Error Type Auto-classified: API / Email / Captcha / Webhook / CORS / Template / Scheduler / Other
Occurred At Timestamp from the original Frappe Error Log
Function Innermost function name from the traceback
Website Master Linkable to a Website Master for filtered views (populated manually if needed)
Frappe Error Log Link to the original entry for full context
Resolved Checkbox to mark the error as handled
Resolution Note Free-text field for the fix or root cause

The list view has standard filters on Error Type, Website Master, and Resolved so on-call triage requires no custom reports.

The capture hook (after_insert on Error Log) swallows all exceptions silently to prevent infinite logging loops.


Author

Built and maintained by Abhishek Chougule at Techbird.


License

MIT

About

Smart email management and communication platform for teams and businesses.

Topics

Resources

License

Stars

1 star

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors