<?php
declare(strict_types=1);
namespace App\Controller;
use App\Exception\ApiException\ApiDeserializeException;
use App\Exception\ApiException\ApiEmailSendException;
use App\Exception\ApiException\ApiValidationException;
use App\Exception\ApiException\NotFoundException;
use App\Model\Email;
use App\Model\EmailMessage;
use App\Model\EmailSearchMessage;
use App\Service\EmailService;
use Nelmio\ApiDocBundle\Annotation\Model;
use Nelmio\ApiDocBundle\Annotation\Security;
use OpenApi\Annotations as OA;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\SerializerInterface;
class EmailController extends AbstractController
{
/** @var LoggerInterface */
protected $log;
/** @var SerializerInterface */
private $serializer;
/** @var EmailService */
private $emailService;
public function __construct(
LoggerInterface $log,
SerializerInterface $serializer,
EmailService $emailService
) {
$this->log = $log;
$this->serializer = $serializer;
$this->emailService = $emailService;
}
/**
* Send an email
*
* @OA\Tag(name="email")
* @OA\Post(summary="Send a mail with a template")
*
* @OA\RequestBody(
* description="Input data format",
* @OA\JsonContent(ref=@Model(type=Email::class)),
* )
* @OA\Response(
* response=200,
* description="Email sent"
* ),
* @OA\Response(
* response=400,
* description="If the request is incorrect, an array of errors will be returned."
* )
* @OA\Response(
* response=403,
* description="Access token does not have the required scope"
* ),
* @Security(name="Bearer")
*
* @param Request $request
*
* @return JsonResponse
* @throws ApiDeserializeException
* @throws ApiEmailSendException
* @throws ApiValidationException
*/
#[Route(path: '/email/send', name: 'post_email_send', methods: ['POST'])]
public function send(Request $request)
{
try {
/** @var Email $email */
$email = $this->serializer->deserialize($request->getContent(), Email::class, 'json');
} catch (\Exception $e) {
throw new ApiDeserializeException($e->getMessage());
}
$templatedEmail = $this->emailService->generateTemplatedEmail($email);
if (true === $email->isDebug()) {
return new JsonResponse([
'subject' => $templatedEmail->getSubject(),
'from' => array_map(fn (Address $address) => $address->toString(), $templatedEmail->getFrom()),
'to' => array_map(fn (Address $address) => $address->toString(), $templatedEmail->getTo()),
'cc' => array_map(fn (Address $address) => $address->toString(), $templatedEmail->getCc()),
'bcc' => array_map(fn (Address $address) => $address->toString(), $templatedEmail->getBcc()),
'locale' => $email->getLocale(),
'attachments' => array_map(fn (DataPart $attachment) => $attachment->asDebugString(), $templatedEmail->getAttachments()),
'template' => $email->getTemplatePath(),
'templateData' => $email->getTemplateData(),
'htmlBody' => $templatedEmail->getHtmlBody(),
], Response::HTTP_OK);
}
$this->emailService->send($templatedEmail);
return new JsonResponse([
'success' => true,
], Response::HTTP_OK);
}
/**
* Search emails by query
*
* @OA\Tag(name="email")
* @OA\Get(
* summary="Search emails by query",
* description="Search emails by query syntax by SendGrid Filter all messages API (https://docs.sendgrid.com/api-reference/e-mail-activity/filter-all-messages)",
* @OA\Parameter(
* name="query",
* in="query",
* description="SendGrid request to filter returned emails (see=https://docs.sendgrid.com/for-developers/sending-email/getting-started-email-activity-api#query-reference)",
* required=true,
* example="subject LIKE '%marchand%'",
* @OA\Schema(
* type="string"
* ),
* ),
* @OA\Parameter(
* name="limit",
* in="query",
* description="Limit the number of information returned",
* @OA\Schema(
* type="integer"
* ),
* ),
* )
* @OA\Response(
* response=200,
* description="List of email messages to JSON",
* @OA\JsonContent(
* type="array",
* @OA\Items(ref=@Model(type=EmailSearchMessage::class))),
* )
* @OA\Response(
* response=400,
* description="If the request is incorrect, an array of errors will be returned."
* )
* @OA\Response(
* response=403,
* description="Access token does not have the required scope"
* )
* @Security(name="Bearer")
*
* @param Request $request
*
* @return JsonResponse
* @throws BadRequestHttpException
*/
#[Route(path: '/email/search', methods: ['GET'], name: 'get_email_search')]
public function search(Request $request)
{
$query = $request->get('query', '');
$limit = $request->get('limit', '');
if (preg_match('/\d+/', $limit)) {
$limit = (int) $limit;
} else {
$limit = 0;
}
try {
return new JsonResponse(
$this->emailService->findMessagesByQuery($query, $limit),
Response::HTTP_OK
);
} catch (\Throwable $t) {
throw new BadRequestHttpException(sprintf('Error on search messages by query: %s', $t->getMessage()), $t);
}
}
/**
* Search email by ID
*
* @OA\Tag(name="email")
* @OA\Get(
* summary="Search email by ID",
* description="Search email by ID by SendGrid Filter messages by message ID (https://docs.sendgrid.com/api-reference/e-mail-activity/filter-all-messages)",
* @OA\Parameter(
* name="messageId",
* in="path",
* description="The ID of the message you are requesting details for.",
* required=true,
* example="ZuL4ObErRj2LcetrX95S5A.filterdrecv-59cb65cf6d-7z4fb-1-6436AA0F-27.0",
* @OA\Schema(
* type="string"
* ),
* ),
* )
* @OA\Response(
* response=200,
* description="Email message result to JSON",
* @OA\JsonContent(ref=@Model(type=EmailMessage::class)),
* ),
* @OA\Response(
* response=400,
* description="If the request is incorrect, an array of errors will be returned."
* ),
* @OA\Response(
* response=404,
* description="If no message found with id."
* ),
* @OA\Response(
* response=403,
* description="Access token does not have the required scope"
* ),
* @Security(name="Bearer")
*
* @param string $messageId
*
* @return JsonResponse
* @throws NotFoundHttpException
* @throws BadRequestHttpException
*/
#[Route(path: '/email/search/{messageId}', methods: ['GET'], name: 'get_email_search_by_id')]
public function searchById(string $messageId)
{
try {
return new JsonResponse(
$this->emailService->findMessageById($messageId),
Response::HTTP_OK
);
} catch (NotFoundException $t) {
throw new NotFoundHttpException($t->getMessage());
} catch (\Throwable $t) {
throw new BadRequestHttpException(sprintf('Error on search messages by id "%s": %s', $messageId, $t->getMessage()), $t);
}
}
}