
Twilio SendGrid: 宛先追加/更新
Twilio SendGrid: Add or Update Contact
この工程は、SendGrid の宛先を追加または更新します。指定したメールアドレスの宛先がすでにある場合、その宛先が更新されます。
Basic Configs
- 工程名
- メモ
Configs for this Auto Step
- conf_Auth
- C1: API キーをトークンとして設定した認証設定 *
- conf_Email
- C2: メールアドレス *
- conf_ListIds
- C3: 宛先を追加するリストの ID(文字型データ項目の場合、1 行に 1 つ)
- conf_AlternateEmails
- C4: 代替メールアドレス(1 行に 1 つ、最大 5 件)
- conf_LastName
- C5: 姓
- conf_FirstName
- C6: 名
- conf_Country
- C7: 国
- conf_PostalCode
- C8: 郵便番号
- conf_Region
- C9: 都道府県
- conf_City
- C10: 市区町村
- conf_Address1
- C11: 住所 1 行目
- conf_Address2
- C12: 住所 2 行目
Notes
- sendgrid.com が対象の自動工程です
- sendgrid.kke.co.jp は対象外です
- API キーの作成方法については、SendGrid のドキュメントを参照してください
- Restricted Access を選択する場合、Marketing の権限をオンにする必要があります


- リスト ID は、URL に含まれています
- mc.sendgrid.com/contacts/lists/(リスト ID)
Capture

See Also
Script (click to open)
- 次のスクリプトが記述されている XML ファイルをダウンロードできます
- sendgrid-contact-upsert.xml (C) Questetra, Inc. (MIT License)
- Professional のワークフロー基盤では、ファイル内容を改変しオリジナルのアドオン自動工程として活用できます
const MAX_EMAIL_LENGTH = 254;
const MAX_ALTERNATE_EMAIL_NUM = 5;
const MAX_NAME_LENGTH = 50;
const MAX_POSTAL_CODE_LENGTH = 60; // API ドキュメントに記載がないが、試したところ 60 文字だった
const MAX_CITY_LENGTH = 60;
const MAX_FIELD_VALUE_LENGTH = 1000;
function main(){
//// == Config Retrieving / 工程コンフィグの参照 ==
const auth = configs.get('conf_Auth');
const listIds = retrieveListIds();
const contact = retrieveContact();
//// == Calculating / 演算 ==
const jobId = upsertContact(auth, listIds, 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 に設定されたリスト ID 一覧を読み出す
* - データ項目が設定されていない場合、null を返す(更新対象から除外するため)
* - データ項目が設定されていて値が空の場合、空のリストを返す(空の値で更新するため)
* @return {Array<String>} listIds
*/
function retrieveListIds() {
const listIdsDef = configs.getObject('conf_ListIds');
if (listIdsDef === null) {
return null;
}
if (listIdsDef.matchDataType('STRING')) {
const listIdsStr = engine.findData(listIdsDef);
if (listIdsStr === null) {
return [];
}
const listIds = listIdsStr.split('\n')
.filter(id => id !== '');
// API ドキュメントに List ID 上限数の記載なしのため、上限数はチェックしない
return listIds;
}
if (listIdsDef.matchDataType('SELECT')) {
const listIdItems = engine.findData(listIdsDef); // List<ItemView>
if (listIdItems === null || listIdItems.size() === 0) {
return [];
}
// 選択肢 ID のリストを返す
const listIds = [];
listIdItems.forEach(item => {
listIds.push(item.getValue()); // 選択肢 ID を格納
});
return listIds;
}
}
/**
* config に設定された宛先情報を、API リクエストボディに設定する形式で読み出す
* ただし、データ項目が設定されていない項目は含めない(更新の場合に、更新対象から除外するため)
* @return {Object} contact
* @return {String} contact.email
* @return {Array<String>} contact.alternate_emails
* @return {String} contact.last_name
* @return {String} contact.first_name
* @return {String} contact.country
* @return {String} contact.postal_code
* @return {String} contact.state_province_region
* @return {String} contact.city
* @return {String} contact.address_line_1
* @return {String} contact.address_line_2
*/
function retrieveContact() {
const email = retrieveConfig('conf_Email', true, MAX_EMAIL_LENGTH, 'Email Address');
const alternateEmails = retrieveAlternateEmails();
const lastName = retrieveConfig('conf_LastName', false, MAX_NAME_LENGTH, 'Last Name');
const firstName = retrieveConfig('conf_FirstName', false, MAX_NAME_LENGTH, 'First Name');
const country = retrieveConfig('conf_Country', false, MAX_NAME_LENGTH, 'Country');
const postalCode = retrieveConfig('conf_PostalCode', false, MAX_POSTAL_CODE_LENGTH, 'Postal Code');
const region = retrieveConfig('conf_Region', false, MAX_NAME_LENGTH, 'Region');
const city = retrieveConfig('conf_City', false, MAX_CITY_LENGTH, 'City');
const address1 = retrieveConfig('conf_Address1', false, MAX_FIELD_VALUE_LENGTH, 'Address 1st Line');
const address2 = retrieveConfig('conf_Address2', false, MAX_FIELD_VALUE_LENGTH, 'Address 2nd Line');
const contact = {
email,
alternate_emails: alternateEmails,
last_name: lastName,
first_name: firstName,
country,
postal_code: postalCode,
state_province_region: region,
city,
address_line_1: address1,
address_line_2: address2
};
// 値が null のものを削除
Object.keys(contact).forEach(key => {
if (contact[key] === null) {
delete contact[key];
}
});
return contact;
}
/**
* config に設定された文字型データ項目の値を読み出す
* required が false で
* - データ項目が設定されていない場合、null を返す(更新対象から除外するため)
* - データ項目が設定されていて値が空の場合、空の文字列を返す(空の値で更新するため)
* @param {String} confName 設定項目名
* @param {boolean} required 必須項目かどうか
* @param {Number} maxLength 最大文字数
* @param {String} label エラー出力用ラベル
* @return {String} value
*/
function retrieveConfig(confName, required, maxLength, label) {
const dataDef = configs.getObject(confName);
if (dataDef === null) { // required が true の場合、dataDef は null にならない
return null;
}
const value = engine.findData(dataDef);
if (value === null) {
if (required) {
throw `${label} is blank.`;
}
return '';
}
if (value.length > maxLength) {
throw `${label} must be within ${maxLength} characters.`;
}
return value;
}
/**
* config に設定された代替メールアドレスの一覧を読み出す
* - データ項目が設定されていない場合、null を返す(更新対象から除外するため)
* - データ項目が設定されていて値が空の場合、空のリストを返す(空の値で更新するため)
* @return {Array<String>} alternateEmails
*/
function retrieveAlternateEmails() {
const alternateEmailsDef = configs.getObject('conf_AlternateEmails');
if (alternateEmailsDef === null) {
return null;
}
const alternateEmailsStr = engine.findData(alternateEmailsDef);
if (alternateEmailsStr === null) {
return [];
}
const alternateEmails = alternateEmailsStr.split('\n')
.filter(email => email !== '');
if (alternateEmails.length > MAX_ALTERNATE_EMAIL_NUM) {
throw `The maximum number of alternate emails is ${MAX_ALTERNATE_EMAIL_NUM}.`;
}
// API ドキュメントに上限文字数の記載はないが、メインのメールアドレスと同様にチェック
if (alternateEmails.some(email => email.length > MAX_EMAIL_LENGTH)) {
throw `Each alternate email must be within ${MAX_EMAIL_LENGTH} characters.`;
}
return alternateEmails;
}
/**
* 宛先を追加/更新する
* @param {String} auth 認証設定名
* @param {Array<String>} listIds 宛先を追加するリスト ID の一覧
* @param {Object} contact 宛先情報
* @return {String} jobId
*/
function upsertContact(auth, listIds, contact) {
const requestBody = {
"list_ids": listIds,
"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.';
}
}