[라라벨] 메일 발송
라라벨에서 다양한 메일 보내는 방식
금번장에서는 라라벨에서 사용하는 다양한 메일 보내는 방식에 대해 설명 드립니다.
Mail(Mailable)을 사용하는 법과 Notificaiton에서의 MailMessage등 비슷하지만 사용법과 적용하는 것이 다른 부분에 대해서 설명 드립니다.
범용적인 메일링 시스템을 구축할때는 Notificaiton 보다는 Mailable 과 queue를 활용한 방식으로 구축할 것을 추천 드립니다.
메일 보내기
Mailable
mailable에서는 전송될 메일의 양식을 정하는 곳이다. 본문내용, from, subject, 첨부파일등등이다.
Mailables 생성
php artisan make:mail OrderShipped
위의 명령을 입력하면 OrderShipped 이라는 클래스가 만들어지는데 내용은 아래처럼 view를 랜더링 하는 형식입니다.
- App\Mail\OrderShipped
...
class OrderShipped extends Mailable
{
use Queueable, SerializesModels;
public function build()
{
return $this->view('view.name');
}
}
다양한 정보 부가
위에 만들어진 OrderShipped 에서는 현재 view 만 랜더링 하는데 아래 처럼 다양한 정보를 추가할 수 있습니다.
- App\Mail\OrderShipped
...
class OrderShipped extends Mailable
{
use Queueable, SerializesModels;
public function build()
{
return $this->view('view.name');
}
/**
* Using the Envelope
* use Illuminate\Mail\Mailables\Address;
* use Illuminate\Mail\Mailables\Envelope;
*
**/
public function envelope(): Envelope
{
return new Envelope(
from: new Address('[email protected]', 'Jeffrey Way'),
replyTo: [new Address('[email protected]', 'Taylor Otwell'),],
subject: 'Order Shipped',
);
}
/**
* view
*/
public function content(): Content
{
return new Content(
view: 'mail.orders.shipped',
// html: 'mail.orders.shipped' // view의 alias
// text: 'mail.orders.shipped-text' // 메시지의 plain-text 버전도 추가 가능하다.
);
}
/** 파일 첨부시 */
public function attachments(): array
{}
/** header */
public function headers(): Headers
{}
}
view 파일로 파라미터 전달하기
기존 라라벨의 컨트롤러에서 view blade 로 파라미터 값을 전달하기 위해서는
return view('sample', ['items'=>$items]);
처럼 전달 하였는데 mailable에서는 약간 다르다.
public 으로 정의하여 바로 전달하기
class OrderShipped extends Mailable
{
public function __construct(
public Order $order,
) {}
public function content(): Content
{
return new Content(
view: 'mail.orders.shipped',
);
}
}
blade에서는 아래 같이 바로 받아서 처리하면 된다.
<div>
Price: {{ $order->price }}
</div>
with 파라미터로 전달하기
class OrderShipped extends Mailable
{
..........
public function content(): Content
{
return new Content(
view: 'mail.orders.shipped',
with: [
'orderPrice' => $this->order->price
]
);
}
}
blade에서는 아래 같이 바로 받아서 처리하면 된다.
<div>
Price: {{ $orderPrice }}
</div>
메일발송
Mailable이 생성되었으면 메일을 보내는 것은 간단하다.
use App\Mail\OrderShipped; // 위에서 생성한 mailable 파일 호출
use Illuminate\Support\Facades\Mail; // Mail 퍼사드 호출
class OrderShipmentController extends Controller
{
public function store(Request $request)
{
//Mail::to()->send(Mailable)
// to 에는 email 이 들어가도 되고 아래처럼 user object가 들어가도 된다.
Mail::to($request->user())->send(new OrderShipped($order));
}
}
Mail관련 속성
- to :
- send :
- queue : 아래 Queueing Mail 에서 설명
- cc :
- bcc
Queueing Mail
대량의 메일을 발송하는 것은 시간이 걸리기 때문에 아래처럼 queue를 이용하여 메일을 보낼 수도 있다.
아래처럼 queue를 사용하기 위해서는 약간의 설정이 필요한데 Queues 설정 을 참조 바랍니다.
public function store(Request $request)
{
Mail::to($request->user())->queue(new OrderShipped($order));
}
Send to multiple users
여러명에게 발송할 경우에 대한 예제입니다.
한번에 모두에게 발송하기
예제 1
아래와 같은 경우 문제점은 to에 여러명이 동시에 들어가기 때문에 메일을 받는 사람이 다른 사용자도 확인할 수가 있어 개인정보보호상 추천드리지 않습니다.
$users = User::whereIn("id", $request->ids)->get();
// $users = [[email protected], [email protected]]; // 배열로 처리해도 됨
Mail::to($users)->queue(new UserEmail($user)); // $user->email을 별도로 하지 않아도 처리됨
예제2
각각으로 분리하여 처리 (추천방식)
$users = User::whereIn("id", $request->ids)->get();
foreach ($users as $key => $user) {
Mail::to($user->email)->send(new UserEmail($user));
// Mail::to($user)->send(new UserEmail($user)); // $user 만 사용하여도 됨 이때 user는 Model의 결과 값이 어도 되고 [(object)['email', 'name']] 과 같은 형식이어도 된다.
}
Mail(Mailable) vs MailNotification(MailMessage)
메일을 보낼때 두개는 거의 동일한 기능을 제공한다.
Mail을 메일을 보낼때 특화되어있고 user 와는 별개로 메일만 있으면 운영가능하나 MailMessage 는 user 정보가 필요하다.
MailNotification 은 메일뿐만 아니라 SMS, Slack등 한번의 액션을 통하여 다양한 채널로 정보를 제공할 수 있는 장점이 있다.
하지만 MailNotification 에서도 MailMessage 가 아니라 Mailable 로도 사용할 수 있으나 user 테이블과 연돌될때 효과적이고 그렇지 않은경우는 Mailable을 사용하는 것이 좋다.
Notification(MailMessage) 를 활용한 방법은 이미 기술한 문서를 참조 바랍니다.
MailNotification 에서 Mailable 사용하기
아래 방식처럼 사용도 가능하나 추천드리지는 않는 방식이다. $notifiable 에는 보낼 user의 정보가 담겨있으나 실제로는 입력시 user 정보를 그대로 사용하는 것이 아니라 user 테이블에서 입력정보를 이용하여 다시 회원정보를 가져온다.
public function toMail($notifiable)
{
return (new NotificationMail($this->user, $this->title, $this->body));
}
- \Mail\NotificationMail
class NotificationMail extends Mailable
{
public function __construct($user, $title, $body)
{
.........
}
public function build()
{
return $this
->to($this->user->email)
->subject($this->title)
->view('mailer.templates.default.notice');
}
}