kopia lustrzana https://github.com/newroco/mail2deck
Merge branch 'master' of github.com:newroco/mail2deck
# Conflicts: # config.phppull/25/head
commit
5c60208eb0
|
@ -0,0 +1,3 @@
|
|||
config.php
|
||||
vendor/
|
||||
.idea/
|
53
README.md
53
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: <code>bot@ncserver.com</code>
|
||||
|
||||
### 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:
|
||||
<code>Update website logo b-'Website' s-'To do'</code>
|
||||
<code>Update website logo b-'website' s-'to do'</code>
|
||||
|
||||
*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: <code>bot+Website@ncserver.com</code>
|
||||
### 2.2: Set the board in the email address
|
||||
At the end of the email address prefix (before @) add "+website"
|
||||
|
||||
Example: <code>bot+website@ncserver.com</code>
|
||||
|
||||
* *If board has multiple words e.g. <code>"some project"</code>, you'll have to send the email to <code>bot+some+project@ncserver.com</code>*
|
||||
|
||||
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.<br>
|
||||
__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:<br>
|
||||
```
|
||||
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.<br>
|
||||
```
|
||||
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:
|
||||
<code>*/5 * * * * /usr/bin/php /home/incoming/mail2deck/index.php >/dev/null 2>&1</code>
|
||||
### Finish
|
||||
|
||||
## Finish
|
||||
Now __mail2deck__ will add new cards every five minutes if new emails are received.
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"require": {
|
||||
"league/html-to-markdown": "^5.1"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
define("NC_SERVER", "localhost"); // https://server.domain (without "https://" attachments will not be created)
|
||||
define("NC_USER", "deckbot");
|
||||
define("NC_PASSWORD", "****");
|
||||
define("MAIL_SERVER", "localhost"); // server.domain
|
||||
define("MAIL_SERVER_FLAGS", "/novalidate-cert"); // flags needed to connect to server. Refer to https://www.php.net/manual/en/function.imap-open.php for a list of valid flags.
|
||||
define("MAIL_SERVER_PORT", "143");
|
||||
define("MAIL_USER", "incoming");
|
||||
define("MAIL_PASSWORD", "****");
|
||||
define("DECODE_SPECIAL_CHARACTERS", true); //requires mbstring, if false special characters (like öäüß) won't be displayed correctly
|
||||
define("ASSIGN_SENDER", true); // if true, sender will be assigned to card if has NC account
|
||||
define("MAIL_NOTIFICATION", true); // if true, send notifications when a new card was created or an error occured
|
||||
?>
|
102
index.php
102
index.php
|
@ -1,26 +1,25 @@
|
|||
<?php
|
||||
error_reporting(E_ERROR | E_PARSE);
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
require_once("config.php");
|
||||
require_once('lib/DeckClass.php');
|
||||
require_once('lib/MailClass.php');
|
||||
require_once('lib/ConvertToMD.php');
|
||||
|
||||
$inbox = imap_open("{" . MAIL_SERVER . "/imap" . MAIL_SERVER_FLAGS . "}INBOX", MAIL_USER, MAIL_PASSWORD)
|
||||
or die("can't connect:" . imap_last_error());
|
||||
|
||||
$emails = imap_search($inbox, 'UNSEEN');
|
||||
$inbox = new MailClass();
|
||||
$emails = $inbox->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);
|
||||
?>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
use League\HTMLToMarkdown\HtmlConverter;
|
||||
|
||||
class ConvertToMD {
|
||||
protected $html;
|
||||
|
||||
public function __construct($html) {
|
||||
$this->converter = new HtmlConverter([
|
||||
'strip_tags' => true,
|
||||
'remove_nodes' => 'title'
|
||||
]);
|
||||
$this->html = $html;
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
return $this->converter->convert($this->html);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,117 +1,137 @@
|
|||
<?php
|
||||
|
||||
class DeckClass {
|
||||
protected function apiCall($request, $endpoint, $data){
|
||||
$curl = curl_init();
|
||||
private $responseCode;
|
||||
|
||||
$headers = [
|
||||
"OCS-APIRequest: true"
|
||||
];
|
||||
|
||||
// set CURLOPTs commmon to all HTTP methods
|
||||
$options = [
|
||||
CURLOPT_USERPWD => 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;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
class MailClass {
|
||||
private $inbox;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->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 = "<h1>You created a new issue on board {$response->boardTitle}.</h1><p>Check out this <a href=\"" . NC_SERVER . "/index.php/apps/deck/#/board/{$response->board}/card/{$response->id}" . "\">link</a> to see your newly created card.</p>";
|
||||
$subject = 'An issue has been reported!';
|
||||
} else {
|
||||
$body = "<h1>There was a problem creating your new card.</h1><p>Make sure you set up the board correctly.</p>";
|
||||
$subject = "Your issue has not been reported!";
|
||||
}
|
||||
|
||||
$message = "<html>";
|
||||
$message .= "<head><title>Mail2Deck response</title></head>";
|
||||
$message .= "<body>$body</body>";
|
||||
$message .= "</html>";
|
||||
|
||||
mail($sender, $subject, $message, $headers);
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue