greatcode / otp-reader
OTP Reader - Thread-safe, atomic, file-based Google OAuth credential storage library in native PHP with Mail Reader & Gmail Driver
Requires
- php: >=8.1
- psr/log: ^3.0
Requires (Dev)
- phpunit/phpunit: ^10.0
README
An enterprise-grade, thread-safe, native PHP library designed for automated mail reading, OTP code extraction in web scraping, and atomic Google OAuth credential management.
Engineered specifically for high-concurrency production environments (PHP-FPM, Docker Replicas, Multi-Worker Scraping Pipelines) on shared Linux filesystems without requiring database dependencies.
๐ Key Features
- ๐ Thread-Safe & Race-Condition Proof: Uses
flock(LOCK_EX)on persistent.lockfiles to prevent concurrent workers or containers from triggering duplicate token refreshes simultaneously. - โก Atomic Storage: File writes use temporary file buffering (
.tmp->fflush()->rename()), ensuring JSON files are never corrupted even during sudden process termination or power loss. - ๐ก๏ธ Automated Corruption Recovery: Automatically recovers stored credentials from
.bakbackup files if primary JSON files are corrupted. - ๐ง Gmail REST API v1 Driver: Native cURL HTTP transport wrapper for Gmail APIโno heavy SDK dependencies required.
- ๐ Automatic OTP Extraction: Built-in heuristic engine for extracting 4โ8 digit or alphanumeric verification codes from both English and Indonesian email payloads.
- โฑ๏ธ Smart Polling Retry & Delay: Retries message polling with customizable attempt limits and delay intervals until the email arrives.
- ๐ซ Auto Mark-as-Read: Automatically marks processed emails as
READupon successfully retrieving OTP codes to prevent re-reading stale messages. - ๐จ Glassmorphism Web UI: Includes a single-line Web Registration handler (
MailReader::handleRegistration()) with a responsive, modern HTML interface. - 0๏ธโฃ Zero Framework Dependencies: Written in pure, strict-typed PHP 8.1+ under the
Greatcode\OtpReader\namespace adhering to PSR-12 standard.
๐๏ธ Architecture Overview
graph TD
A["Scraping Script / Web App"] --> B["Greatcode\OtpReader\Mail\MailReader Facade"]
B --> C["Greatcode\OtpReader\Mail\Drivers\GmailDriver"]
C --> D["Greatcode\OtpReader\Google\CredentialManager"]
D --> E["Greatcode\OtpReader\Google\CredentialLock (flock LOCK_EX)"]
D --> F["Greatcode\OtpReader\Google\CredentialStorage"]
F --> G[("JSON Filesystem /storage/google/")]
C --> H["Gmail REST API v1"]
Loading
๐ฆ Installation
Install via Composer:
composer require greatcode/otp-reader
๐ Quick Start Guide
1. Read OTP for Web Scraping Scripts (1-Line Initialization)
<?php require_once __DIR__ . '/vendor/autoload.php'; use Greatcode\OtpReader\Mail\MailReader; // 1. Initialize MailReader under Greatcode\OtpReader namespace in 1 line $mailReader = MailReader::createGmail( storageDirectory: __DIR__ . '/storage/google', clientId: getenv('GOOGLE_CLIENT_ID'), clientSecret: getenv('GOOGLE_CLIENT_SECRET') ); // 2. Poll & extract OTP in 1 line // Automatically retries 5 times with 2s delay, filters last 5 mins, and marks email as READ $otp = $mailReader->getLatestOtp( email: 'user@gmail.com', from: 'tokopedia', afterTime: time() - 300 ); if ($otp !== null) { echo "โ Extracted OTP: " . $otp; } else { echo "โ OTP not received within timeout."; }
2. Custom Dynamic Body Parser Callable
If your email uses custom verification token formatting (e.g. [AUTH-992810]), pass a custom callable parser:
use Greatcode\OtpReader\Mail\EmailMessage; $token = $mailReader->getLatestOtp( email: 'user@gmail.com', from: 'service.com', afterTime: '10 minutes ago', parser: function (string $body, EmailMessage $message): ?string { if (preg_match('/\[AUTH-(\d{6})\]/', $body, $matches) === 1) { return $matches[1]; } return null; }, maxAttempts: 10, delaySeconds: 3 );
3. One-Line Web Account Registration UI (register.php)
Serve a self-contained, responsive Glassmorphism Web UI for registering accounts via browser in a single line of code:
<?php require_once __DIR__ . '/vendor/autoload.php'; use Greatcode\OtpReader\Mail\MailReader; // Serves HTML page, handles form submissions, and saves OAuth refresh tokens MailReader::handleRegistration( storageDirectory: __DIR__ . '/storage/google', clientId: getenv('GOOGLE_CLIENT_ID'), clientSecret: getenv('GOOGLE_CLIENT_SECRET') );
Run local PHP server to test:
php -S localhost:8080 examples/register_web.php
Open browser at http://localhost:8080 to access the registration UI.
๐ API Reference
Greatcode\OtpReader\Mail\MailReader
| Method | Description |
|---|---|
createGmail($storageDir, $clientId, $clientSecret, $httpHandler = null) |
One-line static factory creating MailReader with Gmail Driver. |
registerAccount($email, $refreshToken) |
Registers/updates an account's OAuth refresh token. |
getLatestOtp($email, $from, $afterTime, $parser, $maxAttempts, $delaySeconds, $autoMarkAsRead) |
Polls, extracts OTP, retries with delay, and auto-marks message as read. |
markAsRead($email, $messageId) |
Marks a specific email message as read in Gmail. |
handleRegistration($storageDir, $clientId, $clientSecret) |
Static helper for handling web HTTP requests and rendering HTML UI. |
๐ ๏ธ Exception Hierarchy
All library exceptions extend from base exception classes:
Greatcode\OtpReader\Google\Exceptions\CredentialException
โโโ CredentialNotFoundException
โโโ CredentialCorruptedException
โโโ CredentialLockException
โโโ CredentialRefreshException
โโโ CredentialStorageException
Greatcode\OtpReader\Mail\Exceptions\MailReaderException
๐งช Testing
Run full PHPUnit test suite:
vendor/bin/phpunit
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.