kopia lustrzana https://github.com/newroco/mail2deck
Add ability to assign card to board based on submitter email address domain
rodzic
d77fda5baf
commit
8484d6998d
|
@ -15,5 +15,5 @@ define("DECODE_SPECIAL_CHARACTERS", true); //requires mbstring, if false special
|
|||
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
|
||||
define("DELETE_MAIL_AFTER_PROCESSING", true);
|
||||
define("NC_DEFAULT_BOARD","Support"); //default Board to use in case it's not sent via email
|
||||
define("NC_BOARD",["DEFAULT_BOARD"=>"Support"]); //default Board to use in case it's not sent via email
|
||||
define("MAIL_SUPPORT","");//If not empty, use this value to send to the Support team: card url, the description and who submitted the request.
|
121
index.php
121
index.php
|
@ -6,6 +6,8 @@ require_once(__DIR__ . '/config.php');
|
|||
use Mail2Deck\MailClass;
|
||||
use Mail2Deck\DeckClass;
|
||||
use Mail2Deck\ConvertToMD;
|
||||
use Mail2Deck\AttachmentClass;
|
||||
use Mail2Deck\CreateCardClass;
|
||||
|
||||
$inbox = new MailClass();
|
||||
$emails = $inbox->getNewMessages();
|
||||
|
@ -22,120 +24,29 @@ for ($j = 0; $j < count($emails) && $j < 5; $j++) {
|
|||
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++) {
|
||||
if ($structure->parts[$i]->ifdparameters) {
|
||||
foreach ($structure->parts[$i]->dparameters as $object) {
|
||||
if (strtolower($object->attribute) == 'filename') {
|
||||
$attachments[$i]['is_attachment'] = true;
|
||||
$attachments[$i]['filename'] = $object->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($structure->parts[$i]->ifparameters) {
|
||||
foreach ($structure->parts[$i]->parameters as $object) {
|
||||
if (strtolower($object->attribute) == 'name') {
|
||||
$attachments[$i]['is_attachment'] = true;
|
||||
$attachments[$i]['name'] = $object->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($attachments[$i]['is_attachment']) {
|
||||
$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']);
|
||||
}
|
||||
elseif ($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
|
||||
$attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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(getcwd() . '/attachments/' . $filename, "w+");
|
||||
fwrite($fp, $attachments[$i]['attachment']);
|
||||
fclose($fp);
|
||||
array_push($attNames, $attachments[$i]['filename']);
|
||||
}
|
||||
}
|
||||
|
||||
//Check for attachment
|
||||
$attclass= new AttachmentClass();
|
||||
$attNames = $attclass->Attachment($structure,$inbox, $emails[$j]);
|
||||
$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 {
|
||||
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);
|
||||
//Create Card
|
||||
$createCardClass= new CreateCardClass();
|
||||
$board = $createCardClass->extractBoardName($overview);
|
||||
|
||||
$data = new stdClass();
|
||||
$data->title = DECODE_SPECIAL_CHARACTERS ? mb_decode_mimeheader($overview->subject) : $overview->subject;
|
||||
$data->type = "plain";
|
||||
$data->order = -time();
|
||||
$body = $inbox->fetchMessageBody($emails[$j], 1.2);
|
||||
|
||||
if (!strlen($body) > 0) {
|
||||
$body = $inbox->fetchMessageBody($emails[$j], 1);
|
||||
}
|
||||
if(count($attachments)) {
|
||||
$data->attachments = $attNames;
|
||||
$description = DECODE_SPECIAL_CHARACTERS ? quoted_printable_decode($body) : $body;
|
||||
} else {
|
||||
$description = DECODE_SPECIAL_CHARACTERS ? quoted_printable_decode($body) : $body;
|
||||
}
|
||||
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;
|
||||
$data = $createCardClass->createMailData($overview, $mailSender);
|
||||
$body = $createCardClass->fetchMailBody($inbox, $emails[$j]);
|
||||
|
||||
$newcard = new DeckClass();
|
||||
if (strpos($data->title, "RE: ") !== false || strpos($data->title, "Fwd") !== false || strpos($data->title, "FW:") !== false || strpos($data->title, "Re:") !== false) {
|
||||
$cleanedSubject = preg_replace('/^(Re: |RE: |Fwd: |FW: )\s*/i', '', $data->title);
|
||||
}else{
|
||||
$cleanedSubject = $newcard->findOriginalSubject(strip_tags($data->description));
|
||||
}
|
||||
$data->attachments = $attNames;
|
||||
$data->description = $createCardClass->mailDescription($body, $base64encode, $attNames);
|
||||
|
||||
$existingCardId = $newcard->findCardBySubject($cleanedSubject);
|
||||
$mailSender->origin .= "{$overview->reply_to[0]->mailbox}@{$overview->reply_to[0]->host}";
|
||||
$mailSender->userId = $overview->reply_to[0]->mailbox;
|
||||
$mailSender->host = $overview->reply_to[0]->host;
|
||||
|
||||
if ($existingCardId) {
|
||||
$cleanedDescription = $newcard->extractForwardedContent($data->description);
|
||||
$response = $newcard->addCommentToCard($existingCardId, $cleanedDescription);
|
||||
error_log("Comment added with response: " . json_encode($response));
|
||||
}else{
|
||||
$response = $newcard->addCard($data, $mailSender->origin);
|
||||
error_log("New card created with response: " . json_encode($response));
|
||||
|
||||
if(MAIL_NOTIFICATION) {
|
||||
if($response) {
|
||||
$inbox->reply($mailSender->origin, $response);
|
||||
} else {
|
||||
$inbox->reply($mailSender->origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!$response) {
|
||||
foreach($attNames as $attachment) unlink(getcwd() . "/attachments/" . $attachment);
|
||||
}
|
||||
$cleanedSubject = $createCardClass->cleanedSubject($data->title, $data->description, $newcard);
|
||||
$createCardClass->createCard($newcard, $data, $mailSender, $cleanedSubject, $inbox);
|
||||
|
||||
//remove email after processing
|
||||
if(DELETE_MAIL_AFTER_PROCESSING) {
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace Mail2Deck;
|
||||
|
||||
class AttachmentClass {
|
||||
|
||||
function Attachment($structure,$inbox, $emails){
|
||||
$attachments = array();
|
||||
$attNames = array();
|
||||
if (isset($structure->parts) && count($structure->parts)) {
|
||||
for ($i = 0; $i < count($structure->parts); $i++) {
|
||||
$parts =$structure->parts[$i];
|
||||
if ($parts->ifdparameters || $parts->ifparameters) {
|
||||
$parameters = $parts->ifdparameters ? $parts->dparameters : $parts->parameters;
|
||||
$attributeName = $parts->ifdparameters ? 'filename' : 'name';
|
||||
|
||||
foreach ($parameters as $object) {
|
||||
if (strtolower($object->attribute) == strtolower($attributeName)) {
|
||||
$attachments[$i]['is_attachment'] = true;
|
||||
$attachments[$i][$attributeName] = $object->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($attachments[$i]['is_attachment']) {
|
||||
$attachments[$i]['attachment'] = $inbox->fetchMessageBody($emails, $i+1);
|
||||
if ($parts->encoding == 3) { // 3 = BASE64
|
||||
$attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
|
||||
}
|
||||
elseif ($parts->encoding == 4) { // 4 = QUOTED-PRINTABLE
|
||||
$attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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(getcwd() . '/attachments/' . $filename, "w+");
|
||||
fwrite($fp, $attachments[$i]['attachment']);
|
||||
fclose($fp);
|
||||
|
||||
array_push($attNames, $attachments[$i]['filename']);
|
||||
}
|
||||
}
|
||||
return $attNames;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
namespace Mail2Deck;
|
||||
|
||||
class CreateCardClass{
|
||||
|
||||
function extractBoardName($overview){
|
||||
$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 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);
|
||||
return $board;
|
||||
}
|
||||
|
||||
function createMailData($overview, $data) {
|
||||
$data->title = DECODE_SPECIAL_CHARACTERS ? mb_decode_mimeheader($overview->subject) : $overview->subject;
|
||||
$data->type = "plain";
|
||||
$data->order = -time();
|
||||
return $data;
|
||||
}
|
||||
|
||||
function fetchMailBody($inbox, $emailId) {
|
||||
$body = $inbox->fetchMessageBody($emailId, 1.2);
|
||||
if (!strlen($body) > 0) {
|
||||
$body = $inbox->fetchMessageBody($emailId, 1);
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
function mailDescription ($body, $base64encode, $attachments) {
|
||||
$description = DECODE_SPECIAL_CHARACTERS ? quoted_printable_decode($body) : $body;
|
||||
if ($base64encode) {
|
||||
$description = base64_decode($description);
|
||||
}
|
||||
if ($description != strip_tags($description)) {
|
||||
$description = (new ConvertToMD($description))->execute();
|
||||
}
|
||||
if (!empty($attachments)) {
|
||||
foreach ($attachments as $attachment) {
|
||||
$filePath = NC_SERVER .'/remote.php/dav/files/'.NC_USER.'/Deck/'.$attachment;
|
||||
$description = preg_replace('/!\[' . preg_quote($attachment, '/') . '\]\(cid:[^)]+\)/',"[$attachment]($filePath)", $description);
|
||||
}
|
||||
}
|
||||
|
||||
return $description;
|
||||
}
|
||||
|
||||
function cleanedSubject($subject, $description, $newcard) {
|
||||
if (strpos($subject, "RE: ") !== false || strpos($subject, "Fwd") !== false || strpos($subject, "FW:") !== false || strpos($subject, "Re:") !== false) {
|
||||
$cleanedSubject = preg_replace('/^(Re: |RE: |Fwd: |FW: )\s*/i', '', $subject);
|
||||
}else{
|
||||
$cleanedSubject = $newcard->findOriginalSubject(strip_tags($description));
|
||||
}
|
||||
return $cleanedSubject;
|
||||
}
|
||||
|
||||
function createCard($newcard, $data, $mailSender, $cleanedSubject, $inbox){
|
||||
$existingCardId = $newcard->findCardBySubject($cleanedSubject);
|
||||
$mailSender->origin .= "{$mailSender->userId}@{$mailSender->host}";
|
||||
|
||||
if (!$existingCardId) {
|
||||
$response = $newcard->addCard($data, $mailSender->origin, $mailSender->host);
|
||||
error_log("New card created with response: " . json_encode($response));
|
||||
|
||||
if (MAIL_NOTIFICATION) {
|
||||
if (!$response) {
|
||||
$inbox->reply($mailSender->origin);
|
||||
}
|
||||
$inbox->reply($mailSender->origin, $response);
|
||||
}
|
||||
}else{
|
||||
$cleanedDescription = $newcard->extractForwardedContent($data->description);
|
||||
$response = $newcard->addCommentToCard($existingCardId, $cleanedDescription);
|
||||
error_log("Comment added with response: " . json_encode($response));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,21 @@ class DeckClass {
|
|||
private function apiCall($request, $endpoint, $data = null, $attachment = false, $userapi = false){
|
||||
$curl = curl_init();
|
||||
if($data && !$attachment) {
|
||||
$endpoint .= '?' . http_build_query($data);
|
||||
if ($request === "PUT") {
|
||||
if (is_array($data) || is_object($data)) {
|
||||
$jsonData = json_encode($data);
|
||||
} else {
|
||||
$jsonData = $data;
|
||||
}
|
||||
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $jsonData);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'Content-Length: ' . strlen($jsonData)
|
||||
]);
|
||||
} else {
|
||||
$endpoint .= '?' . http_build_query($data);
|
||||
}
|
||||
}
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => $endpoint,
|
||||
|
@ -27,15 +41,28 @@ class DeckClass {
|
|||
));
|
||||
|
||||
if ($request === 'POST') {
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, array_merge(
|
||||
array(
|
||||
'Accept: application/json',
|
||||
'OCS-APIRequest: true',
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Basic ' . base64_encode(NC_ADMIN_USER . ':' . NC_ADMIN_PASSWORD),
|
||||
)
|
||||
));
|
||||
if ($attachment){
|
||||
curl_setopt($curl, CURLOPT_POST, true);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, array_merge(
|
||||
array(
|
||||
'Accept: application/json',
|
||||
'Content-Type: multipart/form-data',
|
||||
'Authorization: Basic ' . base64_encode(NC_USER . ':' . NC_PASSWORD),
|
||||
)
|
||||
));
|
||||
curl_setopt($curl, CURLOPT_USERPWD, NC_USER . ":" . NC_PASSWORD);
|
||||
}else{
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, array_merge(
|
||||
array(
|
||||
'Accept: application/json',
|
||||
'OCS-APIRequest: true',
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Basic ' . base64_encode(NC_USER . ':' . NC_PASSWORD),
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$response = curl_exec($curl);
|
||||
|
@ -49,13 +76,20 @@ class DeckClass {
|
|||
return json_decode($response);
|
||||
}
|
||||
|
||||
public function getParameters($params, $boardFromMail = null) {// get the board and the stack
|
||||
public function getParameters($params, $boardFromMail = null, $mail_domain) {// 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);
|
||||
}else{
|
||||
$boardFromMail = NC_DEFAULT_BOARD;
|
||||
$emailSenderDomain = '@'.$mail_domain;
|
||||
if($emailSenderDomain === SUBMITTER_ADDRESS["DOMAIN_OA"]){
|
||||
$boardFromMail = NC_BOARD["OA_BOARD"];
|
||||
}else if($emailSenderDomain === SUBMITTER_ADDRESS["DOMAIN_CA"]){
|
||||
$boardFromMail = NC_BOARD["CA_BOARD"];
|
||||
}else{
|
||||
$boardFromMail = NC_BOARD["DEFAULT_BOARD"];
|
||||
}
|
||||
}
|
||||
if(preg_match('/s-"([^"]+)"/', $params, $m) || preg_match("/s-'([^']+)'/", $params, $m)) {
|
||||
$stackFromMail = $m[1];
|
||||
|
@ -108,8 +142,8 @@ class DeckClass {
|
|||
}
|
||||
|
||||
//Add a new card
|
||||
public function addCard($data, $user, $board = null) {
|
||||
$params = $this->getParameters($data->title, $board);
|
||||
public function addCard($data, $user,$mail_domain, $board = null) {
|
||||
$params = $this->getParameters($data->title, $board, $mail_domain);
|
||||
if($params) {
|
||||
$data->title = $params->newTitle;
|
||||
$data->duedate = $params->dueDate;
|
||||
|
@ -138,8 +172,14 @@ class DeckClass {
|
|||
$data = array(
|
||||
'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);
|
||||
$response = $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);
|
||||
|
||||
if (isset($response->extendedData->fileid)) {
|
||||
$imageUrl = NC_SERVER . "/index.php/apps/files/?dir=/Deck&fileid=" . $response->extendedData->fileid;
|
||||
}
|
||||
|
||||
unlink($file);
|
||||
return $imageUrl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue