芝麻web文件管理V1.00
编辑当前文件:/home/forge/stage.sksb.smartcon-survey.com/app/Services/SendGridService.php
first(); if (! $template) { throw new RuntimeException('Email Template wurde nicht gefunden'); } self::$template = $template; $sendGrid = new SendGrid(config('mail.mailers.sendgrid.apikey')); $mail = new Mail; $mail->setFrom(new From(config('mail.mailers.sendgrid.from.address'), config('mail.mailers.sendgrid.from.name'))); $mail->setTemplateId(self::$template->template_id); $personalization = new Personalization; $personalization->addTo(new To($email)); $personalization->addDynamicTemplateData('survey_link', 'https://smartcon.de'); $mail->addPersonalization($personalization); try { $response = $sendGrid->client->mail()->send()->post($mail); } catch (Exception $e) { throw new RuntimeException( 'Leider konnten die Mails nicht verschickt werden, '.$e->getMessage() ); } return $response->body(); } /** * Sends emails to the recipients. * * @param array $unsavedInvitations An array of unsaved invitations. * @param string $from The email address of the sender. * @param string $to The email address of the recipient. * @param MailingTypes $type The type of mailing. */ public static function sendMails( array $unsavedInvitations, int $templateId, string $from = '', string $to = '', MailingTypes $type = MailingTypes::Regular ): void { self::$from = $from; self::$to = $to; self::$wave = Setting::where('key', 'wave')->first()?->value; self::$type = $type; $template = EmailTemplate::find($templateId); if (! $template) { throw new RuntimeException('Email Template wurde nicht gefunden'); } self::$template = $template; self::checkEnvVariables(); if (empty($unsavedInvitations)) { throw new RuntimeException('Keine Einladungen zum Versenden gefunden!'); } $sendGrid = new SendGrid(config('mail.mailers.sendgrid.apikey')); self::$timeTobeSend = (int) Carbon::now()->timestamp + (int) config('mail.mailers.sendgrid.sendAfter'); $chunkedInvitations = array_chunk($unsavedInvitations, 1000); $mailing = match ($type) { MailingTypes::Individual, MailingTypes::Regular, MailingTypes::Special => self::createMailing($unsavedInvitations), default => null }; if ($mailing === null) { throw new RuntimeException('Bitte geben Sie einen gültigen Mailing-Typ an!'); } foreach ($chunkedInvitations as $key => $invitationsChunk) { try { $response = $sendGrid->client->mail()->send()->post( self::buildMail($invitationsChunk, $mailing) ); } catch (Exception $e) { $mailing->update([ 'status_code' => 0, 'sendgrid_info' => 'Error: '.$e->getMessage(), 'chunk' => $key, ]); throw new RuntimeException( 'Leider konnten die Mails nicht verschickt werden, '.$e->getMessage() ); } $mailing->update([ 'status_code' => $response->statusCode(), 'sendgrid_info' => 'Success'.$response->body(), 'chunk' => $key + 1, ]); if ($response->statusCode() !== 202) { $mailing->update([ 'status_code' => $response->statusCode(), 'sendgrid_info' => 'Error: '.$response->body(), 'chunk' => $key, ]); throw new RuntimeException( 'Leider konnten die Mails nicht verschickt werden, Status code: '.$response->statusCode().', '.$response->body() ); } } } /** * Builds a mail object for sending bulk emails. * * @param array $invitationsChunk The array of recipients for a chunk of emails. * @param Mailing $mailing The mailing object containing additional information. * @return Mail|array Returns a Mail object if no errors occur during building, or an array with the following keys if an error occurs: * - "status": The status of the error, which is set to "error". * - "message": The error message. * * @throws TypeException */ private static function buildMail(array $invitationsChunk, Mailing $mailing): Mail|array { $mail = new Mail; $mail->setFrom( new From( config('mail.mailers.sendgrid.from.address'), config('mail.mailers.sendgrid.from.name') ) ); $mail->setTemplateId(self::$template->template_id); foreach ($invitationsChunk as $invitationData) { $mail->addPersonalization( self::buildPersonalization($invitationData) ); self::createInvitation($invitationData, $mailing); self::$timeTobeSend += (int) config('mail.mailers.sendgrid.interval'); } $mail->setTemplateId(config('mail.mailers.sendgrid.template_id')); return $mail; } /** * Builds a Personalization object for sending personalized emails. * * @param array $invitationData An array containing contact and slug information. * @return Personalization The built Personalization object, which includes the following properties: * - addTo: The recipient's email address is added to the Personalization object. * - setSendAt: The email is scheduled to be sent at the specified timestamp. * - addDynamicTemplateData: Dynamic template data is added to the Personalization object, including: * - "survey_link": The generated survey link based on the provided slug value. * - "company_name": The fixed company name "Löwen Entertainment GmbH". */ private static function buildPersonalization(array $invitationData): Personalization { try { $personalization = new Personalization; $personalization->addTo(new To($invitationData['contact']['email'])); $personalization->setSendAt(new SendAt(self::$timeTobeSend)); $personalization->addDynamicTemplateData('survey_link', Invitation::link($invitationData['slug'])); $personalization->addDynamicTemplateData('company_name', 'Löwen Entertainment GmbH'); return $personalization; } catch (Exception $e) { throw new RuntimeException( "Personalization konnte nicht erstellt werden!, Kontakt ID: {$invitationData['contact']['id']}, Kontakt E-Mail: {$invitationData['contact']['email']} ".$e->getMessage() ); } } /** * Creates an invitation. * * @param Mailing $mailing The mailing associated with the invitation. * @return void Returns null if the invitation is created successfully, otherwise returns an error response array. */ private static function createInvitation(array $invitationData, Mailing $mailing): void { try { Invitation::createEntry( $invitationData['slug'], $invitationData['contact'], $invitationData['topic_id'], $invitationData['topic_id_2'], $mailing->id, self::$from, self::$to, self::$wave, ); } catch (Exception|QueryException $e) { throw new RuntimeException( "Einladung eintrag konnte nicht erstellt werden!, Kontakt ID: {$invitationData['contact']->id}, ".$e->getMessage() ); } } /** * Creates a new mailing and returns the created mailing instance or an error response. * * @param array $unsavedInvitations The unsaved invitations array. * @return Builder|Mailing Returns the created mailing instance if successful, * otherwise returns an error response array with the following keys: * - "status": The status of the response, which is set to "error". * - "message": The error message. */ private static function createMailing(array $unsavedInvitations): Builder|Mailing { try { return Mailing::create([ 'contact_count' => count($unsavedInvitations), 'type' => self::$type->name, 'status_code' => 0, 'sendgrid_info' => '', 'chunk' => 0, 'template_id' => self::$template->id, ]); } catch (Exception|QueryException $e) { throw new RuntimeException( 'Mailing konnte nicht erstellt werden!, '.$e->getMessage() ); } } /** * Checks if all required environment variables are set. * * @return void An array with error status and message */ private static function checkEnvVariables(): void { if (empty(config('mail.mailers.sendgrid.sendAfter')) || empty(config('mail.mailers.sendgrid.interval'))) { throw new RuntimeException('Mail Send After oder Mail Interval ist nicht gesetzt!'); } if (empty(config('mail.mailers.sendgrid.apikey'))) { throw new RuntimeException('SendGrid API Key ist nicht gesetzt!'); } if (empty(config('mail.mailers.sendgrid.from.address')) || empty(config('mail.mailers.sendgrid.from.name'))) { throw new RuntimeException('Mail From Address oder Mail From Name ist nicht gesetzt!'); } } }