如何使用sendgrid和laravel在邮件上显示动态图像?

问题描述 投票:0回答:1

我有一个 Laravel 作业,当发送订单时,会向用户发送一封电子邮件,其中包含一些内容和动态数据。我为此使用 sendgrid 模板。目前,我可以使用一些数据成功向用户发送邮件,但在通过邮件发送产品图像时遇到问题。当我收到邮件时,我收到这样的邮件:

<img src="http://avala-dev.com/api/product/1/image/1" alt="Product Image">

如果我在浏览器的新选项卡中输入该网址,我会收到图像,但在我的邮件中它不会显示,它只会显示这样的 img 标签。我的图像存储在

storage/app/documents
文件夹中,类似于
5b602461-de87-4f46-a320-1f883dbaa686.webp
该怎么做才能渲染该图像并在邮件中显示它?任何帮助表示赞赏。这是我的代码。

PendingOrderJob.php

<?php

namespace App\Jobs;

use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use SendGrid;
use SendGrid\Mail\Mail;

class PendingOrderJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $user;
    public $email;
    public $order;
    public $cart;

    public function __construct($user, $email, $order, $cart)
    {
        $this->user = $user;
        $this->email = $email;
        $this->order = $order;
        $this->cart = $cart;
    }

    public function handle()
    {
        $user = $this->user;
        $email_template = config('sendgrid.templates.events.pending_order');

        $productsData = [];
        foreach ($this->order->products as $product) {
            $productData = [
                'category_id' => $product->category_id,
                'group_id' => $product->group_id,
                'type' => $product->type,
                'sku' => $product->sku,
                'name' => $product->name,
                'visible' => $product->visible,
            ];

            $productData['images'] = $product->images->map(function ($image) use ($product) {
                return route('product-image', ['id' => $product->id, 'image_id' => $image->id]);
            })->toArray();

            $productsData[] = $productData;

        }

        $price = [];
        $quantity = [];
        foreach ($this->order->products as $product) {
            $price[] = $product->pivot->price;
            $quantity[] = $product->pivot->quantity;
        }

        $cartData = [
            'user_id' => $this->cart->user_id,
            'start_date' => $this->cart->start_date,
            'end_date' => $this->cart->end_date,
            'points_required' => $this->cart->points_required,
            'price' => $this->cart->price
        ];

        $email = new Mail();
        $email->setFrom(config('sendgrid.credentials.email', ''), config('sendgrid.credentials.name', ''));
        $email->setSubject("Pending Order");
        $email->addTo($user->email, 'toolbox');
        $email->addDynamicTemplateDatas([
            'user_email' => $user->email,
            'order_id' => $this->order->id,
            'status' => $this->order->status,
            'note' => $this->order->note,
            'price' => $price,
            'quantity' => $quantity,
            'cart' => $cartData,
            'products' => $productsData,
        ]);
        $email->setTemplateId($email_template);

        $sendgrid = new SendGrid(config('sendgrid.credentials.secret_key'));
        try {
            $response = $sendgrid->send($email);
        } catch (Exception $e) {
            Log::error('Pending Order Job Failed: ' . $e->getMessage());
        }
    }
}

api.php

Route::middleware(['throttle:1000,1'])->group(function () {
    Route::match(['get', 'delete'], 'product/{id}/image/{image_id}', [ProductController::class, 'image'])
        ->name('product-image');
});

产品控制器.php

public function image(Request $request, $id, $imageID)
{
    if ($request->method() === 'DELETE') {
        $product = Product::findOrFail($id);
        $image = $product->images()
            ->where('document_id', $imageID)
            ->delete();
        return;
    }

    if ($request->method() === 'GET') {
        $product = Product::findOrFail($id);
        $image = $product->images()
            ->where('document_id', $imageID)
            ->firstOrFail();

        // Get the image data from storage
        $imageData = Storage::get($image->path);
        
        // Determine the MIME type of the image
        $mimeType = Storage::mimeType($image->path);
        
        // Return the image data as a response
        return Response::make($imageData, 200, [
            'Content-Type' => $mimeType,
            'Content-Disposition' => 'inline; filename="' . $image->name . '"',
        ]);
    }
}

在我的 sendgrid 模板上,我将这些图像称为这样的

{{#each products.product}}
   {{#each product.images}}
        <img src={{this}} alt="Product Image">
   {{/each}}
{{/each}}
laravel sendgrid
1个回答
0
投票

我在 Laravel 中从公共存储过渡到本地存储时遇到了类似的挑战。

解决方案涉及将图像直接嵌入到

MailMessage
中。

我正在使用通知向用户发送邮件,我添加了通知类的更新代码:

public function toMail($notifiable)
{  
    $ccEmail = config("constants.team_email");
    $mailMessage = new MailMessage();
    $mailMessage->cc($ccEmail);
    $mailMessage->subject("Hello User,  ".$notifiable->name);
    
    $data = ['user' => $this->user];
    
    if (isset($notifiable->image_path)) {
        $userImg = Swift_Image::fromPath(Storage::disk('local')->path($notifiable->image)); // storage path "users/images/sdnfjnDjknklsdf7frnksj.jpg"
        $mailMessage->withSwiftMessage(function ($message) use ($userImg) {
            $message->embed($userImg);
        }); // embed the image in mail message
        $data['userImg'] = 'cid:' . $userImg->getId(); // store embed image's id in var
    }
    
    $mailMessage->markdown('emails.my-temp', $data);
    
    return $mailMessage;
}

在电子邮件模板(/views/emails/my-temp.blade.php)中,您可以像这样显示嵌入的图像:

    @if(isset($userImg))
       <img src="{{ $userImg }}">
    @endif

有关更多详细信息,您可以参考 Swift Mailer 文档:https://swiftmailer.symfony.com/docs/messages.html

© www.soinside.com 2019 - 2024. All rights reserved.