0. 개요
구글 SMTP를 이용해서 라라벨 이메일 보내기 사이트를 만들어볼 것입니다.
이메일의 템플릿은 Blade 파일을 사용하지 않고 Markdown으로 해보려고 합니다.
- Blade : 기존 view와 같은 방식으로 이메일 템플릿을 작성
- Markdown : 직접 커스텀한 태그 또는 기본 태그를 사용해 이메일 템플릿을 작성
라라벨 공부 다른 글
1. Project Setting
우선 Mail 프로젝트 만듭시다
composer create-project --prefer-dist laravel/laravel mail "9.*"
cd mail
composer install
php artisan key:generate
이제 각자의 환경에 맞춰 가상 호스트를 잡거나 DB 연결 등 부가적인 세팅을 해줍시다.
디비에는 메일을 보낼 사용자의 이메일을 저장할 것입니다.
mysql -u root -p
create database mail
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=mail
DB_USERNAME=root
DB_PASSWORD=secret
2. Google SMTP
메일 보내기 위해서는 특정 드라이버 및 SMTP를 사용해야 합니다.
여기서는 Google SMTP를 사용할 것이기에 아래 방법으로 설정해서 Google SMTP 비밀번호를 메모 해두길 바랍니다.
https://seung.tistory.com/entry/Google-SMTP-%EC%84%A4%EC%A0%95-%EB%B0%A9%EB%B2%95
3. .env 세팅
.env의 메일 세팅 값을 아래와 같이 변경해줍시다.
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=465
MAIL_USERNAME=[본인이메일]
MAIL_PASSWORD=[Google SMTP 비밀번호]
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=[본인이메일]
MAIL_FROM_NAME="Mail Test"
4. 예제
우선 아래와 같은 명령어들을 차례대로 입력해줍시다.
php artisan make:model EmailHistory -m
php artisan migrate
php artisan make:mail Email --markdown=emails.form
php artisan make:controller EmailHistoryController
php artisan make:request EmailSendRequest
차례대로 기능은 다음과 같습니다.
- php artisan make:model EmailHistory -m
- EmailHistory 모델 및 email_histories 마이그레이션 추가
- php artisan migrate
- 테이블 생성
- php artisan make:mail Email --markdown=emails.form
- Email 이름으로 Mailable 클래스 생성 및 emails.form 경로로 markdown 파일 생성
- php artisan make:controller EmailHistoryController
- EmailHistoryController, Controller 클래스 생성
- php artisan make:request EmailSendRequest
- EmailSendRequest, Request 클래스 생성
모델을 수정해줍시다.
/app/Models/EmailHisotry.php
class EmailHistory extends Model
{
use HasFactory;
// 모든 값 대용량 할당 허용
protected $guarded = [];
}
우리는 Gmail에서 이메일 보내기 기능을 만들 것입니다, 여기서 이메일 보낸 이력을 쌓기 위해 만든 테이블이 email_histories입니다, 수정해줍시다.
/database/migrations/yyyy_mm_dd_000000_create_email_histories_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('email_histories', function (Blueprint $table) {
$table->id();
$table->string('email');
$table->string('subject');
$table->string('message');
$table->timestamps();
});
}
...
};
수정한 마이그레이션으로 적용해줍시다
php artisan migrate:refresh
이제 컨트롤러를 수정해줍시다.
emailSend로 요청이 들어오면 request 값으로 이메일 전송 이력을 쌓고 성공 시 메일도 보내는 코드입니다.
/app/Http/Controllers/EmailHistoryController.php
<?php
namespace App\Http\Controllers;
use App\Http\Requests\EmailSendRequest;
use App\Mail\Email;
use App\Models\EmailHistory;
use Illuminate\Support\Facades\Mail;
class EmailHistoryController extends Controller
{
private $emailHistory;
// 의존성 주입
public function __construct(EmailHistory $emailHistory)
{
$this->emailHistory = $emailHistory;
}
public function emailSend(EmailSendRequest $request){
// 유효성 검사 오류시 422 상태 코드로 반환
$validator = $request->safe()->all();
// 이력 저장
$emailHistory = $this->emailHistory->create(
$validator
);
// 저장 성공시 이메일 발송
if($emailHistory){
Mail::to($validator['email'])->send(new Email($emailHistory));
// 성공시 success section 으로 성공 문자 전달
return redirect()->back()
->with([
'success' => '이메일을 성공적으로 발송했습니다.'
]);
}
}
}
위 컨트롤러 코드에서 EmailSendReqeust로 유효성 검사를 했습니다, 다음처럼 룰을 추가하시면 됩니다.
모든 값을 필수로 하되 email에 경우에만 이메일인지 체크하는 룰을 추가했습니다.
/app/Http/Requests/EmailSendRequest.php
class EmailSendRequest extends FormRequest
{
public function authorize()
{
// 로그인 했을 때만 사용할 것인가 = false
return true;
}
public function rules()
{
return [
'email' => 'required|email',
'subject' => 'required',
'message' => 'required'
];
}
}
이제 메일을 발송할 form을 만들어줍시다.
/resources/views 아래로 emailForm.blade.php를 만들어줍시다.
성공 시 Session에는 success 키로 문장이 오게 되고, 입력 값 실수 시 $errors로 실패한 키의 input 위로 마킹이 됩니다.
/resources/views/emailForm.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Laravel Email Test</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.min.css" />
</head>
<body>
<div class="container">
<div class="row mt-5 mb-5">
<div class="col-10 offset-1 mt-5">
<div class="card">
<div class="card-body">
{{--성공시 성공 문장을 출력--}}
@if(Session::has('success'))
<div class="alert alert-success">
{{Session::get('success')}}
</div>
@endif
<form method="POST" action="{{ route('emailSend') }}">
@csrf
<div class="row">
<div class="col-md-12">
<div class="form-group">
<strong>Email:</strong>
<input type="text" name="email" class="form-control" placeholder="Email" value="{{ old('email') }}">
@if ($errors->has('email'))
<span class="text-danger">{{ $errors->first('email') }}</span>
@endif
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<strong>Subject:</strong>
<input type="text" name="subject" class="form-control" placeholder="Subject" value="{{ old('subject') }}">
@if ($errors->has('subject'))
<span class="text-danger">{{ $errors->first('subject') }}</span>
@endif
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<strong>Message:</strong>
<textarea name="message" rows="3" class="form-control">{{ old('message') }}</textarea>
@if ($errors->has('message'))
<span class="text-danger">{{ $errors->first('message') }}</span>
@endif
</div>
</div>
</div>
<div class="form-group text-center">
<button class="btn btn-success" type="reset">Reset</button>
<button class="btn btn-success btn-submit">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
이제 view를 만들었으니 라우팅을 수정하여 emailSend가 EmailHistoryController의 emailSend를 향하게 합시다.
/routes/web.php
<?php
use App\Http\Controllers\EmailHistoryController;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
Route::get('/email', function () {
return view('email');
})->name('emailForm');
Route::post('/emailSend', [EmailHistoryController::class, 'emailSend'])->name('emailSend');
이제 이전 Controller에서 사용한 Mailable 클래스의 내용을 수정해줍시다.
아래 코드를 보시면 Controller에서 아래 코드를 통해 넘긴 $emailHistory로 private 변수에 의존성 주입한 후
Mail::to($validator['email'])->send(new Email($emailHistory));
envelope, content에서 사용해서 값을 넣어주는 것을 확인할 수 있습니다.
/app/Mail/Email.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class Email extends Mailable
{
use Queueable, SerializesModels;
private $emailHistory;
public function __construct($emailHistory)
{
$this->emailHistory = $emailHistory;
}
public function envelope()
{
return new Envelope(
subject: $this->emailHistory->subject,
);
}
public function content()
{
return new Content(
markdown: 'emails.form',
with: [
'message' => $this->emailHistory->message,
'url' => route('emailForm')
]
);
}
public function attachments()
{
return [];
}
public function build()
{
return $this->markdown('emails.form');
}
}
마지막으로 Mailable 클래스인 Email.php 마지막의 build 메소드에서 사용한 발송되는 이메일의 form을 수정해줍시다.
/resources/views/emails/form.blade.php
<x-mail::message>
# Introduction
{{$message}}
<x-mail::button :url="$url">
Home
</x-mail::button>
Thanks,<br>
{{ config('app.name') }}
</x-mail::message>
5. 시연
저 같은 경우는 가상 호스트로 mail.test로 잡아 접속 주소는 다음과 같습니다.
개인이 설정한 것에 맞게 들어가시면 다음과 같이 작동하는 것을 확인 가능합니다.
이메일로 가시면 아래와 같이 잘 온 것을 확인할 수 있습니다.
'PHP > Laravel' 카테고리의 다른 글
[Laravel9] 라라벨 아티즌 콘솔 명령어 만들기(Artisan console) (2) | 2022.10.31 |
---|---|
[Laravel9] 라라벨 테스팅 만들기 with Trait, Factory (0) | 2022.10.28 |
Laravel 9 Observer 써보자, 옵저버로 이력(히스토리) 쌓기 (0) | 2022.09.23 |
Laravel 라라벨 스케줄링(Scheduling)하기 with crontab (0) | 2022.09.15 |
Laravel9 라라벨 csv 읽어서 저장하기(CSV seeding) (0) | 2022.09.07 |