Spring Boot - 使用Logback发送电子邮件

26

我正在尝试配置Logback,使其在发生异常(日志级别:ERROR)时发送电子邮件。到目前为止,我尚未能够使其工作,因此我想请求您在配置方面提供帮助。

我有一个Spring Boot应用程序,在其中执行某些处理:

private void foo() {
 try {
  // do something
 } catch (Exception e) {
  log.error("Logging my exception");
 }
}

每当记录了这个错误时,我希望能够触发一封电子邮件。我按照一些教程的步骤进行操作,将logback.xmlsmtp-appender.xml添加到我的resources目录中:

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml" />
    <include resource="smtp-appender.xml" />
    <logger name="com.mycompany" level="DEBUG">
        <appender-ref ref="SMTP" />
    </logger>
</configuration>

smtp-appender.xml

<?xml version="1.0" encoding="UTF-8"?>

<included>
    <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender">
        <smtpHost>xxx</smtpHost>
        <username>user</username>
        <password>password</password>

        <to>test@email.com</to>
        <from>me@email.com</from>
        <subject>testError</subject>

        <layout class="ch.qos.logback.classic.html.HTMLLayout" />

    </appender>
</included>

我已经通过sendmail在本地主机上设置了本地SMTP服务器。我也尝试过AWS SMTP服务器和Gmail,但目前这些服务都无法工作。

问题是在异常之后我没有收到任何电子邮件,并且日志记录中没有与其对应的输出(当然除了log.error()输出之外),这让我认为应用程序甚至不知道这些配置文件的存在...

这是我的pom.xml中的Maven依赖项:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.5.RELEASE</version>
    <relativePath />
    <!-- lookup parent from repository -->
</parent>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20141113</version>
    </dependency>
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>mail</artifactId>
        <version>1.4</version>
    </dependency>
</dependencies>

非常感谢任何帮助。


我没有看到您的pom文件中包含JavaBeans激活框架,但是发送邮件需要它。 - Deh
我已经将依赖项添加到pom中:http://mvnrepository.com/artifact/javax.activation/activation/1.1.1,但它并没有解决问题。 - Smajl
不包括logback和slf4j。 - Deh
它们被包含在 Spring 中... 我正在使用 Slf4j 记录到控制台和日志文件中。 - Smajl
尝试将邮件属性设置为调试模式,这样您就可以在主日志中看到JAVA和邮件提供商之间发生的情况。 - Angelo Immediata
1
我建议另一种想法——您确定真的想在记录错误时每次都发送电子邮件吗?那么,是否考虑使用单独的服务来聚合日志文件并扫描它们,在发现第一个错误时发送电子邮件(或任何其他推送通知),但例如不频繁超过5分钟1次,以避免淹没您的收件箱? - Bernhard
3个回答

3

smtpappender的默认端口是25,gmail使用smtp服务进行身份验证,您需要使用587端口进行TLS和465端口进行SSL。

我认为这可能是您的问题所在。

首先在本地机器上设置邮件服务器而不进行身份验证,尝试一下是否可以工作。然后再尝试找出如何为gmail配置它。

来自页面http://logback.qos.ch/manual/appenders.html#gmailSTARTTLS

Gmail的SMTPAppender(STARTTLS)

<configuration>   
  <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
    <smtpHost>smtp.gmail.com</smtpHost>
    <smtpPort>587</smtpPort>
    <STARTTLS>true</STARTTLS>
    <username>YOUR_USERNAME@gmail.com</username>
    <password>YOUR_GMAIL_xPASSWORD</password>
    
    <to>EMAIL-DESTINATION</to>
    <to>ANOTHER_EMAIL_DESTINATION</to> <!-- additional destinations are possible -->
    <from>YOUR_USERNAME@gmail.com</from>
    <subject>TESTING: %logger{20} - %m</subject>
    <layout class="ch.qos.logback.classic.PatternLayout">
      <pattern>%date %-5level %logger - %message%n</pattern>
    </layout>       
  </appender>

  <root level="DEBUG">
    <appender-ref ref="EMAIL" />
  </root>  
</configuration>

我已经尝试从本地主机发送电子邮件(我在本地设置了sendmail SMTP服务器),但也没有成功。我相信问题不在于指定端口和主机配置,而是整个集成总体上存在问题... - Smajl
@Smajl,也许在你的配置下,它根本不会起作用。如果你认为是集成的问题,请尝试调试你的应用程序,检查是否有任何东西被传递到 appender,以及那里发生了什么神奇的事情。 - user902383
这个有效。感谢您的帮助,实际上是感谢您提供的链接。因为XML结构似乎有些变化。所以我通过您分享的链接找到了方法。再次感谢。 - leventunver

3
请在pom.xml和logback.xml中添加以下内容(来自我的工作项目),以便获取错误邮件:

pom.xml

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.6.4</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.0.1</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>1.6.4</version>
    </dependency>
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>mail</artifactId>
        <version>1.4</version>
    </dependency>

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="errMailer" class="ch.qos.logback.classic.net.SMTPAppender">
      <smtpHost>xxx</smtpHost>
      <smtpPort>25</smtpPort>
      <from>me@gmail.com</from>
      <to>you@gmail.com</to>
      <subjectStr>App Err Mail</subjectStr>
      <layout class="ch.qos.logback.classic.html.HTMLLayout"/>
      <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
          <level>ERROR</level>
      </filter>
  </appender>
    <root level="ERROR">
        <appender-ref ref="errMailer" />
    </root>
</configuration>

谢谢您的回答,但这并没有解决问题。 - Smajl
1
这是我活跃项目中的一段可工作代码。请分享您使用后遇到的问题细节,并提供支持错误堆栈跟踪。 - Avis
不确定要包括什么...我使用了你的代码,控制台显示了错误消息,但没有触发电子邮件(或者它被触发了,但我没有收到)。你所说的“支持错误堆栈跟踪”是什么意思?我使用的是级别:DEBUG,它支持ERRORs。 - Smajl
我认为最有可能的是您的网络不允许触发邮件发送。 - Avis

0

您需要启用基于标记的电子邮件触发。

在SMTP appender下的logback.xml中包含一个评估器,请参考下面的链接。

http://logback.qos.ch/manual/appenders.html#OnMarkerEvaluator

然后在你的异常捕获块中添加以下逻辑,如果你想像下面一样发送电子邮件,则将标记对象传递给日志记录器方法 -

Marker notifyAdmin = MarkerFactory.getMarker("NOTIFY_ADMIN");
logger.error(notifyAdmin,
  "This is a serious an error requiring the admin's attention",
   new Except
ion("Just testing"));

在某些情况下,您可能不想发送电子邮件,只想记录异常,那么就不要将标记对象传递给记录器方法。

logger.error("This is a serious an error requiring the admin's attention",
   new Except
ion("Just testing"));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接