Laravel 11 ile Mail Gönderme

73

Uygulamalarımızın olmasa olmazlarından birisi de uygulama üzerinden gönderilen maillerdir. Bu mailler rapor özetleri olabileceği gibi kullanıcılara göndereceğimiz şifreler vb bir çok şey olabilir. Maille gönderilecek metinle ilgili çok problem yaşanacağını düşünmüyorum ama işin içine bir görsel girdiği zaman mail istemcileri dolayısıyla işin rengi değişiyor.

Laravel bu konuyu bizim için bayağı kolaylaştırdı. Bu yazımda basit bir şekilde bir mail oluşturup bu mailin içinde nasıl embeded görsel ekleyeceğinizi anlatmaya çalışayım. Öncelikle bir mail sınıfı oluşturmamız gerekiyor. Bu mail gönderimi için yeni kaydolan kullanıcılar için sistem tarafından üretilen şifreyi mail ile gönderme senaryasonu kullanalım.

php artisan make:mail NewUserPassword

Yukarıdaki komutu istemcimize girdikten sonra Laravel, App/Mail klasörü içinde yeni sınıfımızı oluşturacaktır. Bu sınıfın içinde Envelope (Zarf), Content (İçerik) ve Attachment (Ek) olmak üzere 3 metod bulunuyor. 

Örneğin yeni kullanıcı kaydının hemen ardından herhangi bir Queue sırasına almadan olabilecek en yalın haliyle mail göndereceğimizi ele alalım. Normalde Queue'ya almadan mail atmak çok önerilen bir yöntem değildir ama bu yazının amacı Queue sisteminin nasıl kullanıldığı olmadığı için size mail göndermeyi anlatmaya odaklanmak istiyroum.

$password = Str::random(12);
        $user = User::create([
            'name' => 'Murat',
            'surname' => 'Gökoğlu',
            'start_date' => now(),
            'email' => 'muratgokoglu@gmail.com',
            'email_verified_at' => now(),
            'password' => bcrypt($password),
            'user_role_id' => 1,
        ]);

        $logo = public_path('logo.png');

        Mail::to($user)->send(new NewUserPassword($user, $logo, $password));

Yukarıdaki kodda görüldüğü üzere manuel olarak bir kullanıcı ekliyoruz ve eklediğimiz kullanıcıdan hemen sonra kullanıcıya bizim de bilmediğimiz şifresini mail olarak göndermek istiyoruz. Logomuz direkt public klasörünün içinde olduğu için dosya adresini public_path fonksiyonuyla alıp mail sınıfımıza kullanıcı dizisi ve şifresiyle gönderiyoruz. Dolayısıyla bu 3 değişkeni NewUserPassword içinde set ediyoruz.

public function __construct(
        public $user,
        public string $logo,
        public string $password
    )
    {

Dikkat ederseniz $user değişkenini public string olarak göndermiyoruz. Array olduğu için public olarak set ediyoruz. Çünkü dizi içindeki verileri mailimizde kullanmak istiyoruz. 

public function envelope(): Envelope
    {
        return new Envelope(
            subject: config('app.name') . " - " . 'New User Password',
        );
    }

    /**
     * Get the message content definition.
     */
    public function content(): Content
    {
        return new Content(
            view: 'mails.new-user-password',
        );
    }

    /**
     * Get the attachments for the message.
     *
     * @return array<int, \Illuminate\Mail\Mailables\Attachment>
     */
    public function attachments(): array
    {
        return [
            //Attachment::fromPath(public_path('logo.png'))->as('logo.png'),
        ];
    }

Envelope içine dikkatinizi çektiği gibi mailimizin konusunu yazıyoruz. Uygulamanın adını config sınıfından aldık. Content ile kullanmak istediğimiz blade dosyamızın yolunu gösterdik. Benim örneğimde dosyamız mails klasörünü içinde yer almakta. Ayrıca örnek olsun diye commet olarak da bir attachment ekledim. Eğer inline bir dosya dışında farklı bir doküman vb. bir dosya göndermek isterseniz bu metodu da kullanabilirsiniz. 

Gel gelelim blade dosyamıza. Mail olarak göndereceğimiz blade dosyalarında kütüphanemizdeki CSS dosyalarından haricen faydalanmadan kendi tasarımımızı oluşturuyoruz. Yeni parola için aşağıdaki gibi bir taslak oluşturdum.

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Welcome to {{ config('app.name') }}</title>
    <style>
        ::selection {
            color: whitesmoke;
            background: #DC3545FF;
        }
        body {
            font-family: 'Nunito', sans-serif;
            background-color: #eeeeee;
            text-align: center;
        }

        h1 {
            color: #e5e7eb;
            font-weight: lighter;
            font-size: 22px;
        }

        .frame{
            background-color: #1f2937;
            color: #e5e7eb;
            margin: 50px auto;
            max-width: 600px;
            height: auto;
            padding: 50px;
            border-radius: 10px;
        }

        code {
            color: #e5e7eb;
            background-color: #18181b;
            padding: 10px;
            border-radius: 5px;
        }

        a {
            color: #e5e7eb;
            text-decoration: underline;
        }

        a:hover {
            color: #DC3545FF;
            text-decoration: none;
        }

        span {
            margin-bottom: 50px;
        }
    </style>
</head>
<body>
    <div class="frame">
        <span>
            <img src="{{$message->embed($logo)}}" alt="{{config('app.name')}}" height="35px">
        </span>

        <br>
        <h1>Welcome to {{ config('app.name') }} {{ $user->name }}!</h1>
        <br>
        <p>You can log in to <a href="{{ config('app.url') }}">system</a> using this email ({{ $user->email }}) and password below!</p>
        <p><code>{{ $password }}</code></p>
    </div>
</body>
</html>

Buradaki tricklerden birisi de şu; normalde logo olarak eklediğimiz görselin kaynağı normalde bizim local sunucumuz olduğu için, maili gönderdiğimiz kullanıcı public olarak online olmayan bir sunucudan gelen görseli alamayacaktır. Bunu şu şekilde düşünebilirsiniz; eğer yazdığınuz uygulama bir şirketin local bir sunucusunda çalışıyorsa logo gibi görselleri görememek kurumsal kimliğe zarar veren durumlardan birisi olabilir. O yüzden logomuzu direkt olarak göstermektense Laravel'in mailable sınıfının değişlenlerinden birisi olan $message değişkenine embed olarak eklememiz gerekiyor. Bu yöntemle kulağı tersten tutmak yerine normalde SVG de kullanabilirdik ama maalesef birçok mail istemcisi SVG görselleri desteklemiyor. Aklınızın bir köşesinde bulunsun. Mail çıktımız ise aşağıdaki gibi görünüyor.