October 22, 2024
Chicago 12, Melborne City, USA
PHP

How can configure and connect with Azure Communication Services and Laravel?


I am working on the integration of Azure Communication Services Email for Laravel, I have of course the account created, the domain added, the SPF and DKIM validated, after this add in my config/services.php

'azure' => [
        'endpoint' => env('AZURE_ENDPOINT'),
        'accessKey' => env('AZURE_ACCESS_KEY'),
    ]

to be able to use the credentials that I add to the .env, which in this case is something like this as an example:

#Configuration using Azure Communications Services for Email
AZURE_ENDPOINT=https://laravel.unitedstates.communication.azure.com
AZURE_ACCESS_KEY=Ie2zAasb56t4ht86u7axRLh

After this I have created a service for the connection

<?php

namespace App\Services;

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

class AzureEmailService
{
    protected $client;
    protected $endpoint;
    protected $accessKey;

    public function __construct()
    {
        $this->client = new Client();
        $this->endpoint = config('services.azure.endpoint');
        $this->accessKey = config('services.azure.accessKey');
    }

    public function sendEmail($to, $subject, $body)
    {
        $url = "{$this->endpoint}/emails:send?api-version=2021-10-01-preview";
        //dd($url);

        $headers = [
            'Authorization' => 'Bearer ' . $this->accessKey,
            'Content-Type' => 'application/json',
        ];

        $payload = [
            'senderAddress' => 'DoNotReply@mywebsite.com', //dirección de envío
            'recipients' => [
                'to' => [
                    ['address' => $to], // la API
                ],
            ],
            'content' => [
                'subject' => $subject,
                'plainText' => $body, // Cambia aquí si quiero usar HTML
                ],
        ];

        try {
            $response = $this->client->post($url, [
                'headers' => $headers,
                'json' => $payload,
            ]);

            return json_decode($response->getBody()->getContents());

        } catch (RequestException $e) {
            \Log::error('Error al enviar el email: ', ['error' => $e->getMessage()]);
            throw new \Exception("Error al enviar el email", 500);
        }

    }
}

After this I created a livewire component:

class SendEmailForm extends Component
{
    public $email;
    public $subject;
    public $body;

    //validaciones basicas
    protected $rules = [
        'email' => 'required|email',
        'subject' => 'required|string|max:255',
        'body' => 'required|string',
    ];

    // Método para enviar el email
    public function sendEmail(AzureEmailService $azureEmailService)
    {
        // Validamos el formulario antes de enviar
        $this->validate();

        try {
            // Llamamos al servicio Azure para enviar el email
            $azureEmailService->sendEmail($this->email, $this->subject, $this->body);

            // Si el email se envía correctamente, mostramos un mensaje de éxito
            session()->flash('success', 'Email enviado correctamente.');
        } catch (\Exception $e) {
            // Si hay un error, lo mostramos
            session()->flash('error', 'Error al enviar el email: ' . $e->getMessage());
        }
    }

    public function render()
    {
        return view('livewire.send-email-form');
    }
}

to connect it to the view that contains a form for sending email

<div class="max-w-xl mx-auto p-6 bg-white shadow-md rounded-md">
    @if (session()->has('success'))
        <div class="text-green-500 mb-4">
            {{ session('success') }}
        </div>
    @endif

    @if (session()->has('error'))
        <div class="text-red-500 mb-4">
            {{ session('error') }}
        </div>
    @endif

    <form wire:submit.prevent="sendEmail">
        <div class="mb-4">
            <label for="email" class="block text-gray-700">Email:</label>
            <input type="email" id="email" wire:model="email" class="w-full border-gray-300 rounded-md shadow-sm" required>
            @error('email') <span class="text-red-500">{{ $message }}</span> @enderror
        </div>

        <div class="mb-4">
            <label for="subject" class="block text-gray-700">Asunto:</label>
            <input type="text" id="subject" wire:model="subject" class="w-full border-gray-300 rounded-md shadow-sm" required>
            @error('subject') <span class="text-red-500">{{ $message }}</span> @enderror
        </div>

        <div class="mb-4">
            <label for="body" class="block text-gray-700">Mensaje:</label>
            <textarea id="body" wire:model="body" class="w-full border-gray-300 rounded-md shadow-sm" rows="4" required></textarea>
            @error('body') <span class="text-red-500">{{ $message }}</span> @enderror
        </div>

        <button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
            Enviar Email
        </button>
    </form>
</div>

But when sending, I am receiving this error:

[2024-10-18 06:22:19] local.ERROR: Error al enviar el email:  {"error":"Client error: `POST https://laravel.unitedstates.communication.azure.com/emails:send?api-version=2021-10-01-preview` resulted in a `401 Unauthorized` response:
{\"error\":{\"code\":\"Denied\",\"message\":\"Denied by the resource provider.\"}}
"} 

Clearly the error indicates that I do not have authorization, but I don’t understand if I should configure something else in the process, whether to create a token before accessing or something like that… The documentation for those cases is not very clear, in this case my The connection goes through cURL but the other ways there are are using a package or SDK, so for this reason the information is not very clear to me…

How to make this connection correctly? Or is there some step I’m skipping?

I hope I can solve the problem to correct the correct configuration with Azure API to send emails



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video