メールで送信する

RayBarcodeを使って生成したバーコードやQRコードを、Salesforceから送信するメールに埋め込む方法を説明します。RayBarcodeではWeb APIを使ってバーコードの画像を生成できますが、生成したバーコードをSalesforceに保存する機能はないため、その部分の開発が必要です。

ここでは、次の2つの方法を説明します。

  • RayBarcodeで生成したバーコードをPDFファイルに埋め込み、そのPDFファイルをメールの添付ファイルとして送信する。
  • RayBarcodeで生成したバーコードをBASE64文字列に変換し、HTMLメールのIMGタグで表示する。バーコード画像はHTMLメールにBASE64文字列として埋め込まれます。

どちらの方法もSalesforce ClassicとLightning Experienceで使用できます。

ここでは、「キャンペーン」の画面に「招待メールを送信」ボタンを追加し、ユーザがそのボタンをクリックしたときにキャンペーンメンバー内の該当者一覧と「メール送信」ボタンを表示します。

キャンペーンメンバーは「状況」が「Received」になっている、先頭100件です。メール送信の上限に達したかどうかなどのエラー処理は含まれていません。

ここでは例を簡単にするため、メールの本文をApexに記述しています。必要に応じて、メールテンプレートに本文を配置し、それを読みだしてください。

メール添付ファイルでのPDFの送信

次のコントローラ(Apexクラス)はQRコードを生成します。Salesforce Classicの場合、「設定 > 開発 > Apexクラス」に次のコントローラを追加します。Lightning Experienceの場合、歯車アイコンをクリックした後「設定 > カスタムコード > Apexクラス」に次のコントローラを追加します。

// AttachmentPDF.cls
public class AttachmentPDF {
    private final CampaignMember campaignmember;
    private String token;
    
    public AttachmentPDF(ApexPages.StandardController stdController) {
        this.campaignmember = (CampaignMember)stdController.getRecord();
    }

    // アクセストークンを更新する初期化処理
    public PageReference initialize() {
        // アクセストークンの更新
        gcbc.GcBarcodeGlobalAccessTokenGenerator.UpdateAccessToken();
        // アクセストークンの取得
        String tokenSettings = gcbc__GcBarcodeSetting__c.getInstance(UserInfo.getUserId()).gcbc__AccessToken__c;
        this.token = tokenSettings;
        return null;
    }
    
    // QRコードを生成するURLの取得
    public String getQRCodeImageURL() {
        String token = gcbc__GcBarcodeSetting__c.getInstance(UserInfo.getUserId()).gcbc__AccessToken__c;
        return 'https://gcbarcode.azurewebsites.net/api/Png/qrcode?Width=198&Height=198&value=' + this.campaignmember.Id + '&token=' + token;
    }                                  
}

次のVisualforceページはPDFを生成します。Visualforceページを作成するには、Salesforce Classicの場合、「設定 > 開発 > Visualforceページ」を表示します。Lightning Experienceの場合、歯車アイコンをクリックした後「設定 > カスタムコード > Visualforceページ」を表示します。または、Salesforceの「開発者コンソール」を使用します。

<!-- attachmentPDF.vfp -->
<apex:page standardController="CampaignMember" extensions="attachmentPDF" renderAs="PDF" applyBodyTag="false" applyHtmlTag="false" showHeader="false" action="{!initialize}">
    <html>
    <head>
    <style>
        @page {
        size: letter;
        @top-center {
        content: "デモ";
        }
        @bottom-center {
        content: "ページ " counter(page) " / " counter(pages);
        }
        }
        .page-break {
        display:block;
        page-break-after:always;
        }
        body {
        font-family: Arial Unicode MS;
        }
    </style>
    </head>
    <body>

    <h1>オレンジ・インテリア オリジナル製品内覧会</h1><br />
    <h2>FN-秋 チャイルド設備 内覧会 参加証</h2>
    <apex:outputText>{!campaignmember.name} 様</apex:outputText>
    <br />
    <p>いつもお世話になっております。</p>
    <p>このたびは、児童福祉施設向け設備の内覧会に、お申し込みいただき、誠にありがとうございます。</p>
    <p>参加証をお送りいたしますので当日は、本ページを印刷するかスマートフォンなどで表示し、</p>
    <p>お名刺1枚と合わせて受付にお渡しください。</p>
    <p>それでは当日お会いできるのを楽しみにしております。</p>
    <p>開催日:2017年10月25日(水) 10:00 ~ 17:00 (受付開始:9:30)</p>
    <p>会場:東京都千代田区000-00 TOKYO ANOTHER SKYビルXXF</p>
    
    <apex:image url="{!QRCodeImageURL}" />
    
    <br />
    <br />
    <p>お問い合わせ先</p>
    <p>オレンジ・シティ株式会社 内覧会事務局</p>
    <p>メール:contact@orange.int.com</p>
    <p>電話:03-1111-1111</p>

    </body>
    </html>
</apex:page>

次のコントローラはPDFファイルを添付したメールを送信します。Salesforce Classicの場合、「設定 > 開発 > Apexクラス」に次のコントローラを追加します。Lightning Experienceの場合、歯車アイコンをクリックした後「設定 > カスタムコード > Apexクラス」に次のコントローラを追加します。

// SendInvitationByEmailAttachment.cls
public with sharing class SendInvitationByEmailAttachment {
    public List<CampaignMember> cMember {get;private set;}
    private final Campaign campaign;
    private Integer count = 0;
    
    public SendInvitationByEmailAttachment(ApexPages.StandardController stdController) 
    {
        this.campaign = (Campaign)stdController.getRecord();
        if(!Schema.CampaignMember.getSObjectType().getDescribe().isAccessible()){
            this.cMember = null;
            return;
        }
        if (null != this.campaign) {
            ID id = this.campaign.Id;
            this.cMember = [SELECT ID, Name, Lead.Email, Status, CampaignID From CampaignMember WHERE CampaignID = :id and Status = 'Received' limit 100];
        }
        else {
            this.cMember = null;
        }
    }

    // 参考:メールテンプレートの読み出し
    public string getEmailTemplate() {
        if (!Schema.EmailTemplate.getSObjectType().getDescribe().isAccessible()){
            return null;
        }
        string result = '';
        Id templateId = '(メールテンプレートのID)';
        EmailTemplate[] content = [SELECT ID, Name, Subject, Body, HtmlValue, Description FROM EmailTemplate WHERE ID = :templateId LIMIT 1];
        if (content.size() > 0) {
            result = content[0].Subject + ',' + content[0].Body;
        }
        return result;
    }

    public string getResult() {
        return '結果: ' + count.format() + '件を送信。';
    }

    // PDFファイルをプレビュー表示する。プレビューではデータは差し込まれない。
    public PageReference preview() {
         PageReference pdfPage = Page.attachmentPDF;
         return pdfPage;
    }

    // メールを送信する
    public PageReference send() {
        if (null == this.campaign) { return null; };
        
        String subject = 'FN-秋 チャイルド設備 内覧会 参加証の送付';
        count = 0;
        
        for (CampaignMember m : this.cMember) {
            PageReference pdf = Page.attachmentPDF;
            pdf.getParameters().put('id',(String)m.id);
            pdf.setRedirect(true);
            
            // PDFを取得する
            Blob b = pdf.getContent();
            
            // メールの添付ファイルを作成する
            Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
            efa.setFileName('attachment.pdf');
            efa.setBody(b);
            
            // メールの本文を作成する
            String body = m.Name + ' 様\r\n\r\nいつもお世話になっております。\r\n\r\nこのたびは、児童福祉施設向け設備の内覧会に、お申し込みいただき、誠にありがとうございます。参加証をお送りいたしますので当日は、本ページを印刷するかスマートフォンなどで表示し、お名刺1枚と合わせて受付にお渡しください。それでは当日お会いできるのを楽しみにしております。\r\n\r\n\r\nお問い合わせ先\r\nオレンジ・シティ株式会社 内覧会事務局\r\nメール:contact@orange.int.com\r\n電話:03-1111-1111';
            
            // メールの宛先を設定する
            String[] toAddresses = new String[1];
            toAddresses[0] = m.Email;
            Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();

            // メールの件名を設定する 
            email.setSubject(subject);
            email.setToAddresses(toAddresses);
            email.setPlainTextBody(body);
            email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});
            // 参考:email.setTemplateIdは使用できません
            
            // メールを送信する
            Messaging.SendEmailResult [] r = 
                Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});
            count += 1; 
        }
        return null;
    }
}

次のVisualforceページは、メールの送付先の一覧と送信ボタンを表示します。Visualforceページを作成するには、Salesforce Classicの場合、「設定 > 開発 > Visualforceページ」を表示します。Lightning Experienceの場合、歯車アイコンをクリックした後「設定 > カスタムコード > Visualforceページ」を表示します。または、Salesforceの「開発者コンソール」を使用します。

<!-- SendEmailAttachmentButtonsPage.vfp -->
<apex:page standardController="Campaign" extensions="SendInvitationByEmailAttachment">
    <apex:pageBlock title="PDF添付による参加証送付">
        <apex:pageBlockTable value="{!cMember}" var="member">
            <apex:column headerValue="名前 " value="{!member.Name}" />
            <apex:column headerValue="メール" value="{!member.Email}" />
            <apex:column headerValue="状況" value="{!member.Status}" />
        </apex:pageBlockTable>
        <apex:form>
            <br/>
            <br/>
            <apex:commandButton value="メールを送信(PDF添付)" action="{!send}"/> 
            <apex:commandButton value="PDFのプレビュー" action="{!preview}" /> 
        </apex:form>
    </apex:pageBlock>
    <apex:outputPanel id="sendResult" layout="block">
        {!Result}
    </apex:outputPanel>
</apex:page>

ApexクラスとVisualforceページを追加したら、カスタムボタンを作成してページレイアウトに配置します。

  1. Salesforce Classicに切り替える。
  2. 「設定 > ビルド > カスタマイズ > キャンペーン > ボタン、リンク、およびアクション」を表示する。
  3. 「新規ボタンまたはリンク」をクリックする。
  4. 内容のソースに「Visualforceページ」を選択する。
  5. 「コンテンツ」に「SendEmailAttachmentButtonsPage」を選択する。
  6. 「表示ラベル」に「PDF招待メール送信」、「名前」に「PdfEmailSend」を入力して「保存」をクリックする。

次にページレイアウトにボタンを配置します。

  1. 「設定 > ビルド > カスタマイズ > キャンペーン > ページレイアウト」を表示する。
  2. ボタンを配置したいページレイアウトの「編集」をクリックする。
  3. 上部の画面から「ボタン」をクリックし、「PDF招待メール送信」をページレイアウトにドラッグして配置する。
  4. 「保存」をクリックする。

コードを試すには、次の手順を実行します。

  1. Salesforceで「キャンペーン」を開き、新規にキャンペーンを追加する。
  2. 作成したキャンペーンに状況を「Received」でキャンペーンメンバーを追加する。
  3. 再度キャンペーンを開き、「PDF招待メール送信」ボタンをクリックする。
  4. 「PDF添付による参加証送付」画面で宛先を確認し、「メール送信(PDF添付)」をクリックする。

メールが正しく送信されたかどうかを確認するには、自分あてにもメールを送付するか、またはSalesforceの「設定 > 監視 > ログ > メールログファイル」を確認してください。

HTMLメールのIMGタグへの埋め込み

HTMLには IMG タグを使用して画像ファイルの場所を指定すると、その画像ファイルをHTMLに表示できます。Data URI schemeを使うと、画像ファイルの場所の代わりに、画像ファイルの内容を文字列としてHTMLに埋め込むことができます。ファイルの管理や参照が不要になるので、手軽に扱えるようになります。 一方、デメリットもあります。まず画像ファイルの内容はバイナリ形式のため、これを文字列形式に変換する必要があります。この変換の結果、データ量が3~4割ほど増えます。

ここでは、RayBarcodeで生成したバーコード画像をBASE64文字列に変換してSalesforceのオブジェクトのカスタム項目に格納します。カスタム項目の値はメールに差し込むことができるので、 IMG タグに適切な書式で差し込むことでバーコード画像をHTMLメールに埋め込んで表示できます。

<img src="data:image/png;base64,' + m.QRcodeText__c + '" />

まず、キャンペーンメンバーにQRコードの画像をBASE64に変換した文字列を格納するためのカスタム項目を作成します。

Salesforce Classicの場合:

  1. 「設定 > ビルド > カスタマイズ > キャンペーン > キャンペーンメンバー」を表示する。
  2. 「項目」をクリックする。
  3. 「新規」をクリックする。
  4. 「カスタム項目の新規作成」で「ロングテキストエリア」をオンにして「次へ」をクリックする。
  5. 「項目の表示ラベル」に半角英数で「QRcodeText」と入力する。
  6. 「項目名」に半角英数で、おなじく「QRcodeText」と入力する。
  7. 「次へ」をクリックする。
  8. 「ステップ 3. 項目レベルセキュリティの設定」で「次へ」をクリックする。
  9. 「ステップ 4. ページレイアウトへの追加」で「保存」をクリックする。

Lightning Experienceの場合:

  1. 「設定 > オブジェクトマネージャ > キャンペーンメンバー」を表示する。
  2. 「項目とリレーション」をクリックする。
  3. 「新規」をクリックする。
  4. 「カスタム項目の新規作成」で「ロングテキストエリア」をオンにして「次へ」をクリックする。
  5. 「項目の表示ラベル」に半角英数で「QRcodeText」と入力する。
  6. 「項目名」に半角英数で、おなじく「QRcodeText」と入力する。
  7. 「次へ」をクリックする。
  8. 「ステップ 3. 項目レベルセキュリティの設定」で「次へ」をクリックする。
  9. 「ステップ 4. ページレイアウトへの追加」で「保存」をクリックする。

次にApexクラスを追加します。Salesforce Classicの場合、「設定 > 開発 > Apexクラス」に次のコントローラを追加します。Lightning Experienceの場合、歯車アイコンをクリックした後「設定 > カスタムコード > Apexクラス」に次のコントローラを追加します。

// SendInvitationByHtmlEmail.cls
public with sharing class SendInvitationByHtmlEmail {
    public List<CampaignMember> cMember {get;private set;}
    private final Campaign campaign;
    private Integer count = 0;
    private Integer errors = 0;
    private String token;
    
    public SendInvitationByHtmlEmail(ApexPages.StandardController stdController) 
    {
        if(!Schema.CampaignMember.getSObjectType().getDescribe().isAccessible()){
            this.cMember = null;
            return;
        }
        this.campaign = (Campaign)stdController.getRecord();
        if (null != this.campaign) {
            ID id = this.campaign.Id;
            this.cMember = [SELECT ID, Name, Lead.Email, Status, CampaignID, QRcodeText__c From CampaignMember WHERE CampaignID = :id and Status = 'Received' limit 100];
        }
        else {
            this.cMember = null;
        }
    }

    public PageReference initialize() {
        gcbc.GcBarcodeGlobalAccessTokenGenerator.UpdateAccessToken();
        String tokenSettings = gcbc__GcBarcodeSetting__c.getInstance(UserInfo.getUserId()).gcbc__AccessToken__c;
        this.token = tokenSettings;
        return null;
    }

    public static String getQRCodeBase64(String url) {
        HttpRequest req = new HttpRequest();
        req.setEndpoint(url);
        req.setMethod('GET');
        Http binding = new Http();
        HttpResponse res = binding.send(req);
        Blob image = res.getBodyAsBlob();
        return EncodingUtil.base64Encode(image);
    }
    
    public PageReference sendHTML() {
        if (null == this.campaign) { return null; };

        String subject = 'FN-秋 チャイルド設備 内覧会 参加証の送付';
        count = 0;
        errors = 0;
        
        for (CampaignMember m : this.cMember) {
            // QRコードが生成されていない場合、次のレコードを処理する
            if (String.isEmpty(m.QRcodeText__c)) {
                errors += 1;
                continue;
            }

            String body = '<h1>オレンジ・インテリア オリジナル製品内覧会</h1><h2>FN-秋 チャイルド設備 内覧会 参加証</h2><p>' + m.Name+ ' 様</p><p>いつもお世話になっております。</p></br><p>このたびは、児童福祉施設向け設備の内覧会に、お申し込みいただき、誠にありがとうございます。参加証をお送りいたしますので当日は、本ページを印刷するかスマートフォンなどで表示し、お名刺1枚と合わせて受付にお渡しください。それでは当日お会いできるのを楽しみにしております。</p></br><p>開催日:2017年10月25日(水) 10:00 ~ 17:00 (受付開始:9:30)</p><p>会場:東京都千代田区000-00 TOKYO ANOTHER SKYビルXXF</p><img src="data:image/png;base64,' + m.QRcodeText__c + '" /></br></br><p>お問い合わせ先</p><p>オレンジ・シティ株式会社 内覧会事務局</p><p>メール:contact@orange.int.com</p><p>電話:03-1111-1111</p>';            
            
            // メールの宛先を設定する
            String[] toAddresses = new String[1];
            toAddresses[0] = m.Email;
            Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); 
            email.setSubject(subject);
            email.setToAddresses(toAddresses);
            email.setHtmlBody(body);
            
            // メールを送信する
            Messaging.SendEmailResult [] r = 
                Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});
            count += 1;
        }
        
        return null;
    }

    public string getResult() {
        return '結果: ' + count.format() + '件を送信。' + errors.format() + '件のエラー。';
    }

    public PageReference generateQRCode() 
    {
        if (null == this.campaign) { return null; };

        Map<Id, String> barcodes = new Map<Id, String>();
        for (CampaignMember m : this.cMember) {
           String url = 'https://gcbarcode.azurewebsites.net/api/Png/qrcode?Width=198&Height=198&value='
                + m.Id + '&token=' + this.token;
            String b = SendInvitationByHtmlEmail.getQRCodeBase64(url);
            m.QRcodeText__c = b;
        }
        update this.cMember;

        return null;
    }
}

次のVisualforceページは、メールの送付先の一覧と送信ボタンを表示します。Visualforceページを作成するには、Salesforce Classicの場合、「設定 > 開発 > Visualforceページ」を表示します。Lightning Experienceの場合、歯車アイコンをクリックした後「設定 > カスタムコード > Visualforceページ」を表示します。または、Salesforceの「開発者コンソール」を使用します。

<!-- SendHtmlEmailButtonsPage.vfp -->
<apex:page standardController="Campaign" extensions="SendInvitationByHtmlEmail" action="{!initialize}">
    <apex:pageBlock title="HTMLメールによる参加証送付">
        <apex:pageBlockTable value="{!cMember}" var="member">
            <apex:column headerValue="名前 " value="{!member.Name}" />
            <apex:column headerValue="メール" value="{!member.Email}" />
            <apex:column headerValue="状況" value="{!member.Status}" />
        </apex:pageBlockTable>
        <apex:form ><br/><br/>
            <apex:commandButton value="1. QRコード生成" action="{!generateQRCode}" />
            <apex:commandButton value="2. メール送信(HTML埋込)" action="{!sendHTML}" />
        </apex:form>
    </apex:pageBlock>
    <apex:outputPanel id="sendResult" layout="block">
        {!Result}
    </apex:outputPanel>
</apex:page>

ApexクラスとVisualforceページを追加したら、カスタムボタンを作成してページレイアウトに配置します。

  1. Salesforce Classicに切り替える。
  2. 「設定 > ビルド > カスタマイズ > キャンペーン > ボタン、リンク、およびアクション」を表示する。
  3. 「新規ボタンまたはリンク」をクリックする。
  4. 内容のソースに「Visualforceページ」を選択する。
  5. 「コンテンツ」に「SendHtmlEmailButtonsPage」を選択する。
  6. 「表示ラベル」に「HTML招待メール送信」、「名前」に「HtmlEmailSend」を入力して「保存」をクリックする。

次にページレイアウトにボタンを配置します。

  1. 「設定 > ビルド > カスタマイズ > キャンペーン > ページレイアウト」を表示する。
  2. ボタンを配置したいページレイアウトの「編集」をクリックする。
  3. 上部の画面から「ボタン」をクリックし、「HTML招待メール送信」をページレイアウトにドラッグして配置する。
  4. 「保存」をクリックする。

コードを試すには、次の手順を実行します。

  1. Salesforceで「キャンペーン」を開き、新規にキャンペーンを追加する。
  2. 作成したキャンペーンに状況を「Received」でキャンペーンメンバーを追加する。
  3. 再度キャンペーンを開き、「HTML招待メール送信」ボタンをクリックする。
  4. 「HTMLメールによる参加証送付」画面で宛先を確認し、「1. QRコード生成」ボタンをクリックする。
  5. 「2. メール送信(HTML埋込)」ボタンをクリックする。

メールが正しく送信されたかどうかを確認するには、自分のメールアドレス宛にもメールを送信するか、またはSalesforceのメールログファイルを確認してください。メールログファイルの場所は、Salesforce Classicの場合は「設定 > 監視 > ログ > メールログファイル」、Lightning Experienceの場合は「設定 > 環境 > ログ > メールログファイル」です。

Copyright © 2018 GrapeCity inc. All rights reserved.