wip
This commit is contained in:
parent
08a6f7b8d0
commit
58c6f2e63f
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import {connect} from 'react-redux';
|
||||
import randomString from 'random-string';
|
||||
|
||||
import i18n from 'lib-app/i18n';
|
||||
import API from 'lib-app/api-call';
|
||||
|
@ -55,6 +56,7 @@ class AdminPanelEmailSettings extends React.Component {
|
|||
['imap-host']: '',
|
||||
['imap-user']: '',
|
||||
['imap-pass']: 'HIDDEN',
|
||||
['imap-token']: '',
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -135,7 +137,7 @@ class AdminPanelEmailSettings extends React.Component {
|
|||
<SubmitButton className="admin-panel-email-settings__submit" type="secondary"
|
||||
size="small">{i18n('SAVE')}</SubmitButton>
|
||||
<SubmitButton type="tertiary" size="small" onClick={this.testSMTP.bind(this)}>
|
||||
Test
|
||||
{i18n('TEST')}
|
||||
</SubmitButton>
|
||||
</div>
|
||||
</Form>
|
||||
|
@ -148,11 +150,12 @@ class AdminPanelEmailSettings extends React.Component {
|
|||
<FormField name="imap-host" label={i18n('IMAP_SERVER')} fieldProps={{size: 'large'}}/>
|
||||
<FormField name="imap-user" label={i18n('IMAP_USER')} fieldProps={{size: 'large'}}/>
|
||||
<FormField name="imap-pass" label={i18n('IMAP_PASSWORD')} fieldProps={{size: 'large'}}/>
|
||||
<FormField name="imap-token" label={i18n('IMAP_TOKEN')} infoMessage={i18n('IMAP_TOKEN_DESCRIPTION')} fieldProps={{size: 'large', icon: 'refresh', onIconClick: this.generateImapToken.bind(this)}}/>
|
||||
<div className="admin-panel-email-settings__server-form-buttons">
|
||||
<SubmitButton className="admin-panel-email-settings__submit" type="secondary"
|
||||
size="small">{i18n('SAVE')}</SubmitButton>
|
||||
<SubmitButton type="tertiary" size="small" onClick={this.testIMAP.bind(this)}>
|
||||
Test
|
||||
{i18n('TEST')}
|
||||
</SubmitButton>
|
||||
</div>
|
||||
</Form>
|
||||
|
@ -334,6 +337,15 @@ class AdminPanelEmailSettings extends React.Component {
|
|||
AreYouSure.openModal(i18n('WILL_RECOVER_EMAIL_TEMPLATE'), this.recoverEmailTemplate.bind(this));
|
||||
}
|
||||
|
||||
generateImapToken() {
|
||||
this.setState({
|
||||
imapForm: {
|
||||
...this.state.imapForm,
|
||||
['imap-token']: randomString({length: 20}),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
submitEmailAddress(form) {
|
||||
this.editSettings(form, 'EMAIL_SUCCESS');
|
||||
}
|
||||
|
@ -481,6 +493,7 @@ class AdminPanelEmailSettings extends React.Component {
|
|||
['imap-host']: result.data['imap-host'],
|
||||
['imap-user']: result.data['imap-user'],
|
||||
['imap-pass']: 'HIDDEN',
|
||||
['imap-token']: result.data['imap-token'],
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ class Input extends React.Component {
|
|||
password: React.PropTypes.bool,
|
||||
required: React.PropTypes.bool,
|
||||
icon: React.PropTypes.string,
|
||||
error: React.PropTypes.string
|
||||
error: React.PropTypes.string,
|
||||
onIconClick: React.PropTypes.func
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
|
@ -38,7 +39,7 @@ class Input extends React.Component {
|
|||
let icon = null;
|
||||
|
||||
if (this.props.icon) {
|
||||
icon = <span className="input__icon"><Icon name={this.props.icon} /></span>
|
||||
icon = <span className="input__icon" onClick={this.onIconClick.bind(this)}><Icon name={this.props.icon} /></span>
|
||||
}
|
||||
|
||||
return icon;
|
||||
|
@ -66,6 +67,7 @@ class Input extends React.Component {
|
|||
'input': true,
|
||||
'input_with-icon': (this.props.icon),
|
||||
'input_errored': (this.props.errored),
|
||||
'input_icon-clickable': (this.props.onIconClick),
|
||||
['input_' + this.props.size]: true,
|
||||
|
||||
[this.props.className]: (this.props.className)
|
||||
|
@ -74,6 +76,14 @@ class Input extends React.Component {
|
|||
return classNames(classes);
|
||||
}
|
||||
|
||||
onIconClick(event) {
|
||||
if(this.props.onIconClick) {
|
||||
event.preventDefault();
|
||||
this.focus();
|
||||
this.props.onIconClick(event);
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
if (this.refs.nativeInput) {
|
||||
this.refs.nativeInput.focus();
|
||||
|
|
|
@ -58,4 +58,11 @@
|
|||
border: 1px solid $primary-red;
|
||||
}
|
||||
}
|
||||
|
||||
&_icon-clickable {
|
||||
|
||||
.input__icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -144,6 +144,8 @@ export default {
|
|||
'IMAP_USER': 'IMAP User',
|
||||
'IMAP_SERVER': 'IMAP Server',
|
||||
'IMAP_PASSWORD': 'IMAP Password',
|
||||
'IMAP_TOKEN': 'IMAP Token',
|
||||
'IMAP_TOKEN_DESCRIPTION': 'Use this token to authenticate the polling request.',
|
||||
'PORT': 'Port',
|
||||
'RECAPTCHA_PUBLIC_KEY': 'Recaptcha Public Key',
|
||||
'RECAPTCHA_PRIVATE_KEY': 'Recaptcha Private Key',
|
||||
|
@ -382,6 +384,7 @@ export default {
|
|||
'LAST_90_DAYS': 'Last 90 days',
|
||||
'LAST_365_DAYS': 'Last 365 days',
|
||||
|
||||
'TEST': 'Test',
|
||||
'ACTIVITY_COMMENT_THIS': 'commented this ticket',
|
||||
'ACTIVITY_ASSIGN_THIS': 'assigned this ticket to',
|
||||
'ACTIVITY_UN_ASSIGN_THIS': 'unassigned this ticket to',
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
"ifsnop/mysqldump-php": "2.*",
|
||||
"ezyang/htmlpurifier": "^4.8",
|
||||
"codeguy/upload": "^1.3",
|
||||
"php-imap/php-imap": "^3.0"
|
||||
"php-imap/php-imap": "^3.0",
|
||||
"willdurand/email-reply-parser": "^2.8",
|
||||
"ext-fileinfo": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.7"
|
||||
|
|
|
@ -31,5 +31,6 @@ $systemControllerGroup->addController(new DisableUserSystemController);
|
|||
$systemControllerGroup->addController(new EnableUserSystemController);
|
||||
$systemControllerGroup->addController(new TestSMTPController);
|
||||
$systemControllerGroup->addController(new TestIMAPController);
|
||||
$systemControllerGroup->addController(new EmailPollingController);
|
||||
|
||||
$systemControllerGroup->finalize();
|
||||
|
|
|
@ -42,6 +42,7 @@ class EditSettingsController extends Controller {
|
|||
'imap-host',
|
||||
'imap-user',
|
||||
'imap-pass',
|
||||
'imap-token',
|
||||
'smtp-host',
|
||||
'smtp-user',
|
||||
'smtp-pass',
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
use Respect\Validation\Validator as DataValidator;
|
||||
|
||||
class EmailPolling extends Controller {
|
||||
class EmailPollingController extends Controller {
|
||||
const PATH = '/email-polling';
|
||||
const METHOD = 'POST';
|
||||
|
||||
|
@ -9,7 +10,12 @@ class EmailPolling extends Controller {
|
|||
public function validations() {
|
||||
return [
|
||||
'permission' => 'any',
|
||||
'requestData' => []
|
||||
'requestData' => [
|
||||
'token' => [
|
||||
'validation' => DataValidator::length(1, 200),
|
||||
'error' => ERRORS::INVALID_TOKEN
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -19,6 +25,10 @@ class EmailPolling extends Controller {
|
|||
$defaultLanguage = Setting::getSetting('language')->getValue();
|
||||
$defaultDepartmentId = Department::getAll()->first()->id;
|
||||
|
||||
|
||||
if(Controller::request('token') !== Setting::getSetting('imap-token')->getValue())
|
||||
throw new RequestException(ERRORS::INVALID_TOKEN);
|
||||
|
||||
if(Controller::isUserSystemEnabled())
|
||||
throw new RequestException(ERRORS::USER_SYSTEM);
|
||||
|
||||
|
@ -26,12 +36,12 @@ class EmailPolling extends Controller {
|
|||
Setting::getSetting('imap-host')->getValue(),
|
||||
Setting::getSetting('imap-user')->getValue(),
|
||||
Setting::getSetting('imap-pass')->getValue(),
|
||||
__DIR__
|
||||
'files/'
|
||||
);
|
||||
|
||||
$errors = [];
|
||||
$emails = $this->getLastEmails();
|
||||
|
||||
/*
|
||||
$session = Session::getInstance();
|
||||
$oldSession = [
|
||||
'userId' => $session->getUserId(),
|
||||
|
@ -61,6 +71,17 @@ class EmailPolling extends Controller {
|
|||
return null;
|
||||
});
|
||||
|
||||
if($email->getAttachement()) {
|
||||
$attachment = $email->getAttachement();
|
||||
$_FILES['file'] = [
|
||||
'name' => $attachment->name,
|
||||
'type' => mime_content_type($attachment->filePath),
|
||||
'tmp_name' => $attachment->filePath,
|
||||
'error' => UPLOAD_ERR_OK,
|
||||
'size' => filesize($attachment->filePath),
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
if($email->isReply()) {
|
||||
if($email->getTicket()->authorToArray()['email'] === $email->getSender()) {
|
||||
|
@ -79,6 +100,8 @@ class EmailPolling extends Controller {
|
|||
'error' => $e->__toString(),
|
||||
];
|
||||
}
|
||||
|
||||
unset($_FILES['file']);
|
||||
}
|
||||
|
||||
$session->clearSessionData();
|
||||
|
@ -90,7 +113,7 @@ class EmailPolling extends Controller {
|
|||
Response::respondError(ERRORS::EMAIL_POLLING, null, $errors);
|
||||
} else {
|
||||
Response::respondSuccess();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public function getLastEmails() {
|
||||
|
@ -101,12 +124,14 @@ class EmailPolling extends Controller {
|
|||
foreach($mailsIds as $mailId) {
|
||||
$mail = $this->mailbox->getMail($mailId);
|
||||
$mailHeader = $this->mailbox->getMailHeader($mailId);
|
||||
$mailAttachment = count($mail->getAttachments()) ? $mail->getAttachments()[0] : null;
|
||||
|
||||
$emails[] = new Email([
|
||||
'fromAddress' => $mailHeader->fromAddress,
|
||||
'fromName' => $mailHeader->fromName,
|
||||
'subject' => $mailHeader->subject,
|
||||
'content' => $mail->textPlain,
|
||||
'file' => null,
|
||||
'file' => $mailAttachment,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ class GetSettingsController extends Controller {
|
|||
'smtp-user' => Setting::getSetting('smtp-user')->getValue(),
|
||||
'imap-host' => Setting::getSetting('imap-host')->getValue(),
|
||||
'imap-user' => Setting::getSetting('imap-user')->getValue(),
|
||||
'imap-token' => Setting::getSetting('imap-token')->getValue(),
|
||||
'registration' => Setting::getSetting('registration')->getValue(),
|
||||
'departments' => Department::getAllDepartmentNames(),
|
||||
'supportedLanguages' => Language::getSupportedLanguages(),
|
||||
|
|
|
@ -88,7 +88,8 @@ class InitSettingsController extends Controller {
|
|||
'ticket-gap' => Hashing::generateRandomPrime(100000, 999999),
|
||||
'ticket-first-number' => Hashing::generateRandomNumber(100000, 999999),
|
||||
'session-prefix' => 'opensupports-'.Hashing::generateRandomToken().'_',
|
||||
'mail-template-header-image' => 'https://s3.amazonaws.com/opensupports/logo.png'
|
||||
'mail-template-header-image' => 'https://s3.amazonaws.com/opensupports/logo.png',
|
||||
'imap-token' => '',
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ class CommentController extends Controller {
|
|||
public function handler() {
|
||||
$this->requestData();
|
||||
$ticketAuthor = $this->ticket->authorToArray();
|
||||
$isAuthor = $this->ticket->isAuthor(Controller::getLoggedUser());
|
||||
$isAuthor = $this->ticket->isAuthor(Controller::getLoggedUser()) || Session::getInstance()->isTicketSession();
|
||||
$isOwner = $this->ticket->isOwner(Controller::getLoggedUser());
|
||||
|
||||
if((Controller::isUserSystemEnabled() || Controller::isStaffLogged()) && !$isOwner && !$isAuthor) {
|
||||
|
@ -89,13 +89,13 @@ class CommentController extends Controller {
|
|||
$this->storeComment();
|
||||
|
||||
if($isAuthor && $this->ticket->owner) {
|
||||
$this->sendMail([
|
||||
'email' => $this->ticket->owner->email,
|
||||
'name' => $this->ticket->owner->name,
|
||||
'staff' => true
|
||||
]);
|
||||
} else {
|
||||
$this->sendMail($ticketAuthor);
|
||||
$this->sendMail([
|
||||
'email' => $this->ticket->owner->email,
|
||||
'name' => $this->ticket->owner->name,
|
||||
'staff' => true
|
||||
]);
|
||||
} else if($isOwner) {
|
||||
$this->sendMail($ticketAuthor);
|
||||
}
|
||||
|
||||
Log::createLog('COMMENT', $this->ticket->ticketNumber);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
use EmailReplyParser\Parser\EmailParser;
|
||||
|
||||
class Email {
|
||||
private $sender;
|
||||
|
@ -49,7 +50,9 @@ class Email {
|
|||
}
|
||||
|
||||
private function parseContent($data) {
|
||||
return $data['content'];
|
||||
$emailParser = new EmailParser();
|
||||
|
||||
return $emailParser->parse($data['content'])->getVisibleText();
|
||||
}
|
||||
|
||||
private function parseAttachment($data) {
|
||||
|
|
|
@ -41,6 +41,10 @@ class Session {
|
|||
$this->store('token', Hashing::generateRandomToken());
|
||||
}
|
||||
|
||||
public function isTicketSession() {
|
||||
return $this->getStoredData('ticketNumber') && $this->getStoredData('token');
|
||||
}
|
||||
|
||||
public function getTicketNumber() {
|
||||
return $this->getStoredData('ticketNumber');
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue