【Drupal】メール送信機能を実装してみた
はじめに
Drupalのディベロッパー認定試験を二ヶ月後に受験することになったので、最近はDrupalをいろいろ触っています。
それとは別に開発案件で急遽Drupalにメール送信機能を実装する必要が出てきたので、ベストプラクティスを調べてみました。
以前はレンタルサーバーのSMTPを利用してメールを送信することがほとんどでしたが、今回はできるだけメール未到達のリスクの少ない方法をとることにしました。そこで、料金も比較的やすければ扱いやすいSENDGRIDを利用することにしました。
DRUPALでSENDGRIDを利用してメールを配信すると言ってもAPIかSMTPかまたどんなモジュールを使ってどうやって送るのかと言ったところはまだ決めていないのでこの機会にいろいろ調べた結果を記事にしました。
(SENDGRIDは費用がかかるため結局SWIFTMAILERを使用することになりました)
SENDGRIDについて
SendGridは全世界で利用されているメール配信サービスで、クラウドサービスのためアカウントを作成するだけですぐにメールを配信できます。また一般的なSMTPサーバーを利用したものだけでなくAPIを利用することも利用できます。
SENDGRIDのサイトを見てみると以下のような説明が載っていました。
https://sendgrid.kke.co.jp/blog/?p=5009
Web API
SendGridのWeb APIではHTTP経由でメールを送信します。SendGridにメールの送信リクエストを投げて、HTTP応答コード200が返ってきたら、そのメッセージはSendGridに受理されたということです。一方、400や500などが返ってきたら、何か異常が起きてSendGrid側でリクエストを処理できなくなったことを意味します。
SMTP リレー
SMTPリレーでメールを送るためには、Web APIに比べて、より多くのメッセージのやり取りが必要になります。配達のたとえ話で言えば、SMTPリレーは荷物を自分自身で運ぶ方法に近いでしょう。なぜなら、荷物を届けるためには、ポストに投函するよりも更にいろいろなことをやらなければならないからです。送信者がSMTPを利用してSendGridに接続する場合は、SendGridから受信側のISPにメッセージを送る前に、送信者とSendGridの間で個別の情報を複数やりとりしなければなりません。
APIではSMTPで必要なDNS認証手続きなど不要なやり取りがいらないそうなのでAPIが利用できるのであればAPIのほうがメリットがありそうです。
SENDGRID 利用料金
次に、SENDGRIDの料金を調べてみました。
SENDGRID サイトより引用
https://docs.sendgrid.com/ui/account-and-settings/billing
無料プランでは上限が100通/一日に限定されているようです!
お試しでWEB APIを使ってみたかったのですが、いくら利用者が少ないとはいえこれでは少なすぎます。
かといって有料プランに入るほどの利用者もいないので、他で使用しているSMTPサーバーを使ってメールを送信することにしました。
ということで、Drupalの実装方法を検討しています。
DrupalでSENDGRID実装方法の比較検討
しばらくDrupalでSENDGRIDを実装する方法をググっているといろんなコントリビュートモジュールを使った方法が紹介されていました。どれを使ってもメールが送信できればよいのですが、いろいろあるので決めあぐねていると、今度はSENDGRIDの英語のブログ記事にいくつかのモジュールの比較記事がありました。
https://docs.sendgrid.com/for-developers/sending-email/drupal
おー、まさに知りたかったのはこれです!
SendGrid を使用して Drupal から電子メールを送信するには、ニーズに応じて 以下のモジュールが使用できるそうです。
- SendGrid Integration モジュール
- SMTP Authentication Support モジュール、
- Swift Mailer モジュール
- PHPMailer SMTP モジュール
この記事はそれぞれのモジュールを使用した場合のメリットデメリットや設定方法がかなり詳細に記載されています。すべてのモジュールを試してみることはできませんでしたが、とても有用な記事なので翻訳して紹介します。
SendGrid Integration モジュール
SendGrid 統合モジュールは、SendGrid API Web サービスを使用して電子メールを送信します。 SMTP は使用しません。 Web サイトのワークロードによっては、これがパフォーマンスにメリットをもたらす可能性があります。 このモジュールは、人口統計のレポート用のグラフも提供します。 このモジュールをインストールしてセットアップするには、Drupal に関する高度な知識が必要です。 ドラッシュの使用が必要です。
ダウンロードしてインストールし Drupal.org からSendGrid 統合モジュールを 、Composer Manager を使用して Drush 経由で更新を実行します。
インストール後のアクセス admin/config/services/sendgrid
API 認証情報を構成します。
詳細な手順については、 モジュールのドキュメント を参照してください。
https://git.drupalcode.org/project/sendgrid_integration/blob/HEAD/README.md
SMTP Authentication Support モジュール
で SendGrid を使用するには Drupal 、 SMTP 認証サポート モジュール を使用します。 Drupal のバージョンと互換性のあるこのモジュールのバージョンをインストールします。
モジュール ページを開き、SMTP モジュールを見つけて、次の設定を使用して構成します。
- SMTP サーバー - smtp.sendgrid.net
- SMTP ポート - 587
- 暗号化プロトコルを使用 - いいえ。暗号化が必要な場合は、「SSL を使用」を選択し、SMTP ポートを 465 に設定します。
- ユーザー名 - SendGrid ユーザー名: "apikey"
- パスワード - SendGrid API キー
Swift Mailer モジュール
を使用するには Swift Mailer モジュール 、Drupal のバージョンと互換性のあるこのモジュールのバージョンをインストールします。
このモジュールの構成は上記とほぼ同じです。
PHPMailer SMTP モジュール
PHPMailer SMTP は、最新の PHPMailer ライブラリを使用して SMTP 経由で電子メールを送信し、RFC に準拠しています。 モジュールが必要です メール システム 。 ご覧ください。 プロジェクトページを 詳細については
Composer を使用してインストールし、有効にします。
composer require drupal/phpmailer_smtp
インストール後のアクセス admin/config/system/phpmailer-smtp
モジュールを設定します。
- プライマリ SMTP サーバー - smtp.sendgrid.net
- SMTP ポート - 587
- 安全なプロトコルの使用 - TLSで [SMTP 認証] 、ユーザー名とパスワード (API キー) を設定します。
- ユーザー名 - SendGrid ユーザー名: "apikey"
- パスワード - SendGrid API キー
結局どれを使うか
SMTPを利用するので選択肢がおおくて迷いますが、Drupal (Symphony)はSwift Mailをサポートしています。Swift Mailerライブラリを使うと、基本的なHTMLメールは簡単に送ることができます。
そこでSwift mailerを利用したSwift mailerモジュールを使うことにしました。こちらは別案件で採用して実績もあります。
Swift Mailerライブラリの公式サイトはこちらです。
https://swiftmailer.symfony.com/docs/introduction.html
実際に使ってみる
Swift Mailer モジュールのインストールと設定
インストールは簡単です。
以下のDrupal.orgで公開されているSwift Mailerモジュールをダウンロードしてコントリビュートモジュール用のディレクトリ配下に置くかまたはComposerコマンドを実行してモジュールをインストールします。
https://www.drupal.org/project/swiftmailer
Compserを利用する場合は以下のコマンドをターミナル画面で実行してください。
composer require 'drupal/swiftmailer:^2.4'
インストールを完了するには必ず管理画面の機能拡張から対象モジュールを有効化してください。
インストールが正常に完了したら、管理画面から環境設定->システム->Swift Mailerを選択して設定画面を表示します。
メール送信方式をSMTPに設定し、必要なサーバー情報を入力すると設定は完了です。
テスト送信機能がありますので、送信先を指定してメールが正しく受信できることを確認します。
【注意事項】
正しく設定したつもりでもテスト送信するとメールが届かない場合は、CoreモジュールのMail Systemの設定を確認してみてください。デフォルトで使用するメーラーがSwiftMailerになっていない可能性があります。
バックエンドからメールを送信する
少し難易度は高くなりますが、ここからプログラムでメールを送信する方法を紹介します。
実装方法としては、Drupalのメールフック機能でメールのテンプレートを登録し、同じくDrupal Coreのメールプラグインを利用してメールを配信します。
今回やりたいことはあるコンテンツタイプのコンテンツが追加や変更されたときに対象のユーザにメールを送信するというものですが、またこちらも英文ですがとても参考になるサイトを見つけたので翻訳してご紹介します。
https://www.valuebound.com/resources/blog/how-to-send-mail-programmatically-drupal-8
Drupal で電子メールを送信するには、次の 2 つの手順を実行します。
- 適切なhook_mail()実装で電子メールのプロパティ(件名、本文、ヘッダーなど)を定義します。
- 電子メールを送信するには、メール マネージャーを使用します。
今回説明するプログラムは、Drupalのフック機能を使用しています。またフック機能を実装するため、モジュールを追加して拡張子が.moduleのフック用ファイルを作成する必要がありますが、その説明はここでは省略しています。
hook_mailを作成(Mailテンプレートを作る)
メールを送信する場合 プログラムで電子メール 、hook_mail() を実装するモジュール名を指定する必要があります。
では、それをどのように実装するかを見てみましょう。
これは、test_message ($key) として識別される 1 つのテンプレートを定義する単純な実装です。 他の 2 つの関数引数は次のとおりです。
$message: 参照によって渡され、その中にメールに関する定型文を必要なだけ追加します。
$params: 電子メールに含める必要があり、電子メールの送信時にメール マネージャーから渡される追加データの配列
以上がhook_mail()の実装です。
<?php
/**
* Implements hook_mail().
*/
function <module_name>_mail($key, &$message, $params) {
$options = array(
'langcode' => $message['langcode'],
);
switch ($key) {
case 'create_article':
$message['from'] = \Drupal::config('system.site')->get('mail');
$message['subject'] = t('Article created: @title', array('@title' => $params['node_title']), $options);
$message['body'][] = $params['message'];
break;
}
}
?>
hook_entity_insertの作成(記事作成時にメールを配信する)
記事が作成されるたびに呼び出される部分のコードです。
記事が作成されると、Drupal Mail マネージャー サービスをロードし、電子メールの値の設定を開始します。 次の情報が必要です。
- $module :hook_mail()を実装し、テンプレートを定義するモジュール名
- $key : テンプレートID
- $to :受信者の電子メール アドレス (現在のユーザー アカウントで見つかったもの)
- $langcode : $params 配列内に含まれ、件名メッセージの翻訳に使用される言語
- $params['件名'] : メールの件名
- $params['message'] メール本文
- $send : 電子メールを実際に送信する必要があるかどうかを示すブール値
次に、これらすべての値をメール マネージャーの mail() メソッドに渡します。 この中で先に説明したhook_mail()を呼び出します。
最終的に現在インストールされているMail Systemに連携して、メールが配信されます。
以上がDrupal を使用してプログラムで電子メールを送信する方法です。
<?php
/**
* Implements hook_entity_insert().
*/
function <module_name>_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {
if ($entity->getEntityTypeId() !== 'node' || ($entity->getEntityTypeId() === 'node' && $entity->bundle() !== 'article')) {
return;
}
$mailManager = \Drupal::service('plugin.manager.mail');
$module = ‘<module_name>’;
$key = 'create_article';
$to = \Drupal::currentUser()->getEmail();
$params['message'] = $entity->get('body')->value;
$params['node_title'] = $entity->label();
$langcode = \Drupal::currentUser()->getPreferredLangcode();
$send = true;
$result = $mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send);
if ($result['result'] !== true) {
drupal_set_message(t('There was a problem sending your message and it was not sent.'), 'error');
}
else {
drupal_set_message(t('Your message has been sent.'));
}
}
?>
さいごに
いかがだったでしょうか。モジュールの設定からコードの実装までかけ足で説明しました。実際にやってみるとつまずくポイントはいろいろあります。特に後半のコードの作成はコードに馴染みのない方には少し難しいと思いますが、参考記事があまりないのでご紹介しました。
あと、Email送信機能を実際に使ってみたい場合や勉強したい場合は、Example For Developmentモジュールをインストールして実際に動きを追っかけるのが一番だと思います。
次回は、Example For DevelopmentモジュールのEmail送信機能を使ったハンズオン的な記事をご紹介できたらと思います。
参考
Examples for Developersはこちらです。
https://www.drupal.org/project/examples
この記事に関するご質問やご意見などございましたらお問い合わせフォームからお気軽にご連絡ください。