5

我正在尝试通过 log4j 发送错误电子邮件。通过使用以下附加程序:

 <appender name="ERROR_MAIL" class="org.apache.log4j.net.SMTPAppender">
   <param name="SMTPUsername" value="xxxxxx@gmail.com" />
    <param name="SMTPPassword" value="**********" />
    <param name="To" value="test@gmail.com"/>
    <param name="From" value="xxxxxx@gmail.com"/>
    <param name="Subject" value="Newyse Error "/>
    <param name="SMTPHost" value="smtp.gmail.com"/>
    <param name="SMTPPort" value="25" />
    <param name="BufferSize" value="10"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="[%d{ISO8601} %t %5p %c:$L]"/>
    </layout>
    <filter class="org.apache.log4j.varia.LevelRangeFilter">
      <param name="LevelMin" value="ERROR"/>
      <param name="LevelMax" value="FATAL"/>
    </filter>
  </appender>   

但我收到以下异常

com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.0 Must issue a STARTTLS command first. wr9sm43519864pbc.7 - gsmtp

从其他几个问题中,我了解到我需要在smtpAppender

props.put("mail.smtp.starttls.enable", "true");

那么我们如何将它添加到现有的 SMTPAppender 中呢?

4

2 回答 2

15

第一种方式:您可以扩展 SMTP 附加程序并覆盖 createSession() 方法,您可以在其中向 Java 邮件会话添加任何其他属性,例如前面提到的“mail.smtp.starttls.enable”

public class SecureSMTPAppender extends SMTPAppender {

    private boolean useStartTLS;

    public void setUseStartTLS(boolean useStartTLS) {
        this.useStartTLS = useStartTLS;
    }

    @Override
    protected Session createSession() {
        Properties props = null;
        try {
            props = new Properties(System.getProperties());
        } catch (SecurityException ex) {
            props = new Properties();
        }
        if (getSMTPHost() != null) {
            props.put("mail.smtp.host", getSMTPHost());
        }
        if (useStartTLS) {
            props.put("mail.smtp.starttls.enable", "true");
        }
        Authenticator auth = null;
        if (getSMTPPassword() != null && getSMTPUsername() != null) {
            props.put("mail.smtp.auth", "true");
            auth = new Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(getSMTPUsername(), getSMTPPassword());
                }
            };
        }
        Session session = Session.getInstance(props, auth);
        if (getSMTPDebug()) {
            session.setDebug(true);
        }
        return session;
    }
}

第二种方式:您可以使用选项 -Dmail.smtp.starttls.enable=true 启动 Java 进程。这种方法看起来更简单,但需要控制 JVM 选项;它也可能被限制性太强的 SecurityManager 破坏。

于 2013-08-13T12:26:55.413 回答
0

非常感谢@Jk1 给了我答案,让我得到了问题中提到的配置的工作代码。

import java.util.Date;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;

import org.apache.log4j.Layout;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.net.SMTPAppender;
import org.apache.log4j.spi.LoggingEvent;

import com.sun.mail.smtp.SMTPTransport;

/**
 * Extension of Log4j {@link SMTPAppender} for Gmail support
 * 
 */
public class SecureSMTPAppender extends SMTPAppender
{
  /**
   * Cached session for later use i.e. while sending emails
   */
  protected Session session;

  public SecureSMTPAppender()
  {
    super();
  }

  /**
   * Create mail session.
   * 
   * @return mail session, may not be null.
   */
  protected Session createSession()
  {
    Properties props = new Properties();
    props.put("mail.smtps.host", getSMTPHost());
    props.put("mail.smtps.auth", "true");

    Authenticator auth = null;
    if (getSMTPPassword() != null && getSMTPUsername() != null)
    {
      auth = new Authenticator()
      {
        protected PasswordAuthentication getPasswordAuthentication()
        {
          return new PasswordAuthentication(getSMTPUsername(), getSMTPPassword());
        }
      };
    }
    session = Session.getInstance(props, auth);
    if (getSMTPDebug())
    {
      session.setDebug(getSMTPDebug());
    }
    return session;
  }

  /**
   * Send the contents of the cyclic buffer as an e-mail message.
   */
  protected void sendBuffer()
  {
    try
    {
      MimeBodyPart part = new MimeBodyPart();

      StringBuffer sbuf = new StringBuffer();
      String t = layout.getHeader();
      if (t != null)
        sbuf.append(t);
      int len = cb.length();
      for (int i = 0; i < len; i++)
      {
        LoggingEvent event = cb.get();
        sbuf.append(layout.format(event));
        if (layout.ignoresThrowable())
        {
          String[] s = event.getThrowableStrRep();
          if (s != null)
          {
            for (int j = 0; j < s.length; j++)
            {
              sbuf.append(s[j]);
              sbuf.append(Layout.LINE_SEP);
            }
          }
        }
      }

      t = layout.getFooter();
      if (t != null)
        sbuf.append(t);
      part.setContent(sbuf.toString(), layout.getContentType());

      Multipart mp = new MimeMultipart();
      mp.addBodyPart(part);
      msg.setContent(mp);

      msg.setSentDate(new Date());
      send(msg);
    } catch (Exception e)
    {
      LogLog.error("Error occured while sending e-mail notification.", e);
    }
  }

  /**
   * Pulled email send stuff i.e. Transport.send()/Transport.sendMessage(). So
   * that on required this logic can be enhanced.
   * 
   * @param msg
   *          Email Message
   * @throws MessagingException
   */
  protected void send(Message msg) throws MessagingException
  {
    SMTPTransport t = (SMTPTransport) session.getTransport("smtps");
    try
    {
      t.connect(getSMTPHost(), getSMTPUsername(), getSMTPPassword());
      t.sendMessage(msg, msg.getAllRecipients());
    } finally
    {
      System.out.println("Response: " + t.getLastServerResponse());
      t.close();
    }
  }
}
于 2013-08-14T13:10:36.933 回答