diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cf76f7b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+config.php
+vendor/
+.idea/
\ No newline at end of file
diff --git a/README.md b/README.md
index f9c509c..10c76af 100644
--- a/README.md
+++ b/README.md
@@ -1,26 +1,32 @@
# mail2deck
Provides an "email in" solution for the Nextcloud Deck app
-## A. For users
+# 🚀 A. For users
Follow the above steps to add a new card from email.
* Deck Bot is the user who will create the cards and it will be set up by your nextcloud admin.
* In this tutorial email address for Deck Bot will be: bot@ncserver.com
-### 1) Assign Deck Bot to the board.
-### 2) Mail subject & content
+## 1) Assign Deck Bot to the board.
+Deck Bot must be assigned and must have edit permission inside the board.
+
+## 2) Mail subject & content
Let's assume you want to add a card with title "Update website logo" on board "Website" and stack "To do".
You can do this in two ways.
-#### 2.1: Set stack and board in the email subject
+### 2.1: Set stack and board in the email subject
Here's how the email subject should look like:
-Update website logo b-'Website' s-'To do'
+Update website logo b-'website' s-'to do'
-*You can use single or double quotes.*
+* *You can use single or double quotes.*
-#### 2.2: Set the board in the email address
-At the end of the email address prefix (before @) add "+Website"
+* *Case-insensitive for board and stack respectively.*
-Example: bot+Website@ncserver.com
+### 2.2: Set the board in the email address
+At the end of the email address prefix (before @) add "+website"
+
+Example: bot+website@ncserver.com
+
+* *If board has multiple words e.g. "some project"
, you'll have to send the email to bot+some+project@ncserver.com
*
In this case, if you don't specify the stack in the email subject, the card will be added in the first stack (if it exists).
@@ -28,37 +34,40 @@ Note:
* Email content will be card description
* You can add attachments in the email and those will be integrated in the created card
-## B. For NextCloud admins to setup
-### Requirements
+# ⚙️ B. For NextCloud admins to setup
+## Requirements
This app requires php-curl, php-mbstring ,php-imap and some sort of imap server (e.g. Postfix with Courier).
-### NC new user
+## NC new user
Create a new user from User Management on your NC server, which will have to function as a bot. We chose to call him *deckbot*, but you can call it however you want.
__Note__: that you have to assign *deckbot* on each board you want to add new cards from email.
-### Configure Email
-#### Option 1 - Set up Postfix for incoming email
+## Configure Email
+### Option 1 - Set up Postfix for incoming email
You can setup Posfix mail server folowing the instructions on [Posfix setup](https://docs.gitlab.com/ee/administration/reply_by_email_postfix_setup.html), and after that add "+" delimiter (which separe the user from the board in the email address) using the command:
```
sudo postconf -e "recipient_delimiter = +"
```
-#### Option 2 - Use an existing email server
+### Option 2 - Use an existing email server
This could be any hosted email service. The only requirement is that you can connect to it via the IMAP protocol.
*Please note this option may not be as flexible as a self-hosted server. For example your email service may not support the "+"delimiter for directing messages to a specific board.*
-### Download and install
+## Download and install
If using a self-hosted Postfix server, clone this repository into the home directory of the *incoming* user. If not self-hosting, you may need to create a new user on your system and adjust the commands in future steps to match that username.
```
-cd /home/incoming/
-git clone https://github.com/putt1ck/mail2deck.git mail2deck
+su - incoming
+git clone https://github.com/newroco/mail2deck.git mail2deck
```
-Edit the config file as you need:
+Create config.php file and edit it for your needs:
```
-sudo nano /home/incoming/mail2deck/config.php
+cd /home/incoming/mail2deck
+cp config.example.php config.php
+sudo vim config.php
```
*You can refer to https://www.php.net/manual/en/function.imap-open.php for setting the value of MAIL_SERVER_FLAGS*
-### Add a cronjob which will run mail2deck.
+## Add a cronjob which will run mail2deck.
```
sudo crontab -u incoming -e
```
Add the following line in the opened file:
*/5 * * * * /usr/bin/php /home/incoming/mail2deck/index.php >/dev/null 2>&1
-### Finish
+
+## Finish
Now __mail2deck__ will add new cards every five minutes if new emails are received.
diff --git a/attachments/attachment.txt b/attachments/attachment.txt
deleted file mode 100644
index e69de29..0000000
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..5efac28
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,5 @@
+{
+ "require": {
+ "league/html-to-markdown": "^5.1"
+ }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..c693662
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,108 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "55d22588d74c4cd2af8b00fa004ab06f",
+ "packages": [
+ {
+ "name": "league/html-to-markdown",
+ "version": "5.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/html-to-markdown.git",
+ "reference": "e0fc8cf07bdabbcd3765341ecb50c34c271d64e1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/e0fc8cf07bdabbcd3765341ecb50c34c271d64e1",
+ "reference": "e0fc8cf07bdabbcd3765341ecb50c34c271d64e1",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-xml": "*",
+ "php": "^7.2.5 || ^8.0"
+ },
+ "require-dev": {
+ "mikehaertl/php-shellcommand": "^1.1.0",
+ "phpstan/phpstan": "^0.12.99",
+ "phpunit/phpunit": "^8.5 || ^9.2",
+ "scrutinizer/ocular": "^1.6",
+ "unleashedtech/php-coding-standard": "^2.7",
+ "vimeo/psalm": "^4.22"
+ },
+ "bin": [
+ "bin/html-to-markdown"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\HTMLToMarkdown\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Colin O'Dell",
+ "email": "colinodell@gmail.com",
+ "homepage": "https://www.colinodell.com",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Nick Cernis",
+ "email": "nick@cern.is",
+ "homepage": "http://modernnerd.net",
+ "role": "Original Author"
+ }
+ ],
+ "description": "An HTML-to-markdown conversion helper for PHP",
+ "homepage": "https://github.com/thephpleague/html-to-markdown",
+ "keywords": [
+ "html",
+ "markdown"
+ ],
+ "support": {
+ "issues": "https://github.com/thephpleague/html-to-markdown/issues",
+ "source": "https://github.com/thephpleague/html-to-markdown/tree/5.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.colinodell.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.paypal.me/colinpodell/10.00",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/colinodell",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/league/html-to-markdown",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-03-02T17:24:08+00:00"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": [],
+ "plugin-api-version": "2.1.0"
+}
diff --git a/config.example.php b/config.example.php
new file mode 100644
index 0000000..52c6365
--- /dev/null
+++ b/config.example.php
@@ -0,0 +1,13 @@
+
diff --git a/index.php b/index.php
index 9d10a3b..1d8fba6 100644
--- a/index.php
+++ b/index.php
@@ -1,26 +1,25 @@
getNewMessages();
if ($emails)
- for ($j = 0; $j <= count($emails) && $j <= 4; $j++) {
- $structure = imap_fetchstructure($inbox, $emails[$j]);
+ for ($j = 0; $j < count($emails) && $j < 5; $j++) {
+ $structure = $inbox->fetchMessageStructure($emails[$j]);
+ $base64encode = false;
+ if($structure->encoding == 3) {
+ $base64encode = true; // BASE64
+ }
$attachments = array();
+ $attNames = array();
if (isset($structure->parts) && count($structure->parts)) {
for ($i = 0; $i < count($structure->parts); $i++) {
- $attachments[$i] = array(
- 'is_attachment' => false,
- 'filename' => '',
- 'name' => '',
- 'attachment' => ''
- );
-
if ($structure->parts[$i]->ifdparameters) {
foreach ($structure->parts[$i]->dparameters as $object) {
if (strtolower($object->attribute) == 'filename') {
@@ -40,7 +39,7 @@ if ($emails)
}
if ($attachments[$i]['is_attachment']) {
- $attachments[$i]['attachment'] = imap_fetchbody($inbox, $emails[$j], $i+1);
+ $attachments[$i]['attachment'] = $inbox->fetchMessageBody($emails[$j], $i+1);
if ($structure->parts[$i]->encoding == 3) { // 3 = BASE64
$attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
}
@@ -50,51 +49,66 @@ if ($emails)
}
}
}
- for ($i = 1; $i < count($attachments); $i++) {
+ for ($i = 1; $i <= count($attachments); $i++) {
+ if(! file_exists(getcwd() . '/attachments')) {
+ mkdir(getcwd() . '/attachments');
+ }
if ($attachments[$i]['is_attachment'] == 1) {
$filename = $attachments[$i]['name'];
if (empty($filename)) $filename = $attachments[$i]['filename'];
- $fp = fopen("./attachments/" . $filename, "w+");
+ $fp = fopen(getcwd() . '/attachments/' . $filename, "w+");
fwrite($fp, $attachments[$i]['attachment']);
fclose($fp);
+ array_push($attNames, $attachments[$i]['filename']);
}
}
- $hasAttachment = false;
- for ($i = 0; $i < count($attachments); $i++) {
- if ($attachments[$i]['is_attachment'] != '') {
- $hasAttachment = true;
- }
- }
-
- $overview = imap_headerinfo($inbox, $emails[$j]);
- $toAddress = strrev($overview->toaddress);
- if(preg_match('/@([^+]+)/', $toAddress, $m)) {
- global $boardName;
- $boardName = strrev($m[1]);
- }
- if ($hasAttachment) {
- $message = imap_fetchbody($inbox, $emails[$j], 1.1);
+ $overview = $inbox->headerInfo($emails[$j]);
+ $board = null;
+ if(isset($overview->{'X-Original-To'}) && strstr($overview->{'X-Original-To'}, '+')) {
+ $board = strstr(substr($overview->{'X-Original-To'}, strpos($overview->{'X-Original-To'}, '+') + 1), '@', true);
} else {
- $message = imap_fetchbody($inbox, $emails[$j], 1);
+ if(strstr($overview->to[0]->mailbox, '+')) {
+ $board = substr($overview->to[0]->mailbox, strpos($overview->to[0]->mailbox, '+') + 1);
+ }
+ };
+
+ if(strstr($board, '+')) $board = str_replace('+', ' ', $board);
+
+ $data = new stdClass();
+ $data->title = DECODE_SPECIAL_CHARACTERS ? mb_decode_mimeheader($overview->subject) : $overview->subject;
+ $data->type = "plain";
+ $data->order = -time();
+ if(count($attachments)) {
+ $data->attachments = $attNames;
+ $description = DECODE_SPECIAL_CHARACTERS ? quoted_printable_decode($inbox->fetchMessageBody($emails[$j], 1.1)) : $inbox->fetchMessageBody($emails[$j], 1.1);
+ } else {
+ $description = DECODE_SPECIAL_CHARACTERS ? quoted_printable_decode($inbox->fetchMessageBody($emails[$j], 1)) : $inbox->fetchMessageBody($emails[$j], 1);
}
- $mailData = new stdClass();
- $mailData->mailSubject = DECODE_SPECIAL_CHARACTERS ? mb_decode_mimeheader($overview->subject) : $overview->subject;
- $mailData->mailMessage = DECODE_SPECIAL_CHARACTERS ? quoted_printable_decode($message) : $message;
- $mailData->from = $overview->from[0]->mailbox . '@' . $overview->from[0]->host;
+ if($base64encode) {
+ $description = base64_decode($description);
+ }
+ if($description != strip_tags($description)) {
+ $description = (new ConvertToMD($description))->execute();
+ }
+ $data->description = $description;
+ $mailSender = new stdClass();
+ $mailSender->userId = $overview->reply_to[0]->mailbox;
$newcard = new DeckClass();
- $newcard->getParameters();
- $newcard->addCard($data);
+ $response = $newcard->addCard($data, $mailSender, $board);
+ $mailSender->userId .= "@{$overview->reply_to[0]->host}";
- if ($hasAttachment) {
- for ($i = 1; $i <= count($attachments); $i++) {
- $mailData->fileAttached[$i] = $attachments[$i]['name'];
+ if(MAIL_NOTIFICATION) {
+ if($response) {
+ $inbox->reply($mailSender->userId, $response);
+ } else {
+ $inbox->reply($mailSender->userId);
}
- $newcard->addAttachment($data);
+ }
+ if(!$response) {
+ foreach($attNames as $attachment) unlink(getcwd() . "/attachments/" . $attachment);
}
}
-
-imap_close($inbox);
?>
diff --git a/lib/ConvertToMD.php b/lib/ConvertToMD.php
new file mode 100644
index 0000000..0549e19
--- /dev/null
+++ b/lib/ConvertToMD.php
@@ -0,0 +1,22 @@
+converter = new HtmlConverter([
+ 'strip_tags' => true,
+ 'remove_nodes' => 'title'
+ ]);
+ $this->html = $html;
+ }
+
+ public function execute()
+ {
+ return $this->converter->convert($this->html);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/lib/DeckClass.php b/lib/DeckClass.php
index 45d6cc5..802a821 100644
--- a/lib/DeckClass.php
+++ b/lib/DeckClass.php
@@ -1,117 +1,137 @@
NC_USER . ":" . NC_PASSWORD,
+ private function apiCall($request, $endpoint, $data = null, $attachment = false){
+ $curl = curl_init();
+ if($data && !$attachment) {
+ $endpoint .= '?' . http_build_query($data);
+ }
+ curl_setopt_array($curl, array(
CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true,
- CURLOPT_SSLVERSION => "all",
- ];
+ CURLOPT_ENCODING => '',
+ CURLOPT_MAXREDIRS => 10,
+ CURLOPT_TIMEOUT => 0,
+ CURLOPT_FOLLOWLOCATION => true,
+ CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
+ CURLOPT_CUSTOMREQUEST => $request,
+ CURLOPT_HTTPHEADER => array(
+ 'Authorization: Basic ' . base64_encode(NC_USER . ':' . NC_PASSWORD),
+ 'OCS-APIRequest: true',
+ ),
+ ));
- // set HTTP request specific headers and options/data
- if ($request == '') {// an empty request value is used for attachments
- // add data without JSON encoding or JSON Content-Type header
- $options[CURLOPT_POST] = true;
- $options[CURLOPT_POSTFIELDS] = $data;
- } elseif ($request == "POST") {
- array_push($headers, "Content-Type: application/json");
- $options[CURLOPT_POST] = true;
- $options[CURLOPT_POSTFIELDS] = json_encode($data);
- } elseif ($request == "GET") {
- array_push($headers, "Content-Type: application/json");
- }
-
- // add headers to options
- $options[CURLOPT_HTTPHEADER] = $headers;
- curl_setopt_array($curl, $options);
+ if($request === 'POST') curl_setopt($curl, CURLOPT_POSTFIELDS, (array) $data);
$response = curl_exec($curl);
$err = curl_error($curl);
+ $this->responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
-
- if ($err) {
- echo "cURL Error #:" . $err;
- }
+ if($err) echo "cURL Error #:" . $err;
return json_decode($response);
}
- public function getParameters() {// get the board and the stack
- global $mailData;
- global $boardId;
-
- if(preg_match('/b-"([^"]+)"/', $mailData->mailSubject, $m) || preg_match("/b-'([^']+)'/", $mailData->mailSubject, $m)) {
- $boardFromMail = $m[1];
- $mailData->mailSubject = str_replace($m[0], '', $mailData->mailSubject);
- }
- if(preg_match('/s-"([^"]+)"/', $mailData->mailSubject, $m) || preg_match("/s-'([^']+)'/", $mailData->mailSubject, $m)) {
+ public function getParameters($params, $boardFromMail = null) {// get the board and the stack
+ if(!$boardFromMail) // if board is not set within the email address, look for board into email subject
+ if(preg_match('/b-"([^"]+)"/', $params, $m) || preg_match("/b-'([^']+)'/", $params, $m)) {
+ $boardFromMail = $m[1];
+ $params = str_replace($m[0], '', $params);
+ }
+ if(preg_match('/s-"([^"]+)"/', $params, $m) || preg_match("/s-'([^']+)'/", $params, $m)) {
$stackFromMail = $m[1];
- $mailData->mailSubject = str_replace($m[0], '', $mailData->mailSubject);
+ $params = str_replace($m[0], '', $params);
}
- global $boardName;
- $boards = $this->apiCall("GET", NC_SERVER . "/index.php/apps/deck/api/v1.0/boards", '');
+ $boards = $this->apiCall("GET", NC_SERVER . "/index.php/apps/deck/api/v1.0/boards");
+ $boardId = $boardName = null;
foreach($boards as $board) {
- if($board->title == $boardFromMail || $board->title == $boardName) {
+ if(strtolower($board->title) == strtolower($boardFromMail)) {
+ if(!$this->checkBotPermissions($board)) {
+ return false;
+ }
$boardId = $board->id;
+ $boardName = $board->title;
+ break;
+ }
+ }
+
+ if($boardId) {
+ $stacks = $this->apiCall("GET", NC_SERVER . "/index.php/apps/deck/api/v1.0/boards/$boardId/stacks");
+ foreach($stacks as $key => $stack)
+ if(strtolower($stack->title) == strtolower($stackFromMail)) {
+ $stackId = $stack->id;
+ break;
+ }
+ if($key == array_key_last($stacks) && !isset($stackId)) $stackId = $stacks[0]->id;
+ } else {
+ return false;
+ }
+
+ $boardStack = new stdClass();
+ $boardStack->board = $boardId;
+ $boardStack->stack = $stackId;
+ $boardStack->newTitle = $params;
+ $boardStack->boardTitle = $boardName;
+
+ return $boardStack;
+ }
+
+ public function addCard($data, $user, $board = null) {
+ $params = $this->getParameters($data->title, $board);
+
+ if($params) {
+ $data->title = $params->newTitle;
+ $card = $this->apiCall("POST", NC_SERVER . "/index.php/apps/deck/api/v1.0/boards/{$params->board}/stacks/{$params->stack}/cards", $data);
+ $card->board = $params->board;
+ $card->stack = $params->stack;
+
+ if($this->responseCode == 200) {
+ if(ASSIGN_SENDER) $this->assignUser($card, $user);
+ if($data->attachments) $this->addAttachments($card, $data->attachments);
+ $card->boardTitle = $params->boardTitle;
} else {
- echo "Board not found\n";
- }
- }
-
- $stacks = $this->apiCall("GET", NC_SERVER . "/index.php/apps/deck/api/v1.0/boards/$boardId/stacks", '');
- foreach($stacks as $stack) {
- if($stack->title == $stackFromMail) {
- global $stackId;
- $stackId = $stack->id;
- } else if (!is_numeric($stackId)) {
- global $stackId;
- $stackId = $stacks[0]->id;
+ return false;
}
+ return $card;
}
+ return false;
}
- public function addCard($data) {
- global $mailData;
- global $stackId;
-
- $data = new stdClass();
- $data->stackId = $stackId;
- $data->title = $mailData->mailSubject;
- $data->description =
-"$mailData->mailMessage
-***
-### $mailData->from
-";
- $data->type = "plain";
- $data->order = "-" . time(); // put the card to the top
-
- //create card
- $response = $this->apiCall("POST", NC_SERVER . "/index.php/apps/deck/api/v1.0/boards/1/stacks/1/cards", $data);
- global $cardId;
- $cardId = $response->id;
- }
-
- public function addAttachment($data) {
- global $mailData;
- global $cardId;
- $fullPath = getcwd() . "/attachments/"; //get full path to attachments dirctory
-
- for ($i = 1; $i < count($mailData->fileAttached); $i++) {
+ private function addAttachments($card, $attachments) {
+ $fullPath = getcwd() . "/attachments/"; //get full path to attachments directory
+ for ($i = 0; $i < count($attachments); $i++) {
+ $file = $fullPath . $attachments[$i];
$data = array(
- 'file' => new CURLFile($fullPath . $mailData->fileAttached[$i])
- );
- $this->apiCall("", NC_SERVER . "/index.php/apps/deck/api/v1.0/boards/1/stacks/1/cards/$cardId/attachments?type=deck_file", $data);
+ 'file' => new CURLFile($file)
+ );
+ $this->apiCall("POST", NC_SERVER . "/index.php/apps/deck/api/v1.0/boards/{$card->board}/stacks/{$card->stack}/cards/{$card->id}/attachments?type=file", $data, true);
+ unlink($file);
}
}
+
+ public function assignUser($card, $mailUser)
+ {
+ $board = $this->apiCall("GET", NC_SERVER . "/index.php/apps/deck/api/v1.0/boards/{$card->board}");
+ $boardUsers = array_map(function ($user) { return $user->uid; }, $board->users);
+
+ foreach($boardUsers as $user) {
+ if($user === $mailUser->userId) {
+ $this->apiCall("PUT", NC_SERVER . "/index.php/apps/deck/api/v1.0/boards/{$card->board}/stacks/{$card->stack}/cards/{$card->id}/assignUser", $mailUser);
+ break;
+ }
+ }
+ }
+
+ private function checkBotPermissions($board) {
+ foreach($board->acl as $acl)
+ if($acl->participant->uid == NC_USER && $acl->permissionEdit)
+ return true;
+
+ return false;
+ }
}
?>
diff --git a/lib/MailClass.php b/lib/MailClass.php
new file mode 100644
index 0000000..f498162
--- /dev/null
+++ b/lib/MailClass.php
@@ -0,0 +1,77 @@
+inbox = imap_open("{" . MAIL_SERVER . ":" . MAIL_SERVER_PORT . MAIL_SERVER_FLAGS . "}INBOX", MAIL_USER, MAIL_PASSWORD)
+ or die("can't connect:" . imap_last_error());
+ }
+
+ public function __destruct()
+ {
+ imap_close($this->inbox);
+ }
+
+ public function getNewMessages() {
+ return imap_search($this->inbox, 'UNSEEN');
+ }
+
+ public function fetchMessageStructure($email) {
+ return imap_fetchstructure($this->inbox, $email);
+ }
+
+ public function fetchMessageBody($email, $section) {
+ return imap_fetchbody($this->inbox, $email, $section);
+ }
+
+ public function headerInfo($email) {
+ $headerInfo = imap_headerinfo($this->inbox, $email);
+ $additionalHeaderInfo = imap_fetchheader($this->inbox, $email);
+ $infos = explode("\n", $additionalHeaderInfo);
+
+ foreach($infos as $info) {
+ $data = explode(":", $info);
+ if( count($data) == 2 && !isset($head[$data[0]])) {
+ if(trim($data[0]) === 'X-Original-To') {
+ $headerInfo->{'X-Original-To'} = trim($data[1]);
+ break;
+ }
+ }
+ }
+
+ return $headerInfo;
+ }
+
+ public function reply($sender, $response = null) {
+ $server = NC_SERVER;
+
+ if(strstr($server, "https://")) {
+ $server = str_replace('https://', '', $server);
+ } else if(strstr($server, "http://")) {
+ $server = str_replace('http://', '', $server);
+ }
+
+ $headers = array(
+ 'From' => 'no-reply@' . $server,
+ 'MIME-Version' => '1.0',
+ 'Content-Type' => 'text/html'
+ );
+
+ if($response) {
+ $body = "
Check out this board}/card/{$response->id}" . "\">link to see your newly created card.
"; + $subject = 'An issue has been reported!'; + } else { + $body = "Make sure you set up the board correctly.
"; + $subject = "Your issue has not been reported!"; + } + + $message = ""; + $message .= "