code: func ComputeRecipients(notifications notifypb.Notifications, inputBlame []*gitpb.Commit, outputBlame Logs) []EmailNotify {
  	recipients := make([]EmailNotify, 0)
  	for _, notification := range notifications.GetNotifications() {
  		// Aggregate the static list of recipients from the Notifications.
  		for _, recipient := range notification.GetEmail().GetRecipients() {
  			recipients = append(recipients, EmailNotify{
  				Email:    recipient,
  				Template: notification.Template,
  			})
  		}
  
  		// Don't bother dealing with anything blamelist related if there's no config for it.
  		if notification.NotifyBlamelist == nil {
  			continue
  		}
  
  		// If the whitelist is empty, use the static blamelist.
  		whitelist := notification.NotifyBlamelist.GetRepositoryWhitelist()
  		if len(whitelist) == 0 {
  			recipients = append(recipients, commitsBlamelist(inputBlame, notification.Template)...)
  			continue
  		}
  
  		// If the whitelist is non-empty, use the dynamic blamelist.
  		whiteset := stringset.NewFromSlice(whitelist...)
  		recipients = append(recipients, outputBlame.Filter(whiteset).Blamelist(notification.Template)...)
  	}
  	return recipients
  }
docs: // ComputeRecipients computes the set of recipients given a set of
  // notifications, and potentially "input" and "output" blamelists.
  //
  // An "input" blamelist is computed from the input commit to a build, while an
  // "output" blamelist is derived from output commits.