Upgrading Nylas API v2 to v3 for Email Sync in OroCRM/Symfony

Upgrading Nylas API v2 to v3 for Email Sync in OroCRM/Symfony

Summary:

With Nylas v2 API support ending in December 2024, upgrading to v3 is crucial to ensure continued email synchronisation in OroCRM. We recently completed this migration and identified key solutions and best practices that can help others navigate this transition smoothly.

With Nylas v2 API support ending in December 2024, upgrading to v3 is essential for maintaining email synchronisation in OroCRM. Having recently completed this migration in our OroCRM implementation, I wanted to share key insights and solutions that could help others facing the same challenge.

Why Upgrade to Nylas v3?

Nylas v3 offers several significant advantages:

  • Better Performance: Direct provider queries reduce API latency.
  • Enhanced Security: API keys replace v2’s app secret approach.

GDPR/CCPA Compliance: Non-IMAP data isn’t stored on Nylas servers.

The Migration Process: Key Steps

The upgrade process involves three crucial changes:

  1. Update Authentication: Switch to v3’s Hosted OAuth with API keys.
  2. User Re-authentication: All users must create new v3 grants.
  3. Update API Endpoints: Use grant-based v3 endpoints.

Polling for Email Synchronisation

Our OroCRM implementation uses a polling-based approach, where the system periodically checks for new messages at regular intervals through scheduled tasks. This method integrates well with OroCRM’s existing infrastructure and is simpler to implement than real-time solutions.

Key Implementation Components

1. Authentication Service

The authentication service handles the OAuth flow and stores v3 tokens:

// src/Service/NylasAuthService.php
namespace App\Service;

use App\Entity\NylasAccount;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\HttpClient\HttpClient;

class NylasAuthService
{
    private $managerRegistry;
    private $clientId;
    private $apiKey;
    private $apiUri = 'https://api.us.nylas.com/v3';

    public function __construct(ManagerRegistry $managerRegistry, string $clientId, string $apiKey)
    {
        $this->managerRegistry = $managerRegistry;
        $this->clientId = $clientId;
        $this->apiKey = $apiKey;
    }
    public function getAuthUrl(string $redirectUri): string
    {
        $scopes = ['email.read_only', 'calendar'];
        return sprintf(
            '%s/connect/auth?client_id=%s&redirect_uri=%s&scope=%s&response_type=code',
            $this->apiUri,
            $this->clientId,
            urlencode($redirectUri),
            implode(',', $scopes)
        );
    }
    public function exchangeCodeForToken(string $code, string $redirectUri, string $userId): ?array
    {
        $client = HttpClient::create();
        $response = $client->request('POST', $this->apiUri . '/connect/token', [
            'headers' => ['Authorization' => 'Bearer ' . $this->apiKey],
            'body' => [
                'client_id' => $this->clientId,
                'grant_type' => 'authorization_code',
                'code' => $code,
                'redirect_uri' => $redirectUri,
            ],
        ]);
        if ($response->getStatusCode() === 200) {
            $data = $response->toArray();
            // Store the v3 token and grant ID
            $entityManager = $this->managerRegistry->getManager();
            $repository = $entityManager->getRepository(NylasAccount::class);
           
            $account = $repository->findOneBy(['userId' => $userId]) ?? new NylasAccount();
            $account->setUserId($userId);
            $account->setAccessToken($data['access_token']);
            $account->setGrantId($data['grant_id']);
            $account->setIsV3(true);
           
            $entityManager->persist($account);
            $entityManager->flush();
            
            return $data;
        }       

        return null;
    }
}

2. Email Sync Service

This service pulls new emails from Nylas using the v3 API:

