nhance/app/Libraries/GmailAPI.php

267 lines
10 KiB
PHP
Executable File

<?php
namespace App\Libraries;
use Google\Client;
use Google\Service\Gmail;
use Google\Service\Gmail\Message;
use App\Models\SettingsModel;
use CodeIgniter\CLI\CLI;
class GmailAPI
{
protected $client;
protected $service;
protected $tokenField = 'email_token';
protected $myLogger = '';
protected $authField = 'gmail_api_oauth_credentials';
public function __construct()
{
$this->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;
}
}