SparkPost Mail Transport for XF 2.3

SparkPost Mail Transport for XF 2.3 3.0.4

No permission to download

Sim

Well-known member
Sim submitted a new resource:

SparkPost Mail Transport for XF 2.3 - Symfony Mailer transport implementation for SparkPost

Adds a SparkPost mail transport option to have all mails sent via your SparkPost account.

This is the XF v2.3 compatible version of https://xenforo.com/community/resources/sparkpost-mail-transport-for-xf-2-2.7990/ and has been completely rewritten to support Symfony Mail that is used in XF v2.3

This addon has full bounced email and unsubscribed email handling support using the SparkPost Events API - no mailbox required...

Read more about this resource...
 
Note that I only have one production site running XF 2.3 at this point - and it's a brand new site without much traffic yet, so don't consider this addon extensively tested (hence the "beta" tag on the addon). I'm confident it works - but there may be edge cases I haven't encountered yet or tested for.

The bounce handling has not changed from v2 of this addon - but I also haven't yet extensively tested it to ensure it still works with XF v2.3. I don't expect issues, but please pay close attention and report any issues you find.

I aim to get another 4 (more active) sites upgraded to XF 2.3 in the coming weeks, which will allow me to test more thoroughly.
 
Last edited:
Its confusing when you say SparkPost and then it takes you to Bird. Pricing is very expensive too. Unless there is a free version that I am not seeing?
 
Its confusing when you say SparkPost and then it takes you to Bird. Pricing is very expensive too. Unless there is a free version that I am not seeing?

Yeah, Bird bought SparkPost and have basically hidden the transactional email service, which is pretty annoying :rolleyes:

Pricing isn't that expensive when you're sending 100K+ emails per month - especially when you include the cost of a dedicated IP.

