Skip to content

Instantly share code, notes, and snippets.

@githubcom13
Last active June 6, 2023 01:09
Show Gist options
  • Save githubcom13/5fe6ff81d64e4bccdeae36cb6d3939f3 to your computer and use it in GitHub Desktop.
Save githubcom13/5fe6ff81d64e4bccdeae36cb6d3939f3 to your computer and use it in GitHub Desktop.
Add Webhook Postmark support

I finished coding Webhook Postmark support.

Event webhooks (Bounce, Spam plain, SubscriptionChange) from Postmark to Mautic are supported with this change.

I'm using this code in production with Mautic 4.4.2 and it works like a charm.

I share here the portions of code to modify, I hope it will be useful to someone:

in file: /mautic/app/bundles/EmailBundle/Config/config.php

Replace:

'mautic.transport.postmark' => [
                'class' => 'Mautic\EmailBundle\Swiftmailer\Transport\PostmarkTransport',
                'serviceAlias' => 'swiftmailer.mailer.transport.%s',
                'methodCalls' => [
                    'setUsername' => ['%mautic.mailer_user%'],
                    'setPassword' => ['%mautic.mailer_password%'],
                ],
            ],

By:

'mautic.transport.postmark' => [
                'class' => 'Mautic\EmailBundle\Swiftmailer\Transport\PostmarkTransport',
                'serviceAlias' => 'swiftmailer.mailer.transport.%s',
                'arguments' => [
                    'mautic.email.model.transport_callback',
                    '%mautic.mailer_mailjet_sandbox%',
                    '%mautic.mailer_mailjet_sandbox_default_mail%',
                ],
                'methodCalls' => [
                    'setUsername' => ['%mautic.mailer_user%'],
                    'setPassword' => ['%mautic.mailer_password%'],
                ],
            ],

Add:

    'mailer_postmark_sandbox'              => false,
    'mailer_postmark_sandbox_default_mail' => null,

After:

    'mailer_mailjet_sandbox'              => false,
    'mailer_mailjet_sandbox_default_mail' => null,

Clean the cahce beforce mod file PostmarkTransport.php

cd /var/www/html/mautic
php bin/console cache:clear

** Replace all code in file: /mautic/app/bundles/EmailBundle/Swiftmailer/Transport/PostmarkTransport.php

By:

<?php

namespace Mautic\EmailBundle\Swiftmailer\Transport;

use Mautic\EmailBundle\Model\TransportCallback;
use Mautic\LeadBundle\Entity\DoNotContact;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class PostmarkTransport.
 */
class PostmarkTransport extends \Swift_SmtpTransport  implements CallbackTransportInterface
{
    /**
     * @var bool
     */
    private $sandboxMode;

    /**
     * @var string
     */
    private $sandboxMail;

    /**
     * @var TransportCallback
     */
    private $transportCallback;

    /**
     * {@inheritdoc}
     */
    public function __construct(TransportCallback $transportCallback, $sandboxMode = false, $sandboxMail = '')
    {
        parent::__construct('smtp.postmarkapp.com', 587, 'tls');
        $this->setAuthMode('login');

        $this->setSandboxMode($sandboxMode);
        $this->setSandboxMail($sandboxMail);

        $this->transportCallback = $transportCallback;
    }

    /**
     * @param null $failedRecipients
     *
     * @return int|void
     *
     * @throws \Exception
     */
    public function send(\Swift_Mime_SimpleMessage $message, &$failedRecipients = null)
    {
        // add leadIdHash to track this email
        if (isset($message->leadIdHash)) {
            // contact leadidHeash and email to be sure not applying email stat to bcc

            $message->getHeaders()->removeAll('X-MJ-CUSTOMID');

            $message->getHeaders()->addTextHeader('X-MJ-CUSTOMID', $message->leadIdHash.'-'.key($message->getTo()));
        }

        if ($this->isSandboxMode()) {
            $message->setSubject(key($message->getTo()).' - '.$message->getSubject());
            $message->setTo($this->getSandboxMail());
        }

        return parent::send($message, $failedRecipients);
    }


    /**
     * Returns a "transport" string to match the URL path /mailer/{transport}/callback.
     *
     * @return mixed
     */
    public function getCallbackPath()
    {
        return 'postmark';
    }

    /**
     * Handle response.
     *
     * @return mixed
     */
    public function processCallbackRequest(Request $request)
    {
        $postData = json_decode($request->getContent(), true);

        if (is_array($postData)) {

            if (!in_array($postData['RecordType'], ['Bounce', 'SpamComplaint', 'SubscriptionChange'])) {
                return false;
            }

            if ('Bounce' === $postData['RecordType']) {
                $reason = $postData['Name'].': '.$postData['Description'];
                $type   = DoNotContact::BOUNCED;
                    echo "bounce";
            } elseif ('SpamComplaint' === $postData['RecordType']) {
                $reason = $postData['Name'].': '.$postData['Description'];
                $type   = DoNotContact::UNSUBSCRIBED;
            } elseif ('SubscriptionChange' === $postData['RecordType']) {
                $reason = 'User unsubscribed';
                $type   = DoNotContact::UNSUBSCRIBED;
            } else {
                return false;
            }

            $this->transportCallback->addFailureByAddress($postData['Email'], $reason, $type);

        } else {
            // respone must be an array
            return null;
        }
    }

    /**
     * @return bool
     */
    private function isSandboxMode()
    {
        return $this->sandboxMode;
    }

    /**
     * @param bool $sandboxMode
     */
    private function setSandboxMode($sandboxMode)
    {
        $this->sandboxMode = $sandboxMode;
    }

    /**
     * @return string
     */
    private function getSandboxMail()
    {
        return $this->sandboxMail;
    }

    /**
     * @param string $sandboxMail
     */
    private function setSandboxMail($sandboxMail)
    {
        $this->sandboxMail = $sandboxMail;
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment