PHPackages                             partridgerocks/gmail-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. partridgerocks/gmail-client

ActiveLibrary[API Development](/categories/api)

partridgerocks/gmail-client
===========================

A gmail api connector

v2.0.0(11mo ago)02771[6 PRs](https://github.com/PartridgeRocks/laravel-gmail-client/pulls)MITPHPPHP ^8.2

Since May 13Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/PartridgeRocks/laravel-gmail-client)[ Packagist](https://packagist.org/packages/partridgerocks/gmail-client)[ Docs](https://github.com/partridgerocks/gmail-client)[ GitHub Sponsors](https://github.com/PartridgeRocks)[ RSS](/packages/partridgerocks-gmail-client/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (14)Versions (19)Used By (0)

Laravel Gmail Client
====================

[](#laravel-gmail-client)

[![Latest Version on Packagist](https://camo.githubusercontent.com/0238d17e28774228e8f148980b1b1cf6bc4e68aff06eb6d82479909a9f11aadc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f706172747269646765726f636b732f676d61696c2d636c69656e742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/partridgerocks/gmail-client)[![GitHub Tests Action Status](https://camo.githubusercontent.com/63457995d76e69b56e45ff41bcfc688e7c4cb9a6abaa6c3326f14b81e30e14a8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f706172747269646765726f636b732f6c61726176656c2d676d61696c2d636c69656e742f72756e2d74657374732e796d6c3f6272616e63683d6d6173746572266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/partridgerocks/laravel-gmail-client/actions?query=workflow%3Arun-tests+branch%3Amaster)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/e3a90ea9b7a15a8a570fb69df3b5b2debf502ec130614bdb9fc6476c42bb7ce5/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f706172747269646765726f636b732f6c61726176656c2d676d61696c2d636c69656e742f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d6173746572266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/partridgerocks/laravel-gmail-client/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amaster)[![Total Downloads](https://camo.githubusercontent.com/2c44ea35dd9412014475d77e19b51254e1d688472eae3cb128d6bbc5e6ff3b96/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f706172747269646765726f636b732f676d61696c2d636c69656e742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/partridgerocks/gmail-client)[![PHP Version Support](https://camo.githubusercontent.com/8bd831822e2f85723705d3e058715d5469f8e040d5236d3e326ca6d08c972960/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f706172747269646765726f636b732f676d61696c2d636c69656e742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/partridgerocks/gmail-client)[![Laravel Version Support](https://camo.githubusercontent.com/25dc225f4c275030eb9b5c330faa5aaed4bca5a2d8d3e8b481ce20fd88bef396/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31302e7825323025374325323031312e7825323025374325323031322e782d6f72616e67653f7374796c653d666c61742d737175617265)](https://packagist.org/packages/partridgerocks/gmail-client)

A Laravel package that integrates with the Gmail API to seamlessly manage emails within your application. Built with [Saloon PHP](https://github.com/saloonphp/saloon) for API interactions and [Laravel Data](https://github.com/spatie/laravel-data) for structured data handling.

📋 Table of Contents
-------------------

[](#-table-of-contents)

- [Features](#-features)
- [Requirements](#-requirements)
- [Installation](#-installation)
- [Google API Setup](#-google-api-setup)
- [Usage](#-usage)
    - [Authentication](#authentication)
    - [Working with Emails](#working-with-emails)
    - [Contact Parsing &amp; CRM Integration](#contact-parsing--crm-integration)
    - [Working with Labels](#working-with-labels)
    - [Using Without Facade](#using-without-facade)
    - [Integration with User Model](#integration-with-your-user-model)
- [Advanced Usage](#-advanced-usage)
    - [Pagination](#pagination-support)
    - [Memory-Efficient Processing](#memory-efficiency)
    - [Null-Safe Methods](#null-safe-methods-for-robust-applications)
    - [Error Handling](#enhanced-error-handling)
    - [Token Refreshing](#refresh-a-token)
    - [CLI Testing](#command-line-testing)
    - [Custom Templates](#custom-email-templates)
- [Configuration](#-configuration)
- [Events](#-events)
- [Testing](#-testing)
- [Changelog](#-changelog)
- [Contributing](#-contributing)
- [Security](#-security-vulnerabilities)
- [Credits](#-credits)
- [License](#-license)

🚀 Features
----------

[](#-features)

- **OAuth Authentication**: Seamless integration with Gmail's OAuth 2.0 flow
- **Email Operations**:
    - Read emails and threads with full content and attachments
    - Send emails with HTML content
    - Support for CC, BCC, and custom sender addresses
    - Automatic contact parsing for CRM integration
- **Label Management**:
    - List, create, update, and delete email labels
    - Organize emails with custom label hierarchies
- **Performance Optimizations**:
    - Batch statistics retrieval for multi-account dashboards
    - Smart count estimation to prevent timeouts on large mailboxes
    - Connection health monitoring with quota tracking
    - Lazy loading collections for memory-efficient processing
    - Pagination support for large datasets
    - Customizable batch sizes for API requests
- **Developer Experience**:
    - Laravel facade for convenient access
    - Strongly-typed data objects with Laravel Data
    - Full Laravel service container integration
    - Comprehensive exception handling
    - Null-safe methods for robust applications (dashboards, background processing)
    - Command-line testing utilities
- **Enterprise Architecture**:
    - Service layer with interface contracts for enhanced testability
    - Builder pattern for fluent client construction
    - Repository pattern for data access abstraction
    - Factory pattern for centralized service management
    - Type-safe configuration objects
    - Comprehensive test data builders and mock factories

📋 Requirements
--------------

[](#-requirements)

- PHP 8.2 or higher
- Laravel 10.x, 11.x, or 12.x
- Google API credentials

📦 Installation
--------------

[](#-installation)

You can install the package via Composer:

```
composer require partridgerocks/gmail-client
```

After installation, publish the configuration file:

```
php artisan vendor:publish --tag="gmail-client-config"
```

This will create a `config/gmail-client.php` configuration file in your project.

🔐 Google API Setup
------------------

[](#-google-api-setup)

Before you can use the Gmail Client, you need to set up a project in the Google Developer Console and obtain OAuth 2.0 credentials:

1. Go to the [Google Developer Console](https://console.developers.google.com/)
2. Create a new project (or select an existing one)
3. Navigate to "APIs &amp; Services" &gt; "Library"
4. Search for and enable the "Gmail API"
5. Go to "APIs &amp; Services" &gt; "Credentials"
6. Click "Configure Consent Screen" and set up your OAuth consent screen:
    - Select "External" or "Internal" user type (depending on your needs)
    - Fill in the required app information
    - Add the required scopes (see below)
    - Add test users if needed (for external user type)
7. Create OAuth 2.0 credentials:
    - Go to "Credentials" and click "Create Credentials" &gt; "OAuth client ID"
    - Select "Web application" as the application type
    - Add a name for your client
    - Add your authorized redirect URIs (this should match your `GMAIL_REDIRECT_URI` config value)
    - Click "Create"
8. Copy the Client ID and Client Secret to your `.env` file:

```
GMAIL_CLIENT_ID=your-client-id
GMAIL_CLIENT_SECRET=your-client-secret
GMAIL_REDIRECT_URI=https://your-app.com/gmail/auth/callback
GMAIL_FROM_EMAIL=your-email@gmail.com

# Performance optimization settings
GMAIL_SMART_COUNTING=true
GMAIL_COUNT_THRESHOLD=50
GMAIL_CACHE_TTL=300
GMAIL_MAX_CONCURRENT=3
GMAIL_CIRCUIT_BREAKER=true
GMAIL_API_TIMEOUT=30

# Multi-account settings
GMAIL_MAX_ACCOUNTS=5
GMAIL_HEALTH_CHECK_INTERVAL=3600
GMAIL_BULK_OPERATIONS=true

```

> **Note**: The Gmail API requires specific scopes to access different features. The default configuration includes commonly used scopes, but you can customize them in the config file.

🔍 Usage
-------

[](#-usage)

The package automatically registers a Laravel Facade that provides a convenient way to interact with the Gmail API:

```
use PartridgeRocks\GmailClient\Facades\GmailClient;

// Get recent messages
$messages = GmailClient::listMessages();

// Get a specific message
$message = GmailClient::getMessage('message-id');

// Send an email
$email = GmailClient::sendEmail(
    'recipient@example.com',
    'Subject line',
    'Email body in HTML format'
);
```

### Authentication

[](#authentication)

The Gmail Client provides two ways to authenticate with the Gmail API:

#### 1. Manual Authentication Flow

[](#1-manual-authentication-flow)

If you want full control over the authentication process:

```
use PartridgeRocks\GmailClient\Facades\GmailClient;

// 1. Get the authorization URL
$authUrl = GmailClient::getAuthorizationUrl(
    config('gmail-client.redirect_uri'),
    config('gmail-client.scopes'),
    [
        'access_type' => 'offline',
        'prompt' => 'consent'
    ]
);

// 2. Redirect the user to the authorization URL
return redirect($authUrl);

// 3. In your callback route, exchange the code for tokens
public function handleCallback(Request $request)
{
    $code = $request->get('code');

    // Exchange code for tokens
    $tokens = GmailClient::exchangeCode(
        $code,
        config('gmail-client.redirect_uri')
    );

    // Store tokens securely for the authenticated user
    auth()->user()->update([
        'gmail_access_token' => $tokens['access_token'],
        'gmail_refresh_token' => $tokens['refresh_token'] ?? null,
        'gmail_token_expires_at' => now()->addSeconds($tokens['expires_in']),
    ]);

    return redirect()->route('dashboard');
}
```

#### 2. Using Built-in Routes

[](#2-using-built-in-routes)

For a simpler setup, you can enable the built-in routes:

1. Enable route registration in the config file:

```
// config/gmail-client.php
'register_routes' => true,
```

2. Use the provided routes in your app:

```
// Generate a link to the Gmail authentication page
Connect Gmail
```

The package will handle the OAuth flow and store the tokens in the session by default.

### Working with Emails

[](#working-with-emails)

Once authenticated, you can use the client to interact with Gmail:

#### List Messages

[](#list-messages)

```
use PartridgeRocks\GmailClient\Facades\GmailClient;

// Authenticate with a stored token
GmailClient::authenticate($accessToken);

// List recent messages (returns a collection of Email data objects)
$messages = GmailClient::listMessages(['maxResults' => 10]);

foreach ($messages as $message) {
    echo "From: {$message->from}\n";
    echo "Subject: {$message->subject}\n";
    echo "Date: {$message->internalDate->format('Y-m-d H:i:s')}\n";
    echo "Body: {$message->body}\n";
}

// With query parameters (using Gmail search syntax)
$messages = GmailClient::listMessages([
    'q' => 'from:example@gmail.com after:2023/01/01 has:attachment',
    'maxResults' => 20
]);
```

#### Get a Specific Message

[](#get-a-specific-message)

```
// Get a specific message by ID
$email = GmailClient::getMessage('message-id');

echo "Subject: {$email->subject}\n";
echo "From: {$email->from}\n";
echo "Snippet: {$email->snippet}\n";
echo "Body: {$email->body}\n";

// Access message headers
foreach ($email->headers as $name => $value) {
    echo "{$name}: {$value}\n";
}

// Check for specific labels
if (in_array('INBOX', $email->labelIds)) {
    echo "This message is in the inbox\n";
}
```

#### Send an Email

[](#send-an-email)

```
// Send a simple email
$email = GmailClient::sendEmail(
    'recipient@example.com',
    'Email subject',
    'This is the email body in HTML format.'
);

// Send with additional options
$email = GmailClient::sendEmail(
    'recipient@example.com',
    'Email with options',
    'This email includes CC and BCC recipients.',
    [
        'from' => 'your-email@gmail.com',
        'cc' => 'cc@example.com',
        'bcc' => 'bcc@example.com',
    ]
);

// The sent email object is returned
echo "Email sent with ID: {$email->id}";
```

### Performance Features

[](#performance-features)

#### Account Statistics (Batch Retrieval)

[](#account-statistics-batch-retrieval)

For multi-account dashboards, use the batch statistics method to minimize API calls:

```
// Get comprehensive account metrics in 1-2 API calls
$stats = GmailClient::getAccountStatistics([
    'unread_limit' => 25,        // Show exact count up to 25, then "25+"
    'today_limit' => 15,         // Today's messages limit
    'include_labels' => true,    // Include label count
    'estimate_large_counts' => true,  // Use smart estimation
    'background_mode' => false,  // Throw exceptions or return partial data
]);

// Returns:
// [
//     'unread_count' => 23,           // or "25+" for large counts
//     'today_count' => 8,             // Today's messages
//     'labels_count' => 42,           // Total labels
//     'estimated_total' => 15000,     // Total mailbox size estimate
//     'api_calls_made' => 2,          // Actual API calls used
//     'last_updated' => '2024-01-01T12:00:00Z',
//     'partial_failure' => false,     // True if some metrics failed
// ]

// Performance comparison:
// Before: 3-5 API calls per account, 2-5s load time
// After:  1-2 API calls per account,  true,
//     'status' => 'healthy',           // healthy, unhealthy, rate_limited, etc.
//     'api_quota_remaining' => 250,    // Remaining API calls (if available)
//     'last_successful_call' => '2024-01-01T12:00:00Z',
//     'errors' => [],                  // Array of error messages
// ]

// Use for dashboard health indicators
if ($health['status'] === 'rate_limited') {
    // Handle rate limiting gracefully
    $retryAfter = $health['retry_after'] ?? 60;
}
```

### Contact Parsing &amp; CRM Integration

[](#contact-parsing--crm-integration)

The package automatically parses email addresses and names from Gmail messages, making it easy to integrate with CRM systems:

```
// Get an email message
$email = GmailClient::getMessage('message-id');

// Access parsed contact information
$sender = $email->fromContact;
echo "Sender: {$sender->name} email}>\n";
echo "Domain: {$sender->domain}\n";

// Access recipient contacts
foreach ($email->toContacts as $contact) {
    echo "To: {$contact->getDisplayName()} - {$contact->email}\n";
}

// Get all contacts involved in the email
$allContacts = $email->getAllContacts();

// Find contacts from specific domain (useful for CRM)
$externalContacts = array_filter(
    $allContacts,
    fn($contact) => !$contact->isFromDomain('mycompany.com')
);

// Get unique domains for company identification
$domains = $email->getContactDomains();
// Returns: ['example.com', 'client.com', 'mycompany.com']

// Check if email involves specific company
if ($email->hasContactFromDomain('important-client.com')) {
    // Handle VIP client email
}

// Get all contacts from a domain
$clientContacts = $email->getContactsFromDomain('acme-corp.com');
```

#### Manual Contact Parsing

[](#manual-contact-parsing)

You can also parse email strings manually:

```
use PartridgeRocks\GmailClient\Data\Contact;

// Parse single email address
$contact = Contact::parse('"John Doe" ');
echo $contact->name;    // "John Doe"
echo $contact->email;   // "john@example.com"
echo $contact->domain;  // "example.com"

// Parse multiple addresses
$contacts = Contact::parseMultiple('john@example.com, "Jane Doe" ');

// Access contact properties
foreach ($contacts as $contact) {
    echo "Name: " . ($contact->name ?? 'No name') . "\n";
    echo "Email: {$contact->email}\n";
    echo "Domain: {$contact->domain}\n";
    echo "Local part: {$contact->getLocalPart()}\n";
    echo "Display name: {$contact->getDisplayName()}\n";
    echo "Formatted: {$contact->format()}\n";
}
```

#### CRM Integration Examples

[](#crm-integration-examples)

```
// Find all emails from a specific company
$companyEmails = collect($emails)->filter(function ($email) {
    return $email->hasContactFromDomain('target-company.com');
});

// Extract contact data for CRM import
$crmData = [];
foreach ($emails as $email) {
    foreach ($email->getAllContacts() as $contact) {
        if (!$contact->isFromDomain('mycompany.com')) {
            $crmData[] = [
                'name' => $contact->name,
                'email' => $contact->email,
                'company_domain' => $contact->domain,
                'first_contact' => $email->internalDate,
            ];
        }
    }
}

// Group contacts by company domain
$contactsByCompany = collect($emails)
    ->flatMap(fn($email) => $email->getAllContacts())
    ->groupBy('domain')
    ->map(fn($contacts) => $contacts->unique('email'));
```

### Working with Labels

[](#working-with-labels)

Gmail uses labels to organize emails. You can create, retrieve, and manage these labels:

```
// List all labels
$labels = GmailClient::listLabels();

foreach ($labels as $label) {
    echo "Label: {$label->name} (ID: {$label->id})\n";
    echo "Type: {$label->type}\n";

    if ($label->messagesTotal !== null) {
        echo "Messages: {$label->messagesTotal} ({$label->messagesUnread} unread)\n";
    }
}

// Get a specific label
$label = GmailClient::getLabel('label-id');

// Create a new label
$newLabel = GmailClient::createLabel('Important Clients', [
    'labelListVisibility' => 'labelShow',
    'messageListVisibility' => 'show',
    'color' => [
        'backgroundColor' => '#16a765',
        'textColor' => '#ffffff'
    ]
]);

// Update a label (using the LabelResource directly)
$updatedLabel = GmailClient::labels()->update($label->id, [
    'name' => 'VIP Clients',
    'color' => [
        'backgroundColor' => '#4986e7',
        'textColor' => '#ffffff'
    ]
]);

// Delete a label
GmailClient::labels()->delete($label->id);
```

### Using Without Facade

[](#using-without-facade)

If you prefer not to use the facade, you can resolve the client from the container:

```
use PartridgeRocks\GmailClient\GmailClient;

public function index(GmailClient $gmailClient)
{
    $gmailClient->authenticate($accessToken);
    $messages = $gmailClient->listMessages();

    // ...
}
```

### Builder Pattern &amp; Service Integration

[](#builder-pattern--service-integration)

For advanced usage with dependency injection and configuration:

```
use PartridgeRocks\GmailClient\Builders\GmailClientBuilder;
use PartridgeRocks\GmailClient\Contracts\MessageServiceInterface;

// Using builder pattern
$client = GmailClientBuilder::create()
    ->withToken($accessToken)
    ->withConfig($customConfig)
    ->build();

// Using service injection
class EmailController extends Controller
{
    public function __construct(private MessageServiceInterface $messageService) {}

    public function dashboard()
    {
        $recentMessages = $this->messageService->findRecent(10);
        return view('dashboard', compact('recentMessages'));
    }
}
```

### Integration with Your User Model

[](#integration-with-your-user-model)

Here's an example of how you might integrate the Gmail client with your User model:

```
// In your User model
public function connectGmail($accessToken, $refreshToken = null, $expiresAt = null)
{
    $this->gmail_access_token = $accessToken;
    $this->gmail_refresh_token = $refreshToken;
    $this->gmail_token_expires_at = $expiresAt;
    $this->save();
}

public function getGmailClient()
{
    if (empty($this->gmail_access_token)) {
        throw new \Exception('Gmail not connected');
    }

    return app(GmailClient::class)->authenticate(
        $this->gmail_access_token,
        $this->gmail_refresh_token,
        $this->gmail_token_expires_at ? new \DateTime($this->gmail_token_expires_at) : null
    );
}

// In your controller
public function listEmails()
{
    $gmailClient = auth()->user()->getGmailClient();
    return $gmailClient->listMessages(['maxResults' => 20]);
}
```

🔧 Advanced Usage
----------------

[](#-advanced-usage)

### Pagination Support

[](#pagination-support)

The package supports pagination for listing messages and labels:

```
// Get a paginator for messages
$paginator = GmailClient::listMessages(['maxResults' => 25], true);

// Get the first page
$firstPage = $paginator->getNextPage();

// Check if there are more pages
if ($paginator->hasMorePages()) {
    // Get the next page
    $secondPage = $paginator->getNextPage();
}

// Or get all pages at once (use cautiously with large datasets)
$allMessages = $paginator->getAllPages();

// You can also transform the results using the DTO
use PartridgeRocks\GmailClient\Data\Responses\EmailDTO;
$emails = $paginator->transformUsingDTO(EmailDTO::class);
```

### Memory Efficiency

[](#memory-efficiency)

When working with large Gmail accounts, it's important to avoid loading all messages into memory at once:

```
// Lazy loading is the most memory-efficient approach for large datasets
$messages = GmailClient::listMessages(lazy: true);

// Process messages one by one without loading everything into memory
foreach ($messages as $message) {
    processMessage($message);

    // You can stop iteration at any point
    if ($someCondition) {
        break;
    }
}

// For even more efficiency, you can get only message IDs without full details
$messageIds = GmailClient::listMessages(lazy: true, fullDetails: false);

foreach ($messageIds as $messageData) {
    echo "Message ID: {$messageData['id']}\n";

    // Load full details only for specific messages if needed
    if (needsFullDetails($messageData)) {
        $fullMessage = GmailClient::getMessage($messageData['id']);
    }
}
```

### Null-Safe Methods for Robust Applications

[](#null-safe-methods-for-robust-applications)

For applications that need graceful degradation (dashboards, background processing), use the null-safe methods that never throw exceptions:

```
// ✅ Safe for dashboards - returns empty collection on any error
$labels = GmailClient::safeListLabels();
$messages = GmailClient::safeListMessages(['q' => 'is:unread']);

// ✅ Returns null instead of throwing NotFoundException
$message = GmailClient::safeGetMessage('message-id');

// ✅ Connection health check - never throws exceptions
if (GmailClient::isConnected()) {
    // Safe to proceed with Gmail operations
}

// ✅ Account overview with fallback data
$summary = GmailClient::getAccountSummary();
// Returns: ['connected' => true, 'labels_count' => 15, 'has_unread' => true, 'errors' => []]

// ✅ Statistics with graceful degradation
$stats = GmailClient::safeGetAccountStatistics();
// Returns fallback data if API fails: ['unread_count' => '?', 'partial_failure' => true]
```

**Perfect for:**

- Dashboard widgets that should never crash
- Background sync processes
- Health monitoring systems
- Any UI requiring robust error handling

### Enhanced Error Handling

[](#enhanced-error-handling)

The package provides detailed error handling for common Gmail API errors:

```
use PartridgeRocks\GmailClient\Exceptions\AuthenticationException;
use PartridgeRocks\GmailClient\Exceptions\NotFoundException;
use PartridgeRocks\GmailClient\Exceptions\RateLimitException;
use PartridgeRocks\GmailClient\Exceptions\ValidationException;

try {
    $message = GmailClient::getMessage('non-existent-id');
} catch (NotFoundException $e) {
    // Handle not found error
    echo "Message not found: " . $e->getMessage();
} catch (AuthenticationException $e) {
    // Handle authentication errors
    echo "Authentication error: " . $e->getMessage();

    if ($e->getError()->code === 'token_expired') {
        // Refresh the token
        $tokens = GmailClient::refreshToken($refreshToken);
    }
} catch (RateLimitException $e) {
    // Handle rate limit errors
    $retryAfter = $e->getRetryAfter();
    echo "Rate limit exceeded. Retry after {$retryAfter} seconds.";
} catch (ValidationException $e) {
    // Handle validation errors
    echo "Validation error: " . $e->getMessage();
}
```

### Refresh a Token

[](#refresh-a-token)

```
// Refresh an expired token
$tokens = GmailClient::refreshToken($refreshToken);

// The client is automatically authenticated with the new token
// Update the tokens in your storage
$user->update([
    'gmail_access_token' => $tokens['access_token'],
    'gmail_refresh_token' => $tokens['refresh_token'] ?? $user->gmail_refresh_token,
    'gmail_token_expires_at' => now()->addSeconds($tokens['expires_in']),
]);
```

### Command Line Testing

[](#command-line-testing)

The package includes a command to test your Gmail API connection:

```
# Get authentication URL
php artisan gmail-client:test --authenticate

# List recent messages
php artisan gmail-client:test --list-messages

# List labels
php artisan gmail-client:test --list-labels
```

### Custom Email Templates

[](#custom-email-templates)

You can use your own branded email templates:

```
// config/gmail-client.php
'branded_template' => resource_path('views/emails/branded-template.blade.php'),
```

⚙️ Configuration
----------------

[](#️-configuration)

The package configuration file (`config/gmail-client.php`) provides extensive customization options:

### Performance Settings

[](#performance-settings)

```
'performance' => [
    'enable_smart_counting' => true,           // Enable smart count estimation
    'count_estimation_threshold' => 50,        // Show exact count up to this limit
    'default_cache_ttl' => 300,               // Cache TTL in seconds (future use)
    'max_concurrent_requests' => 3,           // Max concurrent API requests (future use)
    'enable_circuit_breaker' => true,         // Enable circuit breaker pattern (future use)
    'api_timeout' => 30,                      // API request timeout in seconds
],
```

### Multi-Account Settings

[](#multi-account-settings)

```
'multi_account' => [
    'max_accounts_per_user' => 5,             // Maximum Gmail accounts per user
    'health_check_interval' => 3600,          // Health check interval in seconds
    'enable_bulk_operations' => true,         // Enable bulk operations (future use)
],
```

### Environment Variables

[](#environment-variables)

All configuration options can be overridden via environment variables:

VariableDefaultDescription`GMAIL_SMART_COUNTING``true`Enable smart count estimation`GMAIL_COUNT_THRESHOLD``50`Threshold for showing exact vs estimated counts`GMAIL_CACHE_TTL``300`Cache time-to-live in seconds`GMAIL_MAX_CONCURRENT``3`Maximum concurrent requests`GMAIL_CIRCUIT_BREAKER``true`Enable circuit breaker pattern`GMAIL_API_TIMEOUT``30`API request timeout in seconds`GMAIL_MAX_ACCOUNTS``5`Maximum accounts per user`GMAIL_HEALTH_CHECK_INTERVAL``3600`Health check interval in seconds`GMAIL_BULK_OPERATIONS``true`Enable bulk operations📡 Events
--------

[](#-events)

The package dispatches events that you can listen for:

- `GmailAccessTokenRefreshed`: When a token is refreshed
- `GmailMessageSent`: When an email is sent

🧪 Testing
---------

[](#-testing)

The package includes tests that you can run with PHPUnit:

```
composer test
```

For testing in your own application, you can use Saloon's built-in mocking capabilities:

```
use Saloon\Laravel\Facades\Saloon;
use Saloon\Http\Faking\MockResponse;

// In your test setup
public function setUp(): void
{
    parent::setUp();

    // Mock all Gmail API responses
    Saloon::fake([
        '*gmail.googleapis.com*' => MockResponse::make([
            'messages' => [
                [
                    'id' => 'test-id-123',
                    'threadId' => 'thread-123',
                    'snippet' => 'This is a test email',
                ]
            ]
        ], 200),
    ]);
}
```

📝 Changelog
-----------

[](#-changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

🤝 Contributing
--------------

[](#-contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

🔒 Security Vulnerabilities
--------------------------

[](#-security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

👨‍💻 Credits
-----------

[](#‍-credits)

- [Jordan Partridge](https://github.com/PartridgeRocks)
- [All Contributors](../../contributors)

📄 License
---------

[](#-license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance72

Regular maintenance activity

Popularity14

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 91.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

11

Last Release

355d ago

Major Versions

v1.5.0 → v2.0.02025-05-29

### Community

Maintainers

![](https://www.gravatar.com/avatar/a6bb27de88a541a632427686306c8fc56366d72582f6a3316d20500efe7971f3?d=identicon)[conduit-ui](/maintainers/conduit-ui)

---

Top Contributors

[![jordanpartridge](https://avatars.githubusercontent.com/u/9040417?v=4)](https://github.com/jordanpartridge "jordanpartridge (86 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (4 commits)")[![coderabbitai[bot]](https://avatars.githubusercontent.com/in/347564?v=4)](https://github.com/coderabbitai[bot] "coderabbitai[bot] (2 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (2 commits)")

---

Tags

integrationlaravelPartridgeRocksgmail-client

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/partridgerocks-gmail-client/health.svg)

```
[![Health](https://phpackages.com/badges/partridgerocks-gmail-client/health.svg)](https://phpackages.com/packages/partridgerocks-gmail-client)
```

###  Alternatives

[scalar/laravel

Render your OpenAPI-based API reference

6183.9k2](/packages/scalar-laravel)[ryangjchandler/bearer

Minimalistic token-based authentication for Laravel API endpoints.

8129.8k](/packages/ryangjchandler-bearer)[codebar-ag/laravel-docuware

DocuWare integration with Laravel

1221.1k](/packages/codebar-ag-laravel-docuware)[codebar-ag/laravel-zammad

Zammad integration with Laravel

106.1k](/packages/codebar-ag-laravel-zammad)[tapp/filament-webhook-client

Add a Filament resource and a policy for Spatie Webhook client

1120.2k](/packages/tapp-filament-webhook-client)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