// Key method from EmailSyncService
public function syncEmails(string $userId, \DateTime $since = null): array
{
    $entityManager = $this->managerRegistry->getManager();
    $account = $entityManager->getRepository(NylasAccount::class)
        ->findOneBy(['userId' => $userId]);  

    if (!$account || !$account->getGrantId() || !$account->isV3()) {
        return ['status' => 'error', 'message' => 'No valid Nylas v3 account'];
    }

    $client = HttpClient::create();
    $params = ['limit' => 50];
  
    // Add date filter if provided
    if ($since) {
        $params['received_after'] = $since->format('c');
    }
  
    $response = $client->request('GET', 
        $this->apiUri . '/grants/' . $account->getGrantId() . '/messages', 
        [
            'headers' => ['Authorization' => 'Bearer ' . $this->apiKey],
            'query' => $params
        ]
    );
   
    if ($response->getStatusCode() === 200) {
        $data = $response->toArray();
        // Process emails...
        return ['status' => 'success', 'count' => count($data['data'])];
    }
    
    return ['status' => 'error', 'message' => 'Failed to fetch emails'];
}

3. Scheduled Sync Command

To regularly check for new emails, we created a Symfony Command that runs via cron:

// src/Command/SyncNylasEmailsCommand.php
class SyncNylasEmailsCommand extends Command
{
    protected static $defaultName = 'app:sync-nylas-emails';
   
    // ... constructor and configuration ...
   
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $entityManager = $this->managerRegistry->getManager();
        $users = $entityManager->getRepository(User::class)->findAll();
        
        // Get emails from last 15 minutes
        $since = new \DateTime('-15 minutes');
        
        foreach ($users as $user) {
            $result = $this->emailSyncService->syncEmails($user->getId(), $since);
            // Process result...
        }
        
        return Command::SUCCESS;
    }
}

Add this to your crontab to run every 15 minutes:

*/15 * * * * /path/to/orocrm/bin/console app:sync-nylas-emails >> /var/log/nylas-sync.log 2>&1

 

User Migration Strategy

For a smooth transition to v3, we implemented:

  1. User Notification: Informed users about the upcoming change.
  2. “Connect” Button: A button for re-authentication was added in Orocrm.
  3. Status Indicator: Displayed which users had upgraded to v3.

This approach allowed us to migrate users without disruption gradually.

Common Challenges and Solutions

During our migration, we encountered a few challenges:

  • Authentication Scopes: Ensure scopes match your email requirements.
  • Rate Limiting: Nylas v3 limits to 20 requests/second, so implement batching if necessary.
  • Error Handling: Add robust error handling, especially around the authentication flow.

Conclusion

Upgrading to Nylas API v3 in OroCRM involves updating authentication flows, API endpoints, and implementing a polling mechanism for email synchronisation. 

Our polling-based approach has proven reliable and integrates well with Orocrm’s existing infrastructure. By focusing on clean authentication implementation and regular polling, we’ve maintained seamless email synchronisation while benefiting from Nylas v3’s improved performance and security features.

Upgrade Nylas v3

Anand Dattani

Author

Anand Dattani is a Senior Developer at BrainStream Technolabs. He is an experienced developer specializing in PHP and modern MVC frameworks, with expertise in backend architecture and building scalable web solutions.

Related Blog

CRM

Unlocking the Power of vTiger CRM: Installation and Configuration Explained

vTiger Open Source CRM is a customer relationship management (CRM) software solution. It’s an open-source platform, meaning its source code is freely available for anyone to use, modify, and distribute. vTiger Open Source CRM is like a special program that...

CRM

How Can The vTiger CRM Software Help Amplify Your Business?

Vtiger CRM software development has all the features and functionalities that are needed to help your organization succeed in each of your marketing efforts, framing future strategies, handling several kinds of information, and obtain brand sustainability. So, what exactly is vTiger...

CRM

Top 5 Reasons to Implement Social-CRM Integration

Brands need to remain highly communicative and create a strong social media presence. Hence, your CRM strategy must include social media as this enables you to track, benchmark, and continue to engage with your customers via their preferred communication channels....

newslatter_bg_image
newslatter_image

Keep up-to-date with our newsletter.

Sign up for our newsletter to receive weekly updates and news directly to your inbox.