- 調査・研究
Salesforceのメールサービス機能を利用して問合わせメールを管理
「最近、問い合わせメールが沢山届くようになったけど、届いたままで管理がてきてない」
という問題をSalesforceで解決するのが『メールサービス』です。
例えば、メールサービスを利用して、受信したメールをリードオブジェクトに自動取込させることでリードの管理・分析に役立ちます。
※今後のSalesforceのバージョンアップにより、異なる箇所があるかもしれませんので、記事の投稿日を確認いただき、最新リファレンスなども併せてご確認ください。
投稿時のver : Salesforce summer ’17
メールサービスとは?
「メールサービスは、Apex クラスを使用して受信メールを処理する自動化されたプロセスです。」
出典(Salesforce Help&Training、メールサービスとは?、https://help.salesforce.com/articleView?id=code_email_services_overview.htm&language=ja&type=0、最終閲覧2018/1/18)
つまりメールを受信したときにApexクラスが起動され、受信メールの内容、ヘッダーおよび添付ファイルに対しての処理を自動で実行することができます。
今回実装した仕様
今回実装した仕様を簡単に説明します。
#前提
・A社はホテルブランドを展開しているホテル会社。
・複数の旅行予約サイトに、A社のホテルを掲載してもらっている。
・ユーザが旅行予約サイト宛てに問合せた内容のメールを、旅行予約サイトからA社のSalesforceへ転送(以下、「問い合わせメール」と呼ぶ)。
#仕様
・A社のSalesforceで、問い合わせメールの内容からリードを自動生成するメールサービスを作成する。
・問い合わせメールからは「氏名」「電話番号」「メールアドレス」の値を抽出して、リードオブジェクトに登録する。
◆◇◆◇◆問い合わせメールサンプル◆◇◆◇◆◇
【顧客情報】
氏名(漢字) : インフォ 太郎
氏名(カナ) : インフォ タロウ
郵便番号 : 123-0000
住所 : 東京都新宿区西新宿7-5-25
メールアドレス : t.info@sample.co.jp
電話番号 : 080-0000-0000
問合内容 : ホテル周辺に飲食店はありますか?
◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇
実装のイメージ
(画像をクリックすると拡大します)
どうやって実現するか
● メール本文を解析し値を抽出
今回のメール本文はテンプレート化されていて、「氏名(漢字): インフォ 太郎」 のように、項目名の隣に項目値があります。
処理の流れは以下のとおりです。
- メール本文を一行一行解析していき、「氏名(漢字) :」「電話番号 :」「メールアドレス : 」のキーワードとなる文言を見つけます。
- キーワードが入っている行から、キーワード以降の文字列を抽出します。
- 全文解析が終了したあと、抽出した項目からリードレコード用のデータを登録します。
● 開発
メールサービス機能を利用するにはApexを作成する必要があります。
今回のApexは、メールサービスから起動されリードレコードに登録するコントローラ用クラスと、メール解析するクラスの2種類のApexを作成します。
また、キーワードの定義には、カスタム設定を使います。
カスタム設定を使うことで、キーワードをApexに直書きやカスタムオブジェクトで管理することなく、簡単な設定情報を保存するのに有用です。
- カスタム設定の作成(キーワードを定義します)
- メール解析用Apexの作成
- コントローラ用Apexの作成
- メールサービスの設定
以上の手順で開発します。
カスタム設定の作成
カスタム設定とは?
組織全体で使うような定数を定義できます。
ガバナ制限の対象となる SOQL クエリを使用する必要はなく、ApexやVisualforceで参照できます。
カスタム設定については Salesforce Developersサイトの「 Apexガイド カスタム設定ページ」をご確認ください。
手順
手順① カスタム設定の定義(Salesforce画面のメニューから 設定 > 開発 > カスタム設定 > 新規ボタン)
「表示ラベル」:任意
「オブジェクト名」:任意
「設定種別」:”リスト”
「表示」:”公開”
手順② カスタム項目の定義
(作成したカスタム設定選択 > カスタム項目の新規ボタン)
「データ型の選択」:”テキスト”
「項目の表示ラベル」:任意
「項目名」:任意
「文字数」:任意
手順③ カスタム項目の設定
(作成したカスタム設定 > Manageボタン > 新規ボタン)
「Name」:”テキスト”
「キーワード_メール」:メール文解析用のキーワードを設定
「キーワード_氏名」:メール文解析用のキーワードを設定
「キーワード_電話」:メール文解析用のキーワードを設定
「会社名」:任意
「媒体」:任意
Apexコードのサンプル
まず、メール解析用クラスから作成します。
なお、リードレコードの登録はコントローラ用クラスで処理しています。
リードオブジェクト以外の登録処理も、insert部分だけを修正するだけでOKです。
■注意点
オブジェクトに登録する際、「氏名」など必須項目が空白にならないようにしてください。Apexがエラーになってしまいます。 例えば、メール解析で抽出に失敗してしまった時など、「氏名」が空白の状態になる可能性があります。失敗時も空白にならないように処理してあげる必要があります。
メール解析用Apex
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
public class AnalysisMailbody { public Boolean throwInvalidField = false; //これをtrueにすると項目の変換に失敗した場合でも例外を投げる private String objectName; public class FieldInfo{ public String name{ get; set; } public DisplayType type{ get; set; } } private Map<String, FieldInfo> fieldMap; public AnalysisMailbody(String objectName){ this.objectName = objectName; this.fieldMap = getFieldMap(); } public SObject MailBodyToSObject( List<String> fieldNames , List<String> keywords , String body , String media , String company){ SObject resultSObject = createDefaultSObject(); List<String> rows = body.split('\n'); integer i = 0; for(String n : fieldNames){ FieldInfo f = fieldMap.get(n); if(f != null){ String keyword = keywords.get(i); //キーワード整形(半角スペース・全角スペース・タブ除去) keyword = keyword.replaceAll(' ', ''); //半角スペース除去 keyword = keyword.replaceAll(' ', ''); //全角スペース除去 keyword = keyword.replaceAll(' ', ''); //タブ除去 String resultWord; integer j = 0; //キーワード設定 String REG_KEYWORD = '^' + keyword; Pattern PTN_KEYWORD = Pattern.compile(REG_KEYWORD); //メール本文解析 for( ; j < rows.size() ; j++){ //検索対象文字列整形(半角スペース・全角スペース・タブ除去) String targetWord = rows.get(j); targetWord = targetWord.replaceAll(' ', ''); //半角スペース除去 targetWord = targetWord.replaceAll(' ', ''); //全角スペース除去 targetWord = targetWord.replaceAll(' ', ''); //タブ除去 Matcher m = PTN_KEYWORD.matcher(targetWord); if( m.find() ){ //キーワード一致:項目値取得(キーワード以降の文字列を取得) resultWord = targetWord.replaceAll(keyword, ''); break; } } //「氏名」(必須項目)が取得できなかった場合 if(f.name == 'LastName' && String.isBlank(resultWord)){ resultWord = '未設定'; //'未記入'を設定する } //(注意)チェックボックス型の項目を明示的にNull指定すると更新時に例外が発生するので設定しないようにする if(resultWord != null || f.type != DisplayType.Boolean){ resultSObject.put( f.name , resultWord); } i++; } } //「媒体」 resultSObject.put(Lead.Media__c.getDescribe().getName(), media); //「メール本文」 resultSObject.put(Lead.MailBody__c.getDescribe().getName(), body); //「会社」 resultSObject.put(Lead.Company.getDescribe().getName(), company); return resultSObject; } private Map<String, FieldInfo> getFieldMap(){ List<SObjectField> fieldList = Schema.getGlobalDescribe().get(objectName).getDescribe().fields.getMap().values(); Map<String, FieldInfo> resultMap = new Map<String, FieldInfo>(); for( SObjectField s : fieldList){ DescribeFieldResult fResult = s.getDescribe(); FieldInfo info = new FieldInfo(); info.name = fResult.getName(); info.type = fResult.getType(); resultMap.put( fResult.getName() , info ); } return resultMap; } private SObject createDefaultSObject(){ return Schema.getGlobalDescribe().get(objectName).newSObject() ; } } |
コントローラ用Apex
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
global class MailServiceToLead implements Messaging.InboundEmailHandler { global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope) { Messaging.InboundEmailResult result = new Messaging.InboundEmailresult(); result.success = true; //メール情報取得 String mail_body = email.plainTextBody; //メール本文 String mail_address = email.fromAddress; //メールアドレスd //カスタム設定「媒体メール振り分け」読込 Map<String, MediamailsSort__c> settingMap = MediamailsSort__c.getAll(); MediamailsSort__c mediamail = settingMap.get(mail_address); //メール本文に記載される想定の項目 List<String> PARSE_FIELD = new List<String>{ Lead.LastName.getDescribe().getName() , //氏名 Lead.Phone.getDescribe().getName(), //電話番号 Lead.Email.getDescribe().getName() //メールアドレス }; //メール本文に記載される想定のキーワード List<String> KEYWORD_FIELD = new List<String>{ mediamail.KW_Name__c, //氏名 mediamail.KW_Tel__c, //電話番号 mediamail.KW_Mail__c //メールアドレス }; //媒体情報 String media = mediamail.Media__c; //会社情報 String company = mediamail.Company__c; try{ Lead l; AnalysisMailbody converter = new AnalysisMailbody('Lead'); //メール本文を解析してリードオブジェクトのインスタンスを生成 l = (Lead)converter.MailBodyToSObject( PARSE_FIELD , KEYWORD_FIELD , mail_body , media , company); insert l; }catch(Exception e){ //何かしら例外発生時の通知文面 //受信したメールの「reply-to」に指定したアドレスに対して送信される(未指定の場合はfrom) result.message = 'メールサービス処理でエラーが発生しました。\n'; result.message += '\n'; result.message += '【元メール】\n'; result.message += mail_body ; result.message += '\n'; result.message += '【エラーメッセージ】\n'; result.message += e.getMessage(); result.success = false; } return result; } } |
メールサービスの設定
●手順
手順① メールサービスの定義
(設定 > 開発 > メールサービス > 新規メールサービスボタン)
「メールサービス名」:任意
「Apexクラス」:起動させるApexを指定(今回は、作成したコントローラ用クラスを指定)
「有効」:チェックつける
その他の設定:任意(今回はデフォルト)
手順② メールアドレスの発行
(手順①で定義したメールサービス > 新規メールアドレスボタン)
「メールアドレス」:任意(@前のアドレスを定義します)
「有効」:チェックつける
「コンテキストユーザ」:Apexの実行ユーザを設定(※今回は管理者権限があるユーザを指定)
「許可する送信元」:任意(送信元を制限する場合に指定。空欄の場合すべて許可になる)
■注意点
「コンテキストユーザ」に設定するユーザに、オブジェクト(今回はリードオブジェクト)を更新する権限がないと、オブジェクト登録のApexがエラーになります。
権限があるユーザを設定するようにします。
(画像をクリックすると拡大します)
手順③ 設定完了
発行されたメールアドレスを確認
有効になっていることを確認
(画像をクリックすると拡大します)
テスト
① カスタム設定の定義
まずは、カスタム設定で定義した「媒体メール振り分け」にキーワードの文言を設定します。
(画像をクリックすると拡大します)
② メール送信
送信先メールアドレスには、メールサービス設定時に発行されたアドレスを指定し、以下のメール本文を送信します。
(画像をクリックすると拡大します)
③ リードオブジェクトに登録
送信が完了するとリードオブジェクトにレコードが登録されました。
(画像をクリックすると拡大します)
リードオブジェクトの「名前」「電話」「メール」に、受信したメール本文から抽出したデータが登録されています。
「メール本文」には受信メール本文が、「会社名」「媒体」はカスタム設定で指定したデータが登録されています。
(画像をクリックすると拡大します)
一見難しいと思うかもしれませんが、作業自体は簡単です。
注意点
注意点として、メールサービスにもガバナ制限があります。
メールサービス: Salesforce で処理する 1 日あたりのメールメッセージの最大数
⇒ユーザライセンス数 × 1,000、最大数 1,000,000(2018年1月時点)
1日分の処理なら十分な数だと思いますが、
もし大量のメールを処理する必要がある場合は、ガバナ制限に注意が必要です。
最後に
外部からのメールを扱う場合に非常に便利だったメールサービス機能を紹介しました。メールサービス機能を活用することで、問い合わせメールといった外部からのメール内容をSaleforceのオブジェクトに簡単に取り込むことができます。今回のようにメール解析のアルゴリズムに工夫が必要ですが、比較的シンプルな構成で実装できたと感じています。
次々と新しいサービスが展開されているSalesforceです。新しいサービスではありませんが、メールを扱う要件の場合は文字通り「メールサービス」をオススメします。