
Twilio SendGrid: 宛先追加/更新(カスタムフィールド)
Twilio SendGrid: Add or Update Contact (Custom Fields)
この工程は、SendGrid の宛先を追加または更新し、指定したカスタムフィールドに値を設定します。指定したメールアドレスの宛先がすでにある場合、その宛先が更新されます。
Basic Configs
- 工程名
- メモ
Configs for this Auto Step
- conf_Auth
- C1: API キーをトークンとして設定した認証設定 *
- conf_Email
- C2: メールアドレス *
- conf_FieldName1
- C3F: カスタムフィールド名_1
- conf_FieldValue1
- C3V: 値_1
- conf_FieldName2
- C4F: カスタムフィールド名_2
- conf_FieldValue2
- C4V: 値_2
- conf_FieldName3
- C5F: カスタムフィールド名_3
- conf_FieldValue3
- C5V: 値_3
- conf_FieldName4
- C6F: カスタムフィールド名_4
- conf_FieldValue4
- C6V: 値_4
- conf_FieldName5
- C7F: カスタムフィールド名_5
- conf_FieldValue5
- C7V: 値_5
- conf_FieldName6
- C8F: カスタムフィールド名_6
- conf_FieldValue6
- C8V: 値_6
- conf_FieldName7
- C9F: カスタムフィールド名_7
- conf_FieldValue7
- C9V: 値_7
- conf_FieldName8
- C10F: カスタムフィールド名_8
- conf_FieldValue8
- C10V: 値_8
Notes
- sendgrid.com が対象の自動工程です
- sendgrid.kke.co.jp は対象外です
- API キーの作成方法については、SendGrid のドキュメントを参照してください
- Restricted Access を選択する場合、Marketing の権限をオンにする必要があります


- カスタムフィールドの使用方法については、SendGrid のドキュメントを参照してください
- カスタムフィールドの値として指定するデータ項目の型は、カスタムフィールドの型と一致させる必要があります
カスタムフィールドの型 | データ項目の型 |
Text | 文字 (単一行) |
Number | 数値 |
Date | 日付 (年月日) |
Capture

See Also
Script (click to open)
- 次のスクリプトが記述されている XML ファイルをダウンロードできます
- sendgrid-contact-upsert-custom-fields.xml (C) Questetra, Inc. (MIT License)
- Professional のワークフロー基盤では、ファイル内容を改変しオリジナルのアドオン自動工程として活用できます
const FIELD_NUM = 8; // 扱えるフィールドの数
const MAX_EMAIL_LENGTH = 254;
const MAX_FIELD_VALUE_LENGTH = 1000;
function main(){
//// == Config Retrieving / 工程コンフィグの参照 ==
const auth = configs.get('conf_Auth');
const email = retrieveEmail();
const customFieldMap = retrieveCustomFieldsAsMap();
//// == Calculating / 演算 ==
const contact = {email};
if (customFieldMap.size > 0) {
const allCustomFields = getAllCustomFields(auth);
setCustomFields(contact, customFieldMap, allCustomFields);
}
const jobId = upsertContact(auth, contact);
// 処理状況を確認し、未完了なら proceed() に進む
if (checkStatus(auth, jobId) === false) {
engine.saveTemporaryData(jobId);
return false;
}
}
function proceed() {
//// == Config Retrieving / 工程コンフィグの参照 ==
const auth = configs.get('conf_Auth');
//// == Restoring Temporary Data / 一時データの読み出し ==
const jobId = engine.restoreTemporaryData();
if (jobId === null) {
throw 'Temporary data has not been saved.';
}
//// == 演算 / Calculating ==
if (checkStatus(auth, jobId) === false) {
return false;
}
}
/**
* config に設定されたメールアドレスを読み出す
* @return {String} email
*/
function retrieveEmail() {
const emailDef = configs.getObject('conf_Email');
const email = engine.findData(emailDef);
if (email === null) {
throw 'Email Address is blank.';
}
if (email.length > MAX_EMAIL_LENGTH) {
throw `Email Address must be within ${MAX_EMAIL_LENGTH} characters.`;
}
return email;
}
/**
* config に設定されたカスタムフィールドの情報を読み出す
* Map のキーはフィールド名、値はデータ定義
* @return {Map<String, DataDefinitionView>} customFieldMap
*/
function retrieveCustomFieldsAsMap() {
const customFieldMap = new Map();
for (let i = 0; i < FIELD_NUM; i++) {
const fieldName = configs.get(`conf_FieldName${i + 1}`);
const fieldValueDef = configs.getObject(`conf_FieldValue${i + 1}`);
if (fieldName === '' || fieldName === null) {
if (fieldValueDef !== null) { // フィールド名が空なのに、値のデータ項目が選択されている場合
throw `Custom Field Name ${i + 1} is blank while its value is selected.`;
}
continue;
}
if (customFieldMap.has(fieldName)) { // フィールド名の指定が重複
throw `Custom Field Name "${fieldName}" is set multiple times.`;
}
if (fieldValueDef === null) { // フィールド名は設定されているのに、値のデータ項目が選択されてない場合
// 「SendGrid: 宛先追加/更新」と仕様を合わせるため、null をセットせずにエラーにする
throw `Value ${i + 1} is not selected while its field name is set.`;
}
const dataObj = engine.findData(fieldValueDef);
// 文字型データを想定した文字数チェック。数値型、日付型データ以外が文字数制限に引っかかることはありえない
if (dataObj !== null && dataObj.toString().length > MAX_FIELD_VALUE_LENGTH) {
throw `Custom Field Value of "${fieldName}" must be within ${MAX_FIELD_VALUE_LENGTH} characters.`;
}
customFieldMap.set(fieldName, fieldValueDef);
}
return customFieldMap;
}
/**
* 全カスタムフィールドの一覧を取得する
* @param {String} auth 認証設定名
* @return {Array<Object>} allCustomFields
*/
function getAllCustomFields(auth) {
const response = httpClient.begin()
.authSetting(auth)
.get('https://api.sendgrid.com/v3/marketing/field_definitions');
const status = response.getStatusCode();
const responseStr = response.getResponseAsString();
if (status !== 200) {
engine.log(responseStr);
throw `Failed to get field definitions. status: ${status}`;
}
return JSON.parse(responseStr).custom_fields;
}
/**
* 宛先オブジェクトにカスタムフィールドの情報を追加する
* @param {Object} contact 宛先オブジェクト
* @param {Map<String, DataDefinitionView>} customFieldMap カスタムフィールドの Map
* @param {Array<Object>} allCustomFields 全カスタムフィールドの一覧
*/
function setCustomFields(contact, customFieldMap, allCustomFields) {
const customFields = {};
customFieldMap.forEach((dataDef, fieldName) => {
const customField = allCustomFields.find(field => field.name === fieldName);
if (customField === undefined) { // 指定したフィールド名のカスタムフィールドがない場合
throw `Custom Field named "${fieldName}" does not exist.`;
}
switch (customField.field_type) {
case 'Text':
addTextField(customFields, customField.id, customField.name, dataDef);
break;
case 'Number':
addNumberField(customFields, customField.id, customField.name, dataDef);
break;
case 'Date':
addDateField(customFields, customField.id, customField.name, dataDef);
break;
default:
// ありえないが、念のため
throw `Custom Field type "${customField.field_type}" is not supported.`;
}
});
Object.assign(contact, {custom_fields: customFields});
}
/**
* 文字型カスタムフィールドの情報を追加する
* @param {Object} customFields 設定するカスタムフィールド一覧
* @param {String} customFieldId カスタムフィールドの ID
* @param {String} customFieldName カスタムフィールドの名前(エラー出力用)
* @param {DataDefinitionView} dataDef データ定義
*/
function addTextField(customFields, customFieldId, customFieldName, dataDef) {
if (!dataDef.matchDataType('STRING_TEXTFIELD')) {
throw `Custom Field "${customFieldName}" is Text type. Its value must be set by STRING_TEXTFIELD type data item.`;
}
const dataObj = engine.findData(dataDef); // String or null
const fieldValue = dataObj ?? ''; // String
Object.assign(customFields, {[customFieldId]: fieldValue});
}
/**
* 数値型カスタムフィールドの情報を追加する
* @param {Object} customFields 設定するカスタムフィールド一覧
* @param {String} customFieldId カスタムフィールドの ID
* @param {String} customFieldName カスタムフィールドの名前(エラー出力用)
* @param {DataDefinitionView} dataDef データ定義
*/
function addNumberField(customFields, customFieldId, customFieldName, dataDef) {
if (!dataDef.matchDataType('DECIMAL')) {
throw `Custom Field "${customFieldName}" is Number type. Its value must be set by DECIMAL type data item.`;
}
const dataObj = engine.findData(dataDef); // BigDecimal or null
let fieldValue = '';
if (dataObj !== null) {
fieldValue = dataObj.doubleValue();
}
Object.assign(customFields, {[customFieldId]: fieldValue});
}
/**
* 日付型カスタムフィールドの情報を追加する
* @param {Object} customFields 設定するカスタムフィールド一覧
* @param {String} customFieldId カスタムフィールドの ID
* @param {String} customFieldName カスタムフィールドの名前(エラー出力用)
* @param {DataDefinitionView} dataDef データ定義
*/
function addDateField(customFields, customFieldId, customFieldName, dataDef) {
if (!dataDef.matchDataType('DATE_YMD')) {
throw `Custom Field "${customFieldName}" is Date type. Its value must be set by DATE_YMD type data item.`;
}
const dataObj = engine.findData(dataDef); // AddableDate or null
let fieldValue = '';
if (dataObj !== null) {
fieldValue = dateFormatter.format('MM/dd/yyyy', dataObj);
}
Object.assign(customFields, {[customFieldId]: fieldValue});
}
/**
* 宛先を追加/更新する
* @param {String} auth 認証設定名
* @param {Object} contact 宛先情報
* @return {String} jobId
*/
function upsertContact(auth, contact) {
const requestBody = {
"contacts": [contact]
};
const response = httpClient.begin()
.authSetting(auth)
.body(JSON.stringify(requestBody), 'application/json')
.put('https://api.sendgrid.com/v3/marketing/contacts');
const status = response.getStatusCode();
const responseStr = response.getResponseAsString();
if (status !== 202) {
engine.log(responseStr);
throw `Failed to upsert contact. status: ${status}`;
}
return JSON.parse(responseStr).job_id;
}
/**
* ジョブの処理状況を確認する
* @param {String} auth 認証設定名
* @param {String} jobId ジョブ ID
* @return {boolean} true: 完了, false: 未完了
*/
function checkStatus(auth, jobId) {
const response = httpClient.begin()
.authSetting(auth)
.get(`https://api.sendgrid.com/v3/marketing/contacts/imports/${jobId}`);
const status = response.getStatusCode();
const responseStr = response.getResponseAsString();
if (status !== 200) {
engine.log(responseStr);
throw `Failed to get upsert status. status: ${status}`;
}
const jobStatus = JSON.parse(responseStr).status;
switch (jobStatus) {
case 'pending': // 処理中
return false;
case 'completed': // 完了
return true;
default: // errored or failed
engine.log(responseStr);
throw 'Failed to complete upserting the contact.';
}
}