{"id":331679,"date":"2026-06-27T18:19:15","date_gmt":"2026-06-27T18:19:15","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/postwave-jmap\/"},"modified":"2026-06-27T18:19:01","modified_gmt":"2026-06-27T18:19:01","slug":"tahhan-jmap-mailer","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/tahhan-jmap-mailer\/","author":23075774,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.3.5","stable_tag":"1.3.5","tested":"7.0","requires":"5.8","requires_php":"7.4","requires_plugins":null,"header_name":"Tahhan JMAP Mailer","header_author":"Tahhan","header_description":"Sends WordPress emails via the modern JMAP protocol (RFC 8620\/8621). No SMTP ports needed \u2014 works with Stalwart, Fastmail, Cyrus and more. Includes live connection testing and full mail logging.","assets_banners_color":"2e2b7a","last_updated":"2026-06-27 18:19:01","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/github.com\/Tahhan-nl\/tahhan-jmap-mailer","header_author_uri":"https:\/\/tahhan.nl","rating":0,"author_block_rating":0,"active_installs":0,"downloads":39,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.3.5":{"tag":"1.3.5","author":"mustafatahhan","date":"2026-06-27 18:19:01"}},"upgrade_notice":{"1.3.3":"<p>Critical fix: emails failed with &quot;Message has to belong to at least one mailbox&quot;. The plugin now finds a fallback mailbox automatically.<\/p>","1.3.2":"<p>Critical fix: emails were blocked when the JMAP server had no Sent mailbox with role &quot;sent&quot;. Update immediately.<\/p>","1.3.1":"<p>Bug fix: resolves a fatal syntax error that prevented the plugin from loading. Update immediately.<\/p>","1.3.0":"<p>UI polish update with empty states, toast notifications, and improved setup wizard. No database changes \u2014 safe to upgrade.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3588268,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3588268,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3588268,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3588268,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.3.5"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3588268,"resolution":"1","location":"assets","locale":"","width":1200,"height":750},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3588268,"resolution":"2","location":"assets","locale":"","width":1200,"height":750},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3588268,"resolution":"3","location":"assets","locale":"","width":1200,"height":750},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3588268,"resolution":"4","location":"assets","locale":"","width":1200,"height":750},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3588268,"resolution":"5","location":"assets","locale":"","width":1200,"height":750}},"screenshots":{"1":"General tab \u2014 enable\/disable toggle, sender information, automatic retry settings, and open tracking configuration.","2":"Connection tab \u2014 JMAP server credentials, identity selection with auto-resolve, and live connection testing with step-by-step feedback.","3":"Mail Log tab \u2014 expandable log entries showing recipient, subject, status badges, JMAP IDs, and error details.","4":"Setup wizard \u2014 guided first-time configuration: server connection, sender information, and activation.","5":"Routing rules editor \u2014 condition builder with field\/value pairs and match operator (ANY\/ALL).","6":"Accounts tab \u2014 multiple JMAP account cards showing status, server URL, and username.","7":"Routing tab \u2014 routing rules table with priority ordering, condition summary, account badges, and enable\/disable status."}},"plugin_section":[],"plugin_tags":[267,269134,450,6696,48586],"plugin_category":[41],"plugin_contributors":[266135],"plugin_business_model":[],"class_list":["post-331679","plugin","type-plugin","status-publish","hentry","plugin_tags-email","plugin_tags-jmap","plugin_tags-mail","plugin_tags-smtp","plugin_tags-transactional-email","plugin_category-communication","plugin_contributors-mustafatahhan","plugin_committers-mustafatahhan"],"banners":{"banner":"https:\/\/ps.w.org\/tahhan-jmap-mailer\/assets\/banner-772x250.png?rev=3588268","banner_2x":"https:\/\/ps.w.org\/tahhan-jmap-mailer\/assets\/banner-1544x500.png?rev=3588268","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/tahhan-jmap-mailer\/assets\/icon-128x128.png?rev=3588268","icon_2x":"https:\/\/ps.w.org\/tahhan-jmap-mailer\/assets\/icon-256x256.png?rev=3588268","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/tahhan-jmap-mailer\/assets\/screenshot-1.png?rev=3588268","caption":"General tab \u2014 enable\/disable toggle, sender information, automatic retry settings, and open tracking configuration."},{"src":"https:\/\/ps.w.org\/tahhan-jmap-mailer\/assets\/screenshot-2.png?rev=3588268","caption":"Connection tab \u2014 JMAP server credentials, identity selection with auto-resolve, and live connection testing with step-by-step feedback."},{"src":"https:\/\/ps.w.org\/tahhan-jmap-mailer\/assets\/screenshot-3.png?rev=3588268","caption":"Mail Log tab \u2014 expandable log entries showing recipient, subject, status badges, JMAP IDs, and error details."},{"src":"https:\/\/ps.w.org\/tahhan-jmap-mailer\/assets\/screenshot-4.png?rev=3588268","caption":"Setup wizard \u2014 guided first-time configuration: server connection, sender information, and activation."},{"src":"https:\/\/ps.w.org\/tahhan-jmap-mailer\/assets\/screenshot-5.png?rev=3588268","caption":"Routing rules editor \u2014 condition builder with field\/value pairs and match operator (ANY\/ALL)."}],"raw_content":"<!--section=description-->\n<p>Tahhan JMAP Mailer replaces WordPress's built-in mailer with the modern <strong>JMAP protocol<\/strong> (RFC 8620 \/ RFC 8621). JMAP is the successor to IMAP and SMTP, designed from scratch for the modern web. It communicates over standard HTTPS, works through firewalls and NAT without any special port configuration, and is natively supported by leading mail servers such as Stalwart Mail Server, Fastmail, and Cyrus IMAP.<\/p>\n\n<p>Unlike SMTP plugins that require relay credentials, third-party services, or open ports, Tahhan JMAP Mailer connects directly to your own JMAP-capable mail server using HTTP Basic authentication over an encrypted HTTPS connection. The JMAP session is auto-discovered from <code>\/.well-known\/jmap<\/code> \u2014 no manual API URL configuration needed.<\/p>\n\n<p>Tahhan JMAP Mailer is built as a proper WordPress plugin: it uses <code>wp_remote_get\/post<\/code>, <code>WP_Error<\/code>, WordPress nonces, and the standard sanitization and escaping APIs throughout. There are zero external PHP dependencies. It hooks into <code>pre_wp_mail<\/code> to intercept every <code>wp_mail()<\/code> call site-wide and deliver the email through a two-step JMAP pipeline: <code>Email\/set<\/code> to create the email object, followed by <code>EmailSubmission\/set<\/code> to submit it for delivery.<\/p>\n\n<p>Every send attempt is logged (recipient, subject, status, JMAP IDs) in a capped mail log \u2014 message bodies are never stored. The plugin ships with a full admin UI including a setup wizard, live connection testing, multi-account management, conditional routing rules, a retry queue with exponential backoff, open tracking, CSV log export, and WooCommerce email type detection.<\/p>\n\n<h3>Features<\/h3>\n\n<ul>\n<li><strong>JMAP Protocol<\/strong> \u2014 Full RFC 8620 \/ RFC 8621 implementation, two-step Email\/set + EmailSubmission\/set delivery<\/li>\n<li><strong>Auto-discovery<\/strong> \u2014 JMAP session discovered automatically from <code>\/.well-known\/jmap<\/code><\/li>\n<li><strong>Multi-account<\/strong> \u2014 Configure multiple JMAP accounts (Primary, Transactional, etc.)<\/li>\n<li><strong>Routing rules<\/strong> \u2014 Route emails to specific accounts based on recipient domain, subject, plugin type, and more<\/li>\n<li><strong>Retry queue<\/strong> \u2014 Failed sends automatically retried via WP-Cron with exponential backoff<\/li>\n<li><strong>Open tracking<\/strong> \u2014 Optional 1x1 pixel tracking for HTML emails, entirely self-hosted<\/li>\n<li><strong>WooCommerce integration<\/strong> \u2014 Detect and route WooCommerce order, customer, and admin emails<\/li>\n<li><strong>Mail log<\/strong> \u2014 Last 100 send attempts with recipient, subject, status, JMAP IDs, error details<\/li>\n<li><strong>CSV export<\/strong> \u2014 Download the full mail log as a CSV file<\/li>\n<li><strong>Multiple identities<\/strong> \u2014 Per-account JMAP sending identities with auto-resolve support<\/li>\n<li><strong>Setup wizard<\/strong> \u2014 Guided first-time configuration with step-by-step instructions<\/li>\n<li><strong>Live connection testing<\/strong> \u2014 AJAX-based JMAP session test with step-by-step feedback<\/li>\n<li><strong>No external dependencies<\/strong> \u2014 Zero third-party PHP libraries required<\/li>\n<\/ul>\n\n<h3>Compatible Servers<\/h3>\n\n<p>Tahhan JMAP Mailer works with any mail server that implements RFC 8621 (JMAP for Mail):<\/p>\n\n<ul>\n<li><strong>Stalwart Mail Server<\/strong> \u2014 Full JMAP support, recommended for self-hosted setups<\/li>\n<li><strong>Fastmail<\/strong> \u2014 Full JMAP support, commercial hosted service<\/li>\n<li><strong>Cyrus IMAP<\/strong> \u2014 Full JMAP support, enterprise self-hosted<\/li>\n<li><strong>Apache James<\/strong> \u2014 Full JMAP support, open source Java-based server<\/li>\n<li><strong>Any RFC 8621-compliant server<\/strong> \u2014 The plugin uses only standard JMAP capabilities<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Download the plugin ZIP from the WordPress.org plugin directory or the GitHub releases page.<\/li>\n<li>In your WordPress admin, go to <strong>Plugins -&gt; Add New -&gt; Upload Plugin<\/strong>.<\/li>\n<li>Upload the ZIP file and click <strong>Install Now<\/strong>.<\/li>\n<li>Click <strong>Activate Plugin<\/strong>.<\/li>\n<li>Go to <strong>Tahhan JMAP Mailer<\/strong> in the left menu and follow the setup wizard to configure your JMAP server.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"what%20is%20jmap%3F\"><h3>What is JMAP?<\/h3><\/dt>\n<dd><p>JMAP (JSON Meta Application Protocol) is a modern, open-standard protocol (RFC 8620 \/ RFC 8621) designed as the successor to IMAP and SMTP. It communicates over HTTPS using JSON, works through firewalls without special port configuration, and is significantly more efficient than legacy email protocols.<\/p><\/dd>\n<dt id=\"how%20is%20jmap%20different%20from%20smtp%3F\"><h3>How is JMAP different from SMTP?<\/h3><\/dt>\n<dd><p>SMTP was designed in 1982 and requires specific TCP ports (25, 465, 587) that are often blocked by firewalls and hosting providers. JMAP works over standard HTTPS (port 443), requires no relay configuration, has no port restrictions, and uses a modern JSON-based API that is far easier to work with programmatically.<\/p><\/dd>\n<dt id=\"which%20mail%20servers%20support%20jmap%3F\"><h3>Which mail servers support JMAP?<\/h3><\/dt>\n<dd><p>Stalwart Mail Server, Fastmail, Cyrus IMAP, and Apache James all support JMAP fully. Any server implementing RFC 8621 will work with Tahhan JMAP Mailer.<\/p><\/dd>\n<dt id=\"does%20tahhan%20jmap%20mailer%20work%20with%20woocommerce%3F\"><h3>Does Tahhan JMAP Mailer work with WooCommerce?<\/h3><\/dt>\n<dd><p>Yes. Tahhan JMAP Mailer includes WooCommerce email type detection. You can create routing rules that detect WooCommerce emails (order confirmations, customer invoices, admin notifications) and route them to a dedicated transactional email account for better deliverability.<\/p><\/dd>\n<dt id=\"can%20i%20use%20multiple%20jmap%20accounts%3F\"><h3>Can I use multiple JMAP accounts?<\/h3><\/dt>\n<dd><p>Yes. The Accounts tab lets you configure multiple JMAP accounts. You can set one as the Primary account (used by default) and configure additional accounts such as a dedicated transactional account for WooCommerce or a support-specific account.<\/p><\/dd>\n<dt id=\"how%20do%20routing%20rules%20work%3F\"><h3>How do routing rules work?<\/h3><\/dt>\n<dd><p>Routing rules are evaluated in order from top to bottom. The first matching rule wins. Each rule can match on recipient email, recipient domain, sender email, subject content, or plugin\/email type. You can match ANY condition (OR logic) or ALL conditions (AND logic). Non-matching emails fall back to the Primary account.<\/p><\/dd>\n<dt id=\"what%20is%20the%20retry%20queue%3F\"><h3>What is the retry queue?<\/h3><\/dt>\n<dd><p>When an email fails to send, Tahhan JMAP Mailer can automatically retry it via WP-Cron. You configure the maximum number of retry attempts (1-5) and an initial delay (5 minutes to 1 hour). Each subsequent retry doubles the delay (exponential backoff). Permanently failed emails are marked as \"exhausted\" in the mail log.<\/p><\/dd>\n<dt id=\"what%20is%20open%20tracking%3F\"><h3>What is open tracking?<\/h3><\/dt>\n<dd><p>Open tracking embeds a 1x1 transparent pixel in outgoing HTML emails. When a recipient opens the email, the pixel loads from your WordPress site, recording the open event. Plain-text emails are never tracked. All tracking data stays on your own server \u2014 nothing is sent to external services. You should disclose tracking in your privacy policy.<\/p><\/dd>\n<dt id=\"what%20is%20the%20mail%20log%3F\"><h3>What is the mail log?<\/h3><\/dt>\n<dd><p>The mail log records every send attempt: timestamp, recipient address, subject line, send status (sent\/failed), JMAP account and identity IDs, email object ID, and any error message. Message bodies, CC\/BCC addresses, and attachment contents are never stored. The log is capped at 100 entries.<\/p><\/dd>\n<dt id=\"can%20i%20export%20the%20mail%20log%3F\"><h3>Can I export the mail log?<\/h3><\/dt>\n<dd><p>Yes. On the Mail Log tab, click \"Export CSV\" to download all log entries as a CSV file. The export includes timestamp, recipient, subject, status, account ID, identity ID, email ID, and error message.<\/p><\/dd>\n<dt id=\"what%20php%20version%20is%20required%3F\"><h3>What PHP version is required?<\/h3><\/dt>\n<dd><p>PHP 7.4 or higher. The plugin is tested with PHP 7.4, 8.0, 8.1, 8.2, and 8.3.<\/p><\/dd>\n<dt id=\"what%20wordpress%20version%20is%20required%3F\"><h3>What WordPress version is required?<\/h3><\/dt>\n<dd><p>WordPress 5.8 or higher. The plugin is tested up to WordPress 6.7.<\/p><\/dd>\n<dt id=\"what%20is%20the%20primary%20account%3F\"><h3>What is the Primary account?<\/h3><\/dt>\n<dd><p>The Primary account is the fallback account used for all emails that do not match a routing rule. It is created automatically during setup from your initial JMAP credentials. You can edit the Primary account's credentials on the Connection tab or in the Accounts tab.<\/p><\/dd>\n<dt id=\"how%20do%20sender%20identities%20work%3F\"><h3>How do sender identities work?<\/h3><\/dt>\n<dd><p>A JMAP identity defines the \"From\" name and email address used when sending. Tahhan JMAP Mailer can auto-resolve the correct identity by matching your configured From Email to an identity on the JMAP server. You can also manually select a specific identity from the Connection tab by clicking \"Load identities\" after saving your credentials.<\/p><\/dd>\n<dt id=\"how%20do%20i%20test%20the%20connection%3F\"><h3>How do I test the connection?<\/h3><\/dt>\n<dd><p>Go to <strong>Tahhan JMAP Mailer -&gt; Connection<\/strong> and click \"Test connection\". The plugin will discover the JMAP session, resolve your sender identity, and verify server capabilities. You can also click \"Send test email\" to fire a real email through the full send pipeline to your configured test recipient.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.3.5<\/h4>\n\n<ul>\n<li>Fixed: Text domain changed to 'postwave-jmap' to match plugin slug for WordPress.org compliance<\/li>\n<li>Fixed: Output escaping issues in admin template<\/li>\n<li>Fixed: Input sanitization now uses wp_unslash() before processing POST data<\/li>\n<li>Improved: Tested up to WordPress 7.0<\/li>\n<\/ul>\n\n<h4>1.3.4<\/h4>\n\n<ul>\n<li>Fixed: Stats block appeared twice on the General tab<\/li>\n<\/ul>\n\n<h4>1.3.3<\/h4>\n\n<ul>\n<li>Fixed: \"Message has to belong to at least one mailbox\" \u2014 the plugin now resolves a fallback mailbox when the server has no Sent folder with role \"sent\". It tries sent \u2192 archive \u2192 inbox \u2192 first available mailbox before giving up.<\/li>\n<\/ul>\n\n<h4>1.3.2<\/h4>\n\n<ul>\n<li>Fixed: \"No JMAP mailbox found with role sent\" \u2014 the Sent mailbox is now optional; emails send successfully even when the server has no Sent folder with that role<\/li>\n<li>Fixed: Mail log Details panel now pops up as an overlay instead of wrapping inside the narrow table column<\/li>\n<li>Improved: Error and email addresses in the Details panel wrap cleanly without character-by-character breaks<\/li>\n<\/ul>\n\n<h4>1.3.1<\/h4>\n\n<ul>\n<li>Fixed: Fatal syntax error in admin template (unexpected endif) preventing plugin from loading<\/li>\n<li>Improved: Mail log now shows a dedicated \"Opened\" column with date\/time instead of a small badge<\/li>\n<li>Improved: Open tracking status is now clearly visible per email in the log table<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>Added: Setup wizard overlay for first-time configuration<\/li>\n<li>Added: Status bar on General tab showing sent today, sent this week, failed today, and total logged counts<\/li>\n<li>Added: Empty state screens for Accounts, Routing, and Mail Log tabs<\/li>\n<li>Added: Toast notifications for save actions<\/li>\n<li>Added: uninstall.php for clean plugin removal (deletes all plugin options and scheduled hooks)<\/li>\n<li>Improved: Admin UI polish and accessibility<\/li>\n<li>Improved: Screenshot and documentation updates<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>Added: Multi-account support \u2014 configure multiple JMAP accounts<\/li>\n<li>Added: Routing rules \u2014 route emails to specific accounts based on conditions<\/li>\n<li>Added: WooCommerce email type detection for routing rules<\/li>\n<li>Added: Account management UI with add, edit, delete, and connection test<\/li>\n<li>Added: Routing rule editor with condition builder and priority ordering<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Added: Retry queue \u2014 failed sends automatically retried via WP-Cron with exponential backoff<\/li>\n<li>Added: Open\/read tracking pixel with privacy controls<\/li>\n<li>Added: CSV log export<\/li>\n<li>Added: Multiple JMAP sending identities with auto-resolve and manual selection<\/li>\n<li>Added: Identity loader \u2014 fetch identities from JMAP server directly in the admin UI<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release<\/li>\n<li>Full JMAP RFC 8620 \/ RFC 8621 implementation<\/li>\n<li>Auto-discovery via <code>\/.well-known\/jmap<\/code><\/li>\n<li>Email\/set + EmailSubmission\/set two-step delivery<\/li>\n<li>HTML + plain-text multipart support<\/li>\n<li>File attachment support via blob upload<\/li>\n<li>CC, BCC, Reply-To header parsing<\/li>\n<li>Reverse-proxy URL normalisation<\/li>\n<li>Mail log (last 100 entries, no message bodies stored)<\/li>\n<li>Professional admin UI with setup wizard<\/li>\n<li>Live connection testing (AJAX)<\/li>\n<\/ul>","raw_excerpt":"Send WordPress emails via the modern JMAP protocol \u2014 no SMTP ports needed.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/331679","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=331679"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/mustafatahhan"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=331679"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=331679"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=331679"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=331679"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=331679"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=331679"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}