919 lines
33 KiB
PHP
919 lines
33 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace App\Http\Controllers;
|
||
|
|
||
|
use App\Conversation;
|
||
|
use App\Folder;
|
||
|
use App\Mailbox;
|
||
|
use App\Thread;
|
||
|
use App\User;
|
||
|
use Illuminate\Http\Request;
|
||
|
use Illuminate\Support\Facades\Hash;
|
||
|
use Illuminate\Support\Facades\Route;
|
||
|
use Validator;
|
||
|
|
||
|
class MailboxesController extends Controller
|
||
|
{
|
||
|
/**
|
||
|
* Create a new controller instance.
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function __construct()
|
||
|
{
|
||
|
$this->middleware('auth');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Mailboxes list.
|
||
|
*/
|
||
|
public function mailboxes()
|
||
|
{
|
||
|
$user = auth()->user();
|
||
|
|
||
|
$mailboxes = $user->mailboxesCanView();
|
||
|
|
||
|
if (!\Eventy::filter('user.can_view_mailbox_menu', false, $user)) {
|
||
|
foreach ($mailboxes as $i => $mailbox) {
|
||
|
if (!$user->canManageMailbox($mailbox->id)) {
|
||
|
$mailboxes->forget($i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return view('mailboxes/mailboxes', ['mailboxes' => $mailboxes]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* New mailbox.
|
||
|
*/
|
||
|
public function create()
|
||
|
{
|
||
|
$this->authorize('create', 'App\Mailbox');
|
||
|
|
||
|
$users = User::nonDeleted()->where('role', '!=', User::ROLE_ADMIN)->get();
|
||
|
|
||
|
return view('mailboxes/create', ['users' => $users]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Create new mailbox.
|
||
|
*
|
||
|
* @param \Illuminate\Http\Request $request
|
||
|
*/
|
||
|
public function createSave(Request $request)
|
||
|
{
|
||
|
$invalid = false;
|
||
|
|
||
|
$this->authorize('create', 'App\Mailbox');
|
||
|
|
||
|
$validator = Validator::make($request->all(), [
|
||
|
'email' => 'required|string|email|max:128|unique:mailboxes',
|
||
|
'name' => 'required|string|max:40',
|
||
|
]);
|
||
|
|
||
|
// //event(new Registered($user = $this->create($request->all())));
|
||
|
|
||
|
if (Mailbox::userEmailExists($request->email)) {
|
||
|
$invalid = true;
|
||
|
$validator->errors()->add('email', __('There is a user with such email. Users and mailboxes can not have the same email addresses.'));
|
||
|
}
|
||
|
|
||
|
if ($invalid || $validator->fails()) {
|
||
|
return redirect()->route('mailboxes.create')
|
||
|
->withErrors($validator)
|
||
|
->withInput();
|
||
|
}
|
||
|
|
||
|
$mailbox = new Mailbox();
|
||
|
$mailbox->fill($request->all());
|
||
|
|
||
|
$mailbox->save();
|
||
|
|
||
|
$mailbox->users()->sync($request->users ?: []);
|
||
|
$mailbox->syncPersonalFolders($request->users);
|
||
|
|
||
|
\Session::flash('flash_success_floating', __('Mailbox created successfully'));
|
||
|
|
||
|
return redirect()->route('mailboxes.update', ['id' => $mailbox->id]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Edit mailbox.
|
||
|
*/
|
||
|
public function update($id)
|
||
|
{
|
||
|
$mailbox = Mailbox::findOrFail($id);
|
||
|
$user = auth()->user();
|
||
|
if (!$user->can('updateSettings', $mailbox) && !$user->can('updateEmailSignature', $mailbox)) {
|
||
|
$accessible_route = '';
|
||
|
|
||
|
$mailbox_settings = $user->mailboxSettings($mailbox->id);
|
||
|
|
||
|
if (!is_array($mailbox_settings->access)) {
|
||
|
$access_permissions = json_decode($mailbox_settings->access ?? '');
|
||
|
} else {
|
||
|
$access_permissions = $mailbox_settings->access;
|
||
|
}
|
||
|
|
||
|
if ($access_permissions && is_array($access_permissions)) {
|
||
|
foreach ($access_permissions as $perm) {
|
||
|
$accessible_route = Mailbox::getAccessPermissionRoute($perm);
|
||
|
if ($accessible_route) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (!$accessible_route) {
|
||
|
$accessible_route = \Eventy::filter('mailbox.accessible_settings_route', '', auth()->user(), $mailbox);
|
||
|
}
|
||
|
if ($accessible_route) {
|
||
|
return redirect()->route($accessible_route, ['id' => $mailbox->id]);
|
||
|
} else {
|
||
|
\Helper::denyAccess();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$user = auth()->user();
|
||
|
$mailbox_user = $user->mailboxesWithSettings()->where('mailbox_id', $id)->first();
|
||
|
if (!$mailbox_user && $user->isAdmin()) {
|
||
|
// Admin may not be connected to the mailbox yet
|
||
|
$user->mailboxes()->attach($id);
|
||
|
$mailbox_user = $user->mailboxesWithSettings()->where('mailbox_id', $id)->first();
|
||
|
}
|
||
|
|
||
|
//$mailboxes = Mailbox::all()->except($id);
|
||
|
|
||
|
return view('mailboxes/update', ['mailbox' => $mailbox, 'mailbox_user' => $mailbox_user, 'flashes' => $this->mailboxActiveWarning($mailbox)]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Save mailbox.
|
||
|
*
|
||
|
* @param int $id
|
||
|
* @param \Illuminate\Http\Request $request
|
||
|
*/
|
||
|
public function updateSave($id, Request $request)
|
||
|
{
|
||
|
$invalid = false;
|
||
|
$mailbox = Mailbox::findOrFail($id);
|
||
|
|
||
|
$user = auth()->user();
|
||
|
|
||
|
if (!$user->can('updateSettings', $mailbox) && !$user->can('updateEmailSignature', $mailbox)) {
|
||
|
\Helper::denyAccess();
|
||
|
}
|
||
|
|
||
|
if ($user->can('updateSettings', $mailbox)) {
|
||
|
|
||
|
// Checkboxes
|
||
|
$request->merge([
|
||
|
'aliases_reply' => ($request->filled('aliases_reply') ?? false),
|
||
|
]);
|
||
|
|
||
|
// if not admin, the text only fields don't pass so spike them into the request.
|
||
|
if (!auth()->user()->isAdmin()) {
|
||
|
$request->merge([
|
||
|
'name' => $mailbox->name,
|
||
|
'email' => $mailbox->email
|
||
|
]);
|
||
|
}
|
||
|
|
||
|
$validator = Validator::make($request->all(), [
|
||
|
'name' => 'required|string|max:40',
|
||
|
'email' => 'required|string|email|max:128|unique:mailboxes,email,'.$id,
|
||
|
'aliases' => 'nullable|string|max:255',
|
||
|
'from_name' => 'required|integer',
|
||
|
'from_name_custom' => 'nullable|string|max:128',
|
||
|
'ticket_status' => 'required|integer',
|
||
|
'template' => 'required|integer',
|
||
|
'ticket_assignee' => 'required|integer',
|
||
|
]);
|
||
|
|
||
|
//event(new Registered($user = $this->create($request->all())));
|
||
|
if (Mailbox::userEmailExists($request->email)) {
|
||
|
$invalid = true;
|
||
|
$validator->errors()->add('email', __('There is a user with such email. Users and mailboxes can not have the same email addresses.'));
|
||
|
}
|
||
|
|
||
|
$validator = \Eventy::filter('mailbox.settings_validator', $validator, $mailbox, $request);
|
||
|
|
||
|
if ($invalid || count($validator->errors()) || $validator->fails()) {
|
||
|
return redirect()->route('mailboxes.update', ['id' => $id])
|
||
|
->withErrors($validator)
|
||
|
->withInput();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($user->can('updateEmailSignature', $mailbox)) {
|
||
|
$validator = Validator::make($request->all(), [
|
||
|
'signature' => 'nullable|string',
|
||
|
]);
|
||
|
|
||
|
if ($validator->fails()) {
|
||
|
return redirect()->route('mailboxes.email_signature', ['id' => $id])
|
||
|
->withErrors($validator)
|
||
|
->withInput();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
\Eventy::action('mailbox.settings_before_save', $mailbox, $request);
|
||
|
|
||
|
$mailbox->fill($request->all());
|
||
|
|
||
|
$mailbox->save();
|
||
|
|
||
|
\Session::flash('flash_success_floating', __('Mailbox settings saved'));
|
||
|
|
||
|
return redirect()->route('mailboxes.update', ['id' => $id]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Mailbox permissions.
|
||
|
*/
|
||
|
public function permissions($id)
|
||
|
{
|
||
|
$mailbox = Mailbox::findOrFail($id);
|
||
|
|
||
|
$this->authorize('updatePermissions', $mailbox);
|
||
|
|
||
|
$users = User::nonDeleted()->where('role', '!=', User::ROLE_ADMIN)->get();
|
||
|
$users = User::sortUsers($users);
|
||
|
|
||
|
$managers = User::nonDeleted()
|
||
|
->select(['users.*', 'mailbox_user.hide', 'mailbox_user.access'])
|
||
|
->leftJoin('mailbox_user', function ($join) use ($mailbox) {
|
||
|
$join->on('mailbox_user.user_id', '=', 'users.id');
|
||
|
$join->where('mailbox_user.mailbox_id', $mailbox->id);
|
||
|
})->get();
|
||
|
$managers = User::sortUsers($managers);
|
||
|
|
||
|
return view('mailboxes/permissions', [
|
||
|
'mailbox' => $mailbox,
|
||
|
'users' => $users,
|
||
|
'managers' => $managers,
|
||
|
'mailbox_users' => $mailbox->users,
|
||
|
]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Save mailbox permissions.
|
||
|
*
|
||
|
* @param int $id
|
||
|
* @param \Illuminate\Http\Request $request
|
||
|
*/
|
||
|
public function permissionsSave($id, Request $request)
|
||
|
{
|
||
|
$mailbox = Mailbox::findOrFail($id);
|
||
|
$this->authorize('updatePermissions', $mailbox);
|
||
|
|
||
|
$user = auth()->user();
|
||
|
|
||
|
$mailbox->users()->sync(\Eventy::filter('mailbox.permission_users', $request->users, $id) ?: []);
|
||
|
$mailbox->syncPersonalFolders($request->users);
|
||
|
|
||
|
// Save admins settings.
|
||
|
$admins = User::nonDeleted()->where('role', User::ROLE_ADMIN)->get();
|
||
|
foreach ($admins as $admin) {
|
||
|
$mailbox_user = $admin->mailboxesWithSettings()->where('mailbox_id', $id)->first();
|
||
|
if (!$mailbox_user) {
|
||
|
// Admin may not be connected to the mailbox yet
|
||
|
$admin->mailboxes()->attach($id);
|
||
|
$mailbox_user = $admin->mailboxesWithSettings()->where('mailbox_id', $id)->first();
|
||
|
}
|
||
|
$mailbox_user->settings->hide = (isset($request->managers[$admin->id]['hide']) ? (int)$request->managers[$admin->id]['hide'] : false);
|
||
|
$mailbox_user->settings->save();
|
||
|
}
|
||
|
|
||
|
// Sets the mailbox_user.access array
|
||
|
$mailbox_users = $mailbox->users;
|
||
|
foreach ($mailbox_users as $mailbox_user) {
|
||
|
$access = [];
|
||
|
$mailbox_with_settings = $mailbox_user->mailboxesWithSettings()->where('mailbox_id', $id)->first();
|
||
|
|
||
|
foreach (Mailbox::$access_permissions as $perm) {
|
||
|
if (!empty($request->managers[$mailbox_user->id]['access'][$perm])) {
|
||
|
$access[] = $request->managers[$mailbox_user->id]['access'][$perm];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($user->id == $mailbox_user->id && !$user->isAdmin()) {
|
||
|
// User with Permission priv's can't edit their own additional priv's.
|
||
|
} else {
|
||
|
$mailbox_with_settings->settings->access = json_encode($access);
|
||
|
}
|
||
|
$mailbox_with_settings->settings->hide = (isset($request->managers[$mailbox_user->id]['hide']) ? (int)$request->managers[$mailbox_user->id]['hide'] : false);
|
||
|
$mailbox_with_settings->settings->save();
|
||
|
}
|
||
|
|
||
|
\Session::flash('flash_success_floating', __('Mailbox permissions saved!'));
|
||
|
|
||
|
return redirect()->route('mailboxes.permissions', ['id' => $id]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Mailbox connection settings.
|
||
|
*/
|
||
|
public function connectionOutgoing($id)
|
||
|
{
|
||
|
$mailbox = Mailbox::findOrFail($id);
|
||
|
$this->authorize('admin', $mailbox);
|
||
|
|
||
|
return view('mailboxes/connection', ['mailbox' => $mailbox, 'sendmail_path' => ini_get('sendmail_path'), 'flashes' => $this->mailboxActiveWarning($mailbox)]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Save mailbox connection settings.
|
||
|
*/
|
||
|
public function connectionOutgoingSave($id, Request $request)
|
||
|
{
|
||
|
$mailbox = Mailbox::findOrFail($id);
|
||
|
$this->authorize('admin', $mailbox);
|
||
|
|
||
|
if ($request->out_method == Mailbox::OUT_METHOD_SMTP) {
|
||
|
$validator = Validator::make($request->all(), [
|
||
|
'out_server' => 'required|string|max:255',
|
||
|
'out_port' => 'required|integer',
|
||
|
'out_username' => 'nullable|string|max:100',
|
||
|
'out_password' => 'nullable|string|max:255',
|
||
|
'out_encryption' => 'required|integer',
|
||
|
]);
|
||
|
|
||
|
if ($validator->fails()) {
|
||
|
return redirect()->route('mailboxes.connection', ['id' => $id])
|
||
|
->withErrors($validator)
|
||
|
->withInput();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Do not save dummy password.
|
||
|
if (preg_match("/^\*+$/", $request->out_password ?? '')) {
|
||
|
$params = $request->except(['out_password']);
|
||
|
} else {
|
||
|
$params = $request->all();
|
||
|
}
|
||
|
$mailbox->fill($params);
|
||
|
$mailbox->save();
|
||
|
|
||
|
if (!empty($request->send_test_to)) {
|
||
|
\Option::set('send_test_to', $request->send_test_to);
|
||
|
}
|
||
|
|
||
|
// Sometimes background job continues to use old connection settings.
|
||
|
\Helper::queueWorkerRestart();
|
||
|
|
||
|
\Session::flash('flash_success_floating', __('Connection settings saved!'));
|
||
|
|
||
|
return redirect()->route('mailboxes.connection', ['id' => $id]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Mailbox incoming settings.
|
||
|
*/
|
||
|
public function connectionIncoming($id, Request $request)
|
||
|
{
|
||
|
$mailbox = Mailbox::findOrFail($id);
|
||
|
$this->authorize('admin', $mailbox);
|
||
|
|
||
|
$fields = [
|
||
|
'in_server' => $mailbox->in_server ?? '',
|
||
|
'in_port' => $mailbox->in_port ?? '',
|
||
|
'in_username' => $mailbox->in_username ?? '',
|
||
|
'in_password' => $mailbox->in_password ?? '',
|
||
|
];
|
||
|
|
||
|
$validator = Validator::make($fields, [
|
||
|
'in_server' => 'required',
|
||
|
'in_port' => 'required',
|
||
|
'in_username' => 'required',
|
||
|
'in_password' => 'required',
|
||
|
]);
|
||
|
|
||
|
return view('mailboxes/connection_incoming', ['mailbox' => $mailbox, 'flashes' => $this->mailboxActiveWarning($mailbox)])->withErrors($validator);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Save mailbox connection settings.
|
||
|
*/
|
||
|
public function connectionIncomingSave($id, Request $request)
|
||
|
{
|
||
|
$mailbox = Mailbox::findOrFail($id);
|
||
|
$this->authorize('admin', $mailbox);
|
||
|
|
||
|
// $validator = Validator::make($request->all(), [
|
||
|
// 'in_server' => 'nullable|string|max:255',
|
||
|
// 'in_port' => 'nullable|integer',
|
||
|
// 'in_username' => 'nullable|string|max:100',
|
||
|
// 'in_password' => 'nullable|string|max:255',
|
||
|
// ]);
|
||
|
|
||
|
// if ($validator->fails()) {
|
||
|
// return redirect()->route('mailboxes.connection.incoming', ['id' => $id])
|
||
|
// ->withErrors($validator)
|
||
|
// ->withInput();
|
||
|
// }
|
||
|
|
||
|
// Checkboxes
|
||
|
$request->merge([
|
||
|
'in_validate_cert' => ($request->filled('in_validate_cert') ?? false),
|
||
|
]);
|
||
|
|
||
|
// Do not save dummy password.
|
||
|
if (preg_match("/^\*+$/", $request->in_password ?? '')) {
|
||
|
$params = $request->except(['in_password']);
|
||
|
} else {
|
||
|
$params = $request->all();
|
||
|
}
|
||
|
|
||
|
\Eventy::action('mailbox.incoming_settings_before_save', $mailbox, $request);
|
||
|
|
||
|
$mailbox->fill($params);
|
||
|
|
||
|
// Save IMAP Folders.
|
||
|
// Save all custom folders except INBOX.
|
||
|
$in_imap_folders = [];
|
||
|
if (is_array($request->in_imap_folders)) {
|
||
|
foreach ($request->in_imap_folders as $imap_folder) {
|
||
|
$in_imap_folders[] = $imap_folder;
|
||
|
}
|
||
|
}
|
||
|
$mailbox->setInImapFolders($in_imap_folders);
|
||
|
|
||
|
$mailbox->save();
|
||
|
|
||
|
\Session::flash('flash_success_floating', __('Connection settings saved!'));
|
||
|
|
||
|
return redirect()->route('mailboxes.connection.incoming', ['id' => $id]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* View mailbox.
|
||
|
*/
|
||
|
public function view(Request $request, $id, $folder_id = null)
|
||
|
{
|
||
|
$user = auth()->user();
|
||
|
|
||
|
$mailbox = Mailbox::findOrFailWithSettings($id, $user->id);
|
||
|
$this->authorize('viewCached', $mailbox);
|
||
|
|
||
|
$folders = $mailbox->getAssesibleFolders();
|
||
|
|
||
|
$folder = null;
|
||
|
if (!empty($folder_id)) {
|
||
|
$folder = $folders->filter(function ($item) use ($folder_id) {
|
||
|
return $item->id == $folder_id;
|
||
|
})->first();
|
||
|
}
|
||
|
// By default we display Unassigned folder
|
||
|
if (empty($folder)) {
|
||
|
$folder = $folders->filter(function ($item) {
|
||
|
return $item->type == Folder::TYPE_UNASSIGNED;
|
||
|
})->first();
|
||
|
}
|
||
|
|
||
|
$this->authorize('view', $folder);
|
||
|
|
||
|
$query_conversations = Conversation::getQueryByFolder($folder, $user->id);
|
||
|
$conversations = $folder->queryAddOrderBy($query_conversations)->paginate(
|
||
|
Conversation::DEFAULT_LIST_SIZE, ['*'], 'page', $request->get('page')
|
||
|
);
|
||
|
|
||
|
return view('mailboxes/view', [
|
||
|
'mailbox' => $mailbox,
|
||
|
'folders' => $folders,
|
||
|
'folder' => $folder,
|
||
|
'conversations' => $conversations,
|
||
|
]);
|
||
|
}
|
||
|
|
||
|
private function mailboxActiveWarning($mailbox)
|
||
|
{
|
||
|
$flashes = [];
|
||
|
|
||
|
if ($mailbox && \Auth::user()->can('admin', $mailbox)) {
|
||
|
if (Route::currentRouteName() != 'mailboxes.connection' && !$mailbox->isOutActive()) {
|
||
|
$flashes[] = [
|
||
|
'type' => 'warning',
|
||
|
'text' => __('Sending emails need to be configured for the mailbox in order to send emails to customers and support agents').' ('.__('Connection Settings').' » <a href="'.route('mailboxes.connection', ['id' => $mailbox->id]).'">'.__('Sending Emails').'</a>)',
|
||
|
'unescaped' => true,
|
||
|
];
|
||
|
}
|
||
|
if (Route::currentRouteName() != 'mailboxes.connection.incoming' && !$mailbox->isInActive()) {
|
||
|
$flashes[] = [
|
||
|
'type' => 'warning',
|
||
|
'text' => __('Receiving emails need to be configured for the mailbox in order to fetch emails from your support email address').' ('.__('Connection Settings').' » <a href="'.route('mailboxes.connection.incoming', ['id' => $mailbox->id]).'">'.__('Receiving Emails').'</a>)',
|
||
|
'unescaped' => true,
|
||
|
];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $flashes;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Auto reply settings.
|
||
|
*/
|
||
|
public function autoReply($id)
|
||
|
{
|
||
|
$mailbox = Mailbox::findOrFail($id);
|
||
|
$this->authorize('updateAutoReply', $mailbox);
|
||
|
|
||
|
if (!$mailbox->auto_reply_subject) {
|
||
|
$mailbox->auto_reply_subject = 'Re: {%subject%}';
|
||
|
}
|
||
|
|
||
|
return view('mailboxes/auto_reply', [
|
||
|
'mailbox' => $mailbox,
|
||
|
]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Save auto reply settings.
|
||
|
*/
|
||
|
public function autoReplySave($id, Request $request)
|
||
|
{
|
||
|
$mailbox = Mailbox::findOrFail($id);
|
||
|
|
||
|
// $this->authorize('update', $mailbox);
|
||
|
$this->authorize('updateAutoReply', $mailbox);
|
||
|
|
||
|
$request->merge([
|
||
|
'auto_reply_enabled' => ($request->filled('auto_reply_enabled') ?? false),
|
||
|
]);
|
||
|
|
||
|
if ($request->auto_reply_enabled) {
|
||
|
$post = $request->all();
|
||
|
$post['auto_reply_message'] = strip_tags($post['auto_reply_message']);
|
||
|
$validator = Validator::make($post, [
|
||
|
'auto_reply_subject' => 'required|string|max:128',
|
||
|
'auto_reply_message' => 'required|string',
|
||
|
]);
|
||
|
$validator->setAttributeNames([
|
||
|
'auto_reply_subject' => __('Subject'),
|
||
|
'auto_reply_message' => __('Message'),
|
||
|
]);
|
||
|
|
||
|
if ($validator->fails()) {
|
||
|
return redirect()->route('mailboxes.auto_reply', ['id' => $id])
|
||
|
->withErrors($validator)
|
||
|
->withInput();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$mailbox->fill($request->all());
|
||
|
|
||
|
$mailbox->save();
|
||
|
|
||
|
\Session::flash('flash_success_floating', __('Auto Reply status saved'));
|
||
|
|
||
|
return redirect()->route('mailboxes.auto_reply', ['id' => $id]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Auto reply settings.
|
||
|
*/
|
||
|
public function emailSignature($id)
|
||
|
{
|
||
|
$mailbox = Mailbox::findOrFail($id);
|
||
|
$this->authorize('updateAutoReply', $mailbox);
|
||
|
|
||
|
if (!$mailbox->auto_reply_subject) {
|
||
|
$mailbox->auto_reply_subject = 'Re: {%subject%}';
|
||
|
}
|
||
|
|
||
|
return view('mailboxes/email_signature', [
|
||
|
'mailbox' => $mailbox,
|
||
|
]);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Users ajax controller.
|
||
|
*/
|
||
|
public function ajax(Request $request)
|
||
|
{
|
||
|
$response = [
|
||
|
'status' => 'error',
|
||
|
'msg' => '', // this is error message
|
||
|
];
|
||
|
|
||
|
$user = auth()->user();
|
||
|
|
||
|
switch ($request->action) {
|
||
|
|
||
|
// Test sending emails from mailbox
|
||
|
case 'send_test':
|
||
|
$mailbox = Mailbox::find($request->mailbox_id);
|
||
|
|
||
|
if (!$mailbox) {
|
||
|
$response['msg'] = __('Mailbox not found');
|
||
|
} elseif (!$user->can('admin', $mailbox)) {
|
||
|
$response['msg'] = __('Not enough permissions');
|
||
|
} elseif (empty($request->to)) {
|
||
|
$response['msg'] = __('Please specify recipient of the test email');
|
||
|
}
|
||
|
|
||
|
// Check if outgoing port is open.
|
||
|
if (!$response['msg'] && $mailbox->out_method == Mailbox::OUT_METHOD_SMTP) {
|
||
|
$test_result = \Helper::checkPort($mailbox->out_server, $mailbox->out_port);
|
||
|
if (!$test_result) {
|
||
|
$response['msg'] = __(':host is not available on :port port. Make sure that :host address is correct and that outgoing port :port on YOUR server is open.', ['host' => '<strong>'.$mailbox->out_server.'</strong>', 'port' => '<strong>'.$mailbox->out_port.'</strong>']);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!$response['msg']) {
|
||
|
$test_result = false;
|
||
|
|
||
|
try {
|
||
|
$test_result = \App\Misc\Mail::sendTestMail($request->to, $mailbox);
|
||
|
} catch (\Exception $e) {
|
||
|
$response['msg'] = $e->getMessage();
|
||
|
}
|
||
|
|
||
|
if (!$test_result && !$response['msg']) {
|
||
|
$response['msg'] = __('Error occurred sending email. Please check your mail server logs for more details.');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!$response['msg']) {
|
||
|
$response['status'] = 'success';
|
||
|
}
|
||
|
|
||
|
// Remember email address
|
||
|
if (!empty($request->to)) {
|
||
|
\App\Option::set('send_test_to', $request->to);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Test sending emails from mailbox
|
||
|
case 'fetch_test':
|
||
|
$mailbox = Mailbox::find($request->mailbox_id);
|
||
|
|
||
|
if (!$mailbox) {
|
||
|
$response['msg'] = __('Mailbox not found');
|
||
|
} elseif (!$user->can('admin', $mailbox)) {
|
||
|
$response['msg'] = __('Not enough permissions');
|
||
|
}
|
||
|
|
||
|
$response = \Eventy::filter('mailbox.fetch_test', $response, $mailbox);
|
||
|
|
||
|
$tested = (isset($response['tested']) && $response['tested'] === true);
|
||
|
|
||
|
// Check if outgoing port is open.
|
||
|
if (!$response['msg'] && !$tested) {
|
||
|
$test_result = \Helper::checkPort($mailbox->in_server, $mailbox->in_port);
|
||
|
if (!$test_result) {
|
||
|
$response['msg'] = __(':host is not available on :port port. Make sure that :host address is correct and that outgoing port :port on YOUR server is open.', ['host' => '<strong>'.$mailbox->in_server.'</strong>', 'port' => '<strong>'.$mailbox->in_port.'</strong>']);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!$response['msg'] && !$tested) {
|
||
|
$test_result = false;
|
||
|
|
||
|
try {
|
||
|
$test_result = \MailHelper::fetchTest($mailbox);
|
||
|
} catch (\Exception $e) {
|
||
|
$response['msg'] = $e->getMessage();
|
||
|
}
|
||
|
|
||
|
if (!$test_result && !$response['msg']) {
|
||
|
$response['msg'] = __('Error occurred connecting to the server');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!$response['msg'] && !$tested) {
|
||
|
$response['status'] = 'success';
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Retrieve a list of available IMAP folders from server.
|
||
|
case 'imap_folders':
|
||
|
$mailbox = Mailbox::find($request->mailbox_id);
|
||
|
|
||
|
if (!$mailbox) {
|
||
|
$response['msg'] = __('Mailbox not found');
|
||
|
} elseif (!$user->can('admin', $mailbox)) {
|
||
|
$response['msg'] = __('Not enough permissions');
|
||
|
}
|
||
|
|
||
|
$response['folders'] = [];
|
||
|
|
||
|
if (!$response['msg']) {
|
||
|
|
||
|
try {
|
||
|
$client = \MailHelper::getMailboxClient($mailbox);
|
||
|
$client->connect();
|
||
|
|
||
|
$imap_folders = $client->getFolders();
|
||
|
|
||
|
if (count($imap_folders)) {
|
||
|
foreach ($imap_folders as $imap_folder) {
|
||
|
if (!empty($imap_folder->name)) {
|
||
|
$response['folders'][] = $imap_folder->name;
|
||
|
}
|
||
|
// Maybe we need a recursion here.
|
||
|
if (!empty($imap_folder->children)) {
|
||
|
foreach ($imap_folder->children as $child_imap_folder) {
|
||
|
// Old library.
|
||
|
if (!empty($child_imap_folder->fullName)) {
|
||
|
$response['folders'][] = $child_imap_folder->fullName;
|
||
|
}
|
||
|
// New library.
|
||
|
if (!empty($child_imap_folder->full_name)) {
|
||
|
$response['folders'][] = $child_imap_folder->full_name;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (count($response['folders'])) {
|
||
|
$response['msg_success'] = __('IMAP folders retrieved: '.implode(', ', $response['folders']));
|
||
|
} else {
|
||
|
$response['msg_success'] = __('Connected, but no IMAP folders found');
|
||
|
}
|
||
|
|
||
|
} catch (\Exception $e) {
|
||
|
$response['msg'] = $e->getMessage();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!$response['msg']) {
|
||
|
$response['status'] = 'success';
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Delete mailbox
|
||
|
case 'delete_mailbox':
|
||
|
$mailbox = Mailbox::find($request->mailbox_id);
|
||
|
|
||
|
if (!$mailbox) {
|
||
|
$response['msg'] = __('Mailbox not found');
|
||
|
} elseif (!$user->can('admin', $mailbox)) {
|
||
|
$response['msg'] = __('Not enough permissions');
|
||
|
} elseif (!$user->isDummyPassword() && !Hash::check($request->password ?? '', $user->password)) {
|
||
|
$response['msg'] = __('Please double check your password, and try again');
|
||
|
}
|
||
|
|
||
|
if (!$response['msg']) {
|
||
|
|
||
|
// Remove threads and conversations.
|
||
|
$conversation_ids = $mailbox->conversations()->pluck('id')->toArray();
|
||
|
|
||
|
for ($i=0; $i < ceil(count($conversation_ids) / \Helper::IN_LIMIT); $i++) {
|
||
|
$slice_ids = array_slice($conversation_ids, $i*\Helper::IN_LIMIT, \Helper::IN_LIMIT);
|
||
|
Thread::whereIn('conversation_id', $slice_ids)->delete();
|
||
|
}
|
||
|
|
||
|
$mailbox->conversations()->delete();
|
||
|
$mailbox->users()->sync([]);
|
||
|
$mailbox->folders()->delete();
|
||
|
// Maybe remove notifications on events in this mailbox?
|
||
|
|
||
|
$mailbox->delete();
|
||
|
|
||
|
\Session::flash('flash_success_floating', __('Mailbox deleted'));
|
||
|
|
||
|
$response['status'] = 'success';
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Mute notifications
|
||
|
case 'mute':
|
||
|
$mailbox = Mailbox::find($request->mailbox_id);
|
||
|
|
||
|
if (!$mailbox) {
|
||
|
$response['msg'] = __('Mailbox not found');
|
||
|
}
|
||
|
|
||
|
if (!$response['msg']) {
|
||
|
|
||
|
$mailbox_user = $user->mailboxesWithSettings()->where('mailbox_id', $mailbox->id)->first();
|
||
|
if (!$mailbox_user) {
|
||
|
// User may not be connected to the mailbox yet
|
||
|
$user->mailboxes()->attach($mailbox->id);
|
||
|
$mailbox_user = $user->mailboxesWithSettings()->where('mailbox_id', $mailbox->id)->first();
|
||
|
}
|
||
|
$mailbox_user->settings->mute = (bool)$request->mute;
|
||
|
$mailbox_user->settings->save();
|
||
|
|
||
|
$response['status'] = 'success';
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
$response['msg'] = 'Unknown action';
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ($response['status'] == 'error' && empty($response['msg'])) {
|
||
|
$response['msg'] = 'Unknown error occurred';
|
||
|
}
|
||
|
|
||
|
return \Response::json($response);
|
||
|
}
|
||
|
|
||
|
public function oauth(Request $request)
|
||
|
{
|
||
|
$mailbox_id = $request->id ?? '';
|
||
|
$provider = $request->provider ?? '';
|
||
|
|
||
|
$state_data = [];
|
||
|
if (!empty($request->state)) {
|
||
|
$state_data = json_decode($request->state, true);
|
||
|
if (!empty($state_data['mailbox_id'])) {
|
||
|
$mailbox_id = $state_data['mailbox_id'];
|
||
|
}
|
||
|
if (!empty($state_data['provider'])) {
|
||
|
$provider = $state_data['provider'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// MS Exchange.
|
||
|
if (!empty($request->error) && $request->error == 'invalid_request' && !empty($request->error_description)) {
|
||
|
return htmlspecialchars($request->error_description);
|
||
|
}
|
||
|
|
||
|
if (empty($provider)) {
|
||
|
return 'Invalid oAuth Provider';
|
||
|
}
|
||
|
|
||
|
$mailbox = Mailbox::findOrFail($mailbox_id);
|
||
|
$this->authorize('admin', $mailbox);
|
||
|
|
||
|
if (empty($mailbox)) {
|
||
|
return __('Mailbox not found').': '.$mailbox_id;
|
||
|
}
|
||
|
if (empty($mailbox->in_username)) {
|
||
|
return 'Enter oAuth Client ID as Username and save mailbox settings';
|
||
|
}
|
||
|
if (empty($mailbox->in_password)) {
|
||
|
return 'Enter oAuth Client Secret as Password and save mailbox settings';
|
||
|
}
|
||
|
|
||
|
$session_data = [];
|
||
|
if (\Session::get('mailbox_oauth_'.$provider.'_'.$mailbox_id)) {
|
||
|
$session_data = \Session::get('mailbox_oauth_'.$provider.'_'.$mailbox_id);
|
||
|
}
|
||
|
|
||
|
if (empty($request->code)) {
|
||
|
$state = [
|
||
|
'provider' => $provider,
|
||
|
'mailbox_id' => $mailbox_id,
|
||
|
'state' => crc32($mailbox->in_username.$mailbox->in_password),
|
||
|
];
|
||
|
$url = \MailHelper::oauthGetAuthorizationUrl(\MailHelper::OAUTH_PROVIDER_MICROSOFT, [
|
||
|
'state' => json_encode($state),
|
||
|
'client_id' => $mailbox->in_username,
|
||
|
]);
|
||
|
if ($url) {
|
||
|
\Session::put('mailbox_oauth_'.$provider.'_'.$mailbox_id, $state);
|
||
|
// [
|
||
|
// 'provider' => $request->provider,
|
||
|
// 'mailbox_id' => $request->mailbox_id,
|
||
|
// 'state' => $provider->getState(),
|
||
|
// ]);
|
||
|
return redirect()->away($url);
|
||
|
} else {
|
||
|
return 'Could not generate authorization URL: check Client ID (Username) and Client Secret (Password)';
|
||
|
}
|
||
|
|
||
|
// Check given state against previously stored one to mitigate CSRF attack
|
||
|
} elseif (empty($request->state) || ($state_data['state'] ?? '') !== ($session_data['state'] ?? '')) {
|
||
|
|
||
|
\Session::forget('mailbox_oauth_'.$provider.'_'.$mailbox_id);
|
||
|
return 'Invalid oAuth state';
|
||
|
|
||
|
} else {
|
||
|
|
||
|
// Try to get an access token (using the authorization code grant)
|
||
|
$token_data = \MailHelper::oauthGetAccessToken(\MailHelper::OAUTH_PROVIDER_MICROSOFT, [
|
||
|
'client_id' => $mailbox->in_username,
|
||
|
'client_secret' => $mailbox->in_password,
|
||
|
'code' => $request->code,
|
||
|
]);
|
||
|
|
||
|
if (!empty($token_data['a_token'])) {
|
||
|
$mailbox->setMetaParam('oauth', $token_data, true);
|
||
|
} elseif (!empty($token_data['error'])) {
|
||
|
return __('Error occurred').': '.htmlspecialchars($token_data['error']);
|
||
|
}
|
||
|
|
||
|
return redirect()->route('mailboxes.connection.incoming', ['id' => $mailbox_id]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function oauthDisconnect(Request $request)
|
||
|
{
|
||
|
$mailbox_id = $request->id ?? '';
|
||
|
$provider = $request->provider ?? '';
|
||
|
|
||
|
$mailbox = Mailbox::findOrFail($mailbox_id);
|
||
|
$this->authorize('admin', $mailbox);
|
||
|
|
||
|
// oAuth Disconnect.
|
||
|
$mailbox->removeMetaParam('oauth', true);
|
||
|
return \MailHelper::oauthDisconnect($provider, route('mailboxes.connection.incoming', ['id' => $mailbox_id]));
|
||
|
}
|
||
|
}
|