ปกติเวลาส่งเมล์ เราจะใช้ mail() ของ php ที่มีให้ มันมักจะมีปัญหาเมื่อส่งไปแล้ว จะเข้าที่ junk หรือไม่ก็ spam วันนี้จึงขอแนะนำการส่งเมล์ด้วย smtp จะช่วยแก้ปัญหานี้ได้ และยังมีบริการให้ใช้ฟรี หลายๆ ราย เช่น google,mandrill อีกทั้งเรายังสามารถทดสอบส่งเมล์ได้ ถึงแม้ระบบของเรายังไม่ขึ้น Prodruction ก็ตาม หรือจะสร้าง layout เมล์แบบต่างๆ ก็สามารถทำได้

วันนี้ขอแนะนำการส่งเมล์ด้วย smtp-google และ smtp-mandrill เพราะฟรีและสามารถทำได้ง่ายๆ ซึ่ง Yii2 เตรียมพร้อมไว้ให้เราแล้ว คือ yii2-swiftmailer มันติดตั้งมาพร้อมแล้ว รอแค่เราตั้งค่าเพื่อเปิดใช้งาน

เตรียมความพร้อมกันก่อน

  • ติดตั้ง yii2-swiftmailer อันนี้สบายเพราะ Yii 2 ติดตั้งมาให้แล้ว
  • smtp ที่ต้องการจะใช้ ซึ่งจะไม่เหมือนกัน เช่น smtp ของ google คือ smpt.gmail.com
  • อีเมล์ account ที่ใช้งานได้จริง ตามตัวอย่างนี้ผมใช้ของ gmail
  • layout อีเมล์ เราสามารถสร้างรูปแบบอีเมล์หลายๆ แบบได้ เช่น layout สำหรับตอนสมัครสมาชิก, layout สำหรับตอนส่งข่าว

เปรียบเทียระหว่าง Gmail และ Mandrill

Gmail คงไม่ต้องอธิบายคงทราบกันดี ส่วน Mandrill นั้นมันเป็นระบบ SMTP Mandrill สำหรับส่งเมล์ในระบบเว็บหรือ App ต่างๆ ฟรี 12000 เมล์/เดือน คือมันสร้างมาเพื่อส่งเมล์โดยเฉพาะครับ มีกราฟแสดงให้ดู ตรวจสอบสถิติต่างๆ ส่งไปกี่เมล์ได้รับกี่เมล์ สามารถส่งได้ทีละเยอะๆ แต่ถ้าส่งไม่เกิน 12000 เมล์/เดือน ก็ฟรีครับ ลองไปสมัครใช้ดูได้

ปล. เท่าที่ผมลองใช้ Mandrill ถ้า server อยู่ในไทย ผมลองแล้วรู้สึกว่า delay นิดนึงครับ แต่ถ้า server อยูต่างประเทศเร็วมากส่งปั๊บเข้าเลย พอดีผมใช้ DigitalOcean ใครสนใจก็ลองได้ server ราคาถูกมากๆ ถูกกว่า Aws

จริงๆ สองตัวนี้มีคุณสมบัติคือสามารถส่งเมล์ผ่าน smtp ได้เหมือนกัน แล้วแต่จะเลือกใช้ครับ ^

เปิดใช้งาน mailer และตั้งค่าตามนี้ ใส่ email และ password ของเรา

ตั้งค่า SMTP Google

ถ้าเป็น Advanced มี 3 ที่แล้วแต่จะเลือกใช้งาน ถ้าหากจะตั้งค่าให้ใช้ได้ทั้ง frontend,backend ให้ไปที่ common/config/main.php แต่ถ้าหากอยากใช้เฉพาะที่ก็ frontend/config/main.php,backend/config/main.php แล้วแต่จะเลือกใช้งานครับ

ถ้าเป็น basic ไฟล์จะอยู่ที่ config/web.php

return [
    //....
    'components' => [
        'mailer' => [
           'class' => 'yii\swiftmailer\Mailer',
                'viewPath' => '@backend/mail',
                'useFileTransport' => false,
                'transport' => [
                    'class' => 'Swift_SmtpTransport',
                    'host' => 'smtp.gmail.com',
                    'username' => 'username@gmail.com',
                    'password' => 'password',
                    'port' => '587',
                    'encryption' => 'tls',
                ],
            ],
        ],
];

ตั้งค่า SMTP Mandrill

return [
    //....
    'components' => [
        'mailer' => [
           'class' => 'yii\swiftmailer\Mailer',
                'viewPath' => '@backend/mail',
                'useFileTransport' => false,
                'transport' => [
                    'class' => 'Swift_SmtpTransport',
                    'host' => 'smtp.mandrillapp.com',
                    'username' => 'username@gmail.com',
                    'password' => 'password',
                    'port' => '587',
                    'encryption' => 'tls',
                ],
        ],
   ],
];

viewPath ถ้าเป็นกรณี app basic ก็ตั้งค่าเป็น @app/mail

สร้าง layout Mail

สร้าง folder ไว้เก็บ view สำหรับเวลาส่งอีเมล์ ชื่อ /mail/layouts/ ไว้ที่ application ของเรา จากนั้นสร้าง view ชื่อ html.php ไว้ที่ /mail/layouts/html.php เมื่อเรียกเป็น alias ก็คือ @app/mail

ซึ่งตัว layout นีจะเป็น layout หลักหรือเป็นหน้าโครงสร้าง html ให้เมล์ของเราส่วนใน layout ข้างในเราค่อยไปใส่เนื้อหาอีกที

<?php
use yii\helpers\Html;
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=<?= Yii::$app->charset ?>" />
    <title><?= Html::encode($this->title) ?></title>
    <?php $this->head() ?>
</head>
<body>
<?php $this->beginBody() ?>

<div style="border: solid 1px rgb(236, 236, 236);border-radius: 5px;padding: 20px;">
    <?= $content ?>
</div>
<p style="text-align:right;margin-top:5px;"> โรงพยาบาลขอนแก่น <small ><i>โทร 043-336789</i></small></p>

<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>

ถ้าหาก preview จะได้แบบนี้

mailer-main-layout.png

จากนั้นเราจะทำการสร้าง view ที่ใช้เป็น template ในการส่ง ในตัวอย่างนี้ผมสร้างอีเมล์แจ้งเตือนการลงทะเบียนงานประชุมวิชาการโรงพยาบาลขอนแก่น

ไปที่โฟลเดอร์ /mail/layouts/ ใน application ของคุณ สร้าง view ชื่อ register.php โดยที่ view นี้จะรับค่าตัวแปรชื่อ $fullname เพื่อแสดงชื่อของผู้ลงทะเบียน

<h1>งานประชุมวิชาการโรงพยาบาลขอนแก่น ครั้งที่ 7 ประจำปี 2558</h1>
<h3>Theme "คุณธรรม คู่คุณภาพ เพื่อประชาชน"</h3>
<p>เนื่องในโอกาสครบรอบ 20 ปี ศูนย์แพทยศาสตรศึกษาชั้นคลินิก โรงพยาบาลขอนแก่น</p>
<p>24 - 26 มิถุนายน 2558 ณ โรงพยาบาลขอนแก่น</p>

<p>เรียนคุณ <?php echo $fullname; ?></p>
<p>ตอนนี้คุณได้ทำการลงทะเบียนเข้าร่วมงานประชุมวิชาการ รพ.ขอนแก่น 2558 เรียบร้อยแล้ว</p>
<p>คุณสามารถดูรายละเอียดกำหนดการต่างๆ  ตามไฟล์แนบได้ หรือดูรายละเอียด <a href="http://seminar.kkh.go.th">ได้ที่นี่</a> </p>

เมือทำการส่งจะได้ layout แบบนี้

ส่งอีเมล์

หลังจากที่เราตั้งค่าที่ component แล้วเราจะสามารถเรียกใช้งานด้วย Yii::$app->mailer ได้ ดูตัวอย่าง

Yii::$app->mailer->compose('@app/mail/layouts/register',[
    'fullname'=>'สาธิต สีถาพล'
])
->setFrom(['seminar@kkh.go.th'=>'Khon Kaen Hospital'])
->setTo('emailTo@gmail.com')
->setSubject('ยินดีต้อนรับสู่งานประชุมวิชาการโรงพยาบาลขอนแก่น 2558')
->send();
  • compose คือการเรียกไปที่ view ที่เราสร้างเป็น template ไว้หากต้องการใช้หลายๆ แบบ ก็สร้างไว้หลายๆ อันแล้วก็เรียกใช้ที่ตรงนี้ หาก view มีการรับค่าตัวแปร ก็ให้ส่งค่าไปด้วย ตามตัวอย่าง register.php รับค่าตัวแปร $fullname
  • setFrom เป็นการระบุว่าส่งมาจากที่ใด และใส่เป็นชื่อได้ด้วย
  • setTo คืออีเมล์ที่เราต้องการส่งไปหาใคร
  • setSubject ชื่อเรื่องอีเมล์ที่เราจะส่ง

จากนั้นทดลองเรียกใช้งาน ก็จะได้รับอีเมล์แบบนี้

หากต้องการแนบไฟล์ให้เพิ่ม attach เข้าไปดังนี้จะใส่กี่ไฟล์ก็ได้

Yii::$app->mailer->compose('@app/mail/layouts/register',[
    'fullname'=>'สาธิต สีถาพล'
])
->setFrom(['seminar@kkh.go.th'=>'Khon Kaen Hospital'])
->setTo('emailTo@gmail.com')
->setSubject('ยินดีต้อนรับสู่งานประชุมวิชาการโรงพยาบาลขอนแก่น 2558')
->attach(Yii::getAlias('@webroot').'/attach/'.'brochure.pdf')
->attach(Yii::getAlias('@webroot').'/attach/'.'Poster.pdf')
->send();

ไม่ควรแนบไฟล์เยอะเพราะจะทำให้ตอนส่งช้าไปด้วย ถ้าไฟล์เยอะจริงๆ แนะนำทำเป็น zip และแนบ link ดาวน์โหลดไปจะดีกว่า

เมื่อแนบไฟล์ เวลาส่งอีเมล์ผู้รับก็จะได้อีเมล์แบบนี้

ในการใช้งานจริงแนะนำให้สร้างเป็น function ไว้ใน controller ก็ได้ แล้วค่อยรับค่า parameter ต่างๆ เข้ามา

<?php
    //...
    public function sendMail($email,$fullname){
         Yii::$app->mailer
         ->compose('@app/mail/layouts/register',[
            'fullname'=>$fullname
          ])
         ->setFrom(['seminar@kkh.go.th'=>'Khon Kaen Hospital'])
         ->setTo($email)
         ->setSubject('ยินดีต้อนรับสู่งานประชุมวิชาการโรงพยาบาลขอนแก่น 2558')
         ->attach(Yii::getAlias('@webroot').'/attach/'.'brochure.pdf')
         ->attach(Yii::getAlias('@webroot').'/attach/'.'Poster.pdf')
         ->send();
    }

ขอให้สนุกกับการส่งเมล์ครับผม.. ^ กะไว้ว่าเรื่องนี้จะเขียนประมาณซัก 20 นาทีเอาเข้าจริงๆ ปาเข้าไป 2 ชั่วโมงแระ ไม่ไหวนอนก่อนครับ