async function sendEmail()

in api/createRepo.ts [409:571]


async function sendEmail(req: IReposAppRequestWithCreateResponse, logic: ICustomizedNewRepositoryLogic, createContext: INewRepositoryContext, mailProvider: IMailProvider, apiKeyRow, correlationId: string, repoCreateResults, approvalRequest: RepositoryMetadataEntity, msProperties, existingRepoId: any, repository: Repository, createdUserLink: ICorporateLink): Promise<void> {
  const { config, insights, viewServices } = getProviders(req);
  const deployment = getCompanySpecificDeployment();
  const emailTemplate = deployment?.views?.email?.repository?.new || defaultMailView;
  const excludeNotificationsValue = config.notifications?.reposNotificationExcludeForUsers;
  const operations = repository.organization.operations;
  let excludeNotifications = [];
  if (excludeNotificationsValue) {
    excludeNotifications = excludeNotificationsValue.split(',');
  }
  if (approvalRequest.createdByCorporateUsername && excludeNotifications && excludeNotifications.includes(approvalRequest.createdByCorporateUsername.toLowerCase())) {
    return;
  }
  const emails = (msProperties?.notify && (msProperties.notify as string).split(',')) || [];
  getAdditionalNotificationEmails(repository).filter(email => email).map(email => {
    if (!emails.includes(email)) {
      emails.push(email);
    }
  });
  let targetType = repoCreateResults.fork ? 'Fork' : 'Repo';
  if (!repoCreateResults.fork && approvalRequest.transferSource) {
    targetType = 'Transfer';
  }
  let managerInfo: ICachedEmployeeInformation = null;
  if (operations.hasCapability(CoreCapability.Hiearchy) && approvalRequest.createdByCorporateId) {
    try {
      const opsHierarchy = operationsWithCapability<IOperationsHierarchy>(operations, CoreCapability.Hiearchy);
      managerInfo = await opsHierarchy.getCachedEmployeeManagementInformation(approvalRequest.createdByCorporateId);
    } catch (ignoreError) {
      console.dir(ignoreError);
    }
  }
  let headline = `${targetType} ready`;
  const serviceShortName = apiKeyRow && apiKeyRow.service ? apiKeyRow.service : undefined;
  let subject = serviceShortName ? `${approvalRequest.repositoryName} ${targetType.toLowerCase()} created by ${serviceShortName}` : `${approvalRequest.repositoryName} ${targetType.toLowerCase()} created`;
  if (existingRepoId) {
    subject = `${approvalRequest.repositoryName} ${targetType.toLowerCase()} ready`;
  }
  const displayHostname = req.hostname;
  const approvalScheme = displayHostname === 'localhost' && config.webServer.allowHttp === true ? 'http' : 'https';
  const reposSiteBaseUrl = `${approvalScheme}://${displayHostname}/`;
  if (repository) {
    try {
      await repository.getDetails();
    } catch (getDetailsErrorIgnored) {
      console.dir(getDetailsErrorIgnored);
    }
  }
  let additionalViewProperties: ICustomizedNewRepoProperties = null;
  try {
    if (createContext && logic) {
      additionalViewProperties = await logic.getNewMailViewProperties(createContext, repository);
    }
  } catch (err) {
    insights?.trackException({ exception: err });
    console.warn(err);
  }
  const mail = {
    to: [...emails, ...additionalViewProperties?.to],
    cc: additionalViewProperties?.cc,
    bcc: additionalViewProperties?.bcc,
    subject,
    correlationId,
    content: undefined,
  };
  if (managerInfo && managerInfo.managerMail) {
    let shouldSend = true;
    if (createContext && logic) {
      shouldSend = logic.shouldNotifyManager(createContext, approvalRequest.createdByCorporateId);
    }
    if (shouldSend) {
      if (mail.cc) {
        mail.cc.push(managerInfo.managerMail);
      } else {
        mail.cc = [managerInfo.managerMail];
      }
    }
  }
  const skuName = operations.hasCapability(CoreCapability.GitHubRestApi) ? operationsWithCapability<IOperationsGitHubRestLibrary>(operations, CoreCapability.GitHubRestApi).githubSkuName : 'GitHub';
  const app = config.brand?.companyName ? `${config.brand.companyName} ${skuName}` : skuName;
  const contentOptions = Object.assign(additionalViewProperties?.viewProperties || {} /* allow a custom provider to override */, {
    reason: `You are receiving this e-mail because the new repository request included the e-mail notification address(es) ${msProperties.notify}, or, you are the manager of the person who created the repo.`,
    headline,
    notification: 'information',
    app,
    correlationId,
    approvalRequest, // old name
    repositoryMetadataEntity: approvalRequest,
    repository,
    organization: repository ? repository.organization : null,
    createdUserLink,
    existingRepoId,
    results: repoCreateResults,
    version: config.logging.version,
    managerInfo,
    reposSiteUrl: reposSiteBaseUrl,
    liveReposSiteUrl: config.urls ? config.urls.repos : null,
    api: serviceShortName, // when used by the client single-page app, this is not considered an API call
    service: serviceShortName,
    serviceOwner: apiKeyRow ? apiKeyRow.owner : undefined,
    serviceDescription: apiKeyRow ? apiKeyRow.description : undefined,
    viewServices,
    isNotBootstrap: true,
  });
  try {
    mail.content = await RenderHtmlMail(config.typescript.appDirectory, emailTemplate, contentOptions);
  } catch (renderError) {
    req.insights.trackException({
      exception: renderError,
      properties: {
        content: contentOptions,
        eventName: 'ApiRepoCreateMailRenderFailure',
      },
    });
    throw renderError;
  }
  const customData = {
    content: contentOptions,
    receipt: null,
    eventName: undefined,
  };
  const additionalMail = { ...mail };
  try {
    insights?.trackEvent({
      name: 'ApiRepoSendMail', properties: {
        to: JSON.stringify(mail.to || ''),
        cc: JSON.stringify(mail.to || ''),
        bcc: JSON.stringify(mail.to || ''),
      }
    });
    customData.receipt = await mailProvider.sendMail(mail);
    insights?.trackEvent({ name: 'ApiRepoCreateMailSuccess', properties: customData });
    req.repoCreateResponse.notified = emails;
  } catch (mailError) {
    customData.eventName = 'ApiRepoCreateMailFailure';
    insights?.trackException({ exception: mailError, properties: customData });
  }
  // send to operations, too
  delete additionalMail.cc;
  let notifyMailAddress: string = null;
  const skipAdditionalSend = config?.notifications?.skipDedicatedNewRepoMail;
  if (operations.hasCapability(CoreCapability.Notifications)) {
    const opsNotifications = operationsWithCapability<IOperationsNotifications>(operations, CoreCapability.Notifications);
    notifyMailAddress = opsNotifications.getRepositoriesNotificationMailAddress();
  }
  const operationsMails = notifyMailAddress ? [notifyMailAddress] : [];
  if (!skipAdditionalSend && operationsMails && operationsMails.length) {
    additionalMail.to = operationsMails;
    contentOptions.reason = `You are receiving this e-mail as the operations contact address(es) ${operationsMails.join(', ')}. A repo has been created or classified.`;
    try {
      additionalMail.content = await RenderHtmlMail(config.typescript.appDirectory, emailTemplate, contentOptions);
    } catch (renderError) {
      console.dir(renderError);
      return;
    }
    try {
      await mailProvider.sendMail(additionalMail);
    } catch (ignoredError) {
      console.dir(ignoredError);
      return;
    }
  }
}