Start: Gmail: Email Message Received
Start Process when Gmail has received a new message.
Configs
- C1: OAuth2 Setting *
- C2: Label (Inbox if blank)
- C3: Data item to save Message ID *
- C4: Data item to save received time
- C5: Data item to save RFC 822 Message-ID header
Script (click to open)
/**
* @typedef {Object} timestamp java.sql.Timestamp オブジェクト
*/
/** 日時フォーマッター */
const dateFormatter = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
/**
* configs から必要な情報の取り出し
* @returns {Object} setting 設定
* @returns {string} setting.auth HTTP 認証設定
* @returns {Array} setting.labels ラベル一覧
*/
const prepare = () => {
const auth = configs.get('conf_auth');
let label = configs.get('conf_label');
let labels = [];
if (label !== null && label !== '') {
labels = label.split('\n')
.map(label => label.trim())
.filter(label => label !== '');
}
return {
auth,
labels
};
};
/**
* 追加されたメールの検索
* @param {Number} limit 取得上限数
* @param timestampLowerLimit timestamp の下限
* @returns {Array} messages メッセージ一覧
* @returns {string} messages[].id Gmail Message ID
* @returns {timestamp} messages[].timestamp メール受信時刻
* @returns {string} messages[].rfc822msgId RFC 822 Message-ID
*/
const list = (limit, timestampLowerLimit) => {
const {auth, labels} = prepare();
let labelIds = ['INBOX'];
if (labels.length !== 0) {
labelIds = getLabelIds(auth, labels);
}
// HTTP リクエスト数制限を考慮する
limit = Math.min(limit, httpClient.getRequestingLimit() - 2);
const messages = getMessages(auth, labelIds, limit, timestampLowerLimit);
logMessages(messages);
return messages;
};
/**
* メッセージ一覧のログ出力
* @param {Array} messages メッセージ一覧
*/
const logMessages = (messages) => {
const replacer = (key, value) => value instanceof java.sql.Timestamp ? dateFormatter.format(value) : value;
messages.forEach(msg => engine.log(JSON.stringify(msg, replacer)));
};
/**
* ラベルからラベル ID を取得する
* @param {String} auth 認証設定
* @param {Array<String>} labels ラベル一覧
* @return {Array<String>} ラベル ID の一覧
*/
function getLabelIds(auth, labels) {
const response = httpClient.begin()
.authSetting(auth)
.get('https://gmail.googleapis.com/gmail/v1/users/me/labels');
const responseJson = response.getResponseAsString();
const status = response.getStatusCode();
if (status >= 300) {
const accessLog = `--- users.labels.list --- ${status}\n${responseJson}\n`;
engine.log(accessLog);
throw `Failed to get labels. status: ${status}`;
}
const json = JSON.parse(responseJson);
let found = json.labels
.filter(label => labels.includes(label.name));
const foundLabels = found.map(label => label.name);
const notFoundLabels = labels.filter(label => !foundLabels.includes(label));
if (notFoundLabels.length > 0) {
const accessLog = `--- users.labels.list --- ${status}\n${responseJson}\n`;
engine.log(accessLog);
// id が見つからない label がある場合、エラーをスロー
throw `label ids of ${notFoundLabels.join(', ')} not found`;
}
return found.map(label => label.id);
}
/**
* Gmail REST API にメール取得の GET リクエストを送信し、メッセージ一覧を返す
* @param {String} auth 認証設定
* @param {Array<String>} labelIds ラベル ID の一覧
* @param {Number} limit 取得上限数
* @param timestampLowerLimit timestamp の下限
* @returns {Array} messages メッセージ一覧
* @returns {string} messages[].id Gmail Message ID
* @returns {timestamp} messages[].timestamp メール受信時刻
* @returns {string} messages[].rfc822msgId RFC 822 Message-ID
*/
function getMessages(auth, labelIds, limit, timestampLowerLimit) {
let request = httpClient.begin()
.authSetting(auth)
.queryParam('maxResults', `${limit}`);
engine.log(`lavelIds: ${labelIds}`);
labelIds.forEach(labelId => {
request = request.queryParam('labelIds', labelId);
});
// 時刻は Sent が対象なので、余裕を持たせて、timestampLowerLimit の 1 日前の時刻から
// 単位はミリ秒ではなく秒
const q = `newer: ${Math.floor(timestampLowerLimit.addDays(-1).getTime() / 1000)}`;
engine.log(`q: ${q}`);
request = request.queryParam('q', q);
const response = request
.get('https://gmail.googleapis.com/gmail/v1/users/me/messages');
// when error thrown
const responseJson = response.getResponseAsString();
const status = response.getStatusCode();
if (status >= 300) {
const accessLog = `--- users.messages.list --- ${status}\n${responseJson}\n`;
engine.log(accessLog);
throw `Failed to get messages. status: ${status}`;
}
const json = JSON.parse(responseJson);
if (json.messages === undefined || json.messages === null) {
// 該当メッセージが無い
engine.log("no messages");
return [];
}
return json.messages
.filter(msg => !engine.isProcessStarted(msg.id)) // 既にプロセス開始済みのものを除く
.map(msg => getMessage(auth, msg.id)) // id 以外の情報を取得
.filter(msg => !msg.timestamp.before(timestampLowerLimit)); // timestamp が下限より前のものを除く
}
/**
* Gmail REST API にメール取得の GET リクエストを送信し、internalDate 等を取得する
* @param auth {String} auth 認証設定
* @param id {String} メッセージ ID
* @return {Object} message メッセージ
* @returns {string} message.id Gmail Message ID
* @returns {timestamp} message.timestamp メール受信時刻
* @returns {string} message.rfc822msgId RFC 822 Message-ID
*/
function getMessage(auth, id) {
const response = httpClient.begin()
.authSetting(auth)
.queryParam('format', 'metadata')
.get(`https://gmail.googleapis.com/gmail/v1/users/me/messages/${id}`);
const responseJson = response.getResponseAsString();
const status = response.getStatusCode();
if (status >= 300) {
const accessLog = `--- users.messages.get --- ${status}\n${responseJson}\n`;
engine.log(accessLog);
throw `Failed to get message ${id}. status: ${status}`;
}
const json = JSON.parse(responseJson);
const msgIdHeader = json.payload.headers.find(h => h.name.toLowerCase() === 'message-id');
const rfc822msgId = msgIdHeader !== undefined ? msgIdHeader.value : '';
return {
id: json.id,
timestamp: new java.sql.Timestamp(Number(json.internalDate)),
rfc822msgId
};
}
Download
2021-03-04 (C) Questetra, Inc. (MIT License)
https://support.questetra.com/bpmn-icons/start-event-gmail-message-received/
The Addon-import feature is available with Professional or Enterprise edition.
Notes
- In addition to user-created labels, system labels such as INBOX, UNREAD and STARRED are also supported. For the list of system labels, see the Gmail API Guide.
- The Questetra BPM Suite will periodically poll the Gmail to check new received messages. If any new messages have been received, the process will be started.
- Process will not be started on the first check. Only the check will be done. You can confirm the check status from “Process Log”.
- If a large number of messages are received in a short period of time, the processes may not be started for all messages. Approx. 90 processes in every 15 minutes.
Capture
