6

シンプルな Gmail アドオンを作成しましたが、以下の戦略に苦労しています。

アドオンをインストールした後、最初の受信トレイが開かれたときに、ユーザーに基本情報の入力を求めます。ユーザーが 2 番目のメールを開いたときに、基本情報の詳細を再度尋ねることはありません。

どうすればこれを処理できますか?

プロパティ サービスを試してみましたが、うまくいきませんでした。

アップデート

var MAX_THREADS = 5;

/**
 * Returns the array of cards that should be rendered for the current
 * e-mail thread. The name of this function is specified in the
 * manifest 'onTriggerFunction' field, indicating that this function
 * runs every time the add-on is started.
 *
 * @param {Object} e data provided by the Gmail UI.
 * @returns {Card[]}
 */
function buildAddOn(e) {
  // Activate temporary Gmail add-on scopes.
  //Logger.log('E', Session.getActiveUser());
  var accessToken = e.messageMetadata.accessToken;
  GmailApp.setCurrentMessageAccessToken(accessToken);
  var userProperties = PropertiesService.getUserProperties();
  var Token = userProperties.getProperty('Token');
  Logger.log('Token value:',typeof Token);
  if(Token != null ){
    var messageId = e.messageMetadata.messageId;
    var senderData = extractSenderData(messageId);
    var cards = [];

    // Build a card for each recent thread from this email's sender.
    if (senderData.recents.length > 0) {
      senderData.recents.forEach(function(threadData) {
        cards.push(buildRecentThreadCard(senderData.email, threadData));
      });
    } else {
      // Present a blank card if there are no recent threads from
      // this sender.
      cards.push(CardService.newCardBuilder()
        .setHeader(CardService.newCardHeader()
        .setTitle('No recent threads from this sender')).build());
    }
    return cards;
  } 
  else{
    var cards = []
    var login_card = build_login_card()
    cards.push(login_card);
    return cards;
  }
}

/**
 *  This function builds a set of data about this sender's presence in your
 *  inbox.
 *
 *  @param {String} messageId The message ID of the open message.
 *  @return {Object} a collection of sender information to display in cards.
 */
function extractSenderData(messageId) {
  // Use the Gmail service to access information about this message.
  var mail = GmailApp.getMessageById(messageId);
  var threadId = mail.getThread().getId();
  var senderEmail = extractEmailAddress(mail.getFrom());

  var recentThreads = GmailApp.search('from:' + senderEmail);
  var recents = [];

  // Retrieve information about up to 5 recent threads from the same sender.
  recentThreads.slice(0,MAX_THREADS).forEach(function(thread) {
    if (thread.getId() != threadId && ! thread.isInChats()) {
      recents.push({
        'subject': thread.getFirstMessageSubject(),
        'count': thread.getMessageCount(),
        'link': 'https://mail.google.com/mail/u/0/#inbox/' + thread.getId(),
        'lastDate': thread.getLastMessageDate().toDateString()
      });
    }
  });

  var senderData = {
    "email": senderEmail,
    'recents': recents
  };

  return senderData;
}

/**
 *  Given the result of GmailMessage.getFrom(), extract only the email address.
 *  getFrom() can return just the email address or a string in the form
 *  "Name <myemail@domain>".
 *
 *  @param {String} sender The results returned from getFrom().
 *  @return {String} Only the email address.
 */
function extractEmailAddress(sender) {
  var regex = /\<([^\@]+\@[^\>]+)\>/;
  var email = sender;  // Default to using the whole string.
  var match = regex.exec(sender);
  if (match) {
    email = match[1];
  }
  return email;
}

/**
 *  Builds a card to display information about a recent thread from this sender.
 *
 *  @param {String} senderEmail The sender email.
 *  @param {Object} threadData Infomation about the thread to display.
 *  @return {Card} a card that displays thread information.
 */
function buildRecentThreadCard(senderEmail, threadData) {
  var card = CardService.newCardBuilder();
  card.setHeader(CardService.newCardHeader().setTitle(threadData.subject));
  var section = CardService.newCardSection()
    .setHeader("<font color=\"#1257e0\">Recent thread</font>");
  section.addWidget(CardService.newTextParagraph().setText(threadData.subject));
  section.addWidget(CardService.newKeyValue()
    .setTopLabel('Sender')
    .setContent(senderEmail));
  section.addWidget(CardService.newKeyValue()
    .setTopLabel('Number of messages')
    .setContent(threadData.count.toString()));
  section.addWidget(CardService.newKeyValue()
    .setTopLabel('Last updated')
    .setContent(threadData.lastDate.toString()));

  var threadLink = CardService.newOpenLink()
    .setUrl(threadData.link)
    .setOpenAs(CardService.OpenAs.FULL_SIZE);
  var button = CardService.newTextButton()
    .setText('Open Thread')
    .setOpenLink(threadLink);
  section.addWidget(CardService.newButtonSet().addButton(button));

  card.addSection(section);
  return card.build();
}
function build_login_card(){
  var card = CardService.newCardBuilder();
  card.setHeader(CardService.newCardHeader().setTitle("Login Here"));
  var userProperties = PropertiesService.getUserProperties();
  var Token = userProperties.setProperty('Token',"Token");
  return card.build()
}
4

2 に答える 2

3

コメントによると、ここでの主な問題は、アドオンをアンインストールしても UserProperties データストアからビットが削除されないため、アドオンを再インストールすると、アドオンの構成手順を再度実行できないことです。

汎用アドオン ソリューション

これが Gmail のアドオンでない場合は、ドキュメントによると、時間ベースのトリガーで簡単に解決できます。

アドオン トリガーは、次のいずれかの状況で起動を停止します。
- アドオンがユーザーによってアンインストールされた場合
- ドキュメントでアドオンが無効にされた場合 (再度有効にすると、トリガーは再び動作可能になります) )
- 開発者がアドオンを非公開にするか、壊れたバージョンをアドオン ストアに送信した場合

つまり、毎日の日付をキー (例: LAST_SEEN) に書き込み、PropertiesService#UserPropertiesどのカードを表示するかを決定する際に TOKEN と LAST_SEEN の両方を確認します。


Gmail アドオン ソリューション:

Gmail アドオンのドキュメントによると、Gmail アドオンでApps Script のシンプルな/インストール可能なトリガーを作成または使用することはできません。したがって、ソリューションの最も簡単な実装は利用できません。LAST_SEENただし、そのキーが更新されるリージョンを移動することで、このアプローチを引き続き使用できます。

現在 (2018 年 3 月)、Gmail アドオンで使用できるトリガーはコンテキスト トリガーのみunconditionalです。

現在、使用可能なコンテキスト トリガー タイプはunconditionalのみで、コンテンツに関係なくすべてのメールに対してトリガーされます。

したがって、このコンテキスト トリガーにバインドすると、アドオンがインストールされている間、ユーザーがメールを開くたびに関数が実行されます。解決策は、コンテキストでトリガーされる関数にスニペットを含めることです

PropertiesService.getUserProperties().setProperty("LAST_SEEN", String(new Date().getTime()));

コンテキストでトリガーされる関数で他にやるべきことがある場合、そのコードはこの追加の影響を受けません。状況に応じてトリガーされる関数がない場合は、return []UI を表示しないようにするために (空のカード スタック) を使用する必要があります。

この新しいプロパティを使用するには、buildAddon(e)メソッドで、使用している TOKEN プロパティに加えて、この値をクエリする必要があります。

var userProps = PropertiesService.getUserProperties().getAll();
var Token = userProps["Token"];
var lastSeen = userProps["LAST_SEEN"] || 0; // If found, will be milliseconds since epoch.
var absence = new Date().getTime() - lastSeen; // Time in ms since last use of add-on.
if (Token == null || absence > /* some duration you choose */ ) {
  // New install, or user has started using app again.
  return [build_login_card()];
} else {
  // User is still using add-on, so do normal stuff.
}

  • これは明らかに完全な解決策ではありません (つまり、uninstallコンテキスト トリガーの方がはるかに優れています) が、使用されていない状況を検出するのに役立ちます。
  • PropertiesService に書き込む頻度にはレート制限があります。高速/「パワー」ユーザーがいる場合、クォータをトリップする可能性があります。
    • CacheService と PropertiesService を組み合わせて、「短い」セッション (最後にキャッシュに保存してから最大 6 時間) で頻繁な読み取りを処理できます。
于 2018-03-21T01:17:49.240 に答える