| 开发者 | shiponkarmakar |
|---|---|
| 更新时间 | 2026年5月13日 02:09 |
| 捐献地址: | 去捐款 |
| PHP版本: | 7.4 及以上 |
| WordPress版本: | 6.9 |
| 版权: | GPLv2 or later |
| 版权网址: | 版权信息 |
wp_mail() traffic through Amazon SES, SendGrid, Mailgun, Brevo (Sendinblue), Postmark, Zoho ZeptoMail, Gmail API, Microsoft 365, or any standard SMTP server — with full email logging, queue, retry, and failure alerts.
Why SendForce Mail SMTP
wp sendforce test, wp sendforce queue process, wp sendforce log list, wp sendforce sysinfo.sendforce_before_send, sendforce_after_send, sendforce_log_entry, sendforce_api_request, sendforce_api_response for extending the plugin without forking.WP_DEBUG_LOG integration — optional mirroring of SMTP and API debug output to debug.log.wp_mail() function, so it works with every plugin that sends email — including WooCommerce, Easy Digital Downloads, Contact Form 7, WPForms, Gravity Forms, Ninja Forms, Fluent Forms, Forminator, MemberPress, LearnDash, BuddyPress, bbPress, MailPoet (transactional), and any custom plugin or theme that uses wp_mail().
sendforce-mail-relay folder to the /wp-content/plugins/ directory, or install directly through the WordPress plugin installer.Yes. You need access to an SMTP server or a transactional email provider account. Most providers (Gmail, Outlook, etc.) offer SMTP access. Transactional services like SendGrid, Mailgun, or Amazon SES offer both SMTP and HTTP API access.
Yes. All credentials are encrypted using AES-256-CBC encryption with a key derived from your WordPress security salts before being stored in the database.
When enabled, emails are stored in a database queue instead of being sent immediately. A WP-Cron job processes the queue every 5 minutes, sending emails in batches. Failed emails are retried with exponential backoff (5 min → 15 min → 45 min).
Yes. SendForce Mail Relay hooks into WordPress's phpmailer_init action (SMTP mode) or pre_wp_mail filter (API mode). Since every plugin — including WooCommerce, contact form plugins, and membership plugins — sends email via WordPress's wp_mail() function, SendForce Mail Relay will handle 100% of outgoing emails.
You should only use one SMTP plugin at a time. Please deactivate any other SMTP or email plugins (FluentSMTP, WP Mail SMTP, etc.) before activating SendForce Mail Relay.
By default, SendForce Mail Relay logs: recipient email, subject, headers, status (sent/failed), error message if any, and timestamp. Email body logging is optional and can be disabled in Settings > Queue & Logging for privacy compliance.
All plugin data (database tables, settings, and scheduled events) is completely removed when you delete the plugin through the WordPress admin.
No. SendForce Mail Relay does not collect any data, make any analytics calls, or communicate with any external server except when sending emails through your configured provider.
$attachments parameter completely — WooCommerce PDF invoices, contact-form file uploads, LMS certificates, and similar plugin-generated attachments would silently disappear when sent via SES. Now they're MIME-encoded and delivered correctly via multipart/mixed. Gmail API mode also routes through the new shared MIME builder so its attachment handling matches.text/html and an auto-derived text/plain alternative (via multipart/alternative). Improves deliverability — Gmail and other inbox providers favour multipart-alternative messages, and plain-text-only mail clients (some IT environments, accessibility tools) get a readable fallback. Previously this setting was silently ignored in API mode.=?UTF-8?B?…?=) before being sent. Without this, strict MTAs would reject the message and lenient ones would render the headers as garbage.build_raw_mime() helper in the base API mailer class. Same MIME format, same encoding rules, same attachment handling — verified against test fixtures covering single-part, multipart/alternative, multipart/mixed (with attachments), Bcc-in-headers (Gmail) vs Bcc-via-API (SES), and non-ASCII headers.AADSTS50011 / redirect URI mismatch. Root cause: the authorize URL was built with add_query_arg(), which does NOT URL-encode the values it inserts. The & characters inside our redirect_uri query value were left bare, so Microsoft / Google parsed &tab=settings&sf_oauth=callback as additional top-level query parameters and saw the redirect_uri truncated at the first &. The fix uses http_build_query() with PHP_QUERY_RFC3986 so every value is properly percent-encoded. Affects every OAuth setup whose Web Redirect URI contains more than one query parameter (i.e. all current SendForce OAuth setups). The get_redirect_uri() hardening from 1.0.23 was real but addressed a different scenario; this is the actual cause of the AADSTS50011 reports.postMessage (fallback when window.opener survives), and parent-side popup-closed polling (final safety net — reloads the settings tab so the connection panel refreshes from the DB even if both signal channels fail). This eliminates the "popup closed but status didn't update" issue some users hit when the browser's COOP behaviour broke the opener relationship after returning from Microsoft / Google.alert() / confirm() dialogs in the OAuth flow ("Save the connection first", "Disconnect this account?", error toasts) with the styled sfShowConfirmModal already used elsewhere in the plugin. Consistent look across the admin UI.graph.microsoft.com were never recorded. It now uses make_request() so the real error (ErrorAccessDenied, MailboxNotEnabledForRESTAPI, AADSTS70008 token expired, etc.) is appended to the failure message and stored in the Email Log. Also captures token-endpoint failures from the OAuth refresh flow (previously silent).access_denied "App is being tested"), the separate Authorised JavaScript origins field (origin-only, no path), and an explicit warning about Azure's confusing "Value vs Secret ID" two-column UI for client secrets (the most common AADSTS7000215 cause). Includes the format of valid Client IDs/Secrets so users can sanity-check what they pasted.Zoho-enczapikey TOKEN string from ZeptoMail's docs into the Send Mail Token field. The mailer now strips the Zoho-enczapikey prefix automatically before constructing the Authorization header, so both pure-token and full-header paste styles work.email.<region>.amazonaws.com were never recorded. It now uses make_request() so real errors like MessageRejected (sandbox, unverified address), MailFromDomainNotVerifiedException, SendingPausedException, or Throttling appear in the failure message and the Email Log.make_request() for the send call, and silently swallowed token-endpoint errors during the OAuth refresh. Errors like invalidArgument (malformed raw email), failedPrecondition (delegation issue), quotaExceeded, or invalid_grant (refresh token revoked / 90-day expiry) are now surfaced. Also captures pre-flight failures (missing client_id / client_secret / refresh_token) with a clear explanation.make_request() so errors like "Domain not found", 401 wrong-region, "freemail recipient unsupported", or "Forbidden" never showed in the UI. Switched to make_request() with application/x-www-form-urlencoded body so debug capture works while preserving Mailgun's required form-encoded body format.Bearer TOKEN (instead of just TOKEN) into the API Key field for SendGrid, Resend, MailerSend, SMTP.com, and SendLayer. Provider docs typically show Authorization: Bearer xxxxx in their cURL examples, and users frequently copy the whole Bearer xxxxx string. The mailer now strips a leading Bearer if present so both paste styles work. Same auto-strip already applies to ZeptoMail's Zoho-enczapikey prefix; refactored to use a shared strip_auth_prefix() helper in the base API mailer class.trim()ed automatically before use. Catches the common case where a user copy-pastes a key from a provider dashboard and accidentally grabs trailing whitespace or a stray newline. Previously some providers (notably SendGrid) would return a generic 401 with no useful explanation when the auth header contained non-printable characters.admin_url cannot strip the query string from the path and produce a truncated redirect_uri. Resolves the intermittent AADSTS50011 (redirect URI mismatch) errors some users hit when clicking "Connect with provider" for Microsoft 365. The final URL is unchanged — only the construction is now immune to third-party admin_url filters.wp_kses whitelist used to render channel logos on the Alerts tab — adds xmlns:xlink, role, aria-label, width, height, fill-rule, clip-rule, the <g> element, and a few missing path/circle attributes. No behaviour change for the bundled icons; future channel logos with these attributes will render instead of being silently stripped.ajax_cleanup_logs_now handler now explicitly returns after each wp_send_json_error(). wp_send_json_error already terminates via wp_die, so behaviour is unchanged — purely a clarity improvement.sendforce_cleanup_logs_now AJAX endpoint (capability + nonce protected) that reports how many rows were removed.rule_matches() + new build_test_context() helper), eliminating any drift between what the tool predicts and what actually happens at send time. Side benefit: the test tool now correctly evaluates time_between, weekday, to_pattern, and from_* conditions (previously partly stubbed in a duplicate local matcher).aria-label so screen readers announce the channel name instead of empty graphics.channels payload and re-load whatever was in the DB; in races between the AJAX channel toggles and the Summary Email form save this could clobber channel state. The sanitizer now respects the incoming payload when present and only falls back to DB state when the form omits channels.SendForce_Logger::cleanup_old_logs()) now returns the number of rows deleted (was void) so callers like the new "Clean Now" handler can surface the count to the user.phpmailer_init action and lets the (possibly routed) settings choose the path. This means a routing rule can freely switch between API and SMTP target connections — e.g. primary SMTP → routed to SES API, or primary API → routed to a different SMTP server.wp_sendforce_routes table (added automatically on plugin upgrade via dbDelta). The routes table is now self-healing — if it's ever missing on an admin page load, it's recreated immediately.from_email and from_domain condition types — match by sender address, not just recipient. Useful when a single site sends from multiple identities (shop@, support@, noreply@).oauth_email field on newly created connections so the schema is consistent from the moment a connection is saved (was previously added only after the first OAuth completes — defensive code in JS handled the missing key, but the data shape was inconsistent).IsContentHtml flag inconsistently — now set explicitly in BOTH HTML and plain-text paths so the rendering matches what the user sent. Previously HTML emails sent via Moosend could render as plain text in some accounts.next_retry_at); on the next cron run any rows whose lease has expired are automatically returned to the queue and retried.sanitize_text_field() so any HTML stored in the option (by any means) cannot leak into admin UI surfaces.wp_strip_all_tags() before being sent to the browser. The client already renders them via .text() so XSS was already blocked, but stripping tags server-side keeps the audit trail clean.default_connection so existing user data is preserved without migration.wp_mail() correctly returns true when the primary fails but the fallback succeeds. The test-email UI now shows a clear "Test email sent via the fallback connection (X). The primary connection (Y) failed; the fallback recovered the send." message instead of misleading the user with the primary failure.Plugin Name: header is now the clean brand name "SendForce Mail Relay" (was the long SEO title), and the Description: header is a single-line summary instead of the full provider list. The long SEO title remains on the WordPress.org directory listing page for search visibility.merge_connection_into() helper; reduces duplication and makes the fallback path use the exact same config-merge rules as the primary.Description: plugin header for better discoverability.Tags to the highest-volume search terms in this category (smtp, wp smtp, email log, mailer, email api).submenu_file filter so the active tab is highlighted correctly when deep-linked..DS_Store file from assets/images/providers/.phpcs:ignore annotations with rationale to four $wpdb queries in includes/class-sendforce-cli.php and includes/class-sendforce-sysinfo.php where the table name is interpolated from $wpdb->prefix plus a hardcoded literal (no user input).log delete --before query onto a single line so the existing phpcs:ignore directive correctly suppresses the InterpolatedNotPrepared warning on the prepared inner statement.<style> and <script> blocks from PHP output. Conflict-detection notice CSS and JS are now in dedicated assets/css/conflict-notice.css and assets/js/conflict-notice.js, properly enqueued via wp_enqueue_style/script. Alerts tab JS bootstrap data now uses wp_add_inline_script.client_secret in the secret-key list.wp sendforce queue clear and wp sendforce log delete.wp sendforce test, wp sendforce queue process|stats|clear, wp sendforce log list|tail|delete|count, wp sendforce sysinfo.sendforce_before_send, sendforce_after_send, sendforce_log_entry filter, sendforce_api_request, sendforce_api_response.debug.log (requires WP_DEBUG_LOG).debug_data log column (Authorization headers redacted).debug_data column on existing installs.