<?php
 namespace App\Modules\Email\Postmark; use App\Core\Email\AbstractEmail; use Illuminate\Support\Facades\Http; class Postmark extends AbstractEmail { protected string $apiUrl = 'https://api.postmarkapp.com/email'; public function sendEmail(array $params) { $validation = $this->validateEmailParams($params); if (! $validation['valid']) { return ['success' => false, 'errors' => $validation['errors']]; } $token = $this->getConfig('server_token'); if (! $token) { return ['success' => false, 'error' => 'Postmark server_token missing']; } $fromEmail = $params['from'] ?? $this->getConfig('from_email'); $fromName = $params['from_name'] ?? $this->getConfig('from_name'); $fromFormatted = $fromName ? "{$fromName} <{$fromEmail}>" : $fromEmail; $body = [ 'From' => $fromFormatted, 'To' => is_array($params['to']) ? implode(',', $params['to']) : $params['to'], 'Subject' => $params['subject'], 'HtmlBody' => $params['html_content'] ?? $params['content'] ?? '', 'TextBody' => $params['text_content'] ?? $this->htmlToText($params['html_content'] ?? $params['content'] ?? ''), 'MessageStream' => $this->getConfig('message_stream', 'outbound'), ]; if (! empty($params['cc'])) { $body['Cc'] = is_array($params['cc']) ? implode(',', $params['cc']) : $params['cc']; } if (! empty($params['bcc'])) { $body['Bcc'] = is_array($params['bcc']) ? implode(',', $params['bcc']) : $params['bcc']; } if (! empty($params['attachments'])) { $body['Attachments'] = array_map(fn ($a) => [ 'Name' => $a['name'] ?? basename($a['path']), 'Content' => base64_encode(file_get_contents($a['path'])), 'ContentType' => $a['mime'] ?? 'application/octet-stream', ], $params['attachments']); } try { $resp = Http::withHeaders([ 'Accept' => 'application/json', 'X-Postmark-Server-Token' => $token, ])->timeout(30)->post($this->apiUrl, $body); $data = $resp->json(); $errorCode = is_array($data) ? ($data['ErrorCode'] ?? null) : null; if (! $resp->successful() || ($errorCode !== null && (int) $errorCode !== 0)) { return [ 'success' => false, 'error' => 'Postmark error: '.($data['Message'] ?? ('HTTP '.$resp->status())), ]; } $messageId = $data['MessageID'] ?? null; if (! $messageId) { return ['success' => false, 'error' => 'Postmark response missing MessageID']; } return [ 'success' => true, 'message_id' => $messageId, 'message' => $data['Message'] ?? 'Email sent', ]; } catch (\Throwable $e) { return ['success' => false, 'error' => $e->getMessage()]; } } public function renderTemplate(array $params) { return ['success' => true, 'rendered' => $params['content'] ?? '']; } public function testConnection(array $params) { $token = $params['server_token'] ?? $this->getConfig('server_token'); if (! $token) { return ['success' => false, 'message' => 'server_token required']; } $resp = Http::withHeaders(['X-Postmark-Server-Token' => $token, 'Accept' => 'application/json']) ->timeout(15) ->get('https://api.postmarkapp.com/server'); return $resp->successful() ? ['success' => true, 'message' => 'Postmark connection OK'] : ['success' => false, 'message' => 'Postmark HTTP '.$resp->status()]; } public function getConfigFields(): array { return [ 'server_token' => [ 'type' => 'password', 'label' => 'Postmark Server Token', 'required' => true, 'encrypted' => true, 'description' => 'Postmark Server API token', ], 'from_email' => [ 'type' => 'email', 'label' => __('modules.email_config_from_email'), 'required' => true, 'description' => __('modules.email_config_from_email_desc'), ], 'from_name' => [ 'type' => 'text', 'label' => __('modules.email_config_from_name'), 'required' => true, 'description' => __('modules.email_config_from_name_desc'), ], 'message_stream' => [ 'type' => 'text', 'label' => 'Message Stream', 'required' => false, 'default' => 'outbound', 'description' => 'Postmark message stream (default: outbound)', ], 'test_mode' => [ 'type' => 'boolean', 'label' => __('modules.email_config_test_mode'), 'required' => false, 'default' => true, 'description' => 'Test modunda çalıştır', ], ]; } public function getRequiredConfigFields(): array { return ['server_token', 'from_email', 'from_name']; } } 