class SendMailPublisher implements Publisher {

    private static final Logger LOGGER = Logger.getLogger(SendMailPublisher.class);
    private static final PebbleEngine ENGINE = new PebbleEngine.Builder().newLineTrimming(false).build();

    public void inform(final PublishContext ctx, final Notification notification, final JsonObject config) {<FILL_FUNCTION_BODY>}

    public void inform(final PublishContext ctx, final Notification notification, final JsonObject config, List<Team> teams) {
        if (config == null) {
            LOGGER.warn("No configuration found. Skipping notification. (%s)".formatted(ctx));
            return;
        }
        final String[] destinations = parseDestination(config, teams);
        sendNotification(ctx, notification, config, destinations);
    }

    private void sendNotification(final PublishContext ctx, Notification notification, JsonObject config, String[] destinations) {
        if (config == null) {
            LOGGER.warn("No publisher configuration found; Skipping notification (%s)".formatted(ctx));
            return;
        }
        if (destinations == null) {
            LOGGER.warn("No destination(s) provided; Skipping notification (%s)".formatted(ctx));
            return;
        }

        final String content;
        final String mimeType;
        try {
            final PebbleTemplate template = getTemplate(config);
            mimeType = getTemplateMimeType(config);
            content = prepareTemplate(notification, template);
        } catch (IOException | RuntimeException e) {
            LOGGER.error("Failed to prepare notification content (%s)".formatted(ctx), e);
            return;
        }

        final boolean smtpEnabled;
        final String smtpFrom;
        final String smtpHostname;
        final int smtpPort;
        final String smtpUser;
        final String encryptedSmtpPassword;
        final boolean smtpSslTls;
        final boolean smtpTrustCert;
        String emailSubjectPrefix;

        try (QueryManager qm = new QueryManager()) {
            smtpEnabled = qm.isEnabled(EMAIL_SMTP_ENABLED);
            if (!smtpEnabled) {
                LOGGER.warn("SMTP is not enabled; Skipping notification (%s)".formatted(ctx));
                return;
            }

            smtpFrom = qm.getConfigProperty(EMAIL_SMTP_FROM_ADDR.getGroupName(), EMAIL_SMTP_FROM_ADDR.getPropertyName()).getPropertyValue();
            emailSubjectPrefix = qm.getConfigProperty(EMAIL_PREFIX.getGroupName(), EMAIL_PREFIX.getPropertyName()).getPropertyValue();
            emailSubjectPrefix = emailSubjectPrefix == null ? " " : emailSubjectPrefix;
            smtpHostname = qm.getConfigProperty(EMAIL_SMTP_SERVER_HOSTNAME.getGroupName(), EMAIL_SMTP_SERVER_HOSTNAME.getPropertyName()).getPropertyValue();
            smtpPort = Integer.parseInt(qm.getConfigProperty(EMAIL_SMTP_SERVER_PORT.getGroupName(), EMAIL_SMTP_SERVER_PORT.getPropertyName()).getPropertyValue());
            smtpUser = qm.getConfigProperty(EMAIL_SMTP_USERNAME.getGroupName(), EMAIL_SMTP_USERNAME.getPropertyName()).getPropertyValue();
            encryptedSmtpPassword = qm.getConfigProperty(EMAIL_SMTP_PASSWORD.getGroupName(), EMAIL_SMTP_PASSWORD.getPropertyName()).getPropertyValue();
            smtpSslTls = qm.isEnabled(EMAIL_SMTP_SSLTLS);
            smtpTrustCert = qm.isEnabled(EMAIL_SMTP_TRUSTCERT);
        } catch (RuntimeException e) {
            LOGGER.error("Failed to load SMTP configuration from datastore (%s)".formatted(ctx), e);
            return;
        }

        final boolean smtpAuth = (smtpUser != null && encryptedSmtpPassword != null);
        final String decryptedSmtpPassword;
        try {
            decryptedSmtpPassword = (encryptedSmtpPassword != null) ? DataEncryption.decryptAsString(encryptedSmtpPassword) : null;
        } catch (Exception e) {
            LOGGER.error("Failed to decrypt SMTP password (%s)".formatted(ctx), e);
            return;
        }

        try {
            final SendMail sendMail = new SendMail()
                    .from(smtpFrom)
                    .to(destinations)
                    .subject(emailSubjectPrefix + " " + notification.getTitle())
                    .body(content)
                    .bodyMimeType(mimeType)
                    .host(smtpHostname)
                    .port(smtpPort)
                    .username(smtpUser)
                    .password(decryptedSmtpPassword)
                    .smtpauth(smtpAuth)
                    .useStartTLS(smtpSslTls)
                    .trustCert(smtpTrustCert);
            sendMail.send();
        } catch (SendMailException | RuntimeException e) {
            LOGGER.error("Failed to send notification email via %s:%d (%s)"
                    .formatted(smtpHostname, smtpPort, ctx), e);
            return;
        }

        if (ctx.shouldLogSuccess()) {
            LOGGER.info("Notification email sent successfully via %s:%d (%s)"
                    .formatted(smtpHostname, smtpPort, ctx));
        }
  }

    @Override
    public PebbleEngine getTemplateEngine() {
        return ENGINE;
    }

    static String[] parseDestination(final JsonObject config) {
        JsonString destinationString = config.getJsonString("destination");
        if ((destinationString == null) || destinationString.getString().isEmpty()) {
          return null;
        }
        return destinationString.getString().split(",");
    }

    static String[] parseDestination(final JsonObject config, final List<Team> teams) {
        String[] destination = teams.stream().flatMap(
                team -> Stream.of(
                                Optional.ofNullable(config.getJsonString("destination"))
                                        .map(JsonString::getString)
                                        .stream()
                                        .flatMap(dest -> Arrays.stream(dest.split(",")))
                                        .filter(Predicate.not(String::isEmpty)),
                                Optional.ofNullable(team.getManagedUsers()).orElseGet(Collections::emptyList).stream().map(ManagedUser::getEmail).filter(Objects::nonNull),
                                Optional.ofNullable(team.getLdapUsers()).orElseGet(Collections::emptyList).stream().map(LdapUser::getEmail).filter(Objects::nonNull),
                                Optional.ofNullable(team.getOidcUsers()).orElseGet(Collections::emptyList).stream().map(OidcUser::getEmail).filter(Objects::nonNull)
                        )
                        .reduce(Stream::concat)
                        .orElseGet(Stream::empty)
                )
                .distinct()
                .toArray(String[]::new);
        return destination.length == 0 ? null : destination;
    }
}

        if (config == null) {
            LOGGER.warn("No configuration found; Skipping notification (%s)".formatted(ctx));
            return;
        }
        final String[] destinations = parseDestination(config);
        sendNotification(ctx, notification, config, destinations);
    
<no_super_class>