(Note: SparkPost pricing is very different to Bird pricing - it's a different service)

To send 100K emails with dedicated IP:
  • SparkPost: US$75 pm
  • SendGrid: US$89.95 pm
  • Brevo (Sendinblue): US$65pm + US$250pa for dedicated IP
  • AWS SES: $39.95 pm
  • Mailgun: US$75 pm
  • Postmark: US$165 pm
Let's compare 50K per month without a dedicated IP:
  • SparkPost: US$20 pm
  • SendGrid: US$35 pm
  • Brevo (Sendinblue): US$39pm
  • AWS SES: US$5 pm
  • Mailgun: US$35 pm
  • Postmark: US $55 pm
... so other than AWS which provides none of the support and analytics services that the other providers offer - which is why it's so cheap - SparkPost is very competitively priced.

Not all mail platforms are the same - at the end of the day, deliverability is what you're after, especially if running a forum as a business like I do. I'm more than happy with what SparkPost offers.
 
Yeah, Bird bought SparkPost and have basically hidden the transactional email service, which is pretty annoying :rolleyes:

Pricing isn't that expensive when you're sending 100K+ emails per month - especially when you include the cost of a dedicated IP.

(Note: SparkPost pricing is very different to Bird pricing - it's a different service)

To send 100K emails with dedicated IP:
  • SparkPost: US$75 pm
  • SendGrid: US$89.95 pm
  • Brevo (Sendinblue): US$65pm + US$250pa for dedicated IP
  • AWS SES: $39.95 pm
  • Mailgun: US$75 pm
  • Postmark: US$165 pm
Let's compare 50K per month without a dedicated IP:
  • SparkPost: US$20 pm
  • SendGrid: US$35 pm
  • Brevo (Sendinblue): US$39pm
  • AWS SES: US$5 pm
  • Mailgun: US$35 pm
  • Postmark: US $55 pm
... so other than AWS which provides none of the support and analytics services that the other providers offer - which is why it's so cheap - SparkPost is very competitively priced.

Not all mail platforms are the same - at the end of the day, deliverability is what you're after, especially if running a forum as a business like I do. I'm more than happy with what SparkPost offers.
Will this add-on still work with anything lower than PHP v8.1? I'm currently running 7.4.33.
 
Will this add-on still work with anything lower than PHP v8.1? I'm currently running 7.4.33.

It's unlikely - there are quite a few composer dependencies for this addon and I'm pretty sure some of them are not backwards compatible with earlier versions of PHP. I had to restrict the addon to 8.1 because of a specific change that occurred in PHP that breaks backwards compatibility.
 
Hi! Seems everything working good, mails are sending correctly. But there is such error in error log
Http\Discovery\NotFoundException: Job Hampel\SparkPostMail:MessageEvent: No php-http message factories found. Note that the php-http message factories are deprecated in favor of the PSR-17 message factories. To use the legacy Guzzle, Diactoros or Slim Framework factories of php-http, install php-http/message and php-http/message-factory and the chosen message implementation. src\addons\Hampel\SparkPostMail\vendor\php-http\discovery\src\MessageFactoryDiscovery.php:29
Php 8.2
XF 2.3.2
 
Hi! Seems everything working good, mails are sending correctly. But there is such error in error log

Php 8.2
XF 2.3.2

Thanks for reporting - I have been able to reproduce the error and am working to find a solution.

As mentioned, this does not affect mail sending - it specifically relates to bounced email processing (retrieving message events from the SparkPost API)
 
Thanks for reporting - I have been able to reproduce the error and am working to find a solution.

As mentioned, this does not affect mail sending - it specifically relates to bounced email processing (retrieving message events from the SparkPost API)
Thanks for the awesome work. I'll definitely check it out.
 
  • Like
Reactions: Sim
This was one plugin holding me back from upgrading to 2.3! Thank you! Can't wait to upgrade the site and try it out this weekend.
 
v3.0.2 fixes incomplete "from" headers where the forum name (or "Default email sender name") is not included in the from header like it should be.

Thanks to @modified for alerting me to this issue.
 
I upgraded from 2.2x to 2.3x which was reported as successful. However, the forum reports the following add-on related errors. Was I supposed to upgrade your addon to the XF 2.3 compatible version before I upgrade xenforo? What do I do now?

Code:
An exception occurred: [Error] Call to undefined method GuzzleHttp\Utils::chooseHandler() in src/vendor/guzzlehttp/guzzle/src/functions.php on line 61

GuzzleHttp\choose_handler() in src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/guzzle/src/HandlerStack.php at line 42
GuzzleHttp\HandlerStack::create() in src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/guzzle/src/Client.php at line 65
GuzzleHttp\Client->__construct() in src/XF/SubContainer/Http.php at line 108
XF\SubContainer\Http->createClient() in src/addons/XFES/Elasticsearch/Api.php at line 52
XFES\Elasticsearch\Api->__construct() in src/addons/XFES/Listener.php at line 44
XFES\Listener::getElasticsearchApi() in src/addons/XFES/Listener.php at line 13
XFES\Listener::searchSourceSetup() in src/XF/Extension.php at line 86
XF\Extension->fire() in src/XF/App.php at line 3368
XF\App->fire() in src/XF/App.php at line 1422
XF\App->XF\{closure}() in src/XF/Container.php at line 33
XF\Container->offsetGet() in src/XF/App.php at line 1417
XF\App->XF\{closure}() in src/XF/Container.php at line 33
XF\Container->offsetGet() in src/XF/App.php at line 3393
XF\App->search() in src/XF/App.php at line 2425
XF\App->getGlobalTemplateData() in src/XF/App.php at line 2359
XF\App->preRender() in src/XF/Pub/App.php at line 495
XF\Pub\App->preRender() in src/XF/Mvc/Dispatcher.php at line 407
XF\Mvc\Dispatcher->render() in src/XF/Mvc/Dispatcher.php at line 66
XF\Mvc\Dispatcher->run() in src/XF/App.php at line 2826
XF\App->run() in src/XF.php at line 806
XF::runApp() in index.php at line 23

Thank you
 
I upgraded from 2.2x to 2.3x which was reported as successful. However, the forum reports the following add-on related errors. Was I supposed to upgrade your addon to the XF 2.3 compatible version before I upgrade xenforo? What do I do now?

Have you upgraded all the addons to XF 2.3 compatible versions?

Had you upgraded them all at the time the error occurred?

Are you still getting errors or was that a once-off error?

I'm thinking it may have been a library clash from different versions of Guzzle being present while not all addons had been upgraded yet?
 
I upgraded to XF 2.3 first. With the plan to upgrade addons after the upgrade. The upgrade was successful. But unfortunately, the error occurred and I was unable to access the ACP to upgrade addons.

Xenforo support advised that I edit src/config.php file to disable addons and regain access to ACP.

As if this moment, everything seems to work fine after I upgraded all addons to XF 2.3 compatible versions.
 
Thanks for confirming.

The version of Guzzle was changed in XF 2.3 - so while old addons exist, they can conflict with the platform's version, leading to errors like this "undefined method" you saw.

I think I'll make a note in the resource that the XF 2.2 version of the addon should be disabled before attempting to upgrade XF to v2.3

You can't upgrade this addon first because it will break an XF 2.2 install.
 
Hello, i get this server error when testing (XF or your add-on testing system) :
Code:
Error: Email to ********@icloud.com from ****@permaforo.net failed: Call to undefined method GuzzleHttp\Exception\ClientException::appendDebug() src/addons/Hampel/SparkPostMail/vendor/hampel/symfonymailer-sparkpost/src/Transport/AbstractHttpTransport.php:57
Code:
#0 src/addons/Hampel/SparkPostMail/vendor/symfony/mailer/Transport/AbstractTransport.php(72): Hampel\Symfony\Mailer\SparkPost\Transport\AbstractHttpTransport->doSend(Object(Symfony\Component\Mailer\SentMessage))
#1 src/XF/Mail/Mailer.php(305): Symfony\Component\Mailer\Transport\AbstractTransport->send(Object(Symfony\Component\Mailer\SentMessage))
#2 src/XF/Mail/Mail.php(576): XF\Mail\Mailer->send(Object(Symfony\Component\Mime\Email), Object(Hampel\Symfony\Mailer\SparkPost\Transport\SparkPostApiTransport))
#3 src/addons/Hampel/SparkPostMail/Test/TransportTest.php(46): XF\Mail\Mail->send()
#4 src/addons/Hampel/SparkPostMail/XF/Admin/Controller/Tools.php(26): Hampel\SparkPostMail\Test\TransportTest->run()
#5 src/XF/Mvc/Dispatcher.php(362): Hampel\SparkPostMail\XF\Admin\Controller\Tools->actionTestSparkPostMail(Object(XF\Mvc\ParameterBag))
#6 src/XF/Mvc/Dispatcher.php(264): XF\Mvc\Dispatcher->dispatchClass('XF:Tools', 'TestSparkpostma...', Object(XF\Mvc\RouteMatch), Object(Hampel\SparkPostMail\XF\Admin\Controller\Tools), NULL)
#7 src/XF/Mvc/Dispatcher.php(121): XF\Mvc\Dispatcher->dispatchFromMatch(Object(XF\Mvc\RouteMatch), Object(Hampel\SparkPostMail\XF\Admin\Controller\Tools), NULL)
#8 src/XF/Mvc/Dispatcher.php(63): XF\Mvc\Dispatcher->dispatchLoop(Object(XF\Mvc\RouteMatch))
#9 src/XF/App.php(2826): XF\Mvc\Dispatcher->run()
#10 src/XF.php(806): XF\App->run()
#11 admin.php(15): XF::runApp('XF\\Admin\\App')
#12 {main}
Code:
array(4) {
  ["url"] => string(35) "/admin.php?tools/test-sparkpostmail"
  ["referrer"] => string(56) "https://permaforo.net/admin.php?tools/test-sparkpostmail"
  ["_GET"] => array(1) {
    ["tools/test-sparkpostmail"] => string(0) ""
  }
  ["_POST"] => array(3) {
    ["_xfToken"] => string(8) "********"
    ["options"] => array(1) {
      ["email"] => string(18) "******@icloud.com"
    }
    ["test"] => string(34) "Hampel\SparkPostMail:TransportTest"
  }
}
 
And this one...
Code:
SparkPost\SparkPostException: Job Hampel\SparkPostMail:MessageEvent: {"errors": [ {"message": "Unauthorized."} ]} src/addons/Hampel/SparkPostMail/vendor/sparkpost/sparkpost/lib/SparkPost/SparkPostPromise.php:77
Code:
#0 src/addons/Hampel/SparkPostMail/SubContainer/SparkPost.php(67): SparkPost\SparkPostPromise->wait()
#1 src/addons/Hampel/SparkPostMail/Job/MessageEvent.php(42): Hampel\SparkPostMail\SubContainer\SparkPost->getMessageEvents(1, 1000, Array, 1727085323, 1728035723)
#2 src/XF/Job/Manager.php(275): Hampel\SparkPostMail\Job\MessageEvent->run(8)
#3 src/XF/Job/Manager.php(205): XF\Job\Manager->runJobInternal(Array, 8)
#4 src/XF/Job/Manager.php(89): XF\Job\Manager->runJobEntry(Array, 8)
#5 job.php(46): XF\Job\Manager->runQueue(false, 8)
#6 {main}
Code:
Previous GuzzleHttp\Exception\ClientException: Client error: `GET https://api.sparkpost.com/api/v1/events/message?page=1&per_page=1000&events=bounce,policy_rejection,out_of_band,generation_rejection,spam_complaint,list_unsubscribe,link_unsubscribe&from=2024-09-23T09%3A55&to=2024-10-04T09%3A55` resulted in a `401 Unauthorized` response:
{"errors": [ {"message": "Unauthorized."} ]}

 - src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:111
#0 src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/guzzle/src/Middleware.php(72): GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Psr7\Request), Object(GuzzleHttp\Psr7\Response), NULL, Array, NULL)
#1 src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/promises/src/Promise.php(209): GuzzleHttp\Middleware::GuzzleHttp\{closure}(Object(GuzzleHttp\Psr7\Response))
#2 src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/promises/src/Promise.php(158): GuzzleHttp\Promise\Promise::callHandler(1, Object(GuzzleHttp\Psr7\Response), NULL)
#3 src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/promises/src/TaskQueue.php(52): GuzzleHttp\Promise\Promise::GuzzleHttp\Promise\{closure}()
#4 src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(167): GuzzleHttp\Promise\TaskQueue->run()
#5 src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(206): GuzzleHttp\Handler\CurlMultiHandler->tick()
#6 src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/promises/src/Promise.php(251): GuzzleHttp\Handler\CurlMultiHandler->execute(true)
#7 src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/promises/src/Promise.php(227): GuzzleHttp\Promise\Promise->invokeWaitFn()
#8 src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/promises/src/Promise.php(272): GuzzleHttp\Promise\Promise->waitIfPending()
#9 src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/promises/src/Promise.php(229): GuzzleHttp\Promise\Promise->invokeWaitList()
#10 src/addons/Hampel/SparkPostMail/vendor/guzzlehttp/promises/src/Promise.php(69): GuzzleHttp\Promise\Promise->waitIfPending()
#11 src/addons/Hampel/SparkPostMail/vendor/php-http/guzzle7-adapter/src/Promise.php(94): GuzzleHttp\Promise\Promise->wait(false)
#12 src/addons/Hampel/SparkPostMail/vendor/sparkpost/sparkpost/lib/SparkPost/SparkPostPromise.php(73): Http\Adapter\Guzzle7\Promise->wait(true)
#13 src/addons/Hampel/SparkPostMail/SubContainer/SparkPost.php(67): SparkPost\SparkPostPromise->wait()
#14 src/addons/Hampel/SparkPostMail/Job/MessageEvent.php(42): Hampel\SparkPostMail\SubContainer\SparkPost->getMessageEvents(1, 1000, Array, 1727085323, 1728035723)
#15 src/XF/Job/Manager.php(275): Hampel\SparkPostMail\Job\MessageEvent->run(8)
#16 src/XF/Job/Manager.php(205): XF\Job\Manager->runJobInternal(Array, 8)
#17 src/XF/Job/Manager.php(89): XF\Job\Manager->runJobEntry(Array, 8)
#18 job.php(46): XF\Job\Manager->runQueue(false, 8)
#19 {main}

Was my Sparkpost account misconfigured?

1728036282541.webp

I just changed to this

1728036363247.webp

I'm running CF

1728036486441.webp
1728036510180.webp

Thanks.
 
Back
Top Bottom