読者です 読者をやめる 読者になる 読者になる

Challenge Java EE !

Java EEを中心に趣味や仕事における開発メモを書いています。

SalesforceからSendGridを利用してメール送信する!

この記事は「SendGrid Advent Calendar 2016」の13日目の記事です。
昨日は @azumakuniyuki さんの「SendGridへリレーする方法、MTA3種盛り。」でした。
明日は @nakansukeさん の「Amazon SESとの比較」です。

Salesforce World Tour Tokyo 2016

本日からSalesforce World Tour Tokyo 2016が開催されますね。SendGridチームは明日12/14(水)、開発者向けの「Developer Forest*1に出展します!私もスタッフとして立っていると思うので、もしご興味ある方は是非ご参加ください!

ということで、今日はSalesforceにおけるメール送信について書いてみたいと思います。

なお、私自身、Salesforceを触ったり、連携するシステム開発の経験はありますが、Salesforce系の資格とか、ゴリゴリApex書いたとか、の経験はありません(>_<;今回のエントリは、自分で調べた範囲の知識にて、もし間違いがあった場合などはご指摘いただけると嬉しいです(^^;

Salesforceにおけるメール送信

Salesforceでは、リードや取引先責任者へメールを送ったり、ワークフローの承認でメールを送ったり、様々な用途、タイミングでメールが利用されます。メール送信に関しては、ざっと調べた範囲でも以下の選択肢があると思います。

機能カテゴリ 機能
Salesforce標準*のメール送信機能 リードへの一括メール送信
取引先責任者への一括メール送信
ワークフロー・承認申請のメールアラート
メール to ケース
メール to Salesforce
Apex(メールサービス) Apexプログラムによるメール送信
メールリレー 既存SMTPサーバをリレーサーバとして利用
AppExchange Sendmail(Salesforce Labs)
Autobahn for AppExchange
Synergy!LEAD
外部サービス(Lightning限定) Gmail
Office 365

他にもあるかもしれません。

せっかくなので、表の中のいくつか試してみます。

取引先責任者への一括メール送信

取引先責任者のツールメニューに「取引先責任者の一括メール送信」があります。

f:id:kikutaro777:20161212162253p:plain

宛先にする責任者をビューから選択します。

f:id:kikutaro777:20161212162307p:plain

メールテンプレートはSalesforceで標準にあったものから適当に選びました。

f:id:kikutaro777:20161212162323p:plain

一括メール送信名を入れて、「送信」ボタンを押すだけです。

f:id:kikutaro777:20161212162334p:plain

ちなみにこの一括メール送信名によって、管理メニューの「監視」->「一括メール送信」の一覧を識別できるようです。

f:id:kikutaro777:20161212183308p:plain

f:id:kikutaro777:20161212183336p:plain

送信完了を確認したら

f:id:kikutaro777:20161212162352p:plain

メールが届いているか確認します。おー、来てますね。

f:id:kikutaro777:20161212162454p:plain

さすが標準機能、手軽です。

外部サービス(Gmail)

表の一番下に入れた「外部サービス」はLightningだけで使える機能なんですね。せっかくなので、これもちょっと試してみました。管理メニューの「メール管理」から「外部サービス」メニューを選択します。

f:id:kikutaro777:20161212161442p:plain:w100

GmailとOffice 365が選べるのですが、今回はGmailを選択しました。右のボタンを「ON」に切り替えます。

f:id:kikutaro777:20161212160921p:plain

あとは「Lightning Experienceに切り替え」ます。

f:id:kikutaro777:20161212161206j:plain

ちなみにLightningへの切替は事前に環境を確認して行ってくださいm(_ _)mまぁSalesforce側で設定変更前に色々確認メニューでるので、ここではこの程度にしておきます。

切り替えた後、取引先責任者一覧へ。

f:id:kikutaro777:20161212165442p:plain

Lightningめっちゃ綺麗(/・ω・)/

メールの部分をみると、Gmailの選択肢がでます!

f:id:kikutaro777:20161212165730p:plain

メールエディタが組み込まれます。
f:id:kikutaro777:20161212170204p:plain

試しに送信すると、ちゃんと届きます。
f:id:kikutaro777:20161212170416p:plain

すごい。便利w

これらの機能はSalesforceで標準的に用意されており、統合された機能として使いやすいです。一方で、一部ガバナ制限を受けるケースがあったり、テンプレートを作成する際に、Web上でのエディタのようなものがなく少し手間だったり、という点もあるかと思います。ここはここでAppExchangeでカバーされる製品もあるとは思います。

なお、どういう制限があるのか、などQA的なものは以下が良さそうでした。

Salesforceのメール送信 ポイント集
help.salesforce.com

では次に、ここに挙げた選択肢以外でどのようなものがあるのか?というところで、SendGridを利用した方法を試したいと思います。

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

SalesforceでSendGridを利用する方法としては、以下の選択肢があると思っています。

方式 方法 利用可能有無 補足
メールリレー × 一番シンプルな方法と思いますが、こちらにあるようにSalesforce側がID/Passの認証対応が現状できないようです。このスレ、相当みなさん文句言っていて面白い…
Apex sendgrid-apex 実はSendGridからApex用のラッパーライブラリがGitHubで公開されてます。詳細は後程。
SendGrid APIを直接叩く 今回時間がなくて試せなかったのですが、Apexでhttpコールができるのであれば、普通にSendGridのAPIをコールすることも
API連携 一番堅実で、SalesforceのSOAPかRESTのAPIで取引先責任者とかメアド取ってきて、SendGridのAPIで送信という形です。

Salesforceのメールリレーの設定は以下のようになっていています。

f:id:kikutaro777:20161212172412j:plain

SendGridでは、SMTPサーバにログインして直接使うこともできるのですが、当然ながらSMTPサーバのユーザIDとパスワードが必要です。しかし、Salesforceの設定ページでは特にそういう設定部がなく…現状、以下ページに書かれているように対応されていないようです。

success.salesforce.com

3つ目のApexでREST APIをコールする部分は今回調べきれなかったです。JavaでいうHttpClientとかJersey Clientみたいなライブラリがつかえると楽なのでしょうが…この辺Apexはどうなっているんでしょうか。。。

また、4つ目のAPI連携は下図のようなイメージです。

f:id:kikutaro777:20161213151606p:plain

今回のAdventでは細かく触れませんが、SalesforceのAPIをJavaで触ったとき(SOAP APIですが)のエントリは前に書いたので、興味ある方はどうぞm(_ _)m

kikutaro777.hatenablog.com

この方法が一番堅実だと個人的には思います。

Apex with SendGrid

さきほど、Apexで利用可能なライブラリがGitHubにあると書きましたが、以下となります。ただ、最終コミットの日付をみていただくとわかるのですが、数年前で止まったままとなっております。

github.com

以降で書くのは、あくまでも私がサンプル的に試したものであり、公式に利用可能であるということは保証できないのでよろしくお願い致します。実際、SendGridでは既にv3というAPIに移行していますが、このApexラッパーのコードを確認すると、v2のラッパーとなっていたりします。

色々ガードはってしまいましたが、早速、試してみましょう。

Salesforceにログインした状態で、GitHubのInstallationの下に表示されているURLをクリックします。
f:id:kikutaro777:20161212171942j:plain

今回は管理者のみでインストールしました。
f:id:kikutaro777:20161212173316j:plain

アクセスの承認をします。ここの2個目はちょっとよくわからず、とりあえず1個目だけチェックしています。
f:id:kikutaro777:20161212173329j:plain

「インストール完了!」と出ればOKです。
f:id:kikutaro777:20161212173340j:plain

開発者は通常EclipseとかでApex触るのだと思いますが、今回は簡単なサンプルなので「開発者コンソール」で進めます。
f:id:kikutaro777:20161212173504j:plain

Apexクラスを作成します。「SendGridController」クラスにしました。
f:id:kikutaro777:20161212173534j:plain

中身は以下のような感じ。お試しされる方は、ID/パスワード/メアドは本物に置き換えてください。
f:id:kikutaro777:20161212173544j:plain

public class SendGridController {

    public void sendMail() {
        SendGrid sendgrid 
            = new SendGrid('sendgridのログインID', 'sendgridのログインパスワード');
        
        SendGrid.Email email = new SendGrid.Email();
        email.addTo('テストで送る宛先メールアドレス');
        email.setFrom('送信元fromのメールアドレス');
        email.setSubject('SalesforceのApexからテスト送信');
        email.setText('Salesforceからこんにちは');
        
        sendgrid.send(email);
    }

}

続いてページを作成します。「Visualforce Page」を選択します。
f:id:kikutaro777:20161212173655j:plain

「SendGridPage」という名前にしました。
f:id:kikutaro777:20161212173703j:plain

中身は以下のように定義。Java EEなどでJSFに慣れていると楽ですね(^^;

<apex:page controller="SendGridController">
    <apex:form>
        <apex:commandButton id="btnSendMail" 
            action="{!sendMail}" value="SendGridでメール送信" />
    </apex:form>
</apex:page>

ページを開いてみます。URLで「https://x.xx2.visual.force.com/apex/SendGridPage」のようにページ名を直接打ってもいいです(xxの辺りはSandboxごとに異なる)し、設定メニューの「ビルド」->「開発」->「Visualforceページ」を選択して
f:id:kikutaro777:20161213141717p:plain:w100

矢印マークからページを起動することもできます。
f:id:kikutaro777:20161213141728p:plain

こんな感じ。
f:id:kikutaro777:20161212174109p:plain

ボタンを押すと、宛先で指定したメールアドレスに送信されます。簡単ですね。

ただ、実際の業務系では、メアドを直接Apexに埋め込むようなコードは書かないですし、こんな画面のユースケースはないと思います。

そこで、取引先責任者のテーブルを作り、メール送信用ボタンをカラムに配置してみたいと思います。その前に、素のままだと見た目があまりにもダサすぎるので、今回VisualStrapを使いました。BootstrapをVisualforceで簡単に使えるようにしてくれるものです。以下ブログが詳しかったです。

tyoshikawa1106.hatenablog.com

先ほどと同じようにApexのクラス(コントローラ)とVisualforceページを以下のように作成しました。今度は先にビューの定義から

<apex:page controller="SendGridTableController">
    <vs:importvisualstrap />
    <vs:visualstrapblock >
        <vs:pageheader title="SendGridによるメール送信" subtitle="デモ" />
        <apex:form >
            <vs:panel >
                <apex:dataTable value="{!contacts}" var="contact" styleClass="table table-striped table-bordered">
                    <apex:column >
                        <apex:facet name="header">取引先担当責任者名</apex:facet>
                        <apex:outputText >{!contact.name}</apex:outputText>
                    </apex:column>
                    <apex:column >
                        <apex:facet name="header">メールアドレス</apex:facet>
                        <apex:outputText >{!contact.email}</apex:outputText>
                    </apex:column>
                    <apex:column >
                        <apex:commandLink styleClass="btn-sm btn-primary" id="btnSendMail" action="{!sendMail}" value="SendGridでメール送信">
                            <apex:param name="email" value="{!contact.email}"/>
                            <apex:param name="name" value="{!contact.name}"/>
                        </apex:commandLink>
                    </apex:column>
                </apex:dataTable>
            </vs:panel>
        </apex:form>
    </vs:visualstrapblock>
</apex:page>
public class SendGridTableController {
    public List<Contact> listContacts;
    
    public void sendMail() {
        String mailTo = System.currentPageReference().getParameters().get('email');
        String name = System.currentPageReference().getParameters().get('name');
        
        //ホントはここで毎回newしないようにするべき
        SendGrid sendgrid
            = new SendGrid('sendgridのログインID', 'sendgridのログインパスワード');
        
        SendGrid.Email email = new SendGrid.Email();
        email.addTo(mailTo);
        
        email.setFrom('送信元fromのメールアドレス');
        email.setSubject('SalesforceのApexからテスト送信');
        
        List<String> subs = new List<String> {name};
        email.addSubstitution('name', subs);
        
        email.addCategory('Salesforce');
        
        email.setHtml('メールコンテンツ');
        sendgrid.send(email);
    }
    
    public List<Contact> getContacts() {
        if(listContacts == null) {
            listContacts = [SELECT Name, Email FROM Contact];
        }
        return listContacts;
    }
}

上記コードにありますが、差し込み(Substitution)カテゴリなどもちゃんと使えます。

で、画面を開くと以下のように取引先責任者一覧が表示されて、各行にメール送信のボタンが付きます。これで送りたい相手のボタンを押せば送れます。ホントはチェックボックス付けたり、がいいのでしょうけど…。
f:id:kikutaro777:20161212182129p:plain

よく考えたらVisualStrapじゃなくて、Lightningで作ってみればよかったな(^^;このVisualforceページをLightningでみたらどうなるんだろう‥と思って切り替えてみたのですがLightning内から開くとVisualforceページが別ウィンドウで呼ばれるんですね(^^;なるほど。

ちなみに、メールの中身ですが、このApexを利用して、以下のようなレスポンシブメールも送信できました!(上記コード内の「email.setHtml('メールコンテンツ');」の部分を変えて)

PC
f:id:kikutaro777:20161213154615j:plain

モバイル

f:id:kikutaro777:20161213142401p:plain:w250

ホントはこの部分もどのようにやったか書こうと思ったのですが、この辺はまたどこかで別途紹介したいと思います。

ちなみに上のサンプルメールはSendGridのマーケティングキャンペーンに関するものをサンプルとしたのですが、最近リリースされた機能なので是非お試しください。以下関連ブログですー。

sendgrid.kke.co.jp

sendgrid.kke.co.jp

*1:SendGridブースへお越しいただく方は、虎ノ門ヒルズフォーラム5Fなので、プリンスパークタワーへ行かないようご注意ください…