myLogger = \Config\Services::mylogger(); $this->client = new Client(); $this->client->setApplicationName('Nhance GmailAPI'); $this->client->setScopes([ '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://mail.google.com/' ]); $this->setAuthConfig(); //die(); $this->client->setAccessType('offline'); $this->client->setPrompt('select_account consent'); // 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); } protected function setAuthConfig() { $settingsModel = new SettingsModel(); $credentials = $settingsModel->where('id', 1)->first(); if (!$credentials) { $this->myLogger->logme('error','OAuth credentials for GmailAPI not found in database.'); throw new \Exception('OAuth credentials for GmailAPI not found in database.'); } // print_r($credentials[$this->authField]);//die(); // $accessToken = $credentials[$this->authField]; $this->client->setAuthConfig(json_decode($credentials[$this->authField],true)); // if ($this->client->isAccessTokenExpired()) { // if ($this->client->getRefreshToken()) { // $this->client->fetchAccessTokenWithRefreshToken($this->client->getRefreshToken()); // $this->storeTokenToDB($this->client->getAccessToken()); // } else { // $this->myLogger->logme('error', 'Access token expired and no refresh token available.'); // throw new \Exception('Access token expired and no refresh token available.'); // } // } } protected function setTokenFromDB() { $settingsModel = new SettingsModel(); $token = $settingsModel->where('id', 1)->first(); // dd(is_array($token) && is_null($token[$this->tokenField])); if (is_array($token) && is_null($token[$this->tokenField])) { $this->myLogger->logme('error','Email Token not found in database.'); throw new \Exception('Email Token not found in database.'); } $accessToken = json_decode($token[$this->tokenField], true); $this->client->setAccessToken($accessToken); if ($this->client->isAccessTokenExpired()) { if ($this->client->getRefreshToken()) { $this->client->fetchAccessTokenWithRefreshToken($this->client->getRefreshToken()); $this->storeTokenToDB($this->client->getAccessToken()); } else { $this->myLogger->logme('error', 'Access token expired and no refresh token available.'); throw new \Exception('Access token expired and no refresh token available.'); } } } protected function storeTokenToDB($token) { $settingsModel = new SettingsModel(); $token = json_encode($token); // $settingsModel->update(['id' => $this->tokenField], ['value' => json_encode($token)]); $settingsModel->where('id', 1)->set([$this->tokenField => $token])->update(); } public function createMessage($to, $subject, $htmlContent, $from, $replyTo, $cc = [], $bcc = [], $attachments = []) { // print_r($to);die(); $boundary = uniqid(rand(), true); // Unique boundary for separating parts // 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/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,$attachments); $res = $this->service->users_messages->send('me', $message); return array('status' => true, 'data' => $res); } catch (\Exception $e) { $err_msg = 'An error occurred while sending the mail: ' . $e->getMessage(); $this->myLogger->logme('error', $err_msg); // throw new \Exception('An error occurred while sending the mail: ' . $e->getMessage()); return array('status' => false, 'data' =>$e->getMessage()); } } public function generateNewToken() { // dd('called'); if (!is_cli()) { throw new \RuntimeException('This method can only be accessed via the command line.'); } if (php_sapi_name() != 'cli') { throw new Exception('This application must be run on the command line.'); } $authUrl = $this->client->createAuthUrl(); CLI::write('Open the following link in your browser'); CLI::write("\n"); CLI::write($authUrl); // printf ("Open the following link in your browser:\n%s\n", $authUrl); CLI::write('Enter verification code: '); // print 'Enter verification code: '; $authCode = trim(fgets(STDIN)); $accessToken = $this->client->fetchAccessTokenWithAuthCode($authCode); if (array_key_exists('error', $accessToken)) { $this->myLogger->logme('error', 'Error in getting access token from authCode' . join(', ', $accessToken)); throw new \Exception(join(', ', $accessToken)); } $this->storeTokenToDB($accessToken); $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; } }