yutaponのブログ

javascript界隈の興味あるネタを備忘録的に残しておく場所

JavaScriptだけでメールが送れるらしいのでやってみた【Backbone.js】

JavaScriptというか、XHRでメールを送信できるサービスがあるらしいので試してみます。
これを知った記事がこちら。
jsだけ使ってメールが送れる世の中らしい - 以下斜め読んだ内容

そんなサービスを提供してるのがMailChimpのMandrill。
Transactional Email from MailChimp - Mandrill

このAPIはデフォルトのレスポンスがJSON形式で返ってくるとのことなので、
Backbone.jsと相性が良さそうなので使ってみます。


Mandrill API使えるようにする

ひとまず、mandrill.comにアクセスしてアカウントを発行して、
APIキーを取得して下さい。
画面に従っていけば難なく発行できると思います。

MandrillのAPIを使うには全てのリクエストでこのAPIキーも一緒に送信する必要があります。
使えるAPIリストはこちら。
API | Mandrill


それでAPI使えてるか確認する用に書いたのがこれ。
/users/info.jsonを取得するコードです。

// @file mail.html

<!-- 結果表示用 -->
<div id="result"></div>

<!-- これをhtml側で読み込んで -->
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<!-- mail.js にロジックを記述する -->
<script src="javascripts/mail.js"></script>

// @file mail.js

var app = {
    config : {
        api : {
            root : 'https://mandrillapp.com/api/1.0/',
            key  : 'xxxxxxxxxxx'
        }
    }
};

var UsersModel = Backbone.Model.extend({
    initialize : function () {
        /**
         * 具体的なリソース
         * @public
         * @type {String}
         */
        this.resource = null;
    },

    url : function url() {
        return app.config.api.root + 'users/' + this.get('resource');
    }
});

app.usersModel = new UsersModel();

var UsersView = Backbone.View.extend({
    model : app.usersModel,

    initialize : function initialize() {
        this.listenTo(this.model, 'sync', this.render);
    },

    render : function render() {
        var json = this.model.toJSON();
        var str  = JSON.stringify(json);
        this.$el.html(str);
        $('#result').html(this.$el);
    },

    getUsersInfo : function getUsersInfo() {
        this.model.set('resource', 'info');

        this.model.fetch({
            data : {
                key : app.config.api.key
            },
            success : function success(model, response, options) {
                // 通信成功時の処理
            }
        });
    }
});


var usersView = new UsersView();
usersView.getUsersInfo();

結果はこんな感じ。

{
    "resource": "info",
    "username": "hogehoge@fuga.com",
    "created_at": "2014-02-01 10:34:56.98672",
    "public_id": "abcd1234567890",
    "reputation": 0,
    "hourly_quota": 250,
    "backlog": 0,
    "stats": {
        "today": {
            "sent": 0,
            "hard_bounces": 0,
            "soft_bounces": 0,
            "rejects": 0,
            "complaints": 0,
            "unsubs": 0,
            "opens": 0,
            "unique_opens": 0,
            "clicks": 0,
            "unique_clicks": 0
        },
        "last_7_days": {
            "sent": 0,
            "hard_bounces": 0,
            "soft_bounces": 0,
            "rejects": 0,
            "complaints": 0,
            "unsubs": 0,
            "opens": 0,
            "unique_opens": 0,
            "clicks": 0,
            "unique_clicks": 0
        },
        "last_30_days": {
            "sent": 0,
            "hard_bounces": 0,
            "soft_bounces": 0,
            "rejects": 0,
            "complaints": 0,
            "unsubs": 0,
            "opens": 0,
            "unique_opens": 0,
            "clicks": 0,
            "unique_clicks": 0
        },
        "last_60_days": {
            "sent": 0,
            "hard_bounces": 0,
            "soft_bounces": 0,
            "rejects": 0,
            "complaints": 0,
            "unsubs": 0,
            "opens": 0,
            "unique_opens": 0,
            "clicks": 0,
            "unique_clicks": 0
        },
        "last_90_days": {
            "sent": 0,
            "hard_bounces": 0,
            "soft_bounces": 0,
            "rejects": 0,
            "complaints": 0,
            "unsubs": 0,
            "opens": 0,
            "unique_opens": 0,
            "clicks": 0,
            "unique_clicks": 0
        },
        "all_time": {
            "sent": 0,
            "hard_bounces": 0,
            "soft_bounces": 0,
            "rejects": 0,
            "complaints": 0,
            "unsubs": 0,
            "opens": 0,
            "unique_opens": 0,
            "clicks": 0,
            "unique_clicks": 0
        }
    }
}

確認ができたので実際にメールを送ってみます。

Mandrill APIでメールを送る

メール送信のAPIはこちら。
Messages API | Mandrill

クエリーが長いので、実際に送信処理を行うmodelと、
送信するメッセージを管理するmodelを作ることにします。
また、users/infoはGETで取得できましたが、All API calls should be made with HTTP POST.
という記述から送信はPOSTで行います。

// @file mail.js

var app = {
    config : {
        api : {
            root : 'https://mandrillapp.com/api/1.0/',
            key  : 'xxxxxxxxxxx'
        }
    }
};

/**
 * 実際に送信するmodel
 */
var MessagesSendModel = Backbone.Model.extend({
    url : function url() {
        return app.config.api.root + 'messages/send';
    }
});

/**
 * メッセージ管理用model
 */
var MessageModel = Backbone.Model.extend({});

app.messagesSendModel = new MessagesSendModel();

/**
 * メール送信を行うView
 */
var MessagesSendView = Backbone.View.extend({
    model : app.messagesSendModel,

    initialize : function () {
        this.listenTo(this.model, 'sync', this.render);
    },

    render : function render() {
        var json = this.model.toJSON();
        var str  = JSON.stringify(json);
        this.$el.html(str);
        $('#result').html(this.$el);
    },

    /**
     * 送信するメソッド
     * @param  {MessageModel} messageModel
     */
    send : function send(messageModel) {
        if (!messageModel) {
            return;
        }

        this.model.set('key', app.config.api.key);
        this.model.set('message', messageModel.toJSON());

        this.model.save({
            success : function success(model, response, options) {
                // 送信成功時の処理
            }
        });
    }
});

/**
 * メッセージの組み立てを行うView
 * htmlにフォームとか用意してそれを受け取れるようにするのがベター
 */
var MessageView = Backbone.View.extend({
    model : new MessageModel(),

    initialize : function initialize() {
        this._setExampleMessage();
    },

    /**
     * サンプルメッセージを組立て
     */
    _setExampleMessage : function _setExampleMessage() {
        this.model.set('text', '日本語のメッセージ');
        this.model.set('subject', 'send test from javascript');
        this.model.set('from_email', 'hoge@fuga.com');
        this.model.set('from_name', 'yutapon');
        this.model.set('to', [{ email: 'hoge123@example.com' }]);
    }
});

var messagesSendView = new MessagesSendView();
var messageView = new MessageView();

messagesSendView.send(messageView.model);  // 送信

レスポンスはこちら。

{
    "0": {
        "email": "hoge123@example.com",
        "status": "sent",
        "_id": "9026513b55e94979a3fe0xxxxxxxxx",
        "reject_reason": null
    }
}

status: "sent" ということで、無事宛先のメールアドレスにメールが届きました。

他にもいろいろとAPIがあるんですが、GMailみたいなサービスを自前で
作ることもできそうな感じです。


おわりに

MandrillのAPIリファレンスの出来がとても良いです。
仕事でもこういうAPIリファレンスで管理できないかなと考えたり。

あまりBackboneのコードについて説明しなかったので、
慣れてないと流れが読めないかも。。
ザーっと書いたので見難いと思います。

それにしてもこのメール送信のお手軽感がすごかったです。
Backboneからメール送信でしたが、普通にNode.jsとかRailsとか
バックエンドから使ってもいいかもしれない。