1
0
mirror of https://github.com/freescout-helpdesk/freescout.git synced 2024-11-25 20:02:30 +01:00
freescout/app/Misc/Mail.php
2018-12-06 01:13:04 -08:00

373 lines
11 KiB
PHP

<?php
namespace App\Misc;
use App\Mailbox;
use App\Option;
use App\SendLog;
use Webklex\IMAP\Client;
// todo: rename into MailHelper
class Mail
{
/**
* Reply separators.
*/
const REPLY_SEPARATOR_HTML = 'fsReplyAbove';
const REPLY_SEPARATOR_TEXT = '-- Please reply above this line --';
/**
* Message-ID prefixes for outgoing emails.
*/
const MESSAGE_ID_PREFIX_NOTIFICATION = 'notify';
const MESSAGE_ID_PREFIX_NOTIFICATION_IN_REPLY = 'conversation';
const MESSAGE_ID_PREFIX_REPLY_TO_CUSTOMER = 'reply';
const MESSAGE_ID_PREFIX_AUTO_REPLY = 'autoreply';
/**
* Mail drivers.
*/
const MAIL_DRIVER_MAIL = 'mail';
const MAIL_DRIVER_SENDMAIL = 'sendmail';
const MAIL_DRIVER_SMTP = 'smtp';
/**
* Encryptions.
*/
const MAIL_ENCRYPTION_NONE = '';
const MAIL_ENCRYPTION_SSL = 'ssl';
const MAIL_ENCRYPTION_TLS = 'tls';
/**
* If reply is not extracted properly from the incoming email, add here a new separator.
* Order is not important.
* Idially separators must contain < or > to avoid false positives.
* If there will be problems, convert into regular expressions.
*/
public static $alternative_reply_separators = [
self::REPLY_SEPARATOR_HTML, // Our HTML separator
self::REPLY_SEPARATOR_TEXT, // Our plain text separator
'<div class="gmail_quote">', // Gmail
'yahoo_quoted_', // Yahoo, full: <div id=3D"ydp6h4f5c59yahoo_quoted_2937493705"
'<blockquote', // General sepator
'<!-- originalMessage -->',
//'---Original---', // QQ separator, wait for emails from QQ and check
];
/**
* Configure mail sending parameters.
*
* @param App\Mailbox $mailbox
*/
public static function setMailDriver($mailbox = null, $user_from = null)
{
if ($mailbox) {
// Configure mail driver according to Mailbox settings
\Config::set('mail.driver', $mailbox->getMailDriverName());
\Config::set('mail.from', $mailbox->getMailFrom($user_from));
// SMTP
if ($mailbox->out_method == Mailbox::OUT_METHOD_SMTP) {
\Config::set('mail.host', $mailbox->out_server);
\Config::set('mail.port', $mailbox->out_port);
\Config::set('mail.username', $mailbox->out_username);
\Config::set('mail.password', $mailbox->out_password);
\Config::set('mail.encryption', $mailbox->getOutEncryptionName());
}
} else {
// Use default settings
\Config::set('mail.driver', \Config::get('mail.driver'));
\Config::set('mail.from', ['address' => self::getSystemMailFrom(), 'name' => '']);
}
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
}
/**
* Set system mail driver for sending system emails to users.
*
* @param App\Mailbox $mailbox
*/
public static function setSystemMailDriver()
{
\Config::set('mail.driver', self::getSystemMailDriver());
\Config::set('mail.from', [
'address' => self::getSystemMailFrom(),
'name' => Option::get('company_name', \Config::get('app.name')),
]);
// SMTP
if (\Config::get('mail.driver') == self::MAIL_DRIVER_SMTP) {
\Config::set('mail.host', Option::get('mail_host'));
\Config::set('mail.port', Option::get('mail_port'));
\Config::set('mail.username', Option::get('mail_username'));
\Config::set('mail.password', Option::get('mail_password'));
\Config::set('mail.encryption', Option::get('mail_encryption'));
}
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
}
/**
* Replace mail vars in the text.
*/
public static function replaceMailVars($text, $data = [])
{
// Available variables to insert into email in UI.
$vars = [];
if (!empty($data['conversation'])) {
$vars['{%subject%}'] = $data['conversation']->subject;
$vars['{%conversation.number%}'] = $data['conversation']->number;
$vars['{%customer.email%}'] = $data['conversation']->customer_email;
}
if (!empty($data['mailbox'])) {
$vars['{%mailbox.email%}'] = $data['mailbox']->email;
$vars['{%mailbox.name%}'] = $data['mailbox']->name;
}
if (!empty($data['customer'])) {
$vars['{%customer.fullName%}'] = $data['customer']->getFullName(true);
$vars['{%customer.firstName%}'] = $data['customer']->getFirstName(true);
$vars['{%customer.lastName%}'] = $data['customer']->last_name;
}
if (!empty($data['user'])) {
$vars['{%user.fullName%}'] = $data['user']->getFullName();
$vars['{%user.firstName%}'] = $data['user']->getFirstName();
$vars['{%user.lastName%}'] = $data['user']->last_name;
}
return strtr($text, $vars);
}
/**
* Check if text has vars in it.
*/
public static function hasVars($text)
{
return preg_match('/({%|%})/', $text);
}
/**
* Remove email from a list of emails.
*/
public static function removeEmailFromArray($list, $email)
{
return array_diff($list, [$email]);
}
/**
* From address for sending system emails.
*/
public static function getSystemMailFrom()
{
$mail_from = Option::get('mail_from');
if (!$mail_from) {
$mail_from = 'freescout@'.\Helper::getDomain();
}
return $mail_from;
}
/**
* Mail driver for sending system emails.
*/
public static function getSystemMailDriver()
{
return Option::get('mail_driver', 'mail');
}
/**
* Send test email from mailbox.
*/
public static function sendTestMail($to, $mailbox = null)
{
if ($mailbox) {
// Configure mail driver according to Mailbox settings
\MailHelper::setMailDriver($mailbox);
$status_message = '';
try {
\Mail::to([$to])->send(new \App\Mail\Test($mailbox));
} catch (\Exception $e) {
// We come here in case SMTP server unavailable for example
$status_message = $e->getMessage();
}
} else {
// System email
\MailHelper::setSystemMailDriver();
$status_message = '';
try {
\Mail::to([['name' => '', 'email' => $to]])
->send(new \App\Mail\Test());
} catch (\Exception $e) {
// We come here in case SMTP server unavailable for example
$status_message = $e->getMessage();
}
}
if (\Mail::failures() || $status_message) {
SendLog::log(null, null, $to, SendLog::MAIL_TYPE_TEST, SendLog::STATUS_SEND_ERROR, null, null, $status_message);
if ($status_message) {
throw new \Exception($status_message, 1);
} else {
return false;
}
} else {
SendLog::log(null, null, $to, SendLog::MAIL_TYPE_TEST, SendLog::STATUS_ACCEPTED);
return true;
}
}
/**
* Check POP3/IMAP connection to the mailbox.
*/
public static function fetchTest($mailbox)
{
$client = new Client([
'host' => $mailbox->in_server,
'port' => $mailbox->in_port,
'encryption' => $mailbox->getInEncryptionName(),
'validate_cert' => true,
'username' => $mailbox->in_username,
'password' => $mailbox->in_password,
'protocol' => $mailbox->getInProtocolName(),
]);
// Connect to the Server
$client->connect();
// Get folder
$folder = $client->getFolder('INBOX');
if (!$folder) {
throw new \Exception('Could not get mailbox folder: INBOX', 1);
}
// Get unseen messages for a period
$messages = $folder->query()->unseen()->since(now()->subDays(1))->leaveUnread()->get();
if ($client->getLastError()) {
throw new \Exception($client->getLastError(), 1);
} else {
return true;
}
}
/**
* Convert list of emails to array.
*
* @return array
*/
public static function sanitizeEmails($emails)
{
$emails_array = [];
if (is_array($emails)) {
$emails_array = $emails;
} else {
$emails_array = explode(',', $emails);
}
foreach ($emails_array as $i => $email) {
$emails_array[$i] = \App\Email::sanitizeEmail($email);
if (!$emails_array[$i]) {
unset($emails_array[$i]);
}
}
return $emails_array;
}
/**
* Check if email format is valid.
*
* @param [type] $email [description]
* @return [type] [description]
*/
public static function validateEmail($email)
{
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
/**
* Send system alert to super admin.
*/
public static function sendAlertMail($text, $title = '')
{
\App\Jobs\SendAlert::dispatch($text, $title)->onQueue('emails');
}
/**
* Send email to developers team.
*/
public static function sendEmailToDevs($subject, $body, $attachments = [], $from_user = null)
{
// Configure mail driver according to Mailbox settings
\MailHelper::setSystemMailDriver();
$status_message = '';
try {
\Mail::raw($body, function ($message) use ($subject, $attachments, $from_user) {
$message
->subject($subject)
->to(\Config::get('app.freescout_email'));
if ($attachments) {
foreach ($attachments as $attachment) {
$message->attach($attachment);
}
}
// Set user as Reply-To
if ($from_user) {
$message->replyTo($from_user->email, $from_user->getFullName());
}
});
} catch (\Exception $e) {
\Log::error(\Helper::formatException($e));
// We come here in case SMTP server unavailable for example
return false;
}
if (\Mail::failures()) {
return false;
} else {
return true;
}
}
/**
* Get email marker for the outgoing email to track replies
* in case Message-ID header is removed by mail service provider.
*
* @param [type] $message_id [description]
*
* @return [type] [description]
*/
public static function getMessageMarker($message_id)
{
// It has to be BASE64, as Gmail converts it into link.
return '{#FS:'.base64_encode($message_id).'#}';
}
/**
* Fetch Message-ID from incoming email body.
*
* @param [type] $message_id [description]
*
* @return [type] [description]
*/
public static function fetchMessageMarkerValue($body)
{
preg_match('/{#FS:([^#]+)#}/', $body, $matches);
if (!empty($matches[1]) && base64_decode($matches[1])) {
// Return first found marker.
return base64_decode($matches[1]);
}
return '';
}
}