Skip to content

Commit

Permalink
Merge branch 'master' of github.com:freescout-helpdesk/freescout into…
Browse files Browse the repository at this point in the history
… dist
  • Loading branch information
freescout-help-desk committed Nov 2, 2024
2 parents 30b07a8 + cbeffb8 commit b6987dd
Show file tree
Hide file tree
Showing 23 changed files with 215 additions and 67 deletions.
8 changes: 8 additions & 0 deletions app/Customer.php
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,14 @@ public static function getMainEmailStatic($customer_id)
return Email::select('email')->where('customer_id', $customer_id)->pluck('email');
}

/**
* Check if the customer has an email address among his emails.
*/
public function hasEmail($email_address)
{
return $this->emails_cached()->where('email', Email::sanitizeEmail($email_address))->exists();
}

/**
* Get customer full name.
*
Expand Down
8 changes: 8 additions & 0 deletions app/Http/Controllers/ConversationsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2991,6 +2991,8 @@ public function getSearchFilters($request)
*/
public function searchCustomers($request, $user)
{
$limited_visibility = config('app.limit_user_customer_visibility') && !$user->isAdmin();

// Get IDs of mailboxes to which user has access
$mailbox_ids = $user->mailboxesIdsCanView();

Expand Down Expand Up @@ -3040,6 +3042,12 @@ public function searchCustomers($request, $user)
//$join->on('conversations.mailbox_id', '=', $filters['mailbox']);
});
$query_customers->where('conversations.mailbox_id', '=', $filters['mailbox']);
} elseif ($limited_visibility) {
// Force only mailboxes the user has access to.
$query_customers->join('conversations', function ($join) use ($filters) {
$join->on('conversations.customer_id', '=', 'customers.id');
});
$query_customers->whereIn('conversations.mailbox_id', $mailbox_ids);
}

$query_customers = \Eventy::filter('search.customers.apply_filters', $query_customers, $filters, $q);
Expand Down
60 changes: 40 additions & 20 deletions app/Http/Controllers/CustomersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ public function ajaxSearch(Request $request)

$q = $request->q;

$user = auth()->user();
$limited_visibility = config('app.limit_user_customer_visibility') && !$user->isAdmin();

$join_emails = false;
if ($request->search_by == 'all' || $request->search_by == 'email' || $request->exclude_email) {
$join_emails = true;
Expand All @@ -279,22 +282,32 @@ public function ajaxSearch(Request $request)
}
}

if ($request->search_by == 'all' || $request->search_by == 'email') {
$customers_query->where('emails.email', 'like', '%'.$q.'%');
}
if ($request->exclude_email) {
$customers_query->where('emails.email', '<>', $request->exclude_email);
}
if ($request->search_by == 'all' || $request->search_by == 'name') {
$customers_query->orWhere('first_name', 'like', '%'.$q.'%')
->orWhere('last_name', 'like', '%'.$q.'%');
}
if ($request->search_by == 'phone') {
$phone_numeric = \Helper::phoneToNumeric($q);
if (!$phone_numeric) {
$phone_numeric = $q;
$customers_query->where(function ($query) use ($q, $request) {
if ($request->search_by == 'all' || $request->search_by == 'email') {
$query->where('emails.email', 'like', '%'.$q.'%');
}
if ($request->exclude_email) {
$query->where('emails.email', '<>', $request->exclude_email);
}
$customers_query->where('customers.phones', 'like', '%'.$phone_numeric.'%');
if ($request->search_by == 'all' || $request->search_by == 'name') {
$query->orWhere('first_name', 'like', '%'.$q.'%')
->orWhere('last_name', 'like', '%'.$q.'%');
}
if ($request->search_by == 'phone') {
$phone_numeric = \Helper::phoneToNumeric($q);
if (!$phone_numeric) {
$phone_numeric = $q;
}
$query->where('customers.phones', 'like', '%'.$phone_numeric.'%');
}
});

if ($limited_visibility) {
$mailbox_ids = $user->mailboxesIdsCanView();

$customers_query->join('conversations', 'conversations.customer_id', '=', 'customers.id');
$customers_query->whereIn('conversations.mailbox_id', $mailbox_ids);
$customers_query->groupby('customers.id');
}

$customers = $customers_query->paginate(20);
Expand Down Expand Up @@ -367,14 +380,21 @@ public function ajax(Request $request)

switch ($request->action) {

// Change conversation user
// Change conversation customer.
case 'create':
// First name or email must be specified
$validator = Validator::make($request->all(), [
$validator_config = [
'first_name' => 'required|string|max:255',
'last_name' => 'nullable|string|max:255',
'email' => 'required|email|unique:emails,email',
]);
];

$limited_visibility = config('app.limit_user_customer_visibility') && !$user->isAdmin();
if ($limited_visibility) {
$validator_config['email'] = 'required|email';
}

// First name or email must be specified.
$validator = Validator::make($request->all(), $validator_config);

if ($validator->fails()) {
foreach ($validator->errors()->getMessages()as $errors) {
Expand Down Expand Up @@ -417,4 +437,4 @@ public function ajax(Request $request)

return \Response::json($response);
}
}
}
1 change: 1 addition & 0 deletions app/Misc/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,7 @@ public static function getRemoteFileContents($url)

$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_URL, $url);
\Helper::setCurlDefaultOptions($ch);
curl_setopt($ch, CURLOPT_TIMEOUT, 180);
Expand Down
23 changes: 23 additions & 0 deletions app/Misc/Mail.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ class Mail
'-------- Αρχικό μήνυμα --------', // Greek
];

/**
* Used to substitue encoding during mail body decoding.
* https://github.com/freescout-help-desk/freescout/issues/4282
*/
public static $encoding_substitution = [
'iso-2022-jp' => 'iso-2022-jp-ms',
'gb2312' => 'gb18030',
];

/**
* md5 of the last applied mail config.
*/
Expand Down Expand Up @@ -581,6 +590,7 @@ public static function isAutoResponder($headers_str)
'x-autorespond' => '',
'x-autoresponder' => '',
'auto-submitted' => '', // this can be auto-replied, auto-generated, etc.
'delivered-to' => ['autoresponder'],
'precedence' => ['auto_reply', 'bulk', 'junk'],
'x-precedence' => ['auto_reply', 'bulk', 'junk'],
];
Expand Down Expand Up @@ -1141,6 +1151,19 @@ public static function parseEml($content, $mailbox) {
return \Webklex\PHPIMAP\Message::make(null, null, $client, $raw_header, $raw_body, [], \Webklex\PHPIMAP\IMAP::ST_UID);
}

// Substitue encoding during mail body decoding.
// https://github.com/freescout-help-desk/freescout/issues/4282
public static function substituteEncoding($encoding)
{
$encoding = strtolower($encoding);

if (!empty(self::$encoding_substitution[$encoding])) {
return self::$encoding_substitution[$encoding];
} else {
return $encoding;
}
}

// public static function oauthGetProvider($provider_code, $params)
// {
// $provider = null;
Expand Down
14 changes: 14 additions & 0 deletions app/Thread.php
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,20 @@ public function parseHeaders()
return \MailHelper::parseHeaders($this->headers);
}

public function getHeader($header_name)
{
return getHeader($this->headers, $header_name);
}

public function getFromHeader()
{
if (empty($this->headers)) {
return '';
}
preg_match("#From:\s*.*[^\s]*\s*<\s*(.*[^\s])\s*>\s*\n#", $this->headers ?? '', $m);
return $m[1] ?? '';
}

public function getMailDate()
{
$data = $this->parseHeaders();
Expand Down
12 changes: 10 additions & 2 deletions config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
| or any other location as required by the application or its packages.
*/

'version' => '1.8.154',
'version' => '1.8.155',

/*
|--------------------------------------------------------------------------
Expand Down Expand Up @@ -465,6 +465,14 @@
*/
'show_only_assigned_conversations' => env('APP_SHOW_ONLY_ASSIGNED_CONVERSATIONS', ''),

/*
|--------------------------------------------------------------------------
| Limit non-admin users to only see customers with conversations
| in mailboxes they are assigned to. This option does not affect admin users.
|-------------------------------------------------------------------------
*/
'limit_user_customer_visibility' => env('APP_LIMIT_USER_CUSTOMER_VISIBILITY', false),

/*
|--------------------------------------------------------------------------
| By default X-Frame-Options header is enabled and set to SAMEORIGIN.
Expand Down Expand Up @@ -628,4 +636,4 @@
'Updater' => Codedge\Updater\UpdaterFacade::class,
],

];
];
4 changes: 1 addition & 3 deletions overrides/webklex/php-imap/src/Header.php
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,7 @@ public function convertEncoding($str, $from = "ISO-8859-2", $to = "UTF-8") {
return $str;
}

if (strtolower($from) == 'iso-2022-jp'){
$from = 'iso-2022-jp-ms';
}
$from = \MailHelper::substituteEncoding($from);

try {
if (function_exists('iconv') && $from != 'UTF-7' && $to != 'UTF-7') {
Expand Down
6 changes: 2 additions & 4 deletions overrides/webklex/php-imap/src/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -749,10 +749,8 @@ public function convertEncoding($str, string $from = "ISO-8859-2", string $to =

$result = '';

if (strtolower($from) == 'iso-2022-jp'){
$from = 'iso-2022-jp-ms';
}

$from = \MailHelper::substituteEncoding($from);

// Try iconv.
if (function_exists('iconv') && $from != 'UTF-7' && $to != 'UTF-7' && $from != 'iso-2022-jp-ms') {
try {
Expand Down
2 changes: 1 addition & 1 deletion resources/lang/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@
"Close": "Zavřít",
"Closed": "Uzavřeno",
"Comma separated emails of extra recipients.": "E-maily dalších příjemců oddělené čárkou.",
"Comma separated list off email addresses from which user can reply to email notifications in addition to user's main Email": "Seznam e-mailových adres oddělených čárkou, ze kterých může uživatel odpovídat na e-mailová oznámení kromě hlavního e-mailu uživatele",
"Comma separated list of email addresses from which user can reply to email notifications in addition to user's main Email": "Seznam e-mailových adres oddělených čárkou, ze kterých může uživatel odpovídat na e-mailová oznámení kromě hlavního e-mailu uživatele",
"Company": "Společnost",
"Company Name": "Název společnosti",
"Configure": "Konfigurace",
Expand Down
7 changes: 5 additions & 2 deletions resources/lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@
"PHP Version": "PHP Version",
"PHP sendmail path:": "PHP sendmail Pfad:",
"PHP's mail() function": "PHP mail() Funktion",
"Pager": "Pager",
"Password": "Passwort",
"Password Changed": "Passwort geändert",
"Password changed notification": "Benachrichtigung über die Änderung des Passworts",
Expand Down Expand Up @@ -666,11 +667,13 @@
"The :module_name module has been deactivated due to an error: :error_message": "Das :module_name Modul wurde auf Grund des folgenden Fehlers deaktiviert : :error_message",
"The following modules have to be installed and activated: :modules": "Die folgenden Module müssen installiert und aktiviert sein: :modules",
"The new password is the same as the old password.": "Das neue Passwort ist das gleiche wie das alte.",
"The original message could not be loaded from mail server, below is the latest truncated copy stored in database.": "Die original Nachricht kann nicht vom Server geladen werden, nachfolgend finden Sie die letzte - in der Datenbank gespeicherte Kopie.",
"There are no conversations here": "Hier gibt es keine Konversationen",
"There are updates available": "Es sind Aktualisierungen verfügbar",
"There is a mailbox with such email. Users and mailboxes can not have the same email addresses.": "Die E-Mail Adresse wird bereits verwendet. Postfächer und Benutzer müssen eindeutige E-Mail Adressen haben.",
"There is a new conversation": "Es gibt eine neue Konversation",
"There is a problem processing outgoing mail queue — an admin should check :%a_begin%System Status:%a_end% and :%a_begin_recommendations%Recommendations:%a_end%": "Es ist ein Fehler mit der Warteschlange für ausgehende E-Mails aufgetreten. — Ein Administrator sollte :%a_begin%System Status:%a_end% und :%a_begin_recommendations%Recommendations:%a_end% prüfen.",
"There is a user with such email. Users and mailboxes can not have the same email addresses.": "Mit dieser E-Mail Adresse wurde bereits ein Benutzerkonto verknüpft. Postfächer und Benutzerkonten können nicht die selbe E-Mail Adresse haben.",
"There were no send attempts yet": "Es gibt noch keine Sendeversuche",
"These folders must be writable by web server user (:user).": "Der Webserver Benutzer (:user) muss für diese Ordner Schreibrechte besitzen.",
"These settings are used to send system emails (alerts to admin and invitation emails to users).": "Diese Einstellungen werden verwendet um System-E-Mails zu versenden (Warnungen an Admins und Einladungen an Benutzer).",
Expand Down Expand Up @@ -705,8 +708,8 @@
"Total": "Insgesamt",
"Translate": "Übersetzen",
"Try to :%a_start%clear cache:%a_end% to force command to start.": "Versuche den :%a_start%Cache zu leeren:%a_end% um den Befehl zu starten.",
"Type": "Gesprächsart",
"Type :delete": "Schreibe :delete",
"Type": "Typ",
"Type :delete": "Typ :delete",
"Unable to process your update": "Fehler beim Durchführen der Aktualisierung",
"Unassigned": "Nicht zugewiesen",
"Unfollow": "Nicht mehr folgen",
Expand Down
Loading

0 comments on commit b6987dd

Please sign in to comment.