Improve email sending system and add Postmark as mail transport
This commit is contained in:
@@ -112,7 +112,7 @@ class Webhook extends Base
|
||||
$this->response->text('Not Authorized', 401);
|
||||
}
|
||||
|
||||
echo $this->postmarkWebhook->parsePayload($this->request->getJson() ?: array()) ? 'PARSED' : 'IGNORED';
|
||||
echo $this->postmark->receiveEmail($this->request->getJson() ?: array()) ? 'PARSED' : 'IGNORED';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,6 +11,7 @@ use Pimple\Container;
|
||||
* @author Frederic Guillot
|
||||
*
|
||||
* @property \Core\Helper $helper
|
||||
* @property \Core\EmailClient $emailClient
|
||||
* @property \Core\HttpClient $httpClient
|
||||
* @property \Core\Paginator $paginator
|
||||
* @property \Core\Request $request
|
||||
@@ -22,9 +23,10 @@ use Pimple\Container;
|
||||
* @property \Integration\HipchatWebhook $hipchatWebhook
|
||||
* @property \Integration\Jabber $jabber
|
||||
* @property \Integration\MailgunWebhook $mailgunWebhook
|
||||
* @property \Integration\PostmarkWebhook $postmarkWebhook
|
||||
* @property \Integration\Postmark $postmark
|
||||
* @property \Integration\SendgridWebhook $sendgridWebhook
|
||||
* @property \Integration\SlackWebhook $slackWebhook
|
||||
* @property \Integration\Smtp $smtp
|
||||
* @property \Model\Acl $acl
|
||||
* @property \Model\Action $action
|
||||
* @property \Model\Authentication $authentication
|
||||
|
||||
43
app/Core/EmailClient.php
Normal file
43
app/Core/EmailClient.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Core;
|
||||
|
||||
/**
|
||||
* Mail client
|
||||
*
|
||||
* @package core
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class EmailClient extends Base
|
||||
{
|
||||
/**
|
||||
* Send a HTML email
|
||||
*
|
||||
* @access public
|
||||
* @param string $email
|
||||
* @param string $name
|
||||
* @param string $subject
|
||||
* @param string $html
|
||||
*/
|
||||
public function send($email, $name, $subject, $html)
|
||||
{
|
||||
$this->container['logger']->debug('Sending email to '.$email.' ('.MAIL_TRANSPORT.')');
|
||||
|
||||
$start_time = microtime(true);
|
||||
$author = 'Kanboard';
|
||||
|
||||
if (Session::isOpen() && $this->userSession->isLogged()) {
|
||||
$author = e('%s via Kanboard', $this->user->getFullname($this->session['user']));
|
||||
}
|
||||
|
||||
switch (MAIL_TRANSPORT) {
|
||||
case 'postmark':
|
||||
$this->postmark->sendEmail($email, $name, $subject, $html, $author);
|
||||
break;
|
||||
default:
|
||||
$this->smtp->sendEmail($email, $name, $subject, $html, $author);
|
||||
}
|
||||
|
||||
$this->container['logger']->debug('Email sent in '.round(microtime(true) - $start_time, 6).' seconds');
|
||||
}
|
||||
}
|
||||
@@ -2,22 +2,20 @@
|
||||
|
||||
namespace Core;
|
||||
|
||||
use Pimple\Container;
|
||||
|
||||
/**
|
||||
* HTTP client
|
||||
*
|
||||
* @package core
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class HttpClient
|
||||
class HttpClient extends Base
|
||||
{
|
||||
/**
|
||||
* HTTP connection timeout in seconds
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
const HTTP_TIMEOUT = 2;
|
||||
const HTTP_TIMEOUT = 5;
|
||||
|
||||
/**
|
||||
* Number of maximum redirections for the HTTP client
|
||||
@@ -31,26 +29,7 @@ class HttpClient
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const HTTP_USER_AGENT = 'Kanboard Webhook';
|
||||
|
||||
/**
|
||||
* Container instance
|
||||
*
|
||||
* @access protected
|
||||
* @var \Pimple\Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @param \Pimple\Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
const HTTP_USER_AGENT = 'Kanboard';
|
||||
|
||||
/**
|
||||
* Send a POST HTTP request
|
||||
@@ -58,19 +37,20 @@ class HttpClient
|
||||
* @access public
|
||||
* @param string $url
|
||||
* @param array $data
|
||||
* @param array $headers
|
||||
* @return string
|
||||
*/
|
||||
public function post($url, array $data)
|
||||
public function post($url, array $data, array $headers = array())
|
||||
{
|
||||
if (empty($url)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$headers = array(
|
||||
$headers = array_merge(array(
|
||||
'User-Agent: '.self::HTTP_USER_AGENT,
|
||||
'Content-Type: application/json',
|
||||
'Connection: close',
|
||||
);
|
||||
), $headers);
|
||||
|
||||
$context = stream_context_create(array(
|
||||
'http' => array(
|
||||
@@ -83,12 +63,21 @@ class HttpClient
|
||||
)
|
||||
));
|
||||
|
||||
$response = @file_get_contents(trim($url), false, $context);
|
||||
$stream = @fopen(trim($url), 'r', false, $context);
|
||||
$response = '';
|
||||
|
||||
if (is_resource($stream)) {
|
||||
$response = stream_get_contents($stream);
|
||||
}
|
||||
else {
|
||||
$this->container['logger']->error('HttpClient: request failed');
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
$this->container['logger']->debug($url);
|
||||
$this->container['logger']->debug(var_export($data, true));
|
||||
$this->container['logger']->debug($response);
|
||||
$this->container['logger']->debug('HttpClient: url='.$url);
|
||||
$this->container['logger']->debug('HttpClient: payload='.var_export($data, true));
|
||||
$this->container['logger']->debug('HttpClient: metadata='.var_export(@stream_get_meta_data($stream), true));
|
||||
$this->container['logger']->debug('HttpClient: response='.$response);
|
||||
}
|
||||
|
||||
return $response;
|
||||
|
||||
@@ -5,13 +5,40 @@ namespace Integration;
|
||||
use HTML_To_Markdown;
|
||||
|
||||
/**
|
||||
* Postmark Webhook
|
||||
* Postmark integration
|
||||
*
|
||||
* @package integration
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class PostmarkWebhook extends \Core\Base
|
||||
class Postmark extends \Core\Base
|
||||
{
|
||||
/**
|
||||
* Send a HTML email
|
||||
*
|
||||
* @access public
|
||||
* @param string $email
|
||||
* @param string $name
|
||||
* @param string $subject
|
||||
* @param string $html
|
||||
* @param string $author
|
||||
*/
|
||||
public function sendEmail($email, $name, $subject, $html, $author)
|
||||
{
|
||||
$headers = array(
|
||||
'Accept: application/json',
|
||||
'X-Postmark-Server-Token: '.POSTMARK_API_TOKEN,
|
||||
);
|
||||
|
||||
$payload = array(
|
||||
'From' => sprintf('%s <%s>', $author, MAIL_FROM),
|
||||
'To' => sprintf('%s <%s>', $name, $email),
|
||||
'Subject' => $subject,
|
||||
'HtmlBody' => $html,
|
||||
);
|
||||
|
||||
$this->httpClient->post('https://api.postmarkapp.com/email', $payload, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse incoming email
|
||||
*
|
||||
@@ -19,7 +46,7 @@ class PostmarkWebhook extends \Core\Base
|
||||
* @param array $payload Incoming email
|
||||
* @return boolean
|
||||
*/
|
||||
public function parsePayload(array $payload)
|
||||
public function receiveEmail(array $payload)
|
||||
{
|
||||
if (empty($payload['From']) || empty($payload['Subject']) || empty($payload['MailboxHash'])) {
|
||||
return false;
|
||||
@@ -29,7 +56,7 @@ class PostmarkWebhook extends \Core\Base
|
||||
$user = $this->user->getByEmail($payload['From']);
|
||||
|
||||
if (empty($user)) {
|
||||
$this->container['logger']->debug('PostmarkWebhook: ignored => user not found');
|
||||
$this->container['logger']->debug('Postmark: ignored => user not found');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -37,13 +64,13 @@ class PostmarkWebhook extends \Core\Base
|
||||
$project = $this->project->getByIdentifier($payload['MailboxHash']);
|
||||
|
||||
if (empty($project)) {
|
||||
$this->container['logger']->debug('PostmarkWebhook: ignored => project not found');
|
||||
$this->container['logger']->debug('Postmark: ignored => project not found');
|
||||
return false;
|
||||
}
|
||||
|
||||
// The user must be member of the project
|
||||
if (! $this->projectPermission->isMember($project['id'], $user['id'])) {
|
||||
$this->container['logger']->debug('PostmarkWebhook: ignored => user is not member of the project');
|
||||
$this->container['logger']->debug('Postmark: ignored => user is not member of the project');
|
||||
return false;
|
||||
}
|
||||
|
||||
71
app/Integration/Smtp.php
Normal file
71
app/Integration/Smtp.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Integration;
|
||||
|
||||
use Swift_Message;
|
||||
use Swift_Mailer;
|
||||
use Swift_MailTransport;
|
||||
use Swift_SendmailTransport;
|
||||
use Swift_SmtpTransport;
|
||||
use Swift_TransportException;
|
||||
|
||||
/**
|
||||
* Smtp
|
||||
*
|
||||
* @package integration
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Smtp extends \Core\Base
|
||||
{
|
||||
/**
|
||||
* Send a HTML email
|
||||
*
|
||||
* @access public
|
||||
* @param string $email
|
||||
* @param string $name
|
||||
* @param string $subject
|
||||
* @param string $html
|
||||
* @param string $author
|
||||
*/
|
||||
public function sendEmail($email, $name, $subject, $html, $author)
|
||||
{
|
||||
try {
|
||||
|
||||
$message = Swift_Message::newInstance()
|
||||
->setSubject($subject)
|
||||
->setFrom(array(MAIL_FROM => $author))
|
||||
->setBody($html, 'text/html')
|
||||
->setTo(array($email => $name));
|
||||
|
||||
Swift_Mailer::newInstance($this->getTransport())->send($message);
|
||||
}
|
||||
catch (Swift_TransportException $e) {
|
||||
$this->container['logger']->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SwiftMailer transport
|
||||
*
|
||||
* @access private
|
||||
* @return \Swift_Transport
|
||||
*/
|
||||
private function getTransport()
|
||||
{
|
||||
switch (MAIL_TRANSPORT) {
|
||||
case 'smtp':
|
||||
$transport = Swift_SmtpTransport::newInstance(MAIL_SMTP_HOSTNAME, MAIL_SMTP_PORT);
|
||||
$transport->setUsername(MAIL_SMTP_USERNAME);
|
||||
$transport->setPassword(MAIL_SMTP_PASSWORD);
|
||||
$transport->setEncryption(MAIL_SMTP_ENCRYPTION);
|
||||
break;
|
||||
case 'sendmail':
|
||||
$transport = Swift_SendmailTransport::newInstance(MAIL_SENDMAIL_COMMAND);
|
||||
break;
|
||||
default:
|
||||
$transport = Swift_MailTransport::newInstance();
|
||||
}
|
||||
|
||||
return $transport;
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,6 @@ namespace Model;
|
||||
|
||||
use Core\Session;
|
||||
use Core\Translator;
|
||||
use Swift_Message;
|
||||
use Swift_Mailer;
|
||||
use Swift_TransportException;
|
||||
|
||||
/**
|
||||
* Notification model
|
||||
@@ -101,43 +98,22 @@ class Notification extends Base
|
||||
*/
|
||||
public function sendEmails($template, array $users, array $data)
|
||||
{
|
||||
try {
|
||||
foreach ($users as $user) {
|
||||
|
||||
$author = '';
|
||||
|
||||
if (Session::isOpen() && $this->userSession->isLogged()) {
|
||||
$author = e('%s via Kanboard', $this->user->getFullname($this->session['user']));
|
||||
// Use the user language otherwise use the application language (do not use the session language)
|
||||
if (! empty($user['language'])) {
|
||||
Translator::load($user['language']);
|
||||
}
|
||||
else {
|
||||
Translator::load($this->config->get('application_language', 'en_US'));
|
||||
}
|
||||
|
||||
$mailer = Swift_Mailer::newInstance($this->container['mailer']);
|
||||
|
||||
foreach ($users as $user) {
|
||||
|
||||
$this->container['logger']->debug('Send email notification to '.$user['username'].' lang='.$user['language']);
|
||||
$start_time = microtime(true);
|
||||
|
||||
// Use the user language otherwise use the application language (do not use the session language)
|
||||
if (! empty($user['language'])) {
|
||||
Translator::load($user['language']);
|
||||
}
|
||||
else {
|
||||
Translator::load($this->config->get('application_language', 'en_US'));
|
||||
}
|
||||
|
||||
// Send the message
|
||||
$message = Swift_Message::newInstance()
|
||||
->setSubject($this->getMailSubject($template, $data))
|
||||
->setFrom(array(MAIL_FROM => $author ?: 'Kanboard'))
|
||||
->setBody($this->getMailContent($template, $data), 'text/html')
|
||||
->setTo(array($user['email'] => $user['name'] ?: $user['username']));
|
||||
|
||||
$mailer->send($message);
|
||||
|
||||
$this->container['logger']->debug('Email sent in '.round(microtime(true) - $start_time, 6).' seconds');
|
||||
}
|
||||
}
|
||||
catch (Swift_TransportException $e) {
|
||||
$this->container['logger']->error($e->getMessage());
|
||||
$this->emailClient->send(
|
||||
$user['email'],
|
||||
$user['name'] ?: $user['username'],
|
||||
$this->getMailSubject($template, $data),
|
||||
$this->getMailContent($template, $data)
|
||||
);
|
||||
}
|
||||
|
||||
// Restore locales
|
||||
@@ -167,40 +143,40 @@ class Notification extends Base
|
||||
{
|
||||
switch ($template) {
|
||||
case 'file_creation':
|
||||
$subject = $this->getStandardMailSubject(t('New attachment'), $data);
|
||||
$subject = $this->getStandardMailSubject(e('New attachment'), $data);
|
||||
break;
|
||||
case 'comment_creation':
|
||||
$subject = $this->getStandardMailSubject(t('New comment'), $data);
|
||||
$subject = $this->getStandardMailSubject(e('New comment'), $data);
|
||||
break;
|
||||
case 'comment_update':
|
||||
$subject = $this->getStandardMailSubject(t('Comment updated'), $data);
|
||||
$subject = $this->getStandardMailSubject(e('Comment updated'), $data);
|
||||
break;
|
||||
case 'subtask_creation':
|
||||
$subject = $this->getStandardMailSubject(t('New subtask'), $data);
|
||||
$subject = $this->getStandardMailSubject(e('New subtask'), $data);
|
||||
break;
|
||||
case 'subtask_update':
|
||||
$subject = $this->getStandardMailSubject(t('Subtask updated'), $data);
|
||||
$subject = $this->getStandardMailSubject(e('Subtask updated'), $data);
|
||||
break;
|
||||
case 'task_creation':
|
||||
$subject = $this->getStandardMailSubject(t('New task'), $data);
|
||||
$subject = $this->getStandardMailSubject(e('New task'), $data);
|
||||
break;
|
||||
case 'task_update':
|
||||
$subject = $this->getStandardMailSubject(t('Task updated'), $data);
|
||||
$subject = $this->getStandardMailSubject(e('Task updated'), $data);
|
||||
break;
|
||||
case 'task_close':
|
||||
$subject = $this->getStandardMailSubject(t('Task closed'), $data);
|
||||
$subject = $this->getStandardMailSubject(e('Task closed'), $data);
|
||||
break;
|
||||
case 'task_open':
|
||||
$subject = $this->getStandardMailSubject(t('Task opened'), $data);
|
||||
$subject = $this->getStandardMailSubject(e('Task opened'), $data);
|
||||
break;
|
||||
case 'task_move_column':
|
||||
$subject = $this->getStandardMailSubject(t('Column Change'), $data);
|
||||
$subject = $this->getStandardMailSubject(e('Column Change'), $data);
|
||||
break;
|
||||
case 'task_move_position':
|
||||
$subject = $this->getStandardMailSubject(t('Position Change'), $data);
|
||||
$subject = $this->getStandardMailSubject(e('Position Change'), $data);
|
||||
break;
|
||||
case 'task_assignee_change':
|
||||
$subject = $this->getStandardMailSubject(t('Assignee Change'), $data);
|
||||
$subject = $this->getStandardMailSubject(e('Assignee Change'), $data);
|
||||
break;
|
||||
case 'task_due':
|
||||
$subject = e('[%s][Due tasks]', $data['project']);
|
||||
|
||||
@@ -64,6 +64,7 @@ class ClassProvider implements ServiceProviderInterface
|
||||
'Webhook',
|
||||
),
|
||||
'Core' => array(
|
||||
'EmailClient',
|
||||
'Helper',
|
||||
'HttpClient',
|
||||
'MemoryCache',
|
||||
@@ -78,9 +79,10 @@ class ClassProvider implements ServiceProviderInterface
|
||||
'HipchatWebhook',
|
||||
'Jabber',
|
||||
'MailgunWebhook',
|
||||
'PostmarkWebhook',
|
||||
'Postmark',
|
||||
'SendgridWebhook',
|
||||
'SlackWebhook',
|
||||
'Smtp',
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace ServiceProvider;
|
||||
|
||||
use Pimple\Container;
|
||||
use Pimple\ServiceProviderInterface;
|
||||
use Swift_SmtpTransport;
|
||||
use Swift_SendmailTransport;
|
||||
use Swift_MailTransport;
|
||||
|
||||
class MailerProvider implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container['mailer'] = function () {
|
||||
switch (MAIL_TRANSPORT) {
|
||||
case 'smtp':
|
||||
$transport = Swift_SmtpTransport::newInstance(MAIL_SMTP_HOSTNAME, MAIL_SMTP_PORT);
|
||||
$transport->setUsername(MAIL_SMTP_USERNAME);
|
||||
$transport->setPassword(MAIL_SMTP_PASSWORD);
|
||||
$transport->setEncryption(MAIL_SMTP_ENCRYPTION);
|
||||
break;
|
||||
case 'sendmail':
|
||||
$transport = Swift_SendmailTransport::newInstance(MAIL_SENDMAIL_COMMAND);
|
||||
break;
|
||||
default:
|
||||
$transport = Swift_MailTransport::newInstance();
|
||||
}
|
||||
|
||||
return $transport;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -27,4 +27,3 @@ $container->register(new ServiceProvider\LoggingProvider);
|
||||
$container->register(new ServiceProvider\DatabaseProvider);
|
||||
$container->register(new ServiceProvider\ClassProvider);
|
||||
$container->register(new ServiceProvider\EventDispatcherProvider);
|
||||
$container->register(new ServiceProvider\MailerProvider);
|
||||
|
||||
@@ -64,6 +64,7 @@ defined('MAIL_SMTP_USERNAME') or define('MAIL_SMTP_USERNAME', '');
|
||||
defined('MAIL_SMTP_PASSWORD') or define('MAIL_SMTP_PASSWORD', '');
|
||||
defined('MAIL_SMTP_ENCRYPTION') or define('MAIL_SMTP_ENCRYPTION', null);
|
||||
defined('MAIL_SENDMAIL_COMMAND') or define('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs');
|
||||
defined('POSTMARK_API_TOKEN') or define('POSTMARK_API_TOKEN', '');
|
||||
|
||||
// Enable or disable "Strict-Transport-Security" HTTP header
|
||||
defined('ENABLE_HSTS') or define('ENABLE_HSTS', true);
|
||||
|
||||
@@ -14,7 +14,7 @@ define('FILES_DIR', 'data/files/');
|
||||
// E-mail address for the "From" header (notifications)
|
||||
define('MAIL_FROM', 'notifications@kanboard.local');
|
||||
|
||||
// Mail transport to use: "smtp", "sendmail" or "mail" (PHP mail function)
|
||||
// Mail transport to use: "smtp", "sendmail", "mail" (PHP mail function), "postmark"
|
||||
define('MAIL_TRANSPORT', 'mail');
|
||||
|
||||
// SMTP configuration to use when the "smtp" transport is chosen
|
||||
@@ -27,6 +27,9 @@ define('MAIL_SMTP_ENCRYPTION', null); // Valid values are "null", "ssl" or "tls"
|
||||
// Sendmail command to use when the transport is "sendmail"
|
||||
define('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs');
|
||||
|
||||
// Postmark API token (used to send emails through their API)
|
||||
define('POSTMARK_API_TOKEN', '');
|
||||
|
||||
// Database driver: sqlite, mysql or postgres (sqlite by default)
|
||||
define('DB_DRIVER', 'sqlite');
|
||||
|
||||
|
||||
@@ -12,6 +12,16 @@ To receive email notifications, users of Kanboard must have:
|
||||
|
||||
Note: The logged user who performs the action doesn't receive any notifications, only other project members.
|
||||
|
||||
Email transports
|
||||
----------------
|
||||
|
||||
There are several email transports available:
|
||||
|
||||
- SMTP
|
||||
- Sendmail
|
||||
- PHP native mail function
|
||||
- Postmark
|
||||
|
||||
Server settings
|
||||
---------------
|
||||
|
||||
@@ -57,6 +67,34 @@ define('MAIL_TRANSPORT', 'sendmail');
|
||||
define('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs');
|
||||
```
|
||||
|
||||
### PHP native mail function
|
||||
|
||||
This is the default configuration:
|
||||
|
||||
```php
|
||||
define('MAIL_TRANSPORT', 'mail');
|
||||
```
|
||||
|
||||
### Postmark HTTP API
|
||||
|
||||
Postmark is a third-party email service.
|
||||
If you already use the Postmark integration to receive emails in Kanboard you can use the same provider to send email too.
|
||||
|
||||
This system use their HTTP API instead of the SMTP protocol.
|
||||
|
||||
Here are the required settings for this configuration:
|
||||
|
||||
```php
|
||||
// We choose "postmark" as mail transport
|
||||
define('MAIL_TRANSPORT', 'postmark');
|
||||
|
||||
// Copy and paste your Postmark API token
|
||||
define('POSTMARK_API_TOKEN', 'COPY HERE YOUR POSTMARK API TOKEN');
|
||||
|
||||
// Be sure to use the Postmark configured sender email address
|
||||
define('MAIL_FROM', 'sender-address-configured-in-postmark@example.org');
|
||||
```
|
||||
|
||||
### The sender email address
|
||||
|
||||
By default, emails will use the sender address `notifications@kanboard.local`.
|
||||
|
||||
@@ -15,6 +15,7 @@ class FakeHttpClient
|
||||
{
|
||||
private $url = '';
|
||||
private $data = array();
|
||||
private $headers = array();
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
@@ -26,16 +27,21 @@ class FakeHttpClient
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
public function toPrettyJson()
|
||||
{
|
||||
return json_encode($this->data, JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
public function post($url, array $data)
|
||||
public function post($url, array $data, array $headers = array())
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->data = $data;
|
||||
//echo $this->toPrettyJson();
|
||||
$this->headers = $headers;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,18 +2,41 @@
|
||||
|
||||
require_once __DIR__.'/Base.php';
|
||||
|
||||
use Integration\PostmarkWebhook;
|
||||
use Integration\Postmark;
|
||||
use Model\TaskCreation;
|
||||
use Model\TaskFinder;
|
||||
use Model\Project;
|
||||
use Model\ProjectPermission;
|
||||
use Model\User;
|
||||
|
||||
class PostmarkWebhookTest extends Base
|
||||
class PostmarkTest extends Base
|
||||
{
|
||||
public function testSendEmail()
|
||||
{
|
||||
$pm = new Postmark($this->container);
|
||||
$pm->sendEmail('test@localhost', 'Me', 'Test', 'Content', 'Bob');
|
||||
|
||||
$this->assertEquals('https://api.postmarkapp.com/email', $this->container['httpClient']->getUrl());
|
||||
|
||||
$data = $this->container['httpClient']->getData();
|
||||
|
||||
$this->assertArrayHasKey('From', $data);
|
||||
$this->assertArrayHasKey('To', $data);
|
||||
$this->assertArrayHasKey('Subject', $data);
|
||||
$this->assertArrayHasKey('HtmlBody', $data);
|
||||
|
||||
$this->assertEquals('Me <test@localhost>', $data['To']);
|
||||
$this->assertEquals('Bob <notifications@kanboard.local>', $data['From']);
|
||||
$this->assertEquals('Test', $data['Subject']);
|
||||
$this->assertEquals('Content', $data['HtmlBody']);
|
||||
|
||||
$this->assertContains('Accept: application/json', $this->container['httpClient']->getHeaders());
|
||||
$this->assertContains('X-Postmark-Server-Token: ', $this->container['httpClient']->getHeaders());
|
||||
}
|
||||
|
||||
public function testHandlePayload()
|
||||
{
|
||||
$w = new PostmarkWebhook($this->container);
|
||||
$w = new Postmark($this->container);
|
||||
$p = new Project($this->container);
|
||||
$pp = new ProjectPermission($this->container);
|
||||
$u = new User($this->container);
|
||||
@@ -26,20 +49,20 @@ class PostmarkWebhookTest extends Base
|
||||
$this->assertEquals(2, $p->create(array('name' => 'test2', 'identifier' => 'TEST1')));
|
||||
|
||||
// Empty payload
|
||||
$this->assertFalse($w->parsePayload(array()));
|
||||
$this->assertFalse($w->receiveEmail(array()));
|
||||
|
||||
// Unknown user
|
||||
$this->assertFalse($w->parsePayload(array('From' => 'a@b.c', 'Subject' => 'Email task', 'MailboxHash' => 'foobar', 'TextBody' => 'boo')));
|
||||
$this->assertFalse($w->receiveEmail(array('From' => 'a@b.c', 'Subject' => 'Email task', 'MailboxHash' => 'foobar', 'TextBody' => 'boo')));
|
||||
|
||||
// Project not found
|
||||
$this->assertFalse($w->parsePayload(array('From' => 'me@localhost', 'Subject' => 'Email task', 'MailboxHash' => 'test', 'TextBody' => 'boo')));
|
||||
$this->assertFalse($w->receiveEmail(array('From' => 'me@localhost', 'Subject' => 'Email task', 'MailboxHash' => 'test', 'TextBody' => 'boo')));
|
||||
|
||||
// User is not member
|
||||
$this->assertFalse($w->parsePayload(array('From' => 'me@localhost', 'Subject' => 'Email task', 'MailboxHash' => 'test1', 'TextBody' => 'boo')));
|
||||
$this->assertFalse($w->receiveEmail(array('From' => 'me@localhost', 'Subject' => 'Email task', 'MailboxHash' => 'test1', 'TextBody' => 'boo')));
|
||||
$this->assertTrue($pp->addMember(2, 2));
|
||||
|
||||
// The task must be created
|
||||
$this->assertTrue($w->parsePayload(array('From' => 'me@localhost', 'Subject' => 'Email task', 'MailboxHash' => 'test1', 'TextBody' => 'boo')));
|
||||
$this->assertTrue($w->receiveEmail(array('From' => 'me@localhost', 'Subject' => 'Email task', 'MailboxHash' => 'test1', 'TextBody' => 'boo')));
|
||||
|
||||
$task = $tf->getById(1);
|
||||
$this->assertNotEmpty($task);
|
||||
@@ -51,7 +74,7 @@ class PostmarkWebhookTest extends Base
|
||||
|
||||
public function testHtml2Markdown()
|
||||
{
|
||||
$w = new PostmarkWebhook($this->container);
|
||||
$w = new Postmark($this->container);
|
||||
$p = new Project($this->container);
|
||||
$pp = new ProjectPermission($this->container);
|
||||
$u = new User($this->container);
|
||||
@@ -62,7 +85,7 @@ class PostmarkWebhookTest extends Base
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test2', 'identifier' => 'TEST1')));
|
||||
$this->assertTrue($pp->addMember(1, 2));
|
||||
|
||||
$this->assertTrue($w->parsePayload(array('From' => 'me@localhost', 'Subject' => 'Email task', 'MailboxHash' => 'test1', 'TextBody' => 'boo', 'HtmlBody' => '<p><strong>boo</strong></p>')));
|
||||
$this->assertTrue($w->receiveEmail(array('From' => 'me@localhost', 'Subject' => 'Email task', 'MailboxHash' => 'test1', 'TextBody' => 'boo', 'HtmlBody' => '<p><strong>boo</strong></p>')));
|
||||
|
||||
$task = $tf->getById(1);
|
||||
$this->assertNotEmpty($task);
|
||||
@@ -71,7 +94,7 @@ class PostmarkWebhookTest extends Base
|
||||
$this->assertEquals('**boo**', $task['description']);
|
||||
$this->assertEquals(2, $task['creator_id']);
|
||||
|
||||
$this->assertTrue($w->parsePayload(array('From' => 'me@localhost', 'Subject' => 'Email task', 'MailboxHash' => 'test1', 'TextBody' => '**boo**', 'HtmlBody' => '')));
|
||||
$this->assertTrue($w->receiveEmail(array('From' => 'me@localhost', 'Subject' => 'Email task', 'MailboxHash' => 'test1', 'TextBody' => '**boo**', 'HtmlBody' => '')));
|
||||
|
||||
$task = $tf->getById(2);
|
||||
$this->assertNotEmpty($task);
|
||||
Reference in New Issue
Block a user