loreal-global-kickoff/EmailService.php
DJP 80b170a735 Add Global to Local CSV transformation backend
Services Created:
- OMGService.php: OMG API integration with detailed error handling
- CSVTransformer.php: CSV parsing and transformation logic
- EmailService.php: Mailgun email notifications
- process-csv.php: Multi-stage CSV processing with progress tracking
- upload-to-box.php: Box upload with approval workflow

Features:
- Comprehensive validation at each stage (upload, parse, campaign, API, transform)
- Detailed error reporting with actionable messages
- Warning system for non-critical issues
- Progress tracking through all stages
- Session-based CSV storage for preview before upload
- Date transformation (parse + add 1 month per blueprint)
- 16x market multiplication per ISO codes
- Business unit mapping per Make.com blueprint logic

Dependencies Added:
- league/csv for CSV parsing
- nesbot/carbon for date manipulation

Configuration:
- Added global_to_local settings (ISO codes, business unit map)
- Added omg_api settings (placeholder for API key)
- Added email settings (Mailgun placeholders)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 16:44:48 -05:00

121 lines
3.7 KiB
PHP

<?php
/**
* Email Service
* Handles email notifications via Mailgun
*/
class EmailService {
private $config;
private $enabled;
public function __construct() {
$appConfig = require __DIR__ . '/config.php';
$this->config = $appConfig['email'];
$this->enabled = $this->config['enabled'] ?? false;
}
/**
* Send email via Mailgun
*/
public function send($to, $subject, $text) {
if (!$this->enabled) {
error_log('Email not sent (service disabled): ' . $subject);
return ['success' => true, 'message' => 'Email disabled'];
}
try {
$url = 'https://api.mailgun.net/v3/' . $this->config['domain'] . '/messages';
$postData = [
'from' => $this->config['from'],
'to' => $to,
'subject' => $subject,
'text' => $text
];
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postData,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERPWD => 'api:' . $this->config['mailgun_api_key'],
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_TIMEOUT => 10
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
curl_close($ch);
if ($curlError) {
error_log('Email send failed: ' . $curlError);
return [
'success' => false,
'error' => 'Email delivery failed',
'details' => $curlError
];
}
if ($httpCode !== 200) {
error_log('Email send failed (HTTP ' . $httpCode . '): ' . $response);
return [
'success' => false,
'error' => 'Email service error',
'details' => 'HTTP ' . $httpCode,
'httpCode' => $httpCode
];
}
error_log('Email sent successfully to ' . $to);
return [
'success' => true,
'httpCode' => $httpCode
];
} catch (Exception $e) {
error_log('Email exception: ' . $e->getMessage());
return [
'success' => false,
'error' => 'Email exception',
'details' => $e->getMessage()
];
}
}
/**
* Send process started notification
*/
public function notifyStarted($userEmail, $filename) {
$subject = 'Regional Hotfolder - Started';
$text = "Document: $filename has been picked up for processing.";
return $this->send($userEmail, $subject, $text);
}
/**
* Send process completed notification
*/
public function notifyCompleted($userEmail, $filename, $outputCount) {
$subject = 'Regional Hotfolder - Completed';
$text = "Document: $filename has completed processing.\n\n";
$text .= "Generated $outputCount regional CSV files.\n";
$text .= "Files should appear in OMG within 5 minutes.";
return $this->send($userEmail, $subject, $text);
}
/**
* Send error notification
*/
public function notifyError($userEmail, $filename, $errorMessage) {
$subject = 'Error - Regional Hotfolder';
$text = "An error occurred while processing: $filename\n\n";
$text .= "Error: $errorMessage\n\n";
$text .= "Please check the file and try again.";
return $this->send($userEmail, $subject, $text);
}
}