kikki's tech note

技術ブログです。UnityやSpine、MS、Javaなど技術色々について解説しています。

SendGridでWebAPIを利用したメール送信

本章では、C#でSendGridを利用してメールを送る方法について共有します。

はじめに

一般的にメールを送る方法は、SMTPでメールを送信することが多いのですが、今回WebAPIを利用したメール送信について紹介します。
WebAPIを利用することで、以下記事にある通り、メール送信以外の便利な機能を利用できます。
sendgrid.kke.co.jp
例えば、以下の機能を利用することでマーケティング戦略・実行の一環として利用できます。

  • メールの開封チェック
  • メール本文のリンクが押されたかどうかの追跡
  • メール送信予約
  • メールをカテゴリ別に分類し集計・分析

事前準備

今回、実装の前にSendGridのWebAPIで利用するユーザを事前に作成します。
f:id:kikkisnrdec:20160517214219p:plain

  1. SendGridにログイン後、左のメニューのSettingsを開く
  2. Credentialsを選択
  3. Add New Credentialsを選択

f:id:kikkisnrdec:20160517214236p:plain

  1. UserNameを入力
  2. Passwordを入力
  3. すべてのチェックボックスにチェック
  4. CreateCredentialをクリック

ここで作成したユーザを以下の節で利用します。

ソース

それでは、実装例を示します。以下の「SendEmail」メソッドを利用することでメールを送信しつつ、カテゴリ分類や送信予約ができます。

public Task<bool> SendEmail(string fromAddress, string fromName, string[] to, string[] cc, string[] bcc, string subject, string painBodyText, string htmlBodyText, BodyType type, string[] categories = null, DateTime? reservationTime = null)
{
    var task = Task.Factory.StartNew(() =>
    {
        var list = new List<string>();
        list.Add("api_user=【SendGridでのユーザ名】");
        list.Add("api_key=【SendGridでのパスワード】");

        list.Add("from=" + fromAddress);
        list.Add("fromname=" + fromName);
        if (to != null)
            foreach (var item in to)
            {
                list.Add("to" + (to.Length > 1 ? "[]" : "") + "=" + item);
            }
        if (cc != null)
            foreach (var item in cc)
            {
                list.Add("cc" + (cc.Length > 1 ? "[]" : "") + "=" + item);
            }
        if (bcc != null)
            foreach (var item in bcc)
            {
                list.Add("bcc" + (bcc.Length > 1 ? "[]" : "") + "=" + item);
            }
        list.Add("subject=" + subject);
        switch (type)
        {
            case BodyType.Plain:
                list.Add("text=" + HttpUtility.UrlEncode(painBodyText));
                break;
            case BodyType.Html:
                list.Add("html=" + HttpUtility.UrlEncode(htmlBodyText));
                break;
            case BodyType.Multipart:
                list.Add("text=" + HttpUtility.UrlEncode(painBodyText));
                list.Add("html=" + HttpUtility.UrlEncode(htmlBodyText));
                break;
            default:
                break;
        }
        if ((categories != null && categories.Length > 0) || reservationTime != null)
        {
            var message = @"x-smtpapi={";
            if (categories != null && categories.Length > 0)
            {
                message += @"""category"": [" + string.Join(",", categories.Select(p => @"""" + p + @"""")) + @"]";
                if (reservationTime != null)
                    message += ", ";
            }
            if (reservationTime != null)
            {
                message += @"""send_at"": " + UnixTime.FromDateTime(reservationTime.Value);
            }
            message += @"}";
            list.Add(message);
        }
        var postData = string.Join("&", list.ToArray());

        var request = (HttpWebRequest)HttpWebRequest.Create(this.MailServer);
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";
        using (var sw = new StreamWriter(request.GetRequestStream()))
        {
            sw.Write(postData);
            sw.Flush();
            sw.Close();
        }
        var response = (HttpWebResponse)request.GetResponse();
        using (var sr = new StreamReader(response.GetResponseStream()))
        {
            string result = sr.ReadToEnd();
            var json = Jil.JSON.Deserialize<MailMessageEntity>(result);
            if (json != null && !String.IsNullOrWhiteSpace(json.message) && json.message == "success")
                return true;
            else
                return false;
        }
    });
    return task;
}

/// <summary>
/// メール本文種別
/// </summary>
public enum BodyType
{
    /// <summary>
    /// プレーンテキスト
    /// </summary>
    Plain,
    /// <summary>
    /// HTML文
    /// </summary>
    Html,
    /// <summary>
    /// マルチパート
    /// </summary>
    Multipart,
}

/// <summary>
/// メール送信日時
/// </summary>
private static class UnixTime
{
    private static readonly DateTime UNIX_EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    public static long Now()
    {
        return (FromDateTime(DateTime.UtcNow));
    }

    public static DateTime FromUnixTime(long unixTime)
    {
        return UNIX_EPOCH.AddSeconds(unixTime).ToLocalTime();
    }

    public static long FromDateTime(DateTime dateTime)
    {
        double nowTicks = (dateTime.ToUniversalTime() - UNIX_EPOCH).TotalSeconds;
        return (long)nowTicks;
    }
}

SendGridをWebAPIで呼び出す場合の注意点として、本文を「HttpUtility.UrlEncode」メソッドエンコードすること、POSTデータのContentTypeを「application/x-www-form-urlencoded」を指定することが重要です。
日本語などの2バイト言語では本文をURLエンコードする必要があり、エンコードしなければ本文が文字化け、またはメール送信ができません。

筆休め

WebAPIによるメール送信は、メールの定時配信や開封チェック、到達率の集計といった、事業の次の一手を打つための手段として利用できます。
エンジニアとしては、メール送信イベントをトリガとしたフックアプリケーションの実装が行えるので遊びとしても利用できます。
是非利用してみてください。

以上、「SendGridでWebAPIを利用したメール送信」でした。


※無断転載禁止 Copyright (C) kikkisnrdec All Rights Reserved.