add OAUth2.0

This commit is contained in:
2026-06-15 11:14:35 +02:00
parent 7973a94498
commit 69f4d6a602
32 changed files with 1126 additions and 51 deletions
+160 -1
View File
@@ -12,7 +12,6 @@ use App\Models\Gruppo;
use App\Models\Individuo;
use App\Models\Documento;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
@@ -402,6 +401,10 @@ class EmailController extends Controller
$this->ensureFoldersExist();
if ($settings->isOauth()) {
return $this->syncEmailsViaOAuth($settings);
}
$mailbox = $this->connectImap($settings);
\Illuminate\Support\Facades\Log::info('IMAP connection established', ['host' => $settings->imap_host]);
@@ -523,6 +526,10 @@ class EmailController extends Controller
$encryption
);
if ($settings->isOauth()) {
$dsn .= '&auth_mode=xoauth2';
}
try {
$transport = \Symfony\Component\Mailer\Transport::fromDsn($dsn);
$mailer = new \Symfony\Component\Mailer\Mailer($transport);
@@ -643,6 +650,10 @@ class EmailController extends Controller
throw new \Exception('Configurazione IMAP non valida');
}
if ($settings->isOauth()) {
return $this->connectOAuthImap($settings);
}
$encryption = match ($settings->imap_encryption) {
'ssl' => 'ssl',
'tls' => 'tls',
@@ -659,6 +670,27 @@ class EmailController extends Controller
]);
}
private function connectOAuthImap($settings): \Webklex\PHPIMAP\Client
{
$token = $settings->getOAuthAccessToken();
if (!$token) {
throw new \Exception('Impossibile ottenere il token OAuth per IMAP');
}
$client = new \Webklex\PHPIMAP\Client([
'host' => $settings->imap_host,
'port' => $settings->imap_port ?? 993,
'encryption' => $settings->imap_encryption ?? 'ssl',
'validate_cert' => false,
'username' => $settings->imap_username,
'password' => $token,
'authentication' => 'oauth',
]);
$client->connect();
return $client;
}
private function processImapMessage($imapMessage, $imapFolder)
{
$folderType = match ($imapFolder) {
@@ -717,6 +749,133 @@ class EmailController extends Controller
}
}
private function syncEmailsViaOAuth($settings): bool
{
$this->ensureFoldersExist();
$client = $this->connectOAuthImap($settings);
$folderMappings = [
'INBOX' => 'inbox',
'Sent' => 'sent',
'[Gmail]/Sent Mail' => 'sent',
'Sent Mail' => 'sent',
'Drafts' => 'drafts',
'[Gmail]/Drafts' => 'drafts',
'Trash' => 'trash',
'[Gmail]/Trash' => 'trash',
];
$totalNew = 0;
foreach (array_keys($folderMappings) as $imapFolderName) {
try {
$folder = $client->getFolder($imapFolderName);
if (!$folder) {
continue;
}
$messages = $folder->messages()
->setFetchFlags(true)
->setFetchBody(true)
->limit(100)
->get();
foreach ($messages as $imapMessage) {
$messageId = $imapMessage->getMessageId() ?? uniqid('msg_');
$existing = EmailMessage::where('message_id', $messageId)->first();
if ($existing) {
continue;
}
$this->processWebklexMessage($imapMessage, $imapFolderName);
$totalNew++;
}
} catch (\Exception $e) {
\Illuminate\Support\Facades\Log::error('Error processing OAuth IMAP folder', ['folder' => $imapFolderName, 'error' => $e->getMessage()]);
continue;
}
}
$client->disconnect();
\Illuminate\Support\Facades\Log::info('OAuth email sync completed', ['new' => $totalNew]);
return true;
}
private function processWebklexMessage($imapMessage, $imapFolder)
{
$folderType = match ($imapFolder) {
'INBOX', 'inbox' => 'inbox',
'Sent', 'sent', '[Gmail]/Sent Mail' => 'sent',
'Drafts', 'drafts', '[Gmail]/Drafts' => 'drafts',
'Trash', 'trash', '[Gmail]/Trash' => 'trash',
'Archive', 'archive', '[Gmail]/All Mail' => 'archive',
'Starred', 'starred', '[Gmail]/Starred' => 'starred',
default => 'inbox',
};
$folder = EmailFolder::where('type', $folderType)->first();
if (!$folder) return;
$messageId = $imapMessage->getMessageId() ?? uniqid('msg_');
$existing = EmailMessage::where('message_id', $messageId)->first();
if ($existing) return;
$from = $imapMessage->getFrom();
$to = $imapMessage->getTo();
$fromName = '';
$fromEmail = '';
if ($from && $from->first()) {
$fromName = $from->first()->personal ?? '';
$fromEmail = ($from->first()->mailbox ?? '') . '@' . ($from->first()->host ?? '');
}
$toEmail = '';
if ($to && $to->first()) {
$toEmail = ($to->first()->mailbox ?? '') . '@' . ($to->first()->host ?? '');
}
$message = EmailMessage::create([
'email_folder_id' => $folder->id,
'message_id' => $messageId,
'subject' => mb_substr($imapMessage->getSubject() ?? '(senza oggetto)', 0, 255),
'from_name' => mb_substr($fromName, 0, 255),
'from_email' => mb_substr($fromEmail, 0, 255),
'to_email' => mb_substr($toEmail, 0, 255),
'body_text' => $imapMessage->getTextBody() ?? '',
'body_html' => $imapMessage->getHTMLBody() ?? '',
'is_read' => !($imapMessage->getFlags()['UNSEEN'] ?? false),
'is_starred' => !empty($imapMessage->getFlags()['FLAGGED']),
'is_sent' => $folderType === 'sent',
'received_at' => $imapMessage->getDate() ?? now(),
'imap_uid' => $imapMessage->getUid() ?? null,
]);
$attachments = $imapMessage->getAttachments();
if ($attachments && count($attachments) > 0) {
foreach ($attachments as $attachment) {
try {
$filename = $attachment->getName() ?? 'attachment';
$contents = $attachment->getContent();
$path = 'email-attachments/' . \Illuminate\Support\Str::uuid() . '_' . $filename;
\Illuminate\Support\Facades\Storage::put($path, $contents);
EmailAttachment::create([
'email_message_id' => $message->id,
'filename' => $filename,
'mime_type' => $attachment->getMimeType() ?? 'application/octet-stream',
'size' => strlen($contents),
'file_path' => $path,
]);
} catch (\Exception $e) {
\Illuminate\Support\Facades\Log::error('Error saving OAuth attachment', ['error' => $e->getMessage()]);
}
}
}
}
private function ensureFoldersExist()
{
$systemFolders = EmailFolder::getSystemFolders();