2024-06-28
(C) Questetra, Inc. (MIT License)
3
2
This item gets an email message in Outlook.
この工程は、Outlook のメールを取得します。
https://support.questetra.com/bpmn-icons/service-task-outlook-message-get/
https://support.questetra.com/ja/bpmn-icons/service-task-outlook-message-get/
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAA/RJREFUWEfN
l1tsDFEYx/+z7W7X7rZFS1nLA42kCU0QEg9oS4IgfXF5ERVxefAg7n1o0bhkoy6RkIhEiMSt4pII
xYNu9cElrqUqhApFabub7W679z1yzsys2Z2ZnWlTYV52Zuec7/t95/y/73zD4R9fXL/8V34tAbjd
kjklwr2L/yWNAFxwjhWeta3rA6j8uifFsbZlkBo4x+7RGpge4E/EYqRa9hTepwdRBxhQ1Gp86hDK
AIPqXIRShpAD/BXn6hDJADqcP9k4AsWjjLq04A8TTKj9CW8wLhlPSqVZkgLQTrQsxw+MAacvd5ip
BWe6cfd9UGrWBaejVPzjjykd0dNJFOBJexg763vgWp+Pps9hVN/rYfburMnDT38cFXUeLC4yY9ss
mxIArReJFJUAJEc/qcCIeYVZsgU5sigX77uiOPm4F0cX56KuOYAVF91snK/GjjZ3FMXHfqFiqgVn
lw1TAQDgdDDfPACf7w1Sb/4aO6wm7bUORgk6e/k9duRkIEaAH74YbCYOw4YY1AHAa0EEkFW60D47
TBn8a0KANk8U0ThQmJcJg4QrHCNw9/EABTYeoKs3BqvJgOwsLg0ALdmOUgGgnUafVO1EgEiMYMaJ
TpSMz4LZyOHamwCaN41EViY/dcBbwM4MHQDHH/YiECHYPtvGHNJnuuxUYPRq+BTCjnpehE0b8vHD
F8fyC26UF5lRVZaN/Q0+VAkiTRFUEoAs/cQVWHreja2zbJg5zsTmP/oSRu0DP66uHK6VsYn32257
cbjJLx/vdAgZXSnPfxGA0tN9Xz3NwgxcehXAh+4oqsuy2fPrjghOP+1j9wcX5sATIGj8FMLy4iEJ
h4ea/Nh+25sWQFUDPSGCwtoOnCgfygxsueVF65YCpnJ6NbaFUHKqi93TNLQaOVao4gS48LIPK6dY
oAKgTwPUcChKcP9jiKmfilEUoBjSZ08M9z4EsW66lTl//j2C8nPdTCudVaMHBhDYa4dZULraZtMU
vN4SxArJclMBXnkdYFPyrYY0AHw1VC1E1OiSInPCd77FgPkTzWzPmzsi7P+brUFcbg5git2ImxV5
GJOTAV+IYFWdGzfeBrUAJIWIWlMQojRyegK+2jQSO+q9LAuUrl1zs1FdloNMA/DwSxhrr3rQsrlA
eQuSSjEDSN/3iQAvvkfw7FtYNQVzzQYsm8xnABUi1Y1chEqHEb8KsmwQPVmMHDy7RyfKsypBygta
xpec68atd5IjWYieDk1tSGSHkl5H+sclt2b/WUsmhqGzOdEfNR2ptyn9KxD9bcsHD8IlRK76qabd
8uhIUeWtGIxPs1TLrHWjjQs3R3iV8nGa2OtB/jjtn9r6Nfo39MDfMN80fiMAAAAASUVORK5CYII=
{
// 認証設定を作成し、指定
const oauth2 = httpClient.createAuthSettingOAuth2(
'Outlook',
'https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize',
'https://login.microsoftonline.com/organizations/oauth2/v2.0/token',
'https://graph.microsoft.com/Mail.Read offline_access',
'client_id',
'client_secret',
'access_token'
);
configs.putObject('conf_OAuth2', oauth2);
// メール ID を設定
const messageIdDef = engine.createDataDefinition('メール ID', 1, 'q_MessageId', 'STRING_TEXTFIELD');
engine.setData(messageIdDef, messageId);
configs.putObject('conf_MessageId', messageIdDef);
// 本文の取得形式を設定
configs.putObject('conf_AsHTML', asHtml);
// 保存用データ項目を準備
const items = ['FromAddress', 'FromName', 'ReplyToAddresses', 'ReplyToNames', 'RecipientAddresses', 'RecipientNames', 'SentDatetime', 'Subject', 'Body', 'Attachments'];
const dataDefs = {};
items.forEach((item, i) => {
let dataType = 'STRING_TEXTFIELD';
let preValue = '事前文字列';
switch(item) {
case 'ReplyToAddresses':
case 'ReplyToNames':
case 'RecipientAddresses':
case 'RecipientNames':
case 'Body':
dataType = 'STRING_TEXTAREA';
preValue = '事前\n文字列';
break;
case 'SentDatetime':
dataType = 'DATETIME';
preValue = java.sql.Timestamp.valueOf('2000-01-01 00:00:00');
break;
case 'Attachments':
dataType = 'FILE';
preValue = new java.util.ArrayList();
preValue.add(new com.questetra.bpms.core.event.scripttask.NewQfile('事前ファイル.csv', 'text/csv', '1,2,3'));
break;
}
const dataDef = engine.createDataDefinition(item, i + 2, `q_${item}`, dataType);
engine.setData(dataDef, preValue); // 事前データをセット
configs.putObject(`conf_${item}`, dataDef);
dataDefs[item] = dataDef;
});
return dataDefs;
};
/**
* 異常系のテスト
* @param errorMsg
*/
const assertError = (errorMsg) => {
let failed = false;
try {
main();
} catch (e) {
failed = true;
expect(e.message).toEqual(errorMsg);
}
if (!failed) {
fail('No error was thrown.');
}
};
/**
* メール ID が空であればエラー
*/
test('Message ID is empty', () => {
prepareConfigs(null, false);
assertError('Message ID is blank.');
});
/**
* 保存先データ項目がひとつも設定されていなければエラー
*/
test('Data items not set', () => {
// 認証設定を作成し、指定
const oauth2 = httpClient.createAuthSettingOAuth2(
'Outlook',
'https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize',
'https://login.microsoftonline.com/organizations/oauth2/v2.0/token',
'https://graph.microsoft.com/Mail.Read offline_access',
'client_id',
'client_secret',
'access_token'
);
configs.putObject('conf_OAuth2', oauth2);
// メール ID を設定
const messageId = 'messageId-1';
const messageIdDef = engine.createDataDefinition('メール ID', 1, 'q_MessageId', 'STRING_TEXTFIELD');
engine.setData(messageIdDef, messageId);
configs.putObject('conf_MessageId', messageIdDef);
assertError('No data item to save the result is set.');
});
/**
* 保存先データ項目が重複していればエラー
* fromAddress と subject が重複
*/
test('The same data item is set multiple times - fromAddress and subject', () => {
const dataDefs = prepareConfigs('messageId', false);
configs.putObject('conf_Subject', dataDefs.FromAddress);
assertError('The same data item is set multiple times.');
});
/**
* 保存先データ項目が重複していればエラー
* recipientNames と body が重複
*/
test('The same data item is set multiple times - recipientNames and body', () => {
const dataDefs = prepareConfigs('messageId', false);
configs.putObject('conf_RecipientNames', dataDefs.Body);
assertError('The same data item is set multiple times.');
});
/**
* 保存先データ項目が重複していればエラー
* recipientAddresses と replyToAddresses が重複
*/
test('The same data item is set multiple times - recipientAddresses and replyToAddresses', () => {
const dataDefs = prepareConfigs('messageId', false);
configs.putObject('conf_RecipientAddresses', dataDefs.ReplyToAddresses);
assertError('The same data item is set multiple times.');
});
/**
* メッセージ取得の GET リクエストのテスト
* @param {Object} request
* @param request.url
* @param request.method
* @param request.headers
* @param messageId
* @param preferredType
*/
const assertGetMessageRequest = ({url, method, headers}, messageId, preferredType) => {
const expectedUrl = `https://graph.microsoft.com/v1.0/me/messages/${encodeURI(messageId)}`
+ `?${generateQueryString('$select', 'from,replyTo,toRecipients,ccRecipients,bccRecipients,subject,body,sentDateTime')}`;
expect(url).toEqual(expectedUrl);
expect(method).toEqual('GET');
expect(headers.Prefer).toEqual(`outlook.body-content-type="${preferredType}"`);
expect(headers.Authorization).toEqual('Bearer access_token');
};
/**
* クエリパラメータのテスト用の文字列を生成する
* @param key
* @param value
* @returns {String}
*/
const generateQueryString = (key, value) => {
const encodedKey = encodeURIComponent(key);
const encodedValue = encodeURIComponent(value);
return `${encodedKey}=${encodedValue}`;
};
/**
* 添付ファイル取得の GET リクエストのテスト
* @param {Object} request
* @param request.url
* @param request.method
* @param request.headers
* @param messageId
*/
const assertGetAttachmentsRequest = ({url, method, headers}, messageId) => {
expect(url).toEqual(`https://graph.microsoft.com/v1.0/me/messages/${encodeURI(messageId)}/attachments`);
expect(method).toEqual('GET');
expect(headers.Authorization).toEqual('Bearer access_token');
};
/**
* メール取得の GET リクエストで失敗
*/
test('Fail in GET message request', () => {
const messageId = 'messageId-1';
prepareConfigs(messageId, false);
httpClient.setRequestHandler((request) => {
assertGetMessageRequest(request, messageId, 'text');
return httpClient.createHttpResponse(400, 'application/json', `{}`);
});
assertError('Failed to get message. status: 400');
});
const SAMPLE_MESSAGE_TEXT = {
"from": {
"emailAddress": {
"address": "from1@example.com",
"name": "From 1 の表示名"
}
},
"replyTo": [
{
"emailAddress": {
"address": "replyTo1@example.com",
"name": "Reply-To 1 の表示名"
}
},
{
"emailAddress": {
"address": "replyTo2@example.com",
"name": "Reply-To 2 の表示名"
}
},
{
"emailAddress": {
"address": "replyTo3@example.com",
"name": "Reply-To 3 の表示名"
}
},
],
"toRecipients": [
{
"emailAddress": {
"address": "to1@example.com",
"name": "To 1 の表示名"
}
},
{
"emailAddress": {
"address": "to2@example.com",
"name": "To 2 の表示名"
}
},
{
"emailAddress": {
"address": "to3@example.com",
"name": "To 3 の表示名"
}
},
],
"ccRecipients": [
{
"emailAddress": {
"address": "cc1@example.com",
"name": "Cc 1 の表示名"
}
},
{
"emailAddress": {
"address": "cc2@example.com",
"name": "Cc 2 の表示名"
}
},
{
"emailAddress": {
"address": "cc3@example.com",
"name": "Cc 3 の表示名"
}
},
],
"bccRecipients": [
{
"emailAddress": {
"address": "bcc1@example.com",
"name": "Bcc 1 の表示名"
}
},
{
"emailAddress": {
"address": "bcc2@example.com",
"name": "Bcc 2 の表示名"
}
},
{
"emailAddress": {
"address": "bcc3@example.com",
"name": "Bcc 3 の表示名"
}
},
],
"subject": "メール 1 の件名",
"body": {
"contentType": "text/plain",
"content": "テキスト形式の\n本文です。"
},
"sentDateTime": "2023-09-14T00:00:00Z"
};
/**
* 成功
* 本文をテキスト形式で取得
* 添付ファイルなし
*/
test('Succeed - body in text, no attachments', () => {
const messageId = 'messageId-1';
const dataDefs = prepareConfigs(messageId, false);
let reqCount = 0;
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertGetMessageRequest(request, messageId, 'text');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(SAMPLE_MESSAGE_TEXT));
}
assertGetAttachmentsRequest(request, messageId);
return httpClient.createHttpResponse(200, 'application/json', `{"value": []}`);
});
expect(main()).toEqual(undefined);
// 保存先データ項目の値を確認
expect(engine.findData(dataDefs.FromAddress)).toEqual('from1@example.com');
expect(engine.findData(dataDefs.FromName)).toEqual('From 1 の表示名');
const replyToAddresses = [
'replyTo1@example.com',
'replyTo2@example.com',
'replyTo3@example.com'
];
const replyToNames = [
'Reply-To 1 の表示名',
'Reply-To 2 の表示名',
'Reply-To 3 の表示名'
];
expect(engine.findData(dataDefs.ReplyToAddresses)).toEqual(replyToAddresses.join('\n'));
expect(engine.findData(dataDefs.ReplyToNames)).toEqual(replyToNames.join('\n'));
const recipientAddresses = [
'to1@example.com',
'to2@example.com',
'to3@example.com',
'cc1@example.com',
'cc2@example.com',
'cc3@example.com',
'bcc1@example.com',
'bcc2@example.com',
'bcc3@example.com'
];
const recipientNames = [
'To 1 の表示名',
'To 2 の表示名',
'To 3 の表示名',
'Cc 1 の表示名',
'Cc 2 の表示名',
'Cc 3 の表示名',
'Bcc 1 の表示名',
'Bcc 2 の表示名',
'Bcc 3 の表示名'
];
expect(engine.findData(dataDefs.RecipientAddresses)).toEqual(recipientAddresses.join('\n'));
expect(engine.findData(dataDefs.RecipientNames)).toEqual(recipientNames.join('\n'));
expect(engine.findData(dataDefs.Subject)).toEqual('メール 1 の件名');
expect(engine.findData(dataDefs.Body)).toEqual('テキスト形式の\n本文です。');
expect(engine.findData(dataDefs.SentDatetime)).toEqual(dateFormatter.parse("yyyy-MM-dd'T'HH:mm:ssX", '2023-09-14T00:00:00Z'));
expect(engine.findData(dataDefs.Attachments).size()).toEqual(0); // 事前に添付されていたファイルは削除される
});
/**
* 添付ファイル取得の GET リクエストで失敗
*/
test('Fail in GET attachments request', () => {
const messageId = 'messageId-1';
prepareConfigs(messageId, false);
let reqCount = 0;
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertGetMessageRequest(request, messageId, 'text');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(SAMPLE_MESSAGE_TEXT));
}
assertGetAttachmentsRequest(request, messageId);
return httpClient.createHttpResponse(400, 'application/json', `{}`);
});
assertError('Failed to get attachments. status: 400');
});
const SAMPLE_MESSAGE_HTML = {
"from": {
"emailAddress": {
"address": "from2@example.com",
"name": ""
}
},
"replyTo": [
{
"emailAddress": {
"address": "replyTo1@example.com",
"name": ""
}
}
],
"toRecipients": [
{
"emailAddress": {
"address": "to1@example.com",
"name": ""
}
}
],
"ccRecipients": [],
"bccRecipients": [
{
"emailAddress": {
"address": "bcc1@example.com",
"name": "Bcc 1 の表示名"
}
}
],
"subject": "メール 2 の件名",
"body": {
"contentType": "text/html",
"content": "HTML 形式の本文です。
"
},
"sentDateTime": "2023-09-01T00:00:00Z"
};
const SAMPLE_ATTACHMENT_1 = {
"name": "添付ファイル1.txt",
"contentType": "text/plain",
"contentBytes": "grGCzJNZlXSDdINAg0ODi4LNClNoaWZ0IEpJUwqCxYK3gUI="
};
const SAMPLE_ATTACHMENT_2 = {
"name": "添付ファイル2.png",
"contentType": "image/png",
"contentBytes": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADPUlEQVRYR8WXX0hTURzHv2dzy5bb1HKKRH+"
+ "gtx7K2izooXI+BVH41F+IglAJmhVICr2kgRG6DFRERXBpGIgkZA/Oeigir+VzIGQE1bTUyXYdy90Tu+5u997dea"
+ "9p3PO2nd+fz/md359zCXReRKv/76cPW4ysoYKAnARoCSj2gCCP16dYAMEMQKYo6OuYhRsqHvnIarGtCjB7wlWEL"
+ "NSCohJAthajACIg6MAKmhxvmJ9r6awJECgrrSSEPgKwTaNjuViYUnKncHyiI5N+RoC5clcbpaj6R8cSNULQXjDG"
+ "VCvZUgQIlDn7CSHnN8O5YINSOlA4PnlBbjMNYDNPnuZMIRISgMSdt2/myeW2KCVV4pxIAvDZbsS0kHCGAgdsdQ0"
+ "w2HPBPvchMvpCMxexWmGrb4SxqBiRl8NgB31i3TBi2CdURwqg3NUCCo8gme8b5g0IK8q8R7C+BuC4NUFMJU7YG7"
+ "0gZnNSLnj3JuL6yUXgdYwxNfHfPEC8yWSxht/iOi949Q7IMkmcccFFLHquI/ZtRhEip/oWtlacS9tjB/sQ7nwi/"
+ "j+yYuG2x5sVDxBwuy4RoE8soQTA71MOodaHWB4ZSh3IakWetwvG3XsVweJXEO5slexR4HKhn/HxALPu0m6AXtUE"
+ "kBASrsR80AlbQ7Mk5HIKJQCA9Dj8E9cSAK5PAErWA8AHg2VBLBbV5FQGwJTDzxxaBShzzScHS8JcxitQdZcuoAh"
+ "AseAYZ/KFCFC5WhoApQBRnV2AglyGCMDhZ1YtzrpdqgCxwA+w/b2wemoBYlCMQ+zrF4Sf9sBWd1+yrw6g4QriAP"
+ "MXz8C4cxdyH3fxDUq8loeeIdTWDPORY7A3tqgDyK5ANQkFAN6ywQD7Ay/MzqOg0SiW7t1GdPIDv6UZAOIk1FCGE"
+ "oDE+bYcd+PP1CS4pWDyxNoBRGWopREpASglglYASSNSasU7Rt+CmFL9fEMAA70Id7eJeaWtmK8E2TDKqfIg+9TZ"
+ "ZOmtTH/m54DaMu0/AHtTqu3SUAgLN66A+zWXUpUPIx5ANo7VHG1gX3kcxw3q+iARTqTrk0yA0PVR+j8ise5neSo"
+ "SOn6YCBC6fpqJS023j9MN1Lsm1b9qWLIw6P4tOAAAAABJRU5ErkJggg=="
};
/**
* 成功
* 本文を HTML 形式で取得
* 添付ファイルあり
*/
test('Succeed - body in html, with attachments', () => {
const messageId = 'messageId-2';
const dataDefs = prepareConfigs(messageId, true);
let reqCount = 0;
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertGetMessageRequest(request, messageId, 'html');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(SAMPLE_MESSAGE_HTML));
}
assertGetAttachmentsRequest(request, messageId);
const attachments = [SAMPLE_ATTACHMENT_1, SAMPLE_ATTACHMENT_2];
return httpClient.createHttpResponse(200, 'application/json', `{"value": ${JSON.stringify(attachments)}}`);
});
expect(main()).toEqual(undefined);
// 保存先データ項目の値を確認
expect(engine.findData(dataDefs.FromAddress)).toEqual('from2@example.com');
expect(engine.findData(dataDefs.FromName)).toEqual('');
expect(engine.findData(dataDefs.ReplyToAddresses)).toEqual('replyTo1@example.com');
expect(engine.findData(dataDefs.ReplyToNames)).toEqual('');
expect(engine.findData(dataDefs.RecipientAddresses)).toEqual('to1@example.com\nbcc1@example.com');
expect(engine.findData(dataDefs.RecipientNames)).toEqual('\nBcc 1 の表示名');
expect(engine.findData(dataDefs.Subject)).toEqual('メール 2 の件名');
expect(engine.findData(dataDefs.Body)).toEqual('HTML 形式の本文です。
');
expect(engine.findData(dataDefs.SentDatetime)).toEqual(dateFormatter.parse("yyyy-MM-dd'T'HH:mm:ssX", '2023-09-01T00:00:00Z'));
expect(engine.findData(dataDefs.Attachments).size()).toEqual(2);
expect(engine.findData(dataDefs.Attachments)[0].getName()).toEqual('添付ファイル1.txt');
expect(engine.findData(dataDefs.Attachments)[1].getName()).toEqual('添付ファイル2.png');
});
/** from なしの下書きメール */
const SAMPLE_MESSAGE_DRAFT = {
"replyTo": [],
"toRecipients": [],
"ccRecipients": [],
"bccRecipients": [],
"subject": "",
"body": {
"contentType": "text/plain",
"content": ""
},
"sentDateTime": "2023-09-10T00:00:00Z"
};
/**
* 成功
* from なしの下書きメール
* 添付ファイルを保存しない
*/
test('Succeed - draft message without from, attachments not saved', () => {
const messageId = 'messageId-3';
const dataDefs = prepareConfigs(messageId, false);
configs.put('conf_Attachments', ''); // 添付ファイルの保存先データ項目を解除
// 添付ファイルを取得する API リクエストは発行されない
httpClient.setRequestHandler((request) => {
assertGetMessageRequest(request, messageId, 'text');
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(SAMPLE_MESSAGE_DRAFT));
});
expect(main()).toEqual(undefined);
// 保存先データ項目の値を確認
expect(engine.findData(dataDefs.FromAddress)).toEqual('');
expect(engine.findData(dataDefs.FromName)).toEqual('');
expect(engine.findData(dataDefs.ReplyToAddresses)).toEqual('');
expect(engine.findData(dataDefs.ReplyToNames)).toEqual('');
expect(engine.findData(dataDefs.RecipientAddresses)).toEqual('');
expect(engine.findData(dataDefs.RecipientNames)).toEqual('');
expect(engine.findData(dataDefs.Subject)).toEqual('');
expect(engine.findData(dataDefs.Body)).toEqual('');
expect(engine.findData(dataDefs.SentDatetime)).toEqual(dateFormatter.parse("yyyy-MM-dd'T'HH:mm:ssX", '2023-09-10T00:00:00Z'));
expect(engine.findData(dataDefs.Attachments).size()).toEqual(1);
expect(engine.findData(dataDefs.Attachments)[0].getName()).toEqual('事前ファイル.csv');
});
]]>