Mailer.prototype._generateLinks = function()

in packages/fxa-auth-server/lib/senders/email.js [3076:3306]


  Mailer.prototype._generateLinks = function (
    primaryLink,
    message,
    query,
    templateName,
    appStoreLink,
    playStoreLink
  ) {
    const { email, uid, metricsEnabled } = message;
    // set this to avoid passing `metricsEnabled` around to all link functions
    this.metricsEnabled = metricsEnabled;

    const localizedUrls = (message) => {
      const defaultSureyUrl =
        'https://survey.alchemer.com/s3/6534408/Privacy-Security-Product-Cancellation-of-Service-Q4-21';

      const urls = {};

      if (
        config.subscriptions.productConfigsFirestore.enabled &&
        message.planConfig
      ) {
        // we are not using `determineLocale` because the product config might support more locales than the FxA supported locales list
        const locales = message.acceptLanguage ? [message.acceptLanguage] : [];
        const localizedConfigs = localizedPlanConfig(
          message.planConfig,
          locales
        );

        // the ToS and Privacy Notice URLs are actually not localized in the product config; the redirect endpoint on the payments server does that.  but we do need it in the urls object so we can overwrite the metadata ones with the Firestore ones.

        // eslint did not like ??=
        localizedConfigs['urls'] ?? (localizedConfigs['urls'] = {});
        const urlKeys = {
          termsOfServiceDownloadURL: 'termsOfServiceDownload',
          privacyNoticeDownloadURL: 'privacyNoticeDownload',
          cancellationSurveyUrl: 'cancellationSurvey',
        };
        Object.entries(urlKeys).forEach(([urlKey, configKey]) => {
          if (localizedConfigs.urls[configKey]) {
            urls[urlKey] = localizedConfigs.urls[configKey];
          }
        });
      }

      const cancellationSurveyUrl =
        (message.productMetadata &&
          message.productMetadata['product:cancellationSurveyURL']) ||
        defaultSureyUrl;
      return {
        ...productDetailsFromPlan(
          {
            product_metadata:
              message.productMetadata || message.subscription?.productMetadata,
          },
          determineLocale(message.acceptLanguage)
        ),
        cancellationSurveyUrl,
        ...urls,
      };
    };

    const {
      termsOfServiceDownloadURL = this.subscriptionTermsUrl,
      privacyNoticeDownloadURL = this.privacyUrl,
      cancellationSurveyUrl,
    } = localizedUrls(message);

    // Generate all possible links. The option to use a specific link
    // is left up to the template.
    const links = {};

    const utmContent = templateNameToContentMap[templateName];

    if (primaryLink && utmContent) {
      links['link'] = this._generateUTMLink(
        primaryLink,
        query,
        templateName,
        utmContent
      );
    }

    if (appStoreLink && utmContent) {
      links['appStoreLink'] = this._generateUTMLink(
        appStoreLink,
        query,
        templateName,
        utmContent
      );
    }

    if (playStoreLink && utmContent) {
      links['playStoreLink'] = this._generateUTMLink(
        playStoreLink,
        query,
        templateName,
        utmContent
      );
    }

    links['privacyUrl'] = this.createPrivacyLink(templateName);

    links['supportLinkAttributes'] = this._supportLinkAttributes(templateName);
    links['supportUrl'] = this.createSupportLink(templateName);
    links['subscriptionSupportUrl'] = this._generateUTMLink(
      this.subscriptionSupportUrl,
      {},
      templateName,
      'subscription-support'
    );

    links['passwordChangeLink'] = this.createPasswordChangeLink(
      email,
      templateName
    );
    links['passwordChangeLinkAttributes'] = this._passwordChangeLinkAttributes(
      email,
      templateName
    );

    links['resetLink'] = this.createPasswordResetLink(
      email,
      templateName,
      query.emailToHashWith
    );
    links['resetLinkAttributes'] = this._passwordResetLinkAttributes(
      email,
      templateName,
      query.emailToHashWith
    );

    links['androidLink'] = this._generateUTMLink(
      this.androidUrl,
      query,
      templateName,
      'connect-android'
    );
    links['iosLink'] = this._generateUTMLink(
      this.iosUrl,
      query,
      templateName,
      'connect-ios'
    );

    links['passwordManagerInfoUrl'] = this._generateUTMLink(
      this.passwordManagerInfoUrl,
      query,
      templateName,
      'password-info'
    );

    links['reportSignInLink'] = this.createReportSignInLink(
      templateName,
      query
    );
    links['reportSignInLinkAttributes'] = this._reportSignInLinkAttributes(
      email,
      templateName,
      query
    );

    links['revokeAccountRecoveryLink'] =
      this.createRevokeAccountRecoveryLink(templateName);
    links['revokeAccountRecoveryLinkAttributes'] =
      this._revokeAccountRecoveryLinkAttributes(templateName);

    links['createAccountRecoveryLink'] =
      this.createAccountRecoveryLink(templateName);

    links.accountSettingsUrl = this._generateUTMLink(
      this.accountSettingsUrl,
      { ...query, email, uid },
      templateName,
      'account-settings'
    );
    links.accountSettingsLinkAttributes = `href="${links.accountSettingsUrl}" target="_blank" rel="noopener noreferrer" style="color:#ffffff;font-weight:500;"`;

    links.cancellationSurveyUrl = cancellationSurveyUrl;

    links.cancellationSurveyLinkAttributes = `href="${links.cancellationSurveyUrl}" style="text-decoration: none; color: #0060DF;"`;

    links.subscriptionTermsUrl = this._legalDocsRedirectUrl(
      this._generateUTMLink(
        termsOfServiceDownloadURL,
        {},
        templateName,
        'subscription-terms'
      )
    );
    links.subscriptionPrivacyUrl = this._legalDocsRedirectUrl(
      this._generateUTMLink(
        privacyNoticeDownloadURL,
        {},
        templateName,
        'subscription-privacy'
      )
    );
    links.cancelSubscriptionUrl = this._generateUTMLink(
      this.subscriptionSettingsUrl,
      { ...query, email, uid },
      templateName,
      'cancel-subscription'
    );
    links.reactivateSubscriptionUrl = this._generateUTMLink(
      this.subscriptionSettingsUrl,
      { ...query, email, uid },
      templateName,
      'reactivate-subscription'
    );
    links.updateBillingUrl = this._generateUTMLink(
      this.subscriptionSettingsUrl,
      { ...query, email, uid },
      templateName,
      'update-billing'
    );

    links.unsubscribeUrl = this.unsubscribeUrl;

    const queryOneClick = extend(query, { one_click: true });
    if (primaryLink && utmContent) {
      links['oneClickLink'] = this._generateUTMLink(
        primaryLink,
        queryOneClick,
        templateName,
        `${utmContent}-oneclick`
      );
    }

    return links;
  };