diff --git a/app/Config/Routes.php b/app/Config/Routes.php index ca0cbe4f..8c1521be 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -355,7 +355,8 @@ $routes->cli('cli/processjobs', 'JobWorker::processJobs'); $routes->get("processjob", "JobWorker::processJob"); $routes->cli('cli/new_gmail_token', 'MasterController::generateNewGmailAPIToken'); -$routes->cli('cli/send_mail_cli(/:any)?', 'MasterController::testGmailAPIViaCLI$1'); +$routes->cli('cli/send_mail_cli', 'MasterController::testGmailAPIViaCLI'); +$routes->cli('cli/check_bounce_mail_cli', 'MasterController::testCheckBounceMails'); $routes->cli('cli/app_check_list', 'MasterController::appCheckList'); $routes->cli('cli/new_gdrive_token', 'GoogleDriveController::generateNewGoogleDriveAccessToken'); diff --git a/app/Controllers/MasterController.php b/app/Controllers/MasterController.php index 691234eb..0a5bb5d1 100755 --- a/app/Controllers/MasterController.php +++ b/app/Controllers/MasterController.php @@ -34,6 +34,8 @@ use App\Models\InsurerExcelExportTemplateModel; use App\Models\SettingsModel; use App\Models\VehicleModel; +use CodeIgniter\CLI\CLI; + class MasterController extends AdminController { use ResponseTrait; @@ -1672,7 +1674,7 @@ class MasterController extends AdminController echo "Check the following..!\n"; echo "1. Update Gmail Oauth credentials in 'gmail_api_oauth_credentials' field in 'settings' table in JSON format.\n"; echo "2. Call this cli route to generate new access token: 'php public/index.php cli/new_gmail_token' from root of the project.\n"; - echo "3. Call this cli route : 'php public/index.php cli/send_mail_cli someone@gmail.com' to send test mail to testGmailAPIViaCLI ( replace someone@gmail.com with real time mail).\n"; + echo "3. Call this cli route : 'php public/index.php cli/send_mail_cli --to someone@gmail.com' to send test mail to testGmailAPIViaCLI ( replace someone@gmail.com with real time mail).\n"; } else { diff --git a/app/Helpers/MailHelper.php b/app/Helpers/MailHelper.php index f94d6419..a65a5b31 100755 --- a/app/Helpers/MailHelper.php +++ b/app/Helpers/MailHelper.php @@ -93,7 +93,8 @@ class MailHelper $emaill = $params['mail']; $subject = $params['subject']; $message = $params['message']; - + $attachments = isset($params['attachments']) && count($params['attachments']) ? $params['attachments'] : []; + //check BCC mail if (isset($params['bcc'])) { $bcc = $params['bcc']; @@ -118,7 +119,7 @@ class MailHelper try { - $res = $gmailapi->sendMessage($emaill, $subject, $message, 'no-reply@nhanceindia.in', $reply_to, $cc, $bcc); + $res = $gmailapi->sendMessage($emaill, $subject, $message, 'no-reply@nhanceindia.in', $reply_to, $cc, $bcc,$attachments); if($res['status']) { diff --git a/app/Libraries/GmailAPI.php b/app/Libraries/GmailAPI.php index f08a832e..e74101d4 100755 --- a/app/Libraries/GmailAPI.php +++ b/app/Libraries/GmailAPI.php @@ -26,18 +26,20 @@ class GmailAPI 'https://www.googleapis.com/auth/gmail.addons.current.message.readonly', 'https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/gmail.labels', - 'https://www.googleapis.com/auth/gmail.send' + 'https://www.googleapis.com/auth/gmail.send', + 'https://mail.google.com/' ]); $this->setAuthConfig(); //die(); $this->client->setAccessType('offline'); $this->client->setPrompt('select_account consent'); - - if (php_sapi_name() !== 'cli' || (uri_string() == 'cli/send_mail_cli' || uri_string() == 'cli/processjob') ) + // echo uri_string();//die(); + if (php_sapi_name() !== 'cli' || (uri_string() == 'cli/send_mail_cli' || uri_string() == 'cli/processjob' || uri_string() == 'cli/check_bounce_mail_cli') ) { + // echo 'getting token';die(); $this->setTokenFromDB(); // Call only if not in CLI } - + // die(); $this->service = new Gmail($this->client); } @@ -99,44 +101,73 @@ class GmailAPI $settingsModel->where('id', 1)->set([$this->tokenField => $token])->update(); } - public function createMessage($to, $subject, $htmlContent, $from, $replyTo, $cc = [], $bcc = []) - { - $boundary = uniqid(rand(), true); + public function createMessage($to, $subject, $htmlContent, $from, $replyTo, $cc = [], $bcc = [], $attachments = []) +{ + // print_r($to);die(); + $boundary = uniqid(rand(), true); // Unique boundary for separating parts - $rawMessageString = "From: $from\r\n"; - $rawMessageString .= "To: $to\r\n"; - $rawMessageString .= "Reply-To: $replyTo\r\n"; + // Initialize raw message headers + $rawMessageString = "From: $from\r\n"; + $rawMessageString .= "To: $to\r\n"; + $rawMessageString .= "Reply-To: $replyTo\r\n"; - if (!empty($cc)) { - $rawMessageString .= "Cc: " . implode(',', $cc) . "\r\n"; - } - - if (!empty($bcc)) { - $rawMessageString .= "Bcc: " . implode(',', $bcc) . "\r\n"; - } - - $rawMessageString .= "Subject: $subject\r\n"; - $rawMessageString .= "MIME-Version: 1.0\r\n"; - $rawMessageString .= "Content-Type: multipart/alternative; boundary=\"$boundary\"\r\n\r\n"; - $rawMessageString .= "--$boundary\r\n"; - $rawMessageString .= "Content-Type: text/html; charset=UTF-8\r\n"; - $rawMessageString .= "Content-Transfer-Encoding: 7bit\r\n\r\n"; - $rawMessageString .= $htmlContent . "\r\n"; - $rawMessageString .= "--$boundary--"; - - $rawMessage = base64_encode($rawMessageString); - $rawMessage = str_replace(['+', '/', '='], ['-', '_', ''], $rawMessage); - - $message = new Message(); - $message->setRaw($rawMessage); - - return $message; + if (!empty($cc)) { + $rawMessageString .= "Cc: " . implode(',', $cc) . "\r\n"; } - public function sendMessage($to, $subject, $htmlContent, $from, $replyTo, $cc = [], $bcc = []) + if (!empty($bcc)) { + $rawMessageString .= "Bcc: " . implode(',', $bcc) . "\r\n"; + } + + $rawMessageString .= "Subject: $subject\r\n"; + $rawMessageString .= "MIME-Version: 1.0\r\n"; + $rawMessageString .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n\r\n"; + + // Add HTML content as an alternative part + $rawMessageString .= "--$boundary\r\n"; + $rawMessageString .= "Content-Type: text/html; charset=UTF-8\r\n"; + $rawMessageString .= "Content-Transfer-Encoding: 7bit\r\n\r\n"; + $rawMessageString .= $htmlContent . "\r\n\r\n"; + + // Process each attachment + foreach ($attachments as $attachment) { + $filePath = $attachment['filePath']; + $fileName = $attachment['fileName']; + $fileData = file_get_contents($filePath); + + if ($fileData === false) { + continue; // Skip this attachment if file cannot be read + } + + $base64File = base64_encode($fileData); + + // Add each attachment with appropriate headers + $rawMessageString .= "--$boundary\r\n"; + $rawMessageString .= "Content-Type: application/octet-stream; name=\"$fileName\"\r\n"; + $rawMessageString .= "Content-Disposition: attachment; filename=\"$fileName\"\r\n"; + $rawMessageString .= "Content-Transfer-Encoding: base64\r\n\r\n"; + $rawMessageString .= chunk_split($base64File) . "\r\n\r\n"; + } + + // End boundary to signify the end of the message + $rawMessageString .= "--$boundary--"; + + // Encode the final raw message in base64 for Gmail API + $rawMessage = base64_encode($rawMessageString); + $rawMessage = str_replace(['+', '/', '='], ['-', '_', ''], $rawMessage); + + // Create Gmail message object + $message = new Message(); + $message->setRaw($rawMessage); + + return $message; +} + + + public function sendMessage($to, $subject, $htmlContent, $from, $replyTo, $cc = [], $bcc = [],$attachments = []) { try { - $message = $this->createMessage($to, $subject, $htmlContent, $from, $replyTo, $cc, $bcc); + $message = $this->createMessage($to, $subject, $htmlContent, $from, $replyTo, $cc, $bcc,$attachments); $res = $this->service->users_messages->send('me', $message); return array('status' => true, 'data' => $res); } catch (\Exception $e) { @@ -177,4 +208,59 @@ class GmailAPI $this->myLogger->logme('error', 'New token generated and stored in the database.'); print 'New token generated and stored in the database.'; } + + + + public function checkBounceStatus( string $userId = 'me',string $from_date = null,string $to_date = null,int $count = null,string $page = null) + { + $query = 'from:mailer-daemon OR "delivery failed" OR "failure notice"'; + if($from_date != '' && $to_date != '') + { + $query .= 'after:' . $from_date . ' before:' . $to_date; + } + $maxResults = $count ? $count : 20; + $pageToken = $page ? $page : null; + + $params = ['q' => $query,'maxResults' => $maxResults]; + if(isset($pageToken)){ $params['pageToken'] = $pageToken; } + $messages = $this->service->users_messages->listUsersMessages($userId, $params); + + $bounceDetails = []; + $pageToken = $messages->getNextPageToken(); + $bounceDetails['pageToken'] = $pageToken; + if (count($messages->getMessages()) > 0) { + foreach ($messages->getMessages() as $message) { + // Get full message details + $msg = $this->service->users_messages->get($userId, $message->getId(), ['format' => 'full']); + + // Extract important headers and content + $headers = $msg->getPayload()->getHeaders(); + $subject = null; + $date = null; + $to = null; + + foreach ($headers as $header) { + if ($header->getName() === 'Subject') { + $subject = $header->getValue(); + } + if ($header->getName() === 'Date') { + $date = $header->getValue(); + } + if ($header->getName() === 'To') { + $to = $header->getValue(); + } + } + + $bounceDetails['data'][] = [ + 'subject' => $subject, + 'date' => $date, + 'to' => $to, + 'snippet' => $msg->getSnippet(), + ]; + } + } + + return $bounceDetails; + } + } diff --git a/app/Views/employee_data_list.php b/app/Views/employee_data_list.php index 69ca1f74..2a70d76a 100755 --- a/app/Views/employee_data_list.php +++ b/app/Views/employee_data_list.php @@ -67,6 +67,7 @@