add dashboard mailbox, added usage log, pending-switch email, mailbox history, email history
This commit is contained in:
@@ -46,6 +46,7 @@ class PlanResource extends Resource
|
||||
TextInput::make('product_id')->required(),
|
||||
TextInput::make('pricing_id')->required(),
|
||||
TextInput::make('price')->numeric()->required(),
|
||||
TextInput::make('mailbox_limit')->numeric()->required(),
|
||||
Select::make('monthly_billing')->options([
|
||||
1 => 'Monthly',
|
||||
0 => 'Yearly',
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Premium;
|
||||
use App\Models\ZEmail;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@@ -48,6 +49,16 @@ class AppController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteP($email = null) {
|
||||
if ($email) {
|
||||
$emails = Premium::getEmails();
|
||||
Premium::removeEmail($email);
|
||||
return redirect()->route('dashboard.premium');
|
||||
} else {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
}
|
||||
|
||||
public function locale($locale) {
|
||||
if (in_array($locale, config('app.locales'))) {
|
||||
session(['locale' => $locale]);
|
||||
|
||||
295
app/Livewire/Dashboard/Mailbox/Inbox.php
Normal file
295
app/Livewire/Dashboard/Mailbox/Inbox.php
Normal file
@@ -0,0 +1,295 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Dashboard\Mailbox;
|
||||
|
||||
use App\ColorPicker;
|
||||
use App\Models\Log;
|
||||
use App\Models\Premium;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
use Livewire\Component;
|
||||
|
||||
class Inbox extends Component
|
||||
{
|
||||
use ColorPicker;
|
||||
|
||||
public $messages = [];
|
||||
public $deleted = [];
|
||||
public $error = '';
|
||||
public $email;
|
||||
public $initial = false;
|
||||
public $type;
|
||||
public $overflow = false;
|
||||
public $messageId;
|
||||
public $list = false;
|
||||
public $emails;
|
||||
public $username, $domain, $domains, $action;
|
||||
public $email_limit = 20;
|
||||
|
||||
protected $listeners = ['updateEmail' => 'syncEmail', 'getEmail' => 'generateEmail', 'fetchMessages' => 'fetch', 'setMessageId' => 'setMessageId'];
|
||||
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->domains = json_decode(config('app.settings.configuration_settings'))->premium_domains ?? [];
|
||||
$this->email = Premium::getEmail();
|
||||
$this->emails = Premium::getEmails();
|
||||
$this->initial = false;
|
||||
$this->checkMultipleEmails();
|
||||
$this->validateDomainInEmail();
|
||||
|
||||
if(auth()->user()->subscribedToProduct(config('app.plans')[0]['product_id'])) {
|
||||
try {
|
||||
$result = auth()->user()->subscriptions()->where(['stripe_status' => 'active'])->orderByDesc('updated_at')->first();
|
||||
$userPriceID = $result['items'][0]['stripe_price'];
|
||||
|
||||
$mailboxLimit = $this->email_limit;
|
||||
foreach (config('app.plans') as $plan) {
|
||||
if ($plan['pricing_id'] === $userPriceID) {
|
||||
$mailboxLimit = $plan['mailbox_limit'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->email_limit = $mailboxLimit;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return redirect()->route('switch', ['email' => $email]);
|
||||
}
|
||||
|
||||
public function syncEmail(): void
|
||||
{
|
||||
$this->email = Premium::getEmail();
|
||||
$this->emails = Premium::getEmails();
|
||||
if (count($this->emails) == 0) {
|
||||
$this->dispatch('getEmail');
|
||||
}
|
||||
$this->checkMultipleEmails();
|
||||
$this->dispatch('syncMailbox', $this->email);
|
||||
$this->dispatch('fetchMessages');
|
||||
}
|
||||
|
||||
public function generateEmail(): void
|
||||
{
|
||||
if ($this->email == null) {
|
||||
Premium::generateRandomEmail();
|
||||
}
|
||||
$this->checkMultipleEmails();
|
||||
$this->dispatch('updateEmail');
|
||||
}
|
||||
|
||||
/* Actions */
|
||||
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 ') . $this->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 = Premium::createCustomEmail($this->username, $this->domain);
|
||||
return redirect()->route('dashboard.premium');
|
||||
|
||||
}
|
||||
public function random() {
|
||||
|
||||
if (!$this->checkEmailLimit()) {
|
||||
return $this->showAlert('error', __('You have reached daily limit of maximum ') . $this->email_limit . __(' temp mail addresses.'));
|
||||
}
|
||||
$this->email = Premium::generateRandomEmail();
|
||||
return redirect()->route('dashboard.premium');
|
||||
}
|
||||
public function gmail() {
|
||||
if (!$this->checkEmailLimit()) {
|
||||
return $this->showAlert('error', __('You have reached daily limit of maximum ') . $this->email_limit . __(' temp mail addresses.'));
|
||||
}
|
||||
$this->email = Premium::generateRandomGmail();
|
||||
return redirect()->route('dashboard.premium');
|
||||
}
|
||||
|
||||
public function deleteEmail()
|
||||
{
|
||||
return redirect()->route('deleteP', ['email' => $this->email]);
|
||||
}
|
||||
|
||||
private function showAlert($type, $message): void
|
||||
{
|
||||
$this->dispatch('showAlert', ['type' => $type, 'message' => $message]);
|
||||
}
|
||||
|
||||
private function checkEmailLimit(): bool
|
||||
{
|
||||
$logs = Log::select('ip', 'email')->where('user_id', auth()->user()->id)->where('created_at', '>', Carbon::now()->subDay())->groupBy('email')->groupBy('ip')->get();
|
||||
if (count($logs) >= $this->email_limit) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function checkUsedEmail(): bool
|
||||
{
|
||||
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(): void
|
||||
{
|
||||
$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'))->premium_domains ?? [];
|
||||
if (!in_array($domain, $domains)) {
|
||||
$key = array_search($this->email, $this->emails);
|
||||
Premium::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('dashboard.premium');
|
||||
} else {
|
||||
redirect()->route('dashboard.premium');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Mailbox */
|
||||
|
||||
|
||||
public function fetch(): void
|
||||
{
|
||||
try {
|
||||
$count = count($this->messages);
|
||||
if ($count > 0) {
|
||||
$this->messages = [];
|
||||
}
|
||||
$responses = [];
|
||||
if (config('app.beta_feature') || !json_decode(config('app.settings.imap_settings'))->premium_cc_check) {
|
||||
$responses = [
|
||||
'to' => Premium::getMessages($this->email, 'to', $this->deleted),
|
||||
'cc' => [
|
||||
'data' => [],
|
||||
'notifications' => []
|
||||
]
|
||||
];
|
||||
} else {
|
||||
$responses = [
|
||||
'to' => Premium::getMessages($this->email, 'to', $this->deleted),
|
||||
'cc' => Premium::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 && count($this->messages) == $count) {
|
||||
$this->overflow = true;
|
||||
}
|
||||
} else {
|
||||
$this->overflow = false;
|
||||
}
|
||||
|
||||
foreach ($notifications as $notification) {
|
||||
$this->dispatch('showNewMailNotification', $notification);
|
||||
}
|
||||
Premium::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->dispatch('stopLoader');
|
||||
$this->initial = true;
|
||||
}
|
||||
|
||||
public function delete($messageId) {
|
||||
|
||||
try {
|
||||
$this->deleted[] = $messageId;
|
||||
foreach ($this->messages as $key => $message) {
|
||||
if ($message['id'] == $messageId) {
|
||||
$directory = public_path('tmp/premium/attachments/') . $messageId;
|
||||
$this->rrmdir($directory);
|
||||
unset($this->messages[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (
|
||||
\Exception $exception
|
||||
) {
|
||||
\Illuminate\Support\Facades\Log::error($exception->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.dashboard.mailbox.inbox')->layout('components.layouts.dashboard');
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,6 @@ use Livewire\Component;
|
||||
class Action extends Component
|
||||
{
|
||||
public $username, $email, $emails, $domain, $domains, $action, $initial;
|
||||
|
||||
|
||||
public function mount() {
|
||||
$this->domains = json_decode(config('app.settings.configuration_settings'))->domains ?? [];
|
||||
$this->email = ZEmail::getEmail();
|
||||
|
||||
@@ -16,6 +16,7 @@ class Log extends Model
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'ip',
|
||||
'email',
|
||||
];
|
||||
|
||||
@@ -12,6 +12,7 @@ class Plan extends Model
|
||||
'product_id',
|
||||
'pricing_id',
|
||||
'price',
|
||||
'mailbox_limit',
|
||||
'monthly_billing',
|
||||
'details'
|
||||
];
|
||||
|
||||
482
app/Models/Premium.php
Normal file
482
app/Models/Premium.php
Normal file
@@ -0,0 +1,482 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\ColorPicker;
|
||||
use Carbon\Carbon;
|
||||
use Ddeboer\Imap\Search\Email\Cc;
|
||||
use Ddeboer\Imap\Search\Email\To;
|
||||
use Ddeboer\Imap\SearchExpression;
|
||||
use Ddeboer\Imap\Server;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
|
||||
class Premium extends Model
|
||||
{
|
||||
use ColorPicker;
|
||||
public static function connectMailBox($imap = null): \Ddeboer\Imap\ConnectionInterface
|
||||
{
|
||||
$imapDB = json_decode(config('app.settings.imap_settings'), true);
|
||||
$imap = [
|
||||
'host' => $imapDB['premium_host'],
|
||||
'port' => $imapDB['premium_port'],
|
||||
'encryption' => $imapDB['premium_encryption'],
|
||||
'validate_cert' => $imapDB['premium_validate_cert'],
|
||||
'username' => $imapDB['premium_username'],
|
||||
'password' => $imapDB['premium_password'],
|
||||
'default_account' => $imapDB['premium_default_account'],
|
||||
'protocol' => $imapDB['premium_protocol'],
|
||||
'cc_check' => $imapDB['premium_cc_check']
|
||||
];
|
||||
|
||||
return ZEmail::connectMailBox($imap);
|
||||
}
|
||||
|
||||
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 = self::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 = '';
|
||||
$contentText = '';
|
||||
$html = $message->getBodyHtml();
|
||||
$text = $message->getBodyText();
|
||||
if ($text) {
|
||||
$contentText = str_replace('<a', '<a target="blank"', str_replace(array("\r\n", "\n"), '', $text));
|
||||
}
|
||||
if ($html) {
|
||||
$content = str_replace('<a', '<a target="blank"', $html);
|
||||
} else {
|
||||
$content = str_replace('<a', '<a target="blank"', str_replace(array("\r\n", "\n"), '<br/>', $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['contentText'] = $contentText;
|
||||
$obj['attachments'] = [];
|
||||
$obj['is_seen'] = true;
|
||||
$obj['sender_photo'] = self::chooseColor(strtoupper(substr($sender->getName() ?: $sender->getAddress(), 0, 1) ));
|
||||
|
||||
//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');
|
||||
$obj['contentText'] = __('Emails from') . ' ' . $domain . ' ' . __('are blocked by Admin');
|
||||
}
|
||||
if ($message->hasAttachments() && !$blocked) {
|
||||
$attachments = $message->getAttachments();
|
||||
$directory = './tmp/premium/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())) {
|
||||
try {
|
||||
file_put_contents(
|
||||
$directory . $attachment->getFilename(),
|
||||
$attachment->getDecodedContent()
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
\Illuminate\Support\Facades\Log::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
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 getMessages($email, $type = 'to', $deleted = []): array
|
||||
{
|
||||
return self::fetchMessages($email, $type, $deleted);
|
||||
}
|
||||
public static function deleteMessage($id): void
|
||||
{
|
||||
$connection = self::connectMailBox();
|
||||
$mailbox = $connection->getMailbox('INBOX');
|
||||
$mailbox->getMessage($id)->delete();
|
||||
$connection->expunge();
|
||||
}
|
||||
public static function getEmail($generate = false) {
|
||||
if (Cookie::has('email')) {
|
||||
return Cookie::get('email');
|
||||
} else {
|
||||
return $generate ? self::generateRandomEmail() : null;
|
||||
}
|
||||
}
|
||||
public static function getEmails() {
|
||||
if (Cookie::has('emails')) {
|
||||
return unserialize(Cookie::get('emails'));
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
public static function setEmail($email): void
|
||||
{
|
||||
$emails = unserialize(Cookie::get('emails'));
|
||||
if (is_array($emails) && in_array($email, $emails)) {
|
||||
Cookie::queue('email', $email, 43800);
|
||||
}
|
||||
}
|
||||
public static function removeEmail($email): void
|
||||
{
|
||||
$emails = self::getEmails();
|
||||
$key = array_search($email, $emails);
|
||||
if ($key !== false) {
|
||||
array_splice($emails, $key, 1);
|
||||
}
|
||||
if (count($emails) > 0) {
|
||||
self::setEmail($emails[0]);
|
||||
Cookie::queue('emails', serialize($emails), 43800);
|
||||
} else {
|
||||
Cookie::queue('email', '', -1);
|
||||
Cookie::queue('emails', serialize([]), -1);
|
||||
}
|
||||
}
|
||||
public static function createCustomEmailFull($email): string
|
||||
{
|
||||
$data = explode('@', $email);
|
||||
$username = $data[0];
|
||||
if (strlen($username) < json_decode(config('app.settings.configuration_settings'))->custom_username_length_min || strlen($username) > json_decode(config('app.settings.configuration_settings'))->custom_username_length_max) {
|
||||
$zemail = new Premium();
|
||||
$username = $zemail->generateRandomUsername();
|
||||
}
|
||||
$domain = $data[1];
|
||||
return self::createCustomEmail($username, $domain);
|
||||
}
|
||||
public static function createCustomEmail($username, $domain): string
|
||||
{
|
||||
$username = preg_replace('/[^a-zA-Z0-9+.]/', '', strtolower($username));
|
||||
|
||||
$settings = json_decode(config('app.settings.configuration_settings'), true);
|
||||
$forbidden_ids = $settings['forbidden_ids'] ?? [];
|
||||
$gmail_usernames = $settings['premium_gmailUsernames'] ?? [];
|
||||
$domains = $settings['premium_domains'] ?? [];
|
||||
|
||||
if (in_array($username, $forbidden_ids)) {
|
||||
return self::generateRandomEmail(true);
|
||||
}
|
||||
|
||||
if ($username === '' && in_array($domain, ['gmail.com', 'googlemail.com'])) {
|
||||
return self::generateRandomGmail(true);
|
||||
}
|
||||
|
||||
$zemail = new Premium();
|
||||
|
||||
if ($username === '' && in_array($domain, $domains)) {
|
||||
return $zemail->generateRandomUsername().'@'.$domain;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (in_array($domain, ['gmail.com', 'googlemail.com'])) {
|
||||
if (str_contains($username, '+')) {
|
||||
[$check_username, $post_username] = explode('+', $username, 2);
|
||||
|
||||
if (in_array($check_username, $gmail_usernames)) {
|
||||
$email = $username . '@' . $domain;
|
||||
} else {
|
||||
$email = $zemail->getRandomGmailUser() . '+' . $post_username . '@' . $domain;
|
||||
}
|
||||
|
||||
} elseif (str_contains($username, '.')) {
|
||||
$check_username = str_replace('.', '', $username);
|
||||
|
||||
if (in_array($check_username, $gmail_usernames)) {
|
||||
$email = $username . '@' . $domain;
|
||||
} else {
|
||||
$email = $zemail->generateRandomGmail() . '@' . $domain;
|
||||
}
|
||||
|
||||
} else {
|
||||
$email = $zemail->getRandomGmailUser() . '+' . $username . '@' . $domain;
|
||||
}
|
||||
|
||||
self::storeEmail($email);
|
||||
return $email;
|
||||
}
|
||||
|
||||
// Handle other custom domains
|
||||
if (!in_array($domain, $domains)) {
|
||||
return self::generateRandomEmail(true);
|
||||
}
|
||||
|
||||
$finalDomain = in_array($domain, $domains) ? $domain : ($domains[0] ?? 'example.com');
|
||||
$email = $username . '@' . $finalDomain;
|
||||
|
||||
self::storeEmail($email);
|
||||
return $email;
|
||||
}
|
||||
public static function generateRandomEmail($store = true): string
|
||||
{
|
||||
$zemail = new Premium();
|
||||
$domain = $zemail->getRandomDomain();
|
||||
if ($domain == "gmail.com") {
|
||||
$rd = mt_rand(0,1);
|
||||
if ($rd == 0) {
|
||||
$email = $zemail->generateRandomGmail();
|
||||
} else {
|
||||
$email = $zemail->getRandomGmailUser().'+'.$zemail->generateRandomUsername().'@gmail.com';
|
||||
}
|
||||
} elseif ($domain == "googlemail.com") {
|
||||
$rd = mt_rand(0,1);
|
||||
if ($rd == 0) {
|
||||
$email = $zemail->generateRandomGmail();
|
||||
} else {
|
||||
$email = $zemail->getRandomGmailUser().'+'.$zemail->generateRandomUsername().'@googlemail.com';
|
||||
}
|
||||
} else {
|
||||
$email = $zemail->generateRandomUsername() . '@' . $domain;
|
||||
}
|
||||
if ($store) {
|
||||
self::storeEmail($email);
|
||||
}
|
||||
return $email;
|
||||
}
|
||||
public static function generateRandomGmail($store = true): string
|
||||
{
|
||||
$zemail = new Premium();
|
||||
$uname = $zemail->getRandomGmailUser();
|
||||
$uname_len = strlen($uname);
|
||||
$len_power = $uname_len - 1;
|
||||
$combination = pow(2,$len_power);
|
||||
$rand_comb = mt_rand(1,$combination);
|
||||
$formatted = implode(' ',str_split($uname));
|
||||
$uname_exp = explode(' ', $formatted);
|
||||
|
||||
$bin = intval("");
|
||||
for($i=0; $i<$len_power; $i++) {
|
||||
$bin .= mt_rand(0,1);
|
||||
}
|
||||
$bin = explode(' ', implode(' ',str_split(strval($bin))));
|
||||
|
||||
$email = "";
|
||||
for($i=0; $i<$len_power; $i++) {
|
||||
$email .= $uname_exp[$i];
|
||||
if($bin[$i]) {
|
||||
$email .= ".";
|
||||
}
|
||||
}
|
||||
$email .= $uname_exp[$i];
|
||||
$gmail_rand = mt_rand(1,10);
|
||||
if($gmail_rand > 5) {
|
||||
$email .= "@gmail.com";
|
||||
} else {
|
||||
$email .= "@googlemail.com";
|
||||
}
|
||||
if ($store) {
|
||||
self::storeEmail($email);
|
||||
}
|
||||
return $email;
|
||||
}
|
||||
private static function storeEmail($email): void
|
||||
{
|
||||
Log::create([
|
||||
'user_id' => auth()->user()->id,
|
||||
'ip' => request()->ip(),
|
||||
'email' => $email
|
||||
]);
|
||||
|
||||
self::storeUsageLog($email);
|
||||
|
||||
Cookie::queue('email', $email, 43800);
|
||||
$emails = Cookie::has('emails') ? unserialize(Cookie::get('emails')) : [];
|
||||
if (!in_array($email, $emails)) {
|
||||
self::incrementEmailStats();
|
||||
$emails[] = $email;
|
||||
Cookie::queue('emails', serialize($emails), 43800);
|
||||
}
|
||||
}
|
||||
public static function incrementEmailStats($count = 1): void
|
||||
{
|
||||
Meta::incrementEmailIdsCreated($count);
|
||||
self::incrementEmailIdsCreated($count);
|
||||
}
|
||||
public static function incrementMessagesStats($count = 1): void
|
||||
{
|
||||
Meta::incrementMessagesReceived($count);
|
||||
self::incrementMessagesReceived($count);
|
||||
}
|
||||
private function generateRandomUsername(): string
|
||||
{
|
||||
$start = json_decode(config('app.settings.configuration_settings'))->random_username_length_min ?? 0;
|
||||
$end = json_decode(config('app.settings.configuration_settings'))->random_username_length_max ?? 0;
|
||||
if ($start == 0 && $end == 0) {
|
||||
return $this->generatePronounceableWord();
|
||||
}
|
||||
return $this->generatedRandomBetweenLength($start, $end);
|
||||
}
|
||||
protected function generatedRandomBetweenLength($start, $end): string
|
||||
{
|
||||
$length = rand($start, $end);
|
||||
return $this->generateRandomString($length);
|
||||
}
|
||||
private function getRandomDomain() {
|
||||
$domains = json_decode(config('app.settings.configuration_settings'))->premium_domains ?? [];
|
||||
$count = count($domains);
|
||||
return $count > 0 ? $domains[rand(1, $count) - 1] : '';
|
||||
}
|
||||
private function getRandomGmailUser() {
|
||||
$gmailusername = json_decode(config('app.settings.configuration_settings'))->premium_gmailUsernames ?? [];
|
||||
$count = count($gmailusername);
|
||||
return $count > 0 ? $gmailusername[rand(1, $count) - 1] : '';
|
||||
}
|
||||
private function generatePronounceableWord(): string
|
||||
{
|
||||
$c = 'bcdfghjklmnprstvwz'; //consonants except hard to speak ones
|
||||
$v = 'aeiou'; //vowels
|
||||
$a = $c . $v; //both
|
||||
$random = '';
|
||||
for ($j = 0; $j < 2; $j++) {
|
||||
$random .= $c[rand(0, strlen($c) - 1)];
|
||||
$random .= $v[rand(0, strlen($v) - 1)];
|
||||
$random .= $a[rand(0, strlen($a) - 1)];
|
||||
}
|
||||
return $random;
|
||||
}
|
||||
private function generateRandomString($length = 10): string
|
||||
{
|
||||
$characters = '0123456789abcdefghijklmnopqrstuvwxyz';
|
||||
$charactersLength = strlen($characters);
|
||||
$randomString = '';
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$randomString .= $characters[rand(0, $charactersLength - 1)];
|
||||
}
|
||||
return $randomString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stats Handling Functions
|
||||
*/
|
||||
|
||||
|
||||
public static function incrementEmailIdsCreated($count = 1): void
|
||||
{
|
||||
$user = Auth::user();
|
||||
if (!$user) {
|
||||
return;
|
||||
}
|
||||
|
||||
$usageLog = UsageLog::firstOrCreate(
|
||||
['user_id' => $user->id],
|
||||
['ip_address' => request()->ip()]
|
||||
);
|
||||
|
||||
$usageLog->increment('emails_created_count', $count);
|
||||
}
|
||||
|
||||
public static function incrementMessagesReceived($count = 1): void
|
||||
{
|
||||
$user = Auth::user();
|
||||
if (!$user) {
|
||||
return;
|
||||
}
|
||||
|
||||
$usageLog = UsageLog::firstOrCreate(
|
||||
['user_id' => $user->id],
|
||||
['ip_address' => request()->ip()]
|
||||
);
|
||||
|
||||
$usageLog->increment('emails_received_count', $count);
|
||||
}
|
||||
|
||||
public static function storeUsageLog($email): void
|
||||
{
|
||||
try {
|
||||
$user = Auth::user();
|
||||
if (!$user) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ip = request()->ip();
|
||||
$usageLog = UsageLog::firstOrCreate(
|
||||
['user_id' => $user->id],
|
||||
['ip_address' => $ip]
|
||||
);
|
||||
|
||||
$history = $usageLog->emails_created_history ?? [];
|
||||
if (!in_array($email, $history)) {
|
||||
$history[] = $email;
|
||||
//$usageLog->emails_created_count += 1;
|
||||
$usageLog->emails_created_history = $history;
|
||||
$usageLog->save();
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
\Log::error($exception->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
23
app/Models/UsageLog.php
Normal file
23
app/Models/UsageLog.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class UsageLog extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'ip_address',
|
||||
'emails_created_count',
|
||||
'emails_received_count',
|
||||
'emails_created_history',
|
||||
'emails_received_history',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'emails_created_history' => 'array',
|
||||
'emails_received_history' => 'array',
|
||||
];
|
||||
|
||||
}
|
||||
@@ -318,100 +318,3 @@ class ZEmail extends Model
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// public static function createCustomEmail($username, $domain): string
|
||||
// {
|
||||
// $username = str_replace('[^a-zA-Z0-9]', '', strtolower($username));
|
||||
// $forbidden_ids = json_decode(config('app.settings.configuration_settings'))->forbidden_ids ?? [];
|
||||
// $gmail_usernames = json_decode(config('app.settings.configuration_settings'))->gmailUsernames ?? [];
|
||||
// if (in_array($username, $forbidden_ids)) {
|
||||
// return ZEmail::generateRandomEmail(true);
|
||||
// }
|
||||
// $zemail = new ZEmail();
|
||||
// if($domain == "gmail.com") {
|
||||
//
|
||||
// if(str_contains($username, "+")){
|
||||
// $check_username = explode("+", $username)[0];
|
||||
// $post_username = explode("+", $username)[1];
|
||||
// if (in_array($check_username, $gmail_usernames)) {
|
||||
// $email = $username . '@gmail.com';
|
||||
// ZEmail::storeEmail($email);
|
||||
// return $email;
|
||||
// } else {
|
||||
//
|
||||
// $email = $zemail->getRandomGmailUser().'+'.$post_username.'@gmail.com';
|
||||
// ZEmail::storeEmail($email);
|
||||
// return $email;
|
||||
// }
|
||||
// }
|
||||
// elseif(str_contains($username, ".")){
|
||||
// $check_username = str_replace(".","",$username);
|
||||
//
|
||||
// if (in_array($check_username, $gmail_usernames)) {
|
||||
// $email = $username . '@gmail.com';
|
||||
// ZEmail::storeEmail($email);
|
||||
// return $email;
|
||||
// } else {
|
||||
//
|
||||
// $email = $zemail->generateRandomGmail();
|
||||
// ZEmail::storeEmail($email);
|
||||
// return $email;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// else {
|
||||
//
|
||||
// $email = $zemail->getRandomGmailUser().'+'.$username.'@gmail.com';
|
||||
// ZEmail::storeEmail($email);
|
||||
// return $email;
|
||||
// }
|
||||
// } elseif($domain == "googlemail.com") {
|
||||
// if(str_contains($username, "+")){
|
||||
// $check_username = explode("+", $username)[0];
|
||||
// $post_username = explode("+", $username)[1];
|
||||
//
|
||||
// if (in_array($check_username, $gmail_usernames)) {
|
||||
// $email = $username . '@googlemail.com';
|
||||
// ZEmail::storeEmail($email);
|
||||
// return $email;
|
||||
// } else {
|
||||
//
|
||||
// $email = $zemail->getRandomGmailUser().'+'.$post_username.'@googlemail.com';
|
||||
// ZEmail::storeEmail($email);
|
||||
// return $email;
|
||||
// }
|
||||
// }
|
||||
// elseif(str_contains($username, ".")){
|
||||
// $check_username = str_replace(".","",$username);
|
||||
//
|
||||
// if (in_array($check_username, $gmail_usernames)) {
|
||||
// $email = $username . '@googlemail.com';
|
||||
// ZEmail::storeEmail($email);
|
||||
// return $email;
|
||||
// } else {
|
||||
//
|
||||
// $email = $zemail->generateRandomGmail();
|
||||
// ZEmail::storeEmail($email);
|
||||
// return $email;
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// $email = $zemail->getRandomGmailUser().'+'.$username.'@googlemail.com';
|
||||
// ZEmail::storeEmail($email);
|
||||
// return $email;
|
||||
// }
|
||||
// } else {
|
||||
// $domains = json_decode(config('app.settings.configuration_settings'))->domains ?? [];
|
||||
// if (in_array($domain, $domains)) {
|
||||
// $email = $username . '@' . $domain;
|
||||
// ZEmail::storeEmail($email);
|
||||
// return $email;
|
||||
// } else {
|
||||
// $email = $username . '@' . $domains[0];
|
||||
// ZEmail::storeEmail($email);
|
||||
// return $email;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -18,6 +18,7 @@ return new class extends Migration
|
||||
$table->string('product_id')->collation('utf8_bin');
|
||||
$table->string('pricing_id')->collation('utf8_bin');
|
||||
$table->integer('price');
|
||||
$table->integer('mailbox_limit')->default(15);
|
||||
$table->boolean('monthly_billing')->default(true);
|
||||
$table->longText('details')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('usage_logs', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('user_id');
|
||||
$table->ipAddress('ip_address');
|
||||
$table->integer('emails_created_count')->default(0);
|
||||
$table->integer('emails_received_count')->default(0);
|
||||
$table->json('emails_created_history')->nullable();
|
||||
$table->json('emails_received_history')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('usage_logs');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('logs', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('user_id')->nullable()->after('id');
|
||||
$table->foreign('user_id')->references('id')->on('users');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('logs', function (Blueprint $table) {
|
||||
$table->dropForeign(['user_id']);
|
||||
$table->dropColumn('user_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -101,8 +101,6 @@
|
||||
</form>
|
||||
</flux:menu>
|
||||
</flux:dropdown>
|
||||
<p class="text-sm font-medium dark:text-white accent-zinc-700">© 2020–{{ date('Y') }} – All Rights Reserved {{ config('app.settings.app_name') }} | Coded with ♥️</p>
|
||||
|
||||
</flux:sidebar>
|
||||
|
||||
<flux:header sticky container class="bg-zinc-50 dark:bg-zinc-900 border-b border-zinc-200 dark:border-zinc-700">
|
||||
@@ -150,16 +148,6 @@
|
||||
@fluxScripts
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
setTimeout(() => {
|
||||
const email = '{{ App\Models\ZEmail::getEmail(true) }}';
|
||||
const add_mail_in_title = "{{ json_decode(config('app.settings.configuration_settings'))->add_mail_in_title ? 'yes' : 'no' }}"
|
||||
if(add_mail_in_title === 'yes') {
|
||||
document.title += ` - ${email}`;
|
||||
}
|
||||
Livewire.dispatch('updateEmail');
|
||||
}, 2000);
|
||||
|
||||
document.addEventListener('stopLoader', () => {
|
||||
document.querySelectorAll('#refresh-icon').forEach(el => {
|
||||
setTimeout(() => {
|
||||
|
||||
245
resources/views/livewire/dashboard/mailbox/inbox.blade.php
Normal file
245
resources/views/livewire/dashboard/mailbox/inbox.blade.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<span>
|
||||
<div class="flex-1 overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700 dark:bg-white/[0.03] sm:px-8 sm:py-8 lg:p-12">
|
||||
<div class="rounded-xl border dark:border-white/[0.1] border-black/[0.3] p-6 shadow-xs ring-white/[0.5] lg:w-1/2 mx-auto">
|
||||
<div class="text-center">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-400">Generate Premium Email</h2>
|
||||
<div class="space-y-6">
|
||||
<div class="my-6">
|
||||
<div class="w-auto relative block group/input cursor-pointer" x-on:click="$dispatch('copyEmail')">
|
||||
<div id="copyEmail" role="textbox" aria-readonly="true" class="truncate w-auto cursor-pointer rounded-lg block disabled:shadow-none dark:shadow-none appearance-none text-base sm:text-sm py-2 h-10 leading-[1.375rem] ps-3 pe-3 bg-zinc-800/5 dark:bg-white/10 dark:disabled:bg-white/[7%] text-zinc-700 placeholder-zinc-500 disabled:placeholder-zinc-400 dark:text-zinc-200 dark:placeholder-white/60 dark:disabled:placeholder-white/40 border-0 text-center">{{ $email ?? __('Create your own Temp Mail') }}</div>
|
||||
<div class="absolute top-0 bottom-0 flex items-center gap-x-1.5 pe-3 end-0 text-xs text-zinc-400"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<form wire:submit.prevent="create" method="post">
|
||||
<div>
|
||||
<div class="mt-2">
|
||||
<div class="flex items-center rounded-md dark:bg-zinc-700 pl-3 outline-1 -outline-offset-1 outline-zinc-200 has-[input:focus-within]:outline-2 has-[input:focus-within]:-outline-offset-2 dark:has-[input:focus-within]:outline-white has-[input:focus-within]:outline-zinc-900">
|
||||
<div class="shrink-0 text-base text-gray-500 select-none sm:text-sm/6 mr-1.5">
|
||||
<flux:icon.mail variant="mini"/>
|
||||
</div>
|
||||
<input type="text" name="username" id="username" autocomplete="false" wire:model.defer="username" class="block min-w-0 grow py-2 pr-3 pl-1 text-base dark:text-white text-gray-900 placeholder:text-gray-400 focus:outline-none sm:text-sm/6" placeholder="{{ __('Enter Username') }}">
|
||||
<div class="grid shrink-0 grid-cols-1 focus-within:relative">
|
||||
<select id="domain" name="domain" aria-label="Domain" wire:model="domain" class="col-start-1 row-start-1 w-full appearance-none rounded-md py-1.5 pr-7 pl-3 text-base text-gray-500 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 dark:focus:outline-white focus:outline-zinc-900 sm:text-sm/6">
|
||||
<option class="dark:bg-zinc-700 dark:text-white bg-zinc-100 accent-gray-700" selected>{{ __('Select Domain') }}</option>
|
||||
@foreach(array_reverse($domains) as $domain)
|
||||
<option x-on:click="$refs.domain.value = '{{ $domain }}'; $wire.setDomain('{{ $domain }}')" class="dark:bg-zinc-700 dark:text-white bg-zinc-100 accent-gray-700">{{ $domain }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<svg class="pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-gray-500 sm:size-4" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" data-slot="icon">
|
||||
<path fill-rule="evenodd" d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex my-6">
|
||||
<div class="flex w-full">
|
||||
<flux:button class="w-full btn-success cursor-pointer" type="submit" variant="primary">{{ __('Create') }}</flux:button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<flux:separator text="or" />
|
||||
|
||||
<div class="flex w-full">
|
||||
<div class="w-1/2">
|
||||
<flux:button wire:click="random()" class="cursor-pointer w-full btn-primary" type="submit" variant="filled">{{ __('Random') }} Email</flux:button>
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<flux:button wire:click="gmail()" class="cursor-pointer w-full ml-2 btn-warning" type="submit" variant="filled">Disposable Gmail</flux:button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($email !== null)
|
||||
<div class="mt-8 rounded-xl border dark:border-white/[0.1] border-black/[0.3]">
|
||||
<div class="mt-4 w-full text-center">
|
||||
<div class="flex flex-full flex-row">
|
||||
<div class="w-1/3"><flux:button class="w-3/4 cursor-pointer" x-on:click="$dispatch('copyEmail')">Copy</flux:button></div>
|
||||
<div class="w-1/3">
|
||||
<button type="button" class="relative items-center font-medium justify-center gap-2 whitespace-nowrap disabled:opacity-75 dark:disabled:opacity-75 disabled:cursor-default disabled:pointer-events-none h-10 text-sm rounded-lg px-4 inline-flex bg-white hover:bg-zinc-50 dark:bg-zinc-700 dark:hover:bg-zinc-600/75 text-zinc-800 dark:text-white border border-zinc-200 hover:border-zinc-200 border-b-zinc-300/80 dark:border-zinc-600 dark:hover:border-zinc-600 shadow-xs [[data-flux-button-group]_&]:border-s-0 [:is([data-flux-button-group]>&:first-child,_[data-flux-button-group]_:first-child>&)]:border-s-[1px] w-3/4 cursor-pointer" data-flux-button="data-flux-button" data-flux-group-target="data-flux-group-target" x-on:click="Livewire.dispatch('fetchMessages'); document.getElementById('refresh-icon').classList.add('animate-spin')">
|
||||
<svg id="refresh-icon" class="shrink-0 [:where(&)]:size-4" data-flux-icon="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
||||
<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path>
|
||||
<path d="M21 3v5h-5"></path>
|
||||
<path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"></path>
|
||||
<path d="M8 16H3v5"></path>
|
||||
</svg>
|
||||
Refresh
|
||||
</button>
|
||||
</div>
|
||||
<div class="w-1/3">
|
||||
<flux:button class="w-3/4 cursor-pointer inbox-btn" wire:click="deleteEmail()" type="submit">{{ __('Delete') }}</flux:button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full mt-4">
|
||||
<div x-data="{ show: false, id: 0 }" class="mx-3">
|
||||
@if($messages)
|
||||
<div class="mailbox">
|
||||
<div x-show="!show" class="list">
|
||||
<div class="mb-3"></div>
|
||||
@foreach(array_reverse($messages) as $i => $message)
|
||||
<div class="inbox-list cursor-pointer" x-on:click="show = true; id = {{ $message['id'] }};" data-id="{{ $message['id'] }}">
|
||||
<div class="block rounded-lg bg-white shadow-md dark:bg-zinc-700 text-left">
|
||||
<div class="flex items-center px-4 py-4 sm:px-6">
|
||||
<div class="flex flex-1 items-center min-w-0">
|
||||
<div class="flex-shrink-0">
|
||||
<span class="relative inline-block">
|
||||
{{-- <img src="{{ asset('images/user.webp') }}" class="size-12" alt="inbox-logo" />--}}
|
||||
<span class="{{ $message['sender_photo']['dark'] }} {{ $message['sender_photo']['light'] }} inline-flex items-center justify-center shrink-0 select-none overflow-hidden rounded-full align-middle size-11 text-[22px] transition">
|
||||
<span id="sender-logo" class="font-medium leading-none text-gray-100 dark:text-gray-300 dark:group-hover:text-gray-200 group-hover:text-gray-700 truncate">{{ strtoupper(substr($message['sender_name'] ?: $message['sender_email'], 0, 1) ) }}</span>
|
||||
</span>
|
||||
@if(!$message['is_seen'])
|
||||
<span class="shadow-solid absolute bottom-0 right-0 block w-3 h-3 dark:text-gray-500 text-white bg-amber-300 dark:bg-amber-400 rounded-full"></span>
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex-1 px-4 min-w-0 md:grid md:gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<div class="dark:text-accent text-accent-content text-sm font-medium leading-5 truncate">
|
||||
{{ $message['sender_name'] }}
|
||||
</div>
|
||||
<div class="flex items-center mt-2 dark:text-gray-400 text-gray-500 text-sm leading-5">
|
||||
<svg fill="currentColor" viewBox="0 0 20 20"
|
||||
class="flex-shrink-0 mr-1.5 w-5 h-5 text-gray-400">
|
||||
<path fill-rule="evenodd"
|
||||
d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884zM18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"
|
||||
clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
<span class="truncate">{{ $message['sender_email'] }}</span></div>
|
||||
</div>
|
||||
<div class="hidden md:block">
|
||||
<div>
|
||||
<div class="dark:text-gray-300 text-gray-900 text-sm leading-5 truncate">
|
||||
{{ $message['subject'] }}
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center mt-2 text-gray-400 dark:text-gray-400 text-sm leading-5 truncate">
|
||||
{{ Str::limit($message['contentText'], 100) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<svg fill="currentColor" viewBox="0 0 20 20" class="w-5 h-5 text-gray-400">
|
||||
<path fill-rule="evenodd"
|
||||
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
|
||||
clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div x-show="show" class="message mx-2 mb-2 ">
|
||||
@foreach(array_reverse($messages) as $message)
|
||||
<div x-show="id === {{ $message['id'] }}" id="message-{{ $message['id'] }}">
|
||||
<textarea class="hidden">To: {{ $this->email ?? "" }} From: "{{ $message['sender_name'] }}" <{{ $message['sender_email'] }}> Subject: {{ $message['subject'] }} Date: {{ $message['date'] }} Content-Type: text/html {{ $message['content'] }}</textarea>
|
||||
<span>
|
||||
<div class="-mx-2">
|
||||
<nav class="flex items-center cursor-pointer" x-on:click="show = false">
|
||||
<flux:icon.chevron-left variant="mini"/>
|
||||
<flux:text>{{ __('Get back to MailBox') }}</flux:text>
|
||||
</nav>
|
||||
|
||||
<div class="mt-2 md:flex md:items-center md:justify-between">
|
||||
<div class="flex-1 min-w-0">
|
||||
<h2 class="dark:text-gray-300 text-gray-900 text-2xl font-bold leading-7 sm:truncate">
|
||||
{{ $message['subject'] }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="flex flex-shrink-0 mt-4 overflow-y-auto md:ml-4 md:mt-0 gap-2">
|
||||
<flux:button iconVariant="mini" iconLeading="download" x-on:click="$dispatch('downloadFile', { download_id: {{ $message['id'] }} })" class="cursor-pointer">Download</flux:button>
|
||||
{{-- <flux:button iconVariant="mini" iconLeading="file">Source</flux:button>--}}
|
||||
<flux:button iconVariant="mini" iconLeading="printer" x-on:click="$dispatch('printFile', { print_id: {{ $message['id'] }} })" class="cursor-pointer">Print</flux:button>
|
||||
<flux:button iconVariant="mini" iconLeading="trash" x-on:click="show = false; id = 0; document.querySelector(`[data-id='{{ $message['id'] }}']`).remove()" wire:click="delete({{ $message['id'] }})" class="cursor-pointer" style="color: #F14743;">{{ __('Delete') }}</flux:button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 px-4 py-5 bg-white border-b border-gray-200 dark:border-gray-900 shadow overflow-hidden sm:px-6 sm:rounded-md">
|
||||
<div class="flex flex-wrap items-center justify-between -ml-4 -mt-4 sm:flex-nowrap">
|
||||
<div class="ml-4 mt-4">
|
||||
<div class="flex items-center">
|
||||
<div class="flex-shrink-0">
|
||||
<span class="{{ $message['sender_photo']['dark'] }} {{ $message['sender_photo']['light'] }} inline-flex items-center justify-center shrink-0 select-none overflow-hidden rounded-full align-middle size-11 text-[22px] transition">
|
||||
<span id="sender-logo" class="font-medium leading-none text-gray-100 dark:text-gray-300 dark:group-hover:text-gray-200 group-hover:text-gray-700 truncate">{{ strtoupper(substr($message['sender_name'] ?: $message['sender_email'], 0, 1) ) }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
<div class="text-gray-700 text-lg font-medium leading-6">
|
||||
{{ $message['sender_name'] }}
|
||||
<span class="text-gray-700 text-sm font-normal leading-5">{{ $message['sender_email'] }}</span>
|
||||
</div>
|
||||
<div class="flex items-center mt-2 text-gray-500 text-sm leading-5">
|
||||
<svg fill="currentColor" viewBox="0 0 20 20" class="flex-shrink-0 mr-1.5 w-5 h-5 text-gray-400">
|
||||
<path fill-rule="evenodd" d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884zM18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
<span class="truncate"><a href="mailto:{{ $message['sender_email'] }}"
|
||||
class="ml-1">{{ $email ?? "" }};</a></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-shrink-0 ml-4 mt-4">
|
||||
<time datetime="2025-04-24T10:11:55+00:00" class="text-gray-500 truncate">
|
||||
{{ $message['datediff'] }}
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4 py-5 sm:px-6">
|
||||
<iframe srcdoc="{{ $message['content'] }}" class="w-full iframe-min-height">
|
||||
</iframe>
|
||||
</div>
|
||||
@if (count($message['attachments']) > 0)
|
||||
<div class="grid grid-cols-1 mt-2 text-sm leading-5 text-gray-900 lg:grid-cols-4 md:grid-cols-3 sm:grid-cols-2">
|
||||
@foreach ($message['attachments'] as $attachment)
|
||||
<button class="mb-2 mr-2 border border-gray-200 rounded-md text-sm leading-5 hover:text-gray-500 cursor-pointer" onclick="window.open('{{ $attachment['url'] }}', '_blank')">
|
||||
<div class="py-3 pl-3 pr-4">
|
||||
<div class="flex flex-1 items-center">
|
||||
<svg class="h-5 w-5 flex-shrink-0 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M8 4a3 3 0 00-3 3v4a5 5 0 0010 0V7a1 1 0 112 0v4a7 7 0 11-14 0V7a5 5 0 0110 0v4a3 3 0 11-6 0V7a1 1 0 012 0v4a1 1 0 102 0V7a3 3 0 00-3-3z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
<span class="ml-2 flex-1 truncate">{{ $attachment['file'] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@else
|
||||
<div class="mb-3"></div>
|
||||
<div class="mb-3 block rounded-b-lg bg-white shadow-md dark:bg-zinc-700 items-center">
|
||||
<div class="flex mailbox-min-height w-full items-center justify-center px-4 py-4 sm:px-6">
|
||||
<div class="waitingBox flex flex-col items-center relative -space-y-4">
|
||||
<div class="absolute -mt-4 inset-0 flex justify-center items-center animate-spin duration-2000">
|
||||
<flux:icon.refresh-cw variant="mini" style="color: #ffffdf" />
|
||||
</div>
|
||||
<svg width="120" height="124" viewBox="0 0 92 87" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M26 54.37V38.9C26.003 37.125 26.9469 35.4846 28.48 34.59L43.48 25.84C45.027 24.9468 46.933 24.9468 48.48 25.84L63.48 34.59C65.0285 35.4745 65.9887 37.1167 66 38.9V54.37C66 57.1314 63.7614 59.37 61 59.37H31C28.2386 59.37 26 57.1314 26 54.37Z" fill="#8C92A5"></path>
|
||||
<path d="M46 47.7L26.68 36.39C26.2325 37.1579 25.9978 38.0312 26 38.92V54.37C26 57.1314 28.2386 59.37 31 59.37H61C63.7614 59.37 66 57.1314 66 54.37V38.9C66.0022 38.0112 65.7675 37.1379 65.32 36.37L46 47.7Z" fill="#CDCDD8"></path>
|
||||
<path d="M27.8999 58.27C28.7796 58.9758 29.8721 59.3634 30.9999 59.37H60.9999C63.7613 59.37 65.9999 57.1314 65.9999 54.37V38.9C65.9992 38.0287 65.768 37.1731 65.3299 36.42L27.8999 58.27Z" fill="#E5E5F0"></path>
|
||||
</svg>
|
||||
<flux:text>{{ $initial ? __('Empty Inbox') : __('Fetching') }}</flux:text>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</span>
|
||||
@@ -4,6 +4,7 @@ use App\Http\Controllers\AppController;
|
||||
use App\Http\Middleware\CheckPageSlug;
|
||||
use App\Livewire\Blog;
|
||||
use App\Livewire\Dashboard\Dashboard;
|
||||
use App\Livewire\Dashboard\Mailbox\Inbox;
|
||||
use App\Livewire\Frontend\Mailbox;
|
||||
use App\Livewire\Home;
|
||||
use App\Livewire\ListBlog;
|
||||
@@ -21,6 +22,7 @@ Route::get('/mailbox/{email?}', [AppController::class, 'mailbox'])->name('mailbo
|
||||
|
||||
Route::get('/switch/{email}', [AppController::class, 'switch'])->name('switch');
|
||||
Route::get('/delete/{email?}', [AppController::class, 'delete'])->name('delete');
|
||||
Route::get('/deleteP/{email?}', [AppController::class, 'deleteP'])->name('deleteP');
|
||||
|
||||
Route::get('locale/{locale}', [AppController::class, 'locale'])->name('locale');
|
||||
Route::get('/blog', ListBlog::class)->name('list-blog');
|
||||
@@ -42,7 +44,7 @@ Route::post('/sync', function (Request $request) {
|
||||
|
||||
Route::middleware(['auth', 'verified'])->group(function () {
|
||||
Route::get('dashboard', Dashboard::class)->name('dashboard');
|
||||
Route::get('dashboard/generate-premium-email', Dashboard::class)->name('dashboard.premium');
|
||||
Route::get('dashboard/generate-premium-email', Inbox::class)->name('dashboard.premium');
|
||||
Route::get('dashboard/generate-10minute-email', Dashboard::class)->name('dashboard.10minute');
|
||||
Route::get('dashboard/bulk-email-generator', Dashboard::class)->name('dashboard.bulk');
|
||||
Route::get('dashboard/compose-email', Dashboard::class)->name('dashboard.compose');
|
||||
|
||||
Reference in New Issue
Block a user