blastengine 宛先設定 できること / できないこと

# はじめに
先の記事で `blastengine` を利用できるようになりましたが、[SDK](https://github.com/blastengineMania/blastengine-node)のReadmeを見ても紹介されていない挙動もあります。

https://qiita.com/katahiro/private/a46613b5f6940928e36e

トライアル環境での振る舞いについても紹介できればと思います。時折別で利用しているSendgridのサービスと比較しつつお話出来ればと思います。
ご紹介内容は、`Node.js`のSDK利用環境についてになります。

# Transaction
`blastengine`では、1通ずつ送るようなメール送信処理は `Transaction`、一斉配信は `bulk` によるメール送信を行うように案内されています。

## Transactionで複数の宛先にメール送信可能か？
結論から言うと `To`の宛先は1つのみ、 `CC`や`BCC`の宛先は複数(最大10件)が指定可能です。

```javascript:sample.js
const transaction = new Transaction;
transaction
  .setFrom('アカウントメールアドレス, 'Admin')
  .setSubject('メールの件名')
  .setTo('メールアドレスA')
  .setTo('メールアドレスB') // 後勝ちでこちらの宛先が設定される
  .setText('メールの本文');
```
例えば、このように `To`のアドレスを設定する `.setTo`を複数回呼び出した場合、1つしか設定できないため、送信先のメールアドレスは「後勝ち」になり、 `メールアドレスB`に送信するTransactionメールが作成されます。

## CC/BCCの宛先を追加する
何気にReadmeに記載が無くて、SDKの中身を確認してわかったのですが、 `.addCc()`を使って追加可能です。BCCの場合は `.addBcc()`になります。
```javascript:sample.js
const transaction = new Transaction;
transaction
  .setFrom('アカウントメールアドレス, 'Admin')
  .setSubject('メールの件名')
  .setTo('メールアドレスA')
  .addCc('メールアドレスB')
  .setText('メールの本文');
```
これで、CCにもメールを飛ばすことが出来ます。

## CC/BCCに宛先を複数設定する
CCの宛先を設定した配列を渡すことが出来れば良かったのですが、SDK側が1つずつ受け取ってそれをCCの宛先配列に設定するようになっています。設定時点でCC宛先配列の要素数が10を超えていたら、それ以上設定できないということですね。
```typescript:transaction.ts
/**
 * Add a recipient to the transaction delivery as Cc.
 *
 * @param {string} email - The email address of the recipient.
 * @return {BEReturnType} - The current instance.
 */
addCc(email: string): Transaction {
  if (this.cc.length >= 10) throw new Error("Cc is limited to 10.");
  this.cc.push(email);
  return this;
}
```
なので、現状の仕様ではCC/BCCの宛先追加はその分実行する必要があります。
```javascript:sample.js
const transaction = new Transaction;
transaction
  .setFrom('アカウントメールアドレス, 'Admin')
  .setSubject('メールの件名')
  .setTo('メールアドレスA')
  .addCc('メールアドレスB')
  .addCc('メールアドレスC')
  .addCc('メールアドレスD')
  .setText('メールの本文');
```

## (トライアル)To/CC/BCCに送信不可のアドレスが含まれている場合の挙動
トライアルでは送信先として許可した最大5件のメールアドレスにしか配信することができません。その状況で送信できないメールアドレスを含めたメール送信をプログラムで実行するとどうなるのでしょうか？

結論から言うと、プログラムでは特にエラーは発生せず、 `blastengine`側で、送信許可の設定をしていないメールアドレスはドロップされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/98ba2d38-c1d7-2353-afb1-4211c509f9fd.png)

この時に注意が必要なのは、`許可されていないメールへは配信されない`だけなので、そのメールに設定されたCC等から対象のメールアドレスが除去されるわけではありません。
つまり`メールアドレスA`を許可、 `メールアドレスB`を不可として設定された状態で、ToをメールアドレスA、CCをメールアドレスBとして送信した場合、メールアドレスAは、CCにメールアドレスBが設定されたメールを受信します。これだけ見るとメールアドレスAの受信者はメールアドレスBもその内容を受け取っていると想像しますが、実際はblastengineでドロップされているので、メールアドレスBは一切その情報を把握していないことになります。

はたから見ると受信してるはずなのに、届いていないとなると、ビジネスだと問題になりそうなので、トライアルでは十分理解した利用が必要ですね。

## 送信元アドレスの設定
これが、現在Sendgridのサービスでは許可されていなくて、blastengineでは実現できるポイントですね。

これまでのサンプルコードでは、全て `.setFrom('アカウントメールアドレス, 'Admin')` を設定しているので、blastengineに作成したアカウントのメールアドレスがFromになってメールが飛びます。
ここで指定するメールアドレスは、 `別にアカウントメールアドレスでなくても良い`というのが仕様です。

試しに存在しないメールアドレスを設定して送信します。
```javascript:sample.js
const transaction = new Transaction;
transaction
  .setFrom('system-administrator@katahiro.com, 'Admin') // 存在しないアドレス
  .setSubject('メールの件名')
  .setTo('メールアドレスA')
  .setText('メールの本文');
```
無事に `system-administrator@katahiro.com` という存在しないメールアドレスからメールを受信することが出来ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/bbe21c5b-4f8f-f655-9a1f-837aa56249e2.png)

以前はSendgridのサービスでもできたのですが、今はSender Authentificationのプロセスがあり、認証を行った存在するメールアドレスでしか送信することが許可されていません。

このあたりは、システムから通知のみの目的で送られてくる `no-reply@hogehoge.com` といったのを指定しやすいですが、他者のメールアドレスを設定できてしまう部分でもあるので、今後機能改修がされるかもしれないですね。

# bulk
`bulk`は先に述べたように一斉配信のための機能なので、複数の宛先を指定したりすることができますが、予想外の罠があったので紹介します。

## bulkで宛先を設定する
まず `bulk` を利用する際は、次の順序でメール配信を行います
1. `bulk`での送信を行うために `送信元アドレス`、`件名`、`本文`の3つを最低宣言して `blastengine`側にbulk送信するための器を作成する
1. 作成した器に宛先を設定する
1. 器の配信、配信予約を実施する

ここで罠があります。

SDKの[Readme](https://github.com/blastengineMania/blastengine-node#update--add-delivery-address-to-bulk)には、この記事が公開される12/14時点では、~~宛先設定で次のように記載されています。~~

:::note info
記事掲載後にReadmeが無事に更新されました！
:::
```javascript
bulk.setTo('test1@example.jp', {key: '__code1__', value: 'value!'});
bulk.setTo('test2@example.jp', {key: '__code1__', value: 'value2!'});
const updateRes = await bulk.update();
console.log(updateRes);
// { delivery_id: 22 }
```
実は`bulk`のオブジェクトに宛先を設定している `.setTo()`のメソッドが**存在しません**。
SDKの中身を見ていくと `.addTo()`があるので、これで設定するみたい。
```typescript:bulk.ts
  /**
   * Adds a recipient to the bulk delivery.
   *
   * @param {string} email - The email address of the recipient.
   * @param {InsertCode} insertCode - The insert code for the recipient.
   * @return {Bulk} - The current instance.
   */
  addTo(email: string, insertCode?: InsertCode): Bulk {
    const params: BulkUpdateTo = {email};
    params.insert_code = this.hashToInsertCode(insertCode);
    this.to.push(params);
    return this;
  }
```
この記事が公開されるとすぐに `Readme.md` が修正されそうですね。

これまでのSDKのメソッド名を見ている限りでは `.setHoge()` タイプのメソッドは、通常1件しか設定しないものの名称で使われているように思います。例えば、件名や本文、Transactionにおける宛先も1件しか登録できないので、 `.setText()`、`.setSubject()`、`.setTo()`が宣言されています。
一方、TransactionにおけるCCの宛先や、Bulkの宛先といった複数設定可能なパラメータを指定するメソッド名は `.addHoge()`の名称が使われているように見えますね。 `.addCc()`、`.addBcc()`、`.addTo()`がそれらにあたります。そう覚えると、利用者もどっちで設定するんだっけ？と迷わなくなりそうです。

## bulkでの送信プロセス
先に書いた項番の順序ですが、以下のように記述することで送信することが可能です。
```javascript:sample.js
// bulkオブジェクトの作成
const bulk = new Bulk;

// 送信元、件名、本文の設定
bulk
  .setFrom('送信元メールアドレス', 'Admin')
  .setSubject('メールの件名')
  .setText('メールの本文')

const res = await bulk.register();

// 宛先の設定
bulk.addTo('宛先メールアドレス');
await bulk.update();

// 送信の実行
const resSend = await bulk.send();
console.log(JSON.stringify(resSend));
```
送信元や件名を設定する時に、宛先も一緒に設定できないのだろうかと思うかもしれませんが、それはできません。
`bulk.register()`のメソッドは内部的には `https://app.engn.jp/api/v1/deliveries/bulk/begin`の[API](https://blastengine.jp/documents/#tag/deliveries/operation/delivery-bulk-post)を実行しているようで、このAPIには宛先を設定するパラメータを受け付けていません。従って `.register()`を登録する前に `bulk`オブジェクトに宛先を設定していたとしても大きな意味が無い、ということになります。

ただ、 `.register()`メソッドは `bulk`オブジェクトに設定された送信元アドレスや、件名、本文を登録するだけなので、宛先を設定していても動作はします。

つまり、次のような実装をしても動作します。
```javascript:sample.js
// bulkオブジェクトの作成
const bulk = new Bulk;

// 送信元、件名、本文の設定
bulk
  .setFrom('送信元メールアドレス', 'Admin')
  .setSubject('メールの件名')
  .setText('メールの本文')
  .addTo('宛先メールアドレス'); // 宛先を事前に設定

const res = await bulk.register();

// 宛先の設定
await bulk.update();

// 送信の実行
const resSend = await bulk.send();
console.log(JSON.stringify(resSend));
```
宛先を登録する[API](https://blastengine.jp/documents/#tag/deliveries/operation/delivery-bulk-update)、正確には宛先を含めて先ほど登録した送信元アドレスや件名を更新できる `.update()`を`.register()`の後に呼び出せば送信を実行することが可能です。

# トライアルの10000通まで送信可能の計算対象は？
こちらは先ほどの画像ですが、残り通数が `9994通`(画面右上に表示)、ドロップされずに配信成功した宛先が `6通`なので、ドロップされたメールはカウントせず、配信を実行したメール数がその数として算出されるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/98ba2d38-c1d7-2353-afb1-4211c509f9fd.png)

注意が必要なのは、例えば `To`と `CC`に同じメールアドレスを設定して送信した場合、それは2件として算出されます。

# さいごに
いかがでしたでしょうか？
癖のある部分はありますが、今回ご紹介した実装方法を使って、個人でも簡単にメール送信がプログラムから実現できそうです。
せっかくだしblastengine使ってみよう！という方々のお役に立てれば幸いです。