在Laravel邮件中创建退订链接

huangapple go评论74阅读模式
英文:

Create Unsubscribe Link in Laravel email

问题

我正在尝试允许用户通过服务器端取消订阅电子邮件链接。

只需让他们点击链接,向我的表格中添加一列,并显示告诉他们已取消订阅的页面。

该链接如下:

https://mysite.test/unsubscribe-confirm/eyJpdiI6Ims3Y3RJdHhvWTgyNGVLais1UXlzdlE9PSIsInZhbHVlIjoiUUF0NFZUUkNqTklmTT11elRmZEdyaEUvN1kzcXpLNmNhRit3enpPNDE0ak5xalRaa1JQQS91elBCazIzTWFxayIsIm1hYyI6IjMzZDM4MDUwNTYzZjY1ZjQ4OTEyNDI3ZjJhY2M4NzgxNzgwMDFiMGQ2NjQ4ZjBiMGFjNGJlNjg3YzY0Zjc5NTkiLCJ0YWciOiIifQ==/1

在我的工作 JobToSendEmails 中,我像这样创建 $unsubscribeLink

// 生成令牌
$unsubscribeToken = encrypt($sponsor->email);
// 生成取消订阅链接
$unsubscribeLink = route('unsubscribe.confirm', ['token' => $unsubscribeToken, 'campaign_id' => $emailCampaign->id]);

然后将其传递给我的电子邮件,像这样:

Mail::to($sponsor->email)->send(new EmailToUsers(
...
$unsubscribeLink
));

然后在 EmailToUsers 视图中,我有这一行:

如果您不再希望接收这些电子邮件,您可以随时[取消订阅]({{ $unsubscribeLink }})

该链接转到此路由:

Route::post('/unsubscribe-confirm/{token}/{campaign_id}', [EmailPreferenceController::class, 'confirmUnsubscribe'])->name('unsubscribe.confirm');

然后,在 EmailPreferenceController 中,confirmUnsubscribe 方法如下:

public function confirmUnsubscribe()
{
    $token = Request::get('token');
    $user  = User::findByToken($token);
    if ($user) {
        $emailCampaignId         = Request::get('email_campaign_id');
        $emailCampaignPreference = EmailCampaignPreference::updateOrCreate(
            [
                'user_id'           => $user->id,
                'email_campaign_id' => $emailCampaignId,
            ],
            [
                'opt_out' => true,
                'email'   => $user->email,
            ]
        );

        return redirect()->route('unsubscribe');
    }
    Log::error('User not found by token: ' . $token);

    return response()->view('errors.404', [], 404);
}

findByToken 如下:

public static function findByToken($token): User
{
    $email = decrypt($token);
    return static::where('email', $email)->first();
}

当我在电子邮件中点击取消订阅链接时,我收到以下错误:

Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
"不支持路由 unsubscribe-confirm/eyJpdiI6Ims3Y3RJdHhvWTgyNGVLais1UXlzdlE9PSIsInZhbHVlIjoiUUF0NFZUUkNqTklmTT11elRmZEdyaEUvN1kzcXpLNmNhRit3enpPNDE0ak5xalRaa1JQQS91elBCazIzTWFxayIsIm1hYyI6IjMzZDM4MDUwNTYzZjY1ZjQ4OTEyNDI3ZjJhY2M4NzgxNzgwMDFiMGQ2NjQ4ZjBiMGFjNGJlNjg3YzY0Zjc5NTkiLCJ0YWciOiIifQ==/1。
支持的方法:POST。

如何修复这个问题?我在路由上使用了 POST 方法。我想保持电子邮件中的这种格式 [取消订阅]({{ $unsubscribeLink }})

任何帮助将不胜感激。

英文:

I'm trying to allow a user to Unsubscribe from a email link via the server side.

Simply want them to click the link, add a column to my table and show them a page that tells them they have been unsubscribed.

The link looks like this:

https://mysite.test/unsubscribe-confirm/eyJpdiI6Ims3Y3RJdHhvWTgyNGVLais1UXlzdlE9PSIsInZhbHVlIjoiUUF0NFZUUkNqTklmTTExTVRmZEdyaEUvN1kzcXpLNmNhRit3enpPNDE0ak5xalRaa1JQQS91elBCazIzTWFxayIsIm1hYyI6IjMzZDM4MDUwNTYzZjY1ZjQ4OTEyNDI3ZjJhY2M4NzgxNzgwMDFiMGQ2NjQ0ZjFiMGFjNGJlNjg3YzY0Zjc5NTkiLCJ0YWciOiIifQ==/1

In my job JobToSendEmails I'm creating the $unsubscribeLink like this:

// Generate token
$unsubscribeToken = encrypt($sponsor->email);
// Generate unsubscribe link
$unsubscribeLink = route('unsubscribe.confirm', ['token' => $unsubscribeToken, 'campaign_id' => $emailCampaign->id]);

And then passing to my email like this:

Mail::to($sponsor->email)->send(new EmailToUsers(
...
$unsubscribeLink
));

Then in the EmailToUsers view I have this line:

If you no longer wish to receive these emails, you can [unsubscribe]({{ $unsubscribeLink }}) at any time.

The link goes to this route:

Route::post('/unsubscribe-confirm/{token}/{campaign_id}', [EmailPreferenceController::class, 'confirmUnsubscribe'])->name('unsubscribe.confirm');

Then in the EmailPreferenceController the confirmUnsubscribe method looks like this:

    public function confirmUnsubscribe()
    {
        $token = Request::get('token');
        $user  = User::findByToken($token);
        if ($user) {
            $emailCampaignId         = Request::get('email_campaign_id');
            $emailCampaignPreference = EmailCampaignPreference::updateOrCreate(
                [
                    'user_id'           => $user->id,
                    'email_campaign_id' => $emailCampaignId,
                ],
                [
                    'opt_out' => true,
                    'email'   => $user->email,
                ]
            );

            return redirect()->route('unsubscribe');
        }
        Log::error('User not found by token: ' . $token);

        return response()->view('errors.404', [], 404);
    }

findByToken looks like this:

public static function findByToken($token): User
  {
    $email = decrypt($token);
    return static::where('email', $email)->first();
  }

When I click the unsubscribe link in the email, I get the error:

> Symfony \Component \HttpKernel \Exception \MethodNotAllowedHttpException
> "The GET method is not supported for route
> unsubscribe-confirm/eyJpdiI6Ims3Y3RJdHhvWTgyNGVLais1UXlzdlE9PSIsInZhbHVlIjoiUUF0NFZUUkNqTklmTTExTVRmZEdyaEUvN1kzcXpLNmNhRit3enpPNDE0ak5xalRaa1JQQS91elBCazIzTWFxayIsIm1hYyI6IjMzZDM4MDUwNTYzZjY1ZjQ4OTEyNDI3ZjJhY2M4NzgxNzgwMDFiMGQ2NjQ0ZjFiMGFjNGJlNjg3YzY0Zjc5NTkiLCJ0YWciOiIifQ==/1.
> Supported methods: POST."

What can I do to fix this? I'm using a Post method on the route. I would like to keep this format in the email, [unsubscribe]({{ $unsubscribeLink }})

Any help would be appreciated.

答案1

得分: 0

更改从POST到GET的路由是主要问题。

然后,在EmailPreferenceController中,confirmUnsubscribe方法现在如下所示:

public function confirmUnsubscribe($token, $campaign_id)
{
    $user = User::findByToken($token);

    if ($user) {
        $emailCampaignPreference = EmailCampaignPreference::updateOrCreate(
            [
                'user_id'           => $user->id,
                'email_campaign_id' => $campaign_id,
                'opt_out'           => true,
                'email'             => $user->email,
            ]
        );

        return redirect()->route('unsubscribe');
    }
    Log::error('User not found by token: ' . $token);

    return response()->view('errors.404', [], 404);
}

User模型的findByToken方法如下所示:

public static function findByToken($token): User
{
    $email = decrypt($token);
    return static::where('email', $email)->first();
}

用户立即取消订阅,并且数据存储在表中。

英文:

Changing the route from post to get was the main issue.

Changed:
Route::post('/unsubscribe-confirm/{token}/{campaign_id}', [EmailPreferenceController::class, 'confirmUnsubscribe'])->name('unsubscribe.confirm');

To:
Route::get('/unsubscribe-confirm/{token}/{campaign_id}', [EmailPreferenceController::class, 'confirmUnsubscribe'])->name('unsubscribe.confirm');

Then in the EmailPreferenceController the confirmUnsubscribe method now looks like this:

    public function confirmUnsubscribe($token, $campaign_id)
    {
        $user = User::findByToken($token);

        if ($user) {
            $emailCampaignPreference = EmailCampaignPreference::updateOrCreate(
                [
                    'user_id'           => $user->id,
                    'email_campaign_id' => $campaign_id,
                    'opt_out'           => true,
                    'email'             => $user->email,
                ]
            );

            return redirect()->route('unsubscribe');
        }
        Log::error('User not found by token: ' . $token);

        return response()->view('errors.404', [], 404);
    }

User Model findByToken looks like this:

    public static function findByToken($token): User
    {
        $email = decrypt($token);
        return static::where('email', $email)->first();
    }

User gets unsubscribed immediately and data gets stored in table.

huangapple
  • 本文由 发表于 2023年3月7日 05:57:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/75656201.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定