diff --git a/app/Http/Controllers/AppController.php b/app/Http/Controllers/AppController.php
new file mode 100644
index 0000000..c1e8bfe
--- /dev/null
+++ b/app/Http/Controllers/AppController.php
@@ -0,0 +1,54 @@
+enable_create_from_url) {
+ ZEmail::createCustomEmailFull($email);
+ }
+ return redirect()->route('mailbox');
+ }
+ if (!ZEmail::getEmail()) {
+ return redirect()->route('home');
+ }
+ if (json_decode(config('app.settings.configuration_settings'))->disable_mailbox_slug) {
+ return redirect()->route('home');
+ }
+ return $this->app();
+ }
+
+ public function app() {
+ return redirect()->route('home');
+ }
+
+ private function getStringBetween($string, $start, $end) {
+ $string = ' ' . $string;
+ $ini = strpos($string, $start);
+ if ($ini == 0) return '';
+ $ini += strlen($start);
+ $len = strpos($string, $end, $ini) - $ini;
+ return substr($string, $ini, $len);
+ }
+ private function setHeaders($page) {
+ $header = $page->header;
+ foreach ($page->meta ? unserialize($page->meta) : [] as $meta) {
+ if ($meta['name'] == 'canonical') {
+ $header .= '';
+ } else if (str_contains($meta['name'], 'og:')) {
+ $header .= '';
+ } else {
+ $header .= '';
+ }
+ }
+ $page->header = $header;
+ return $page;
+ }
+
+
+}
diff --git a/app/Livewire/Email.php b/app/Livewire/Email.php
new file mode 100644
index 0000000..6b4f259
--- /dev/null
+++ b/app/Livewire/Email.php
@@ -0,0 +1,13 @@
+currentEmail = ZEmail::getEmail();
+ $this->loadMessages();
+ }
+
+ public function loadMessages()
+ {
+ if ($this->currentEmail) {
+ $this->messages = ZEmail::getMessages($this->currentEmail);
+ }
+ }
+
+ public function selectMessage($messageId)
+ {
+ $this->selectedMessage = $messageId;
+ }
+
+ public function deleteMessage($messageId)
+ {
+ ZEmail::deleteMessage($messageId);
+ $this->loadMessages();
+ $this->selectedMessage = null;
+ }
+
+ public function generateNewEmail()
+ {
+ $this->currentEmail = ZEmail::generateRandomEmail();
+ $this->loadMessages();
+ }
+
+ public function getPollingInterval()
+ {
+ return $this->refreshInterval * 1000; // Convert to milliseconds
+ }
+
+ public function render()
+ {
+ return view('livewire.email-inbox', [
+ 'messages' => $this->messages,
+ 'currentEmail' => $this->currentEmail
+ ]);
+ }
+}
diff --git a/app/Livewire/Frontend/Action.php b/app/Livewire/Frontend/Action.php
new file mode 100644
index 0000000..626f823
--- /dev/null
+++ b/app/Livewire/Frontend/Action.php
@@ -0,0 +1,134 @@
+domains = json_decode(config('app.settings.configuration_settings'))->domains ?? [];
+ $this->email = ZEmail::getEmail();
+ $this->emails = ZEmail::getEmails();
+ $this->validateDomainInEmail();
+ }
+
+ public function create() {
+ if (!$this->username) {
+ return $this->showAlert('error', __('Please enter Username'));
+ }
+ $this->checkDomainInUsername();
+ if (strlen($this->username) < json_decode(config('app.settings.configuration_settings'))->custom_username_length_min || strlen($this->username) > json_decode(config('app.settings.configuration_settings'))->custom_username_length_max) {
+ return $this->showAlert('error', __('Username length cannot be less than') . ' ' . json_decode(config('app.settings.configuration_settings'))->custom_username_length_min . ' ' . __('and greater than') . ' ' . json_decode(config('app.settings.configuration_settings'))->custom_username_length_max);
+ }
+ if (!$this->domain) {
+ return $this->showAlert('error', __('Please Select a Domain'));
+ }
+ if (in_array($this->username, json_decode(config('app.settings.configuration_settings'))->forbidden_ids)) {
+ return $this->showAlert('error', __('Username not allowed'));
+ }
+ if (!$this->checkEmailLimit()) {
+ return $this->showAlert('error', __('You have reached daily limit of MAX ') . json_decode(config('app.settings.configuration_settings'))->email_limit . __(' temp mail'));
+ }
+ if (!$this->checkUsedEmail()) {
+ return $this->showAlert('error', __('Sorry! That email is already been used by someone else. Please try a different email address.'));
+ }
+
+ $this->email = ZEmail::createCustomEmail($this->username, $this->domain);
+ $this->dispatch('updateEmail');
+ $this->dispatch('closeModal');
+
+ }
+ public function random() {
+ if (!$this->checkEmailLimit()) {
+ return $this->showAlert('error', __('You have reached daily limit of maximum ') . json_decode(config('app.settings.configuration_settings'))->email_limit . __(' temp mail addresses.'));
+ }
+ $this->email = ZEmail::generateRandomEmail();
+ $this->dispatch('updateEmail');
+ $this->dispatch('closeModal');
+
+ //$this->redirect(route('mailbox'));
+ }
+
+ public function gmail() {
+ if (!$this->checkEmailLimit()) {
+ return $this->showAlert('error', __('You have reached daily limit of maximum ') . json_decode(config('app.settings.configuration_settings'))->email_limit . __(' temp mail addresses.'));
+ }
+ $this->email = ZEmail::generateRandomGmail();
+ $this->dispatch('updateEmail');
+ $this->dispatch('closeModal');
+ }
+
+ public function deleteEmail() {
+ ZEmail::removeEmail($this->email);
+// if (count($this->emails) <= 1 && json_decode(config('app.settings.configuration_settings'))->after_last_email_delete == 'redirect_to_homepage') {
+// return redirect()->route('home');
+// }
+ $this->email = ZEmail::getEmail(true);
+ $this->emails = ZEmail::getEmails();
+
+ $this->dispatch('updateEmail');
+ $this->dispatch('closeModal');
+ }
+
+ private function showAlert($type, $message): void
+ {
+ $this->dispatch('showAlert', ['type' => $type, 'message' => $message]);
+ }
+
+ private function checkEmailLimit() {
+ $logs = Log::select('ip', 'email')->where('ip', request()->ip())->where('created_at', '>', Carbon::now()->subDay())->groupBy('email')->groupBy('ip')->get();
+ if (count($logs) >= json_decode(config('app.settings.configuration_settings'))->email_limit) {
+ return false;
+ }
+ return true;
+ }
+
+ private function checkUsedEmail() {
+ if (json_decode(config('app.settings.configuration_settings'))->disable_used_email) {
+ $check = Log::where('email', $this->user . '@' . $this->domain)->where('ip', '<>', request()->ip())->count();
+ if ($check > 0) {
+ return false;
+ }
+ return true;
+ }
+ return true;
+ }
+
+ private function checkDomainInUsername() {
+ $parts = explode('@', $this->username);
+ if (isset($parts[1])) {
+ if (in_array($parts[1], $this->domains)) {
+ $this->domain = $parts[1];
+ }
+ $this->username = $parts[0];
+ }
+ }
+
+ private function validateDomainInEmail(): void
+ {
+ $data = explode('@', $this->email);
+ if (isset($data[1])) {
+ $domain = $data[1];
+ $domains = json_decode(config('app.settings.configuration_settings'))->domains ?? [];
+ if (!in_array($domain, $domains)) {
+ $key = array_search($this->email, $this->emails);
+ ZEmail::removeEmail($this->email);
+ if ($key == 0 && count($this->emails) == 1 && json_decode(config('app.settings.configuration_settings'))->after_last_email_delete == 'redirect_to_homepage') {
+ redirect()->route('home');
+ } else {
+ redirect()->route('mailbox');
+ }
+ }
+ }
+ }
+ public function render() {
+ return view('livewire.frontend.action');
+ }
+}
diff --git a/app/Livewire/Frontend/ActionOld.php b/app/Livewire/Frontend/ActionOld.php
new file mode 100644
index 0000000..1931052
--- /dev/null
+++ b/app/Livewire/Frontend/ActionOld.php
@@ -0,0 +1,222 @@
+domains = config('app.settings.domains');
+ $this->email = ZEmail::getEmail();
+ $this->emails = ZEmail::getEmails();
+ $this->validateDomainInEmail();
+ }
+
+ public function refreshMessages()
+ {
+ $this->emit('fetchMessages');
+ }
+
+ public function loadMsg($email) {
+ $this->email = $email;
+ if (count($this->emails) == 0) {
+ $this->emails = [$email];
+ }
+ }
+
+ public function syncEmail($email) {
+ $this->email = $email;
+ if (count($this->emails) == 0) {
+ $this->emails = [$email];
+ }
+ }
+
+ public function setDomain($domain) {
+ $this->domain = $domain;
+ }
+
+ public function checkReCaptcha3($token, $action) {
+ $response = Http::post('https://www.google.com/recaptcha/api/siteverify?secret=' . config('app.settings.recaptcha3.secret_key') . '&response=' . $token);
+ $data = $response->json();
+ if ($data['success']) {
+ $captcha = $data['score'];
+ if ($captcha > 0.5) {
+ if ($action == 'create') {
+ $this->create();
+ } else {
+ $this->random();
+ }
+ } else {
+ return $this->showAlert('error', __('Captcha Failed! Please try again'));
+ }
+ } else {
+ return $this->showAlert('error', __('Captcha Failed! Error: ') . json_encode($data['error-codes']));
+ }
+ }
+ public function create() {
+ if (!$this->user) {
+ return $this->showAlert('error', __('Please enter Username'));
+ }
+ $this->checkDomainInUsername();
+ if (strlen($this->user) < config('app.settings.custom.min') || strlen($this->user) > config('app.settings.custom.max')) {
+ return $this->showAlert('error', __('Username length cannot be less than') . ' ' . config('app.settings.custom.min') . ' ' . __('and greater than') . ' ' . config('app.settings.custom.max'));
+ }
+ if (!$this->domain) {
+ return $this->showAlert('error', __('Please Select a Domain'));
+ }
+ if (in_array($this->user, config('app.settings.forbidden_ids'))) {
+ return $this->showAlert('error', __('Username not allowed'));
+ }
+ if (!$this->checkEmailLimit()) {
+ return $this->showAlert('error', __('You have reached daily limit of MAX ') . config('app.settings.email_limit', 5) . __(' temp mail'));
+ }
+ if (!$this->checkUsedEmail()) {
+ return $this->showAlert('error', __('Sorry! That email is already been used by someone else. Please try a different email address.'));
+ }
+ if (!$this->validateCaptcha()) {
+ return $this->showAlert('error', __('Invalid Captcha. Please try again'));
+ }
+ $this->email = ZEmail::createCustomEmail($this->user, $this->domain);
+ $this->redirect(route('mailbox'));
+ }
+
+ public function random() {
+ if (!$this->checkEmailLimit()) {
+ return $this->showAlert('error', __('You have reached daily limit of maximum ') . config('app.settings.email_limit', 5) . __(' temp mail addresses.'));
+ }
+ if (!$this->validateCaptcha()) {
+ return $this->showAlert('error', __('Invalid Captcha. Please try again'));
+ }
+ $this->email = ZEmail::generateRandomEmail();
+ $this->redirect(route('mailbox'));
+ }
+
+ public function tempgmail() {
+ if (!$this->checkEmailLimit()) {
+ return $this->showAlert('error', __('You have reached daily limit of maximum ') . config('app.settings.email_limit', 5) . __(' temp mail addresses.'));
+ }
+ if (!$this->validateCaptcha()) {
+ return $this->showAlert('error', __('Invalid Captcha. Please try again'));
+ }
+ $this->email = ZEmail::generateRandomGmail();
+ $this->redirect(route('mailbox'));
+ }
+
+ public function deleteEmail() {
+ ZEmail::removeEmail($this->email);
+ if (count($this->emails) == 1 && config('app.settings.after_last_email_delete') == 'redirect_to_homepage') {
+ return redirect()->route('home');
+ }
+ $this->email = ZEmail::getEmail(true);
+ $this->emails = ZEmail::getEmails();
+ return redirect()->route('mailbox');
+ }
+
+ public function render() {
+ if (count($this->emails) >= intval(config('app.settings.email_limit', 5))) {
+ for ($i = 0; $i < (count($this->emails) - intval(config('app.settings.email_limit', 5))); $i++) {
+ ZEmail::removeEmail($this->emails[$i]);
+ }
+ $this->emails = ZEmail::getEmails();
+ ZEmail::setEmail($this->email);
+ }
+ return view('livewire.frontend.action');
+ }
+
+ /**
+ * Private Functions
+ */
+
+ private function showAlert($type, $message) {
+ $this->dispatchBrowserEvent('showAlert', ['type' => $type, 'message' => $message]);
+ }
+
+ /**
+ * Don't allow used email
+ */
+ private function checkUsedEmail() {
+ if (config('app.settings.disable_used_email', false)) {
+ $check = Log::where('email', $this->user . '@' . $this->domain)->where('ip', '<>', request()->ip())->count();
+ if ($check > 0) {
+ return false;
+ }
+ return true;
+ }
+ return true;
+ }
+
+ /**
+ * Validate Captcha
+ */
+ private function validateCaptcha() {
+ if (config('app.settings.captcha') == 'hcaptcha') {
+ $response = Http::asForm()->post('https://hcaptcha.com/siteverify', [
+ 'response' => $this->captcha,
+ 'secret' => config('app.settings.hcaptcha.secret_key')
+ ])->object();
+ return $response->success;
+ } else if (config('app.settings.captcha') == 'recaptcha2') {
+ $response = Http::asForm()->post('https://www.google.com/recaptcha/api/siteverify', [
+ 'response' => $this->captcha,
+ 'secret' => config('app.settings.recaptcha2.secret_key')
+ ])->object();
+ return $response->success;
+ }
+ return true;
+ }
+
+ /**
+ * Check if the user is crossing email limit
+ */
+ private function checkEmailLimit() {
+ $logs = Log::select('ip', 'email')->where('ip', request()->ip())->where('created_at', '>', Carbon::now()->subDay())->groupBy('email')->groupBy('ip')->get();
+ if (count($logs) >= config('app.settings.email_limit', 5)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check if Username already consist of Domain
+ */
+ private function checkDomainInUsername() {
+ $parts = explode('@', $this->user);
+ if (isset($parts[1])) {
+ if (in_array($parts[1], $this->domains)) {
+ $this->domain = $parts[1];
+ }
+ $this->user = $parts[0];
+ }
+ }
+
+ /**
+ * Validate if Domain in Email Exist
+ */
+ private function validateDomainInEmail() {
+ $data = explode('@', $this->email);
+ if (isset($data[1])) {
+ $domain = $data[1];
+ $domains = config('app.settings.domains');
+ if (!in_array($domain, $domains)) {
+ $key = array_search($this->email, $this->emails);
+ TMail::removeEmail($this->email);
+ if ($key == 0 && count($this->emails) == 1 && config('app.settings.after_last_email_delete') == 'redirect_to_homepage') {
+ return redirect()->route('home');
+ } else {
+ return redirect()->route('mailbox');
+ }
+ }
+ }
+ }
+
+}
diff --git a/app/Livewire/Frontend/App.php b/app/Livewire/Frontend/App.php
new file mode 100644
index 0000000..66f643d
--- /dev/null
+++ b/app/Livewire/Frontend/App.php
@@ -0,0 +1,109 @@
+ 'fetch', 'syncEmail'];
+
+ public function mount()
+ {
+ $this->email = ZEmail::getEmails();
+ $this->initial = false;
+ }
+
+ public function syncEmail($email) {
+ $this->email = $email;
+ }
+
+ public function fetch() {
+ try {
+ $count = count($this->messages);
+ $responses = [];
+ if (config('app.beta_feature') || !json_decode(config('app.settings.imap_settings'))->cc_check) {
+ $responses = [
+ 'to' => ZEmail::getMessages($this->email, 'to', $this->deleted),
+ 'cc' => [
+ 'data' => [],
+ 'notifications' => []
+ ]
+ ];
+ } else {
+ $responses = [
+ 'to' => ZEmail::getMessages($this->email, 'to', $this->deleted),
+ 'cc' => ZEmail::getMessages($this->email, 'cc', $this->deleted)
+ ];
+ }
+ $this->deleted = [];
+ $this->messages = array_merge($responses['to']['data'], $responses['cc']['data']);
+ $notifications = array_merge($responses['to']['notifications'], $responses['cc']['notifications']);
+ if (count($notifications)) {
+ if ($this->overflow == false && count($this->messages) == $count) {
+ $this->overflow = true;
+ }
+ } else {
+ $this->overflow = false;
+ }
+ foreach ($notifications as $notification) {
+ $this->dispatchBrowserEvent('showNewMailNotification', $notification);
+ }
+ ZEmail::incrementMessagesStats(count($notifications));
+ } catch (\Exception $e) {
+ if (Auth::check() && Auth::user()->level == 9) {
+ $this->error = $e->getMessage();
+ } else {
+ $this->error = 'Not able to connect to Mail Server';
+ }
+ }
+ $this->dispatchBrowserEvent('stopLoader');
+ $this->dispatchBrowserEvent('loadDownload');
+ $this->initial = true;
+ }
+
+ public function delete($messageId) {
+ if (config('app.beta_feature')) {
+ Message::find($messageId)->delete();
+ }
+ $this->deleted[] = $messageId;
+ foreach ($this->messages as $key => $message) {
+ if ($message['id'] == $messageId) {
+ $directory = './tmp/attachments/' . $messageId;
+ $this->rrmdir($directory);
+ unset($this->messages[$key]);
+ }
+ }
+ }
+
+ public function render()
+ {
+ return view('livewire.frontend.app');
+ }
+ private function rrmdir($dir): void
+ {
+ if (is_dir($dir)) {
+ $objects = scandir($dir);
+ foreach ($objects as $object) {
+ if ($object != "." && $object != "..") {
+ if (is_dir($dir . DIRECTORY_SEPARATOR . $object) && !is_link($dir . "/" . $object))
+ $this->rrmdir($dir . DIRECTORY_SEPARATOR . $object);
+ else
+ unlink($dir . DIRECTORY_SEPARATOR . $object);
+ }
+ }
+ rmdir($dir);
+ }
+ }
+
+}
diff --git a/app/Livewire/Frontend/Email.php b/app/Livewire/Frontend/Email.php
new file mode 100644
index 0000000..22d34f8
--- /dev/null
+++ b/app/Livewire/Frontend/Email.php
@@ -0,0 +1,65 @@
+ 'syncEmail', 'getEmail' => 'generateEmail'];
+
+ public function mount(): void
+ {
+ $this->email = ZEmail::getEmail();
+ $this->emails = ZEmail::getEmails();
+ $this->initial = false;
+ $this->checkMultipleEmails();
+ }
+
+ private function checkMultipleEmails(): void
+ {
+ if (count($this->emails) == 0) {
+ $this->emails = [$this->email];
+ }
+ if (count($this->emails) > 1) {
+ $this->list = true;
+ } else {
+ $this->list = false;
+ }
+ }
+
+ public function switchEmail($email): void
+ {
+ ZEmail::setEmail($email);
+ $this->email = $email;
+ $this->dispatch('updateEmail');
+ }
+
+ public function syncEmail(): void
+ {
+ $this->email = ZEmail::getEmail();
+ $this->emails = ZEmail::getEmails();
+ if (count($this->emails) == 0) {
+ $this->dispatch('getEmail');
+ }
+ $this->checkMultipleEmails();
+ }
+
+ public function generateEmail(): void
+ {
+ if ($this->email == null) {
+ ZEmail::generateRandomEmail();
+ }
+ $this->checkMultipleEmails();
+ $this->dispatch('updateEmail');
+ }
+
+ public function render()
+ {
+ return view('livewire.frontend.email')->with(['email' => $this->email, 'emails' => $this->emails, 'initial' => $this->initial, 'type' => $this->type, 'list' => $this->list]);
+ }
+}
diff --git a/app/Livewire/Home.php b/app/Livewire/Home.php
new file mode 100644
index 0000000..0374ba4
--- /dev/null
+++ b/app/Livewire/Home.php
@@ -0,0 +1,13 @@
+created_at;
- $obj['date'] = $message->created_at->format(json_decode(config('app.settings.configuration_settings'))->date_format, 'd M Y h:i A');
+ $obj['date'] = $message->created_at->format(json_decode(config('app.settings.configuration_settings'))->date_format ?? 'd M Y h:i A');
$obj['datediff'] = $message->created_at->diffForHumans();
$obj['id'] = $message->id;
$obj['content'] = $content;
@@ -105,4 +110,239 @@ class Message extends Model
}
return $response;
}
+
+ public static function fetchMessages($email, $type = 'to', $deleted = []): array
+ {
+ $allowed = explode(',', 'doc,docx,xls,xlsx,ppt,pptx,xps,pdf,dxf,ai,psd,eps,ps,svg,ttf,zip,rar,tar,gzip,mp3,mpeg,wav,ogg,jpeg,jpg,png,gif,bmp,tif,webm,mpeg4,3gpp,mov,avi,mpegs,wmv,flx,txt');
+ $connection = ZEmail::connectMailBox();
+
+ $mailbox = $connection->getMailbox('INBOX');
+ $search = new SearchExpression();
+ if ($type == 'cc') {
+ $search->addCondition(new Cc($email));
+ } else {
+ $search->addCondition(new To($email));
+ }
+ $search->addCondition(new Since((new \DateTime('-1 day'))));
+ $messages = $mailbox->getMessages($search, \SORTDATE, true);
+ $limit = json_decode(config('app.settings.configuration_settings'))->fetch_messages_limit ?? 15;
+ $count = 1;
+ $response = [
+ 'data' => [],
+ 'notifications' => []
+ ];
+
+ foreach ($messages as $message) {
+ if (in_array($message->getNumber(), $deleted)) {
+ $message->delete();
+ continue;
+ }
+ $blocked = false;
+ $sender = $message->getFrom();
+ $date = $message->getDate();
+ if (!$date) {
+ $date = new \DateTime();
+ if ($message->getHeaders()->get('udate')) {
+ $date->setTimestamp($message->getHeaders()->get('udate'));
+ }
+ }
+ $datediff = new Carbon($date);
+ $content = '';
+ $html = $message->getBodyHtml();
+ if ($html) {
+ $content = str_replace('getBodyText();
+ $content = str_replace('', $text));
+ }
+ if (json_decode(config('app.settings.configuration_settings'))->enable_masking_external_link) {
+ $content = str_replace('href="', 'href="http://href.li/?', $content);
+ }
+ $obj = [];
+ $obj['subject'] = $message->getSubject();
+ $obj['sender_name'] = $sender->getName();
+ $obj['sender_email'] = $sender->getAddress();
+ $obj['timestamp'] = $message->getDate();
+ $obj['date'] = $date->format(json_decode(config('app.settings.configuration_settings'))->date_format ?? 'd M Y h:i A');
+ $obj['datediff'] = $datediff->diffForHumans();
+ $obj['id'] = $message->getNumber();
+ $obj['content'] = $content;
+ $obj['attachments'] = [];
+ //Checking if Sender is Blocked
+ $domain = explode('@', $obj['sender_email'])[1];
+ $blocked = in_array($domain, json_decode(config('app.settings.configuration_settings'))->blocked_domains);
+ if ($blocked) {
+ $obj['subject'] = __('Blocked');
+ $obj['content'] = __('Emails from') . ' ' . $domain . ' ' . __('are blocked by Admin');
+ }
+ if ($message->hasAttachments() && !$blocked) {
+ $attachments = $message->getAttachments();
+ $directory = './tmp/attachments/' . $obj['id'] . '/';
+ is_dir($directory) || mkdir($directory, 0777, true);
+ foreach ($attachments as $attachment) {
+ $filenameArray = explode('.', $attachment->getFilename());
+ $extension = $filenameArray[count($filenameArray) - 1];
+ if (in_array($extension, $allowed)) {
+ if (!file_exists($directory . $attachment->getFilename())) {
+ file_put_contents(
+ $directory . $attachment->getFilename(),
+ $attachment->getDecodedContent()
+ );
+ }
+ if ($attachment->getFilename() !== 'undefined') {
+ $url = config('app.settings.app_base_url') . str_replace('./', '/', $directory . $attachment->getFilename());
+ $structure = $attachment->getStructure();
+ if (isset($structure->id) && str_contains($obj['content'], trim($structure->id, '<>'))) {
+ $obj['content'] = str_replace('cid:' . trim($structure->id, '<>'), $url, $obj['content']);
+ }
+ $obj['attachments'][] = [
+ 'file' => $attachment->getFilename(),
+ 'url' => $url
+ ];
+ }
+ }
+ }
+ }
+ $response['data'][] = $obj;
+ if (!$message->isSeen()) {
+ $response['notifications'][] = [
+ 'subject' => $obj['subject'],
+ 'sender_name' => $obj['sender_name'],
+ 'sender_email' => $obj['sender_email']
+ ];
+ if (config('app.zemail_log')) {
+ file_put_contents(storage_path('logs/zemail.csv'), request()->ip() . "," . date("Y-m-d h:i:s a") . "," . $obj['sender_email'] . "," . $email . PHP_EOL, FILE_APPEND);
+ }
+ }
+ $message->markAsSeen();
+ if (++$count > $limit) {
+ break;
+ }
+ }
+
+ $response['data'] = array_reverse($response['data']);
+ $connection->expunge();
+ return $response;
+ }
+
+// public static function fetchMessages($email, $type = 'to', $deleted = []): array
+// {
+// $startTime = microtime(true);
+// $allowed = explode(',', 'doc,docx,xls,xlsx,ppt,pptx,xps,pdf,dxf,ai,psd,eps,ps,svg,ttf,zip,rar,tar,gzip,mp3,mpeg,wav,ogg,jpeg,jpg,png,gif,bmp,tif,webm,mpeg4,3gpp,mov,avi,mpegs,wmv,flx,txt');
+// $connection = ZEmail::connectMailBox();
+//
+// $mailbox = $connection->getMailbox('INBOX');
+// $search = new SearchExpression();
+// if ($type == 'cc') {
+// $search->addCondition(new Cc($email));
+// } else {
+// $search->addCondition(new To($email));
+// }
+// $search->addCondition(new Since((new \DateTime('-1 day'))));
+// $stepStart = microtime(true);
+// $messages = $mailbox->getMessages($search, \SORTDATE, true);
+// \Log::info("1111 messages took: " . (microtime(true) - $stepStart));
+//
+// $limit = json_decode(config('app.settings.configuration_settings'))->fetch_messages_limit ?? 15;
+// $count = 1;
+// $response = [
+// 'data' => [],
+// 'notifications' => []
+// ];
+//
+// foreach ($messages as $message) {
+// if (in_array($message->getNumber(), $deleted)) {
+// $message->delete();
+// continue;
+// }
+// $blocked = false;
+// $sender = $message->getFrom();
+// $date = $message->getDate();
+// if (!$date) {
+// $date = new \DateTime();
+// if ($message->getHeaders()->get('udate')) {
+// $date->setTimestamp($message->getHeaders()->get('udate'));
+// }
+// }
+// $datediff = new Carbon($date);
+// $content = '';
+// $html = $message->getBodyHtml();
+// if ($html) {
+// $content = str_replace('getBodyText();
+// $content = str_replace('', $text));
+// }
+// if (json_decode(config('app.settings.configuration_settings'))->enable_masking_external_link) {
+// $content = str_replace('href="', 'href="http://href.li/?', $content);
+// }
+// $obj = [];
+// $obj['subject'] = $message->getSubject();
+// $obj['sender_name'] = $sender->getName();
+// $obj['sender_email'] = $sender->getAddress();
+// $obj['timestamp'] = $message->getDate();
+// $obj['date'] = $date->format(json_decode(config('app.settings.configuration_settings'))->date_format ?? 'd M Y h:i A');
+// $obj['datediff'] = $datediff->diffForHumans();
+// $obj['id'] = $message->getNumber();
+// $obj['content'] = $content;
+// $obj['attachments'] = [];
+// //Checking if Sender is Blocked
+// $domain = explode('@', $obj['sender_email'])[1];
+// $blocked = in_array($domain, json_decode(config('app.settings.configuration_settings'))->blocked_domains);
+// if ($blocked) {
+// $obj['subject'] = __('Blocked');
+// $obj['content'] = __('Emails from') . ' ' . $domain . ' ' . __('are blocked by Admin');
+// }
+// if ($message->hasAttachments() && !$blocked) {
+// $attachments = $message->getAttachments();
+// $directory = './tmp/attachments/' . $obj['id'] . '/';
+// is_dir($directory) || mkdir($directory, 0777, true);
+// foreach ($attachments as $attachment) {
+// $filenameArray = explode('.', $attachment->getFilename());
+// $extension = $filenameArray[count($filenameArray) - 1];
+// if (in_array($extension, $allowed)) {
+// if (!file_exists($directory . $attachment->getFilename())) {
+// file_put_contents(
+// $directory . $attachment->getFilename(),
+// $attachment->getDecodedContent()
+// );
+// }
+// if ($attachment->getFilename() !== 'undefined') {
+// $url = config('app.settings.app_base_url') . str_replace('./', '/', $directory . $attachment->getFilename());
+// $structure = $attachment->getStructure();
+// if (isset($structure->id) && str_contains($obj['content'], trim($structure->id, '<>'))) {
+// $obj['content'] = str_replace('cid:' . trim($structure->id, '<>'), $url, $obj['content']);
+// }
+// $obj['attachments'][] = [
+// 'file' => $attachment->getFilename(),
+// 'url' => $url
+// ];
+// }
+// }
+// }
+// }
+// $response['data'][] = $obj;
+// if (!$message->isSeen()) {
+// $response['notifications'][] = [
+// 'subject' => $obj['subject'],
+// 'sender_name' => $obj['sender_name'],
+// 'sender_email' => $obj['sender_email']
+// ];
+// if (config('app.zemail_log')) {
+// file_put_contents(storage_path('logs/zemail.csv'), request()->ip() . "," . date("Y-m-d h:i:s a") . "," . $obj['sender_email'] . "," . $email . PHP_EOL, FILE_APPEND);
+// }
+// }
+// $message->markAsSeen();
+// if (++$count > $limit) {
+// break;
+// }
+// }
+//
+// $response['data'] = array_reverse($response['data']);
+// $connection->expunge();
+// $endTime = microtime(true);
+// $executionTime = $endTime - $startTime;
+// \Log::info("getMessages execution time: {$executionTime} seconds");
+// return $response;
+// }
}
diff --git a/app/Models/ZEmail.php b/app/Models/ZEmail.php
index a971124..910cf9f 100644
--- a/app/Models/ZEmail.php
+++ b/app/Models/ZEmail.php
@@ -3,6 +3,7 @@
namespace App\Models;
use Carbon\Carbon;
+use Ddeboer\Imap\Search\Date\Since;
use Ddeboer\Imap\Search\Email\Cc;
use Ddeboer\Imap\Search\Email\To;
use Ddeboer\Imap\SearchExpression;
@@ -38,112 +39,7 @@ class ZEmail extends Model
if (config('app.beta_feature')) {
return Message::getMessages($email);
}
- $allowed = explode(',', 'doc,docx,xls,xlsx,ppt,pptx,xps,pdf,dxf,ai,psd,eps,ps,svg,ttf,zip,rar,tar,gzip,mp3,mpeg,wav,ogg,jpeg,jpg,png,gif,bmp,tif,webm,mpeg4,3gpp,mov,avi,mpegs,wmv,flx,txt');
- $connection = ZEmail::connectMailBox();
- $mailbox = $connection->getMailbox('INBOX');
- $search = new SearchExpression();
- if ($type == 'cc') {
- $search->addCondition(new Cc($email));
- } else {
- $search->addCondition(new To($email));
- }
- $messages = $mailbox->getMessages($search, \SORTDATE, true);
- $limit = json_decode(config('app.settings.configuration_settings'))->fetch_messages_limit ?? 15;
- $count = 1;
- $response = [
- 'data' => [],
- 'notifications' => []
- ];
- foreach ($messages as $message) {
- if (in_array($message->getNumber(), $deleted)) {
- $message->delete();
- continue;
- }
- $blocked = false;
- $sender = $message->getFrom();
- $date = $message->getDate();
- if (!$date) {
- $date = new \DateTime();
- if ($message->getHeaders()->get('udate')) {
- $date->setTimestamp($message->getHeaders()->get('udate'));
- }
- }
- $datediff = new Carbon($date);
- $content = '';
- $html = $message->getBodyHtml();
- if ($html) {
- $content = str_replace('getBodyText();
- $content = str_replace('', $text));
- }
- if (json_decode(config('app.settings.configuration_settings'))->enable_masking_external_link) {
- $content = str_replace('href="', 'href="http://href.li/?', $content);
- }
- $obj = [];
- $obj['subject'] = $message->getSubject();
- $obj['sender_name'] = $sender->getName();
- $obj['sender_email'] = $sender->getAddress();
- $obj['timestamp'] = $message->getDate();
- $obj['date'] = $date->format(json_decode(config('app.settings.configuration_settings'))->date_format, 'd M Y h:i A');
- $obj['datediff'] = $datediff->diffForHumans();
- $obj['id'] = $message->getNumber();
- $obj['content'] = $content;
- $obj['attachments'] = [];
- //Checking if Sender is Blocked
- $domain = explode('@', $obj['sender_email'])[1];
- $blocked = in_array($domain, json_decode(config('app.settings.configuration_settings'))->blocked_domains);
- if ($blocked) {
- $obj['subject'] = __('Blocked');
- $obj['content'] = __('Emails from') . ' ' . $domain . ' ' . __('are blocked by Admin');
- }
- if ($message->hasAttachments() && !$blocked) {
- $attachments = $message->getAttachments();
- $directory = './tmp/attachments/' . $obj['id'] . '/';
- is_dir($directory) || mkdir($directory, 0777, true);
- foreach ($attachments as $attachment) {
- $filenameArray = explode('.', $attachment->getFilename());
- $extension = $filenameArray[count($filenameArray) - 1];
- if (in_array($extension, $allowed)) {
- if (!file_exists($directory . $attachment->getFilename())) {
- file_put_contents(
- $directory . $attachment->getFilename(),
- $attachment->getDecodedContent()
- );
- }
- if ($attachment->getFilename() !== 'undefined') {
- $url = config('app.settings.app_base_url') . str_replace('./', '/', $directory . $attachment->getFilename());
- $structure = $attachment->getStructure();
- if (isset($structure->id) && str_contains($obj['content'], trim($structure->id, '<>'))) {
- $obj['content'] = str_replace('cid:' . trim($structure->id, '<>'), $url, $obj['content']);
- }
- $obj['attachments'][] = [
- 'file' => $attachment->getFilename(),
- 'url' => $url
- ];
- }
- }
- }
- }
- $response['data'][] = $obj;
- if (!$message->isSeen()) {
- $response['notifications'][] = [
- 'subject' => $obj['subject'],
- 'sender_name' => $obj['sender_name'],
- 'sender_email' => $obj['sender_email']
- ];
- if (config('app.zemail_log')) {
- file_put_contents(storage_path('logs/zemail.csv'), request()->ip() . "," . date("Y-m-d h:i:s a") . "," . $obj['sender_email'] . "," . $email . PHP_EOL, FILE_APPEND);
- }
- }
- $message->markAsSeen();
- if (++$count > $limit) {
- break;
- }
- }
- $response['data'] = array_reverse($response['data']);
- $connection->expunge();
- return $response;
+ return Message::fetchMessages($email, $type, $deleted);
}
public static function deleteMessage($id): void
diff --git a/composer.json b/composer.json
index 03b7421..f51eba3 100644
--- a/composer.json
+++ b/composer.json
@@ -11,6 +11,7 @@
"filament/filament": "3.3",
"laravel/framework": "^12.0",
"laravel/tinker": "^2.10.1",
+ "livewire/flux": "^2.1",
"livewire/livewire": "^3.6"
},
"require-dev": {
diff --git a/composer.lock b/composer.lock
index c7f2dd0..2a4065e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "3c178f04aa87a34364e767ad999d5889",
+ "content-hash": "8a5cd9a0ccf67c460d95ecb968192ef2",
"packages": [
{
"name": "anourvalar/eloquent-serialize",
@@ -3143,6 +3143,69 @@
],
"time": "2024-12-08T08:18:47+00:00"
},
+ {
+ "name": "livewire/flux",
+ "version": "v2.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/livewire/flux.git",
+ "reference": "a19709fc94f5a1b795ce24ad42662bd398c19371"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/livewire/flux/zipball/a19709fc94f5a1b795ce24ad42662bd398c19371",
+ "reference": "a19709fc94f5a1b795ce24ad42662bd398c19371",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/console": "^10.0|^11.0|^12.0",
+ "illuminate/support": "^10.0|^11.0|^12.0",
+ "illuminate/view": "^10.0|^11.0|^12.0",
+ "laravel/prompts": "^0.1|^0.2|^0.3",
+ "livewire/livewire": "^3.5.19",
+ "php": "^8.1",
+ "symfony/console": "^6.0|^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "aliases": {
+ "Flux": "Flux\\Flux"
+ },
+ "providers": [
+ "Flux\\FluxServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Flux\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "proprietary"
+ ],
+ "authors": [
+ {
+ "name": "Caleb Porzio",
+ "email": "calebporzio@gmail.com"
+ }
+ ],
+ "description": "The official UI component library for Livewire.",
+ "keywords": [
+ "components",
+ "flux",
+ "laravel",
+ "livewire",
+ "ui"
+ ],
+ "support": {
+ "issues": "https://github.com/livewire/flux/issues",
+ "source": "https://github.com/livewire/flux/tree/v2.1.4"
+ },
+ "time": "2025-04-14T11:59:19+00:00"
+ },
{
"name": "livewire/livewire",
"version": "v3.6.3",
diff --git a/public/images/logo.webp b/public/images/logo.webp
new file mode 100644
index 0000000..942d56c
Binary files /dev/null and b/public/images/logo.webp differ
diff --git a/public/images/user.webp b/public/images/user.webp
new file mode 100644
index 0000000..7c6ecba
Binary files /dev/null and b/public/images/user.webp differ
diff --git a/public/images/zemail-logo-dark.webp b/public/images/zemail-logo-dark.webp
new file mode 100644
index 0000000..f124840
Binary files /dev/null and b/public/images/zemail-logo-dark.webp differ
diff --git a/public/images/zemail-logo-light.webp b/public/images/zemail-logo-light.webp
new file mode 100644
index 0000000..694131c
Binary files /dev/null and b/public/images/zemail-logo-light.webp differ
diff --git a/resources/css/app.css b/resources/css/app.css
index 3e6abea..be63e5f 100644
--- a/resources/css/app.css
+++ b/resources/css/app.css
@@ -1,11 +1,52 @@
@import 'tailwindcss';
+
+@import '../../vendor/livewire/flux/dist/flux.css';
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
@source '../**/*.blade.php';
@source '../**/*.js';
+
+@custom-variant dark (&:where(.dark, .dark *));
+
+/*@theme {*/
+/* --font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',*/
+/* 'Segoe UI Symbol', 'Noto Color Emoji';*/
+/*}*/
+
@theme {
- --font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
- 'Segoe UI Symbol', 'Noto Color Emoji';
+ --font-sans: Inter, sans-serif;
}
+
+/* Re-assign Flux's gray of choice... */
+@theme {
+ --color-zinc-50: var(--color-gray-50);
+ --color-zinc-100: var(--color-gray-100);
+ --color-zinc-200: var(--color-gray-200);
+ --color-zinc-300: var(--color-gray-300);
+ --color-zinc-400: var(--color-gray-400);
+ --color-zinc-500: var(--color-gray-500);
+ --color-zinc-600: var(--color-gray-600);
+ --color-zinc-700: var(--color-gray-800);
+ --color-zinc-800: var(--color-gray-800);
+ --color-zinc-900: var(--color-gray-900);
+ --color-zinc-950: var(--color-gray-950);
+ /*--color-white: var(--color-gray-100);*/
+}
+
+@theme {
+ --color-accent: var(--color-gray-900);
+ --color-accent-content: var(--color-gray-900);
+ --color-accent-foreground: var(--color-white);
+}
+
+@layer theme {
+ .dark {
+ --color-accent: var(--color-white);
+ --color-accent-content: var(--color-white);
+ --color-accent-foreground: var(--color-gray-900);
+ }
+}
+
+
diff --git a/resources/css/boil.css b/resources/css/boil.css
index 44e66b5..345d9e2 100644
--- a/resources/css/boil.css
+++ b/resources/css/boil.css
@@ -1,3 +1,60 @@
-.art {
- color: orange;
+.inbox-btn {
+ background-color: #F14743;
+ color: white;
+ transition: background-color 0.3s ease;
+}
+
+.inbox-btn:hover {
+ background-color: #f72a25;
+}
+
+.btn-primary {
+ color: white;
+ background-color: #4361ee;
+}
+
+.btn-warning {
+ color: white;
+ background-color: #e2a03f;
+}
+.btn-success {
+ background-color: #00AB55;
+ color: white;
+}
+.inbox-list {
+ margin-bottom: 10px;
+}
+.inbox-new {
+ background-color: #00AB55;
+}
+
+.iframe-min-height {
+ min-height: 70vh;
+}
+@keyframes slide-in {
+ from {
+ transform: translateY(-1rem);
+ opacity: 0;
+ }
+ to {
+ transform: translateY(0);
+ opacity: 1;
+ }
+}
+
+@keyframes progress {
+ from {
+ width: 100%;
+ }
+ to {
+ width: 0%;
+ }
+}
+
+.animate-slide-in {
+ animation: slide-in 0.3s ease-out;
+}
+
+.animate-progress {
+ animation: progress 4s linear forwards;
}
diff --git a/resources/js/boil.js b/resources/js/boil.js
new file mode 100644
index 0000000..3470bab
--- /dev/null
+++ b/resources/js/boil.js
@@ -0,0 +1,69 @@
+document.addEventListener('DOMContentLoaded', () => {
+ if (window.Livewire && typeof window.Livewire.dispatch === 'function') {
+ setTimeout(() => {
+ Livewire.dispatch('getEmail');
+ }, 2000);
+
+ document.addEventListener('closeModal', () => {
+ document.querySelectorAll('dialog[data-modal]').forEach(dialog => {
+ if (typeof dialog.close === 'function') {
+ dialog.close();
+ console.log(`Closed dialog with data-modal="${dialog.getAttribute('data-modal')}"`);
+ }
+ });
+ });
+
+ } else {
+ console.warn('Livewire is not loaded yet.');
+ }
+});
+
+
+function showToast({ type = 'success', message = '' }) {
+const container = document.getElementById('toast-container');
+
+const colors = {
+success: {
+icon: 'text-green-500 bg-green-100 dark:bg-green-800 dark:text-green-200',
+svg: `
+
+
+ © {{ config('app.settings.app_name') }}
+You're about to delete this account.
+
+ {{ $email ?? __('...') }}
+ @else
+
+
+