简体   繁体   中英

How can i set TO address at runtime with log4j2 SMTPAppender

I'm converting a simple java healthcheck application we use from using log4j1 to log4j2-17.2. It currently uses a custom SMTPAppender which extends the built in one to set subject and To address at runtime from values in the logged event.

In log4j2 can't do that as the SMTPAppender plugin class is final. Have got it working using the built in one for subject using a ThreadContext lookup, but that doesn't work for TO address and struggling to find anyway to set the To address that works.

This is what I have so far

For subject the SMTPAppender config is:

<SMTP   name="ErrorMail"
                subject="$${ctx:subject:-Int HealthCheck Error}" 
                to="user@company.com" 
                from="support@company.com"
                smtpHost="ldnsmtp" 
                smtpPort="25" 
                bufferSize="2000" 
                ignoreExceptions="true">
                <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            <EmailLoggerLayout />               
          </SMTP>

With this code setting the subject then logging the event. This works and the subject appears in the email OK

            if (healthCheckAlert.getSubject() != null) {
                ThreadContext.put("subject", subjectPrefix + healthCheckAlert.getSubject());
            }
            warningSender.log(level, message);

For the To address I'm trying this to use a ThreadContext variable in same way:

         <SMTP  name="WarningMail" 
                subject="$${ctx:subject:-Int HealthCheck Warning}"
                to="$${ctx:mailto}" 
                from="support@company.com"
                smtpHost="ldnsmtp" 
                smtpPort="25" 
                bufferSize="2000" 
                ignoreExceptions="true">
                <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> 
                <EmailLoggerLayout />               
         </SMTP>

With this code to set it:

        if (healthCheckAlert.getMailTo() != null) {
            ThreadContext.put("mailto", healthCheckAlert.getMailTo());
        }

But get the error below, which indicates it hasn't been expanded

2023-01-05 12:40:25,951 main ERROR SmtpManager SMTP:${ctx:mailto}:::support@company.com::${ctx:subject:-Int HealthCheck Warning}:smtp:ldnsmtp:25:::INFO Could not set SmtpAppender message options: javax.mail.internet.AddressException: Local address contains illegal character in string ``${ctx:mailto}'' javax.mail.internet.AddressException: Local address contains illegal character in string ``${ctx:mailto}''
    at javax.mail.internet.InternetAddress.checkAddress(InternetAddress.java:1216)
    at javax.mail.internet.InternetAddress.parse(InternetAddress.java:1091)
    at javax.mail.internet.InternetAddress.parse(InternetAddress.java:633)
    at org.apache.logging.log4j.core.net.MimeMessageBuilder.parseAddresses(MimeMessageBuilder.java:99)
    at org.apache.logging.log4j.core.net.MimeMessageBuilder.setRecipients(MimeMessageBuilder.java:66)
    at org.apache.logging.log4j.core.net.SmtpManager.createMimeMessage(SmtpManager.java:71)
    at org.apache.logging.log4j.core.net.SmtpManager.connect(SmtpManager.java:340)
    at org.apache.logging.log4j.core.net.SmtpManager.sendEvents(SmtpManager.java:172)
    at org.apache.logging.log4j.core.appender.SmtpAppender.append(SmtpAppender.java:353)
    at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:161)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:134)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:125)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:89)
    at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:675)
    at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:633)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:616)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:552)
    at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:82)
    at org.apache.logging.log4j.core.Logger.log(Logger.java:161)
    at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2205)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2159)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2142)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:1994)
    at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1852)
    at org.apache.logging.log4j.spi.AbstractLogger.log(AbstractLogger.java:1642)
    at com.company.utils.healthcheck.logging.EmailLogger.log(EmailLogger.java:42)
    at com.company.utils.healthcheck.EmailLoggerTest.testWarnAlert(EmailLoggerTest.java:42)

Have done a lot of searching to find a way to do this to no avail. Can anyone let me know if this can be done with the ThreadContext lookup somehow, or is that just not possible in log4j2 for the TO address? If so any clues on some other way to do this?.

My current backstop idea is to make our own copy of the SMTPAppender class using the log4j2 source code and modify that, but would rather not.

The SMTPAppender only evaluates the subject of an e-mail as a pattern . The remaining fields are immutable.

What you can do is to use RoutingAppender to create a different SMTP appender per e-mail recipient. Something like this should work (I didn't test it):

<Routing name="Routing">
  <Routes pattern="$${ctx:mailto}">
    <Route>
         <SMTP  name="WarningMail" 
                subject="$${ctx:subject:-Int HealthCheck Warning}"
                to="${ctx:mailto}" 
                from="support@company.com"
                smtpHost="ldnsmtp" 
                smtpPort="25" 
                bufferSize="2000" 
                ignoreExceptions="true">
                <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> 
                <EmailLoggerLayout />               
         </SMTP>
    </Route>
  </Routes>
  <IdlePurgePolicy timeToLive="15" timeUnit="minutes"/>
</Routing>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM