php 로 메일 보내기

정현섭·2021년 4월 13일
1

배경

  • takeme 프로젝트에서 뉴스 작성하기 라는 기능을 추가하고 싶었다.
    • 뉴스 작성하기 기능은 어떤 글을 즐겨찾기한 모든 사람들에게 News message가 담긴 이메일을 보내는 기능이다.
  • 백앤드는 php로 개발중이었다.

google계정을 하나 새로파서 php에서 그 구글계정을 통해서 다른 이메일 주소들로 메일을 보내는 방법을 알아야했다.



메일을 주고받는 구조

메일을 주고받는 두 client가 메일서버(smtp server)를 통해서 어떻게 메일을 주고받는지 보자.

  • 서버에 smtp 서버가 세팅되어있지 않아서 php자체에서 제공하는 mail function은 안썼다.

  • 메일을 받아서 전송해 줄 smtp서버로 google(smtp.gmail.com)을 이용했다. (library 사용. 위의 1번 부분.)



방법

PHPmailer 라는 library를 사용했다.

https://github.com/PHPMailer/PHPMailer/

우선 서버의 document root로 가서 아래 명령어를 통해 PHPmailer를 설치한다.

$ composer.phar require phpmailer/phpmailer

그리고 아래와 같이 send_mail function을 만들 수 있다.

(gmail smtp server를 이용했다.)

<?php
// Import PHPMailer classes into the global namespace
// These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;

// Load Composer's autoloader
require $_SERVER['DOCUMENT_ROOT'] . '/vendor/autoload.php';

// Instantiation and passing `true` enables exceptions

function send_mail($addresses, $subject, $body) {
    $mail = new PHPMailer(true);
    
    try {
        //Server settings
        $mail->isSMTP();                                            // Send using SMTP
        $mail->Host       = 'smtp.gmail.com';                    // Set the SMTP server to send through
        $mail->SMTPAuth   = true;                                   // Enable SMTP authentication
        $mail->Username   = '**id**';                     // SMTP username
        $mail->Password   = '**pw**';                               // SMTP password
        $mail->CharSet = 'utf-8'; 
        $mail->Encoding = "base64";
        $mail->SMTPSecure = 'ssl';          
        $mail->Port       = 465;                                    // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above

        //Recipients
        $mail->setFrom('eventapp.notify@gmail.com', 'eventapp');

        foreach ($addresses as $address) {
            $mail->addAddress($address);     // Add a recipient
        }

        // Content
        $mail->isHTML(true);                                  // Set email format to HTML
        $mail->Subject = $subject;
        $mail->Body    = $body;

        $mail->send();
        echo 'Message has been sent';
        return true;
    } catch (Exception $e) {
        //echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
        return false;
    }
}

오류 핸들링

발신 gmail계정에서 보안 탭에 보안 수준이 낮은 앱 엑세스사용으로 해줘야

php가 해당 계정에 접근하여 메일을 보낼 수 있다.



결과

메일 보내기

뉴스 작성하기를 누르면 텍스트가 지정된 이메일로 보내지도록 만들었다.

수신된 이메일!


뉴스 작성이 완료되고 수신된 메일.



해결하지 못한 문제

  • 뉴스 작성하기 를 클릭한 뒤에 server가 해당되는 모든사람에게 이메일을 다 보낼때 까지 작성자가 계속 기다려야 한다는 문제가 있었다. (위의 로딩화면으로 계속 기다려야 함.)

    • 작성자에게는 빨리 결과를 반환해줘서 기다리게 안하고, php의 mail전송 로직은 Asynchronous하게 따로 돌아갔으면 좋겠다.
    • 그냥 그런 비동기적인 작동은 php에서 안되는 것 같다는 결론을 내고 넘어갔다.. ㅎㅎ
  • 또한 메일 전송 로직에서 속도저하가 너무 심한데 이것도 해결 못했다..

    • 사용자가 메일이 다 전송되기를 기다려야하는데 심지어 속도도 느려서 사용자 입장에서 엄청 답답할 것 같다.. ㅋㅋㅋ

+ (추가)

  • php를 FastCGI모드로 이용하면 응답을 바로 주고 백그라운드에서 남은 일들을 처리하는 방식이 가능하다!
  • PHP-FPM 라는 php extension을 설치후에 사용할 수 있다. (PHP FastCGI Process Manager)

0개의 댓글