Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Logback: the reliable, generic, fast and flexible logging framework. Copyright (C) 1999-2011, QOS.ch. All rights reserved. This program and the accompanying materials are dual-licensed under either the terms of the Eclipse Public License v1.0 as published by the Eclipse Foundation or (per the licensee's choosing) under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation.
 
 package ch.qos.logback.core.net;
 
 import java.util.Date;
 import java.util.List;
 
 import  javax.mail.Message;
 import  javax.mail.MessagingException;
 import  javax.mail.Multipart;
 import  javax.mail.Session;
 import  javax.mail.Transport;
 import  javax.mail.internet.AddressException;
 import  javax.mail.internet.InternetAddress;
 import  javax.mail.internet.MimeBodyPart;
 import  javax.mail.internet.MimeMessage;
 import  javax.mail.internet.MimeMultipart;
 
 
 // Contributors:
 // Andrey Rybin charset encoding support http://jira.qos.ch/browse/LBCORE-69
 
An abstract class that provides support for sending events to an email address.

See http://logback.qos.ch/manual/appenders.html#SMTPAppender for further documentation.

Author(s):
Ceki Gülcü
Sébastien Pennec
 
 public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
 
   static InternetAddress[] EMPTY_IA_ARRAY = new InternetAddress[0];
   // ~ 14 days
 
   long lastTrackerStatusPrint = 0;
 
   protected Layout<E> subjectLayout;
   protected Layout<E> layout;
 
   private String from;
   private String subjectStr = null;
   private String smtpHost;
   private int smtpPort = 25;
   private boolean starttls = false;
   private boolean ssl = false;
   private boolean sessionViaJNDI = false;
   private String jndiLocation = . + "/mail/Session";
 
 
 
   boolean asynchronousSending = true;
 
   private String charsetEncoding = "UTF-8";
 
   protected MimeMessage mimeMsg;
 
   protected EventEvaluator<E> eventEvaluator;
 
   protected Discriminator<E> discriminator = new DefaultDiscriminator<E>();
   protected CyclicBufferTracker<E> cbTracker;
  private int errorCount = 0;

  
return a layout for the subject string as appropriate for the module. If the subjectStr parameter is null, then a default value for subjectStr should be used.

Parameters:
subjectStr
Returns:
a layout as appropriate for the module
  abstract protected Layout<E> makeSubjectLayout(String subjectStr);

  
Start the appender
  public void start() {
    if ( == null) {
       = new CyclicBufferTrackerImpl<E>();
    }
    Session session = null;
    if ()
      session = lookupSessionInJNDI();
    else
      session = buildSessionFromProperties();
    if (session == null) {
      addError("Failed to obtain javax.mail.Session. Cannot start.");
      return;
    }
     = new MimeMessage(session);
    try {
      if ( != null) {
        .setFrom(getAddress());
      } else {
        .setFrom();
      }
       = true;
    } catch (MessagingException e) {
      addError("Could not activate SMTPAppender options."e);
    }
  }
  private Session lookupSessionInJNDI() {
    addInfo("Looking up javax.mail.Session at JNDI location [" +  + "]");
    try {
      Context initialContext = new InitialContext();
      Object obj = initialContext.lookup();
      return (Session) obj;
    } catch (Exception e) {
      addError("Failed to obtain javax.mail.Session from JNDI location [" + +"]");
      return null;
    }
  }
  private Session buildSessionFromProperties() {
    Properties props = new Properties(OptionHelper.getSystemProperties());
    if ( != null) {
      props.put("mail.smtp.host");
    }
    props.put("mail.smtp.port", Integer.toString());
    if ( != null) {
      props.put("mail.smtp.localhost");
    }
    LoginAuthenticator loginAuthenticator = null;
    if ( != null) {
      loginAuthenticator = new LoginAuthenticator();
      props.put("mail.smtp.auth""true");
    }
    if (isSTARTTLS() && isSSL()) {
      addError("Both SSL and StartTLS cannot be enabled simultaneously");
    } else {
      if (isSTARTTLS()) {
        // see also http://jira.qos.ch/browse/LBCORE-225
        props.put("mail.smtp.starttls.enable""true");
      }
      if (isSSL()) {
        String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
        props.put("mail.smtp.socketFactory.port", Integer.toString());
        props.put("mail.smtp.socketFactory.class"SSL_FACTORY);
        props.put("mail.smtp.socketFactory.fallback""true");
      }
    }
    // props.put("mail.debug", "true");
    return Session.getInstance(propsloginAuthenticator);
  }

  
Perform SMTPAppender specific appending actions, delegating some of them to a subclass and checking if the event triggers an e-mail to be sent.
  protected void append(E eventObject) {
    if (!checkEntryConditions()) {
      return;
    }
    String key = .getDiscriminatingValue(eventObject);
    long now = System.currentTimeMillis();
    final CyclicBuffer<E> cb = .getOrCreate(keynow);
    subAppend(cbeventObject);
    try {
      if (.evaluate(eventObject)) {
        // clone the CyclicBuffer before sending out asynchronously
        CyclicBuffer<E> cbClone = new CyclicBuffer<E>(cb);
        // see http://jira.qos.ch/browse/LBCLASSIC-221
        cb.clear();
        if () {
          // perform actual sending asynchronously
          SenderRunnable senderRunnable = new SenderRunnable(cbCloneeventObject);
          .getExecutorService().execute(senderRunnable);
        } else {
          // synchronous sending
          sendBuffer(cbCloneeventObject);
        }
      }
    } catch (EvaluationException ex) {
      ++;
        addError("SMTPAppender's EventEvaluator threw an Exception-"ex);
      }
    }
    // immediately remove the buffer if asked by the user
    if (isEventMarkedForBufferRemoval(eventObject)) {
      .removeBuffer(key);
    }
      addInfo("SMTPAppender [" +  + "] is tracking [" + .size() + "] buffers");
       = now;
      // quadruple 'delay' assuming less than max delay
         *= 4;
      }
    }
  }
  abstract protected boolean isEventMarkedForBufferRemoval(E eventObject);
  abstract protected void subAppend(CyclicBuffer<E> cb, E eventObject);

  
This method determines if there is a sense in attempting to append.

It checks whether there is a set output target and also if there is a set layout. If these checks fail, then the boolean value false is returned.

  public boolean checkEntryConditions() {
    if (!this.) {
      addError("Attempting to append to a non-started appender: "
              + this.getName());
      return false;
    }
    if (this. == null) {
      addError("Message object not configured.");
      return false;
    }
    if (this. == null) {
      addError("No EventEvaluator is set for appender [" +  + "].");
      return false;
    }
    if (this. == null) {
      addError("No layout set for appender named ["
              + 
              + "]. For more information, please visit http://logback.qos.ch/codes.html#smtp_no_layout");
      return false;
    }
    return true;
  }
  synchronized public void stop() {
    this. = false;
  }
  InternetAddress getAddress(String addressStr) {
    try {
      return new InternetAddress(addressStr);
    } catch (AddressException e) {
      addError("Could not parse address [" + addressStr + "]."e);
      return null;
    }
  }
  private List<InternetAddress> parseAddress(E event) {
    int len = .size();
    List<InternetAddress> iaList = new ArrayList<InternetAddress>();
    for (int i = 0; i < leni++) {
      try {
        PatternLayoutBase<E> emailPL = .get(i);
        String email = emailPL.doLayout(event);
        if (email == null || email.length() == 0) {
          continue;
        }
        InternetAddress[] tmp = InternetAddress.parse(emailtrue);
        iaList.addAll(Arrays.asList(tmp));
      } catch (AddressException e) {
        addError("Could not parse email address for [" + .get(i) + "] for event [" + event + "]"e);
        return iaList;
      }
    }
    return iaList;
  }

  
Returns value of the toList option.
  public List<PatternLayoutBase<E>> getToList() {
    return ;
  }

  
Send the contents of the cyclic buffer as an e-mail message.
  protected void sendBuffer(CyclicBuffer<E> cb, E lastEventObject) {
    // Note: this code already owns the monitor for this
    // appender. This frees us from needing to synchronize on 'cb'.
    try {
      MimeBodyPart part = new MimeBodyPart();
      StringBuffer sbuf = new StringBuffer();
      String header = .getFileHeader();
      if (header != null) {
        sbuf.append(header);
      }
      String presentationHeader = .getPresentationHeader();
      if (presentationHeader != null) {
        sbuf.append(presentationHeader);
      }
      fillBuffer(cbsbuf);
      String presentationFooter = .getPresentationFooter();
      if (presentationFooter != null) {
        sbuf.append(presentationFooter);
      }
      String footer = .getFileFooter();
      if (footer != null) {
        sbuf.append(footer);
      }
      String subjectStr = "Undefined subject";
      if ( != null) {
        subjectStr = .doLayout(lastEventObject);
      }
      .setSubject(subjectStr);
      List<InternetAddress> destinationAddresses = parseAddress(lastEventObject);
      if (destinationAddresses.isEmpty()) {
        addInfo("Empty destination address. Aborting email transmission");
        return;
      }
      InternetAddress[] toAddressArray = destinationAddresses.toArray();
      .setRecipients(Message.RecipientType.TO, toAddressArray);
      String contentType = .getContentType();
      if (ContentTypeUtil.isTextual(contentType)) {
        part.setText(sbuf.toString(), , ContentTypeUtil
                .getSubType(contentType));
      } else {
        part.setContent(sbuf.toString(), .getContentType());
      }
      Multipart mp = new MimeMultipart();
      mp.addBodyPart(part);
      .setContent(mp);
      .setSentDate(new Date());
      Transport.send();
      addInfo("Sent out SMTP message \"" + subjectStr + "\" to " + Arrays.toString(toAddressArray));
    } catch (Exception e) {
      addError("Error occurred while sending e-mail notification."e);
    }
  }
  abstract protected void fillBuffer(CyclicBuffer<E> cbStringBuffer sbuf);

  
Returns value of the From option.
  public String getFrom() {
    return ;
  }

  
Returns value of the Subject option.
  public String getSubject() {
    return ;
  }

  
The From option takes a string value which should be a e-mail address of the sender.
  public void setFrom(String from) {
    this. = from;
  }

  
The Subject option takes a string value which should be a the subject of the e-mail message.
  public void setSubject(String subject) {
    this. = subject;
  }

  
Alias for smtpHost

Parameters:
smtpHost
  public void setSMTPHost(String smtpHost) {
    setSmtpHost(smtpHost);
  }

  
The smtpHost option takes a string value which should be a the host name of the SMTP server that will send the e-mail message.
  public void setSmtpHost(String smtpHost) {
    this. = smtpHost;
  }

  
Alias for getSmtpHost().
  public String getSMTPHost() {
    return getSmtpHost();
  }

  
Returns value of the SMTPHost option.
  public String getSmtpHost() {
    return ;
  }

  
Alias for setSmtpPort.

Parameters:
port
  public void setSMTPPort(int port) {
    setSmtpPort(port);
  }

  
The port where the SMTP server is running. Default value is 25.

Parameters:
port
  public void setSmtpPort(int port) {
    this. = port;
  }

  
Alias for getSmtpPort

Returns:
  public int getSMTPPort() {
    return getSmtpPort();
  }

  
See setSmtpPort

Returns:
  public int getSmtpPort() {
    return ;
  }
  public String getLocalhost() {
    return ;
  }

  
Set the "mail.smtp.localhost" property to the value passed as parameter to this method.

Useful in case the hostname for the client host is not fully qualified and as a consequence the SMTP server rejects the clients HELO/EHLO command.

Parameters:
localhost
  public void setLocalhost(String localhost) {
    this. = localhost;
  }
    return ;
  }
  public void setCyclicBufferTracker(CyclicBufferTracker<E> cbTracker) {
    this. = cbTracker;
  }
  public Discriminator<E> getDiscriminator() {
    return ;
  }
  public void setDiscriminator(Discriminator<E> discriminator) {
    this. = discriminator;
  }
  public boolean isAsynchronousSending() {
    return ;
  }

  
By default, SMTAppender transmits emails asynchronously. For synchronous email transmission set asynchronousSending to 'false'.

Parameters:
asynchronousSending determines whether sending is done asynchronously or not
Since:
1.0.4
  public void setAsynchronousSending(boolean asynchronousSending) {
    this. = asynchronousSending;
  }
  public void addTo(String to) {
    if (to == null || to.length() == 0) {
      throw new IllegalArgumentException("Null or empty <to> property");
    }
    plb.setContext();
    plb.start();
    this..add(plb);
  }
  abstract protected PatternLayoutBase<E> makeNewToPatternLayout(String toPattern);
    List<StringtoList = new ArrayList<String>();
    for (PatternLayoutBase plb : ) {
      toList.add(plb.getPattern());
    }
    return toList;
  }
  // for testing purpose only
  public Message getMessage() {
    return ;
  }
  // for testing purpose only
  public void setMessage(MimeMessage msg) {
    this. = msg;
  }
  public boolean isSTARTTLS() {
    return ;
  }
  public void setSTARTTLS(boolean startTLS) {
    this. = startTLS;
  }
  public boolean isSSL() {
    return ;
  }
  public void setSSL(boolean ssl) {
    this. = ssl;
  }

  
The EventEvaluator option takes a string value representing the name of the class implementing the EventEvaluator interface. A corresponding object will be instantiated and assigned as the event evaluator for the SMTPAppender.
  public void setEvaluator(EventEvaluator<E> eventEvaluator) {
    this. = eventEvaluator;
  }
  public String getUsername() {
    return ;
  }
  public void setUsername(String username) {
    this. = username;
  }
  public String getPassword() {
    return ;
  }
  public void setPassword(String password) {
    this. = password;
  }

  

Returns:
the charset encoding value
See also:
setCharsetEncoding(String)
  public String getCharsetEncoding() {
    return ;
  }
  public String getJndiLocation() {
    return ;
  }

  
Set the location where a javax.mail.Session resource is located in JNDI. Default value is "java:comp/env/mail/Session".

Parameters:
jndiLocation
Since:
1.0.6
  public void setJndiLocation(String jndiLocation) {
    this. = jndiLocation;
  }
  public boolean isSessionViaJNDI() {
    return ;
  }

  
If set to true, a javax.mail.Session resource will be retrieved from JNDI. Default is false.

Parameters:
sessionViaJNDI whether to obtain a javax.mail.Session by JNDI
Since:
1.0.6
  public void setSessionViaJNDI(boolean sessionViaJNDI) {
    this. = sessionViaJNDI;
  }

  
Set the character set encoding of the outgoing email messages. The default encoding is "UTF-8" which usually works well for most purposes.

Parameters:
charsetEncoding
  public void setCharsetEncoding(String charsetEncoding) {
    this. = charsetEncoding;
  }
  public Layout<E> getLayout() {
    return ;
  }
  public void setLayout(Layout<E> layout) {
    this. = layout;
  }
  class SenderRunnable implements Runnable {
    final CyclicBuffer<E> cyclicBuffer;
    final E e;
    SenderRunnable(CyclicBuffer<E> cyclicBuffer, E e) {
      this. = cyclicBuffer;
      this. = e;
    }
    public void run() {
      sendBuffer();
    }
  }
New to GrepCode? Check out our FAQ X