【18日目】Discordでメールを受け取る

# はじめに
こんにちは、なりかくんです。
今回は、Discord内でメールを受け取れるようにしてみたいと思います。

# どうやってメールを受信するのか
今回はNode.jsで製作したいと思います。Node.jsにはメールを受信（IMAPクライアント）のライブラリが複数個存在します。その中でも私は、inboxというライブラリを使いました。
非常にシンプルである程度ドキュメントがあるためおすすめできます。

https://www.npmjs.com/package/inbox

ドキュメントにあるサンプルコードをいろいろ合わせて以下のようなコードを作ると新着メールを受信できます。
このコードでは、新着メールを受け取るとそのメールのタイトルを表示するプログラムです。
```js
const inbox = require("inbox");
 
let client = inbox.createConnection(false, "メールサーバーのアドレス（IMAP）", {
    secureConnection: true,
    auth:{
        user: "ユーザー名",
        pass: "パスワード"
    }
});
 
client.connect();
 
client.on("connect", function(){
    client.openMailbox("INBOX", function(error, info){
        if(error) throw error;
        console.log("Successfully connected to server");
    });
});

client.on("new", function(message){
    console.log("New incoming message " + message.title);
});
```

# メールのソースを分析する
次にメールのソースからメッセージ内容などを分析します。これもライブラリを利用します。
今回は、mailpaserというライブラリを利用しました。

https://www.npmjs.com/package/mailparser

以下のようなコードでメールのソースを解析できます。
```js
const { simpleParser } = require("mailparser");

let mailParse = await simpleParser(メールのソース);
let mailBody = mailParse.text;
let mailTitle = mailParse.subject;
let from = mailParse.from.text;
let to = mailParse.to.text;
let messageId = mailParse.messageId;
```

# 受信したメールのUIDからソースを取得
では、受信したメールのUIDからソースを取得するコードを作ってみましょう。
以下のようなコードでUIDからメール内容を取得できます。（ついでにさっきのパースも行います。）
`createMessageStream`で内容を取得します。
```js
mailClient.on("new", async function(message) {
    let mailSource = mailClient.createMessageStream(message.UID);
    let mailParse = await simpleParser(mailSource);
    console.log(mailParse);
});
```

# すべてを組み合わせてDiscordに送ってみよう
では、すべてを組み合わせてDiscordに送信するプログラムを作ってみます。今回は、WebHookで通知するようにします。
メールを受信した際に送信するコードは以下のようになりました。メールの内容が長すぎるとDiscord APIに引っかかるので1900文字以内になるように切り取っています。
```js
mailClient.on("new", async function(message) {
    let mailSource = mailClient.createMessageStream(message.UID);
    let mailParse = await simpleParser(mailSource);
    let mailBody = mailParse.text || "本文なし";
    let mailTitle = mailParse.subject || "件名なし";
    let from = mailParse.from.text;
    let to = mailParse.to.text;
    let messageId = mailParse.messageId;
    await getRequest({
        url: "WebHookのURL",
        headers: {
            'Accept': 'application/json',
            'Content-type': 'application/json',
        },
        method: "POST",
        json: {
            embeds: [{
                title: mailTitle,
                author: {
                    name: from
                },
                footer: {
                    text: to
                },
                description: `\`\`\`\n${String(mailBody).substring(0, 1900)}\n\`\`\``
            }],
            username: messageId
        }
    });
});
```

# 実際に動かしてみる
では、実際に動かしてみます。試しにメールを送信してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/847cdf16-4c68-274f-6b94-a62d10be061a.png)

すると、以下のように指定したWebHookチャンネルにメールの通知が届きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/0bb25059-d8d6-8ee5-b81d-82a0c49f37bf.png)

# 最後に
受信してみた感じ、ほぼリアルタイムだったのでこれはいろいろなところで使えそうだと思いました。
また、今回はWebHookで製作しましたがこれをBot化してスレッド等を活用してDiscordサーバー一つを丸々メールボックスにしてみたり、送信機能等をつけてみると面白そうですね。

以上です、最後までお読みいただきありがとうございました。

今回制作したコードを載せておきます。ぜひ参考にしてみてください。
```js:discordmail.js
var inbox = require('inbox');
const { simpleParser } = require("mailparser");
const request = require("request");

var mailClient = inbox.createConnection(false, "メールサーバーのアドレス（IMAP）", {
    secureConnection: true,
    auth:{
        user: "ユーザー名",
        pass: "パスワード"
    }
});

mailClient.on("connect", function() {
    mailClient.openMailbox("INBOX", async function(err, info) {
        if (err) {
            console.error(err);
        }
        console.log("メールサーバーに接続しました。");
    });
});

mailClient.on("new", async function(message) {
    let mailSource = mailClient.createMessageStream(message.UID);
    let mailParse = await simpleParser(mailSource);
    let mailBody = mailParse.text || "本文なし";
    let mailTitle = mailParse.subject || "件名なし";
    let from = mailParse.from.text;
    let to = mailParse.to.text;
    let messageId = mailParse.messageId;
    await getRequest({
        url: "WebHookのURL",
        headers: {
            'Accept': 'application/json',
            'Content-type': 'application/json',
        },
        method: "POST",
        json: {
            embeds: [{
                title: mailTitle,
                author: {
                    name: from
                },
                footer: {
                    text: to
                },
                description: `\`\`\`\n${String(mailBody).substring(0, 1900)}\n\`\`\``
            }],
            username: messageId
        }
    });
});

mailClient.connect();

function getRequest(option) {
    return new Promise((resolve, reject) => {
        request(option, function (error, response, body) {
            if (error) {
                reject(error);
            } else {
                resolve(body);
            }
        });
    });
}
```