All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pentaho.di.trans.steps.mail.Mail Maven / Gradle / Ivy

The newest version!
/*! ******************************************************************************
 *
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2017 by Hitachi Vantara : http://www.pentaho.com
 *
 *******************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/

package org.pentaho.di.trans.steps.mail;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.activation.DataHandler;
import javax.activation.URLDataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSelectInfo;
import org.apache.commons.vfs2.FileSelector;
import org.apache.commons.vfs2.FileType;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.util.Utils;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.logging.LogChannelInterface;
import org.pentaho.di.core.vfs.KettleVFS;
import org.pentaho.di.core.xml.XMLHandler;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.BaseStep;
import org.pentaho.di.trans.step.StepDataInterface;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.step.StepMetaInterface;

/**
 * Send mail step. based on Mail job entry
 *
 * @author Samatar
 * @since 28-07-2008
 */

public class Mail extends BaseStep implements StepInterface {
  private static Class PKG = MailMeta.class; // for i18n purposes, needed by Translator2!!

  private MailMeta meta;
  private MailData data;

  public Mail( StepMeta stepMeta, StepDataInterface stepDataInterface, int copyNr, TransMeta transMeta, Trans trans ) {
    super( stepMeta, stepDataInterface, copyNr, transMeta, trans );
  }

  public boolean processRow( StepMetaInterface smi, StepDataInterface sdi ) throws KettleException {
    meta = (MailMeta) smi;
    data = (MailData) sdi;

    Object[] r = getRow(); // get row, set busy!
    if ( r == null ) { // no more input to be expected...

      setOutputDone();
      return false;
    }

    if ( first ) {
      first = false;

      // get the RowMeta
      data.previousRowMeta = getInputRowMeta().clone();

      // Check is filename field is provided
      if ( Utils.isEmpty( meta.getDestination() ) ) {
        throw new KettleException( BaseMessages.getString( PKG, "Mail.Log.DestinationFieldEmpty" ) );
      }

      // Check is replyname field is provided
      if ( Utils.isEmpty( meta.getReplyAddress() ) ) {
        throw new KettleException( BaseMessages.getString( PKG, "Mail.Log.ReplyFieldEmpty" ) );
      }

      // Check is SMTP server is provided
      if ( Utils.isEmpty( meta.getServer() ) ) {
        throw new KettleException( BaseMessages.getString( PKG, "Mail.Log.ServerFieldEmpty" ) );
      }

      // Check Attached filenames when dynamic
      if ( meta.isDynamicFilename() && Utils.isEmpty( meta.getDynamicFieldname() ) ) {
        throw new KettleException( BaseMessages.getString( PKG, "Mail.Log.DynamicFilenameFielddEmpty" ) );
      }

      // Check Attached zipfilename when dynamic
      if ( meta.isZipFilenameDynamic() && Utils.isEmpty( meta.getDynamicZipFilenameField() ) ) {
        throw new KettleException( BaseMessages.getString( PKG, "Mail.Log.DynamicZipFilenameFieldEmpty" ) );
      }

      if ( meta.isZipFiles() && Utils.isEmpty( meta.getZipFilename() ) ) {
        throw new KettleException( BaseMessages.getString( PKG, "Mail.Log.ZipFilenameEmpty" ) );
      }

      // check authentication
      if ( meta.isUsingAuthentication() ) {
        // check authentication user
        if ( Utils.isEmpty( meta.getAuthenticationUser() ) ) {
          throw new KettleException( BaseMessages.getString( PKG, "Mail.Log.AuthenticationUserFieldEmpty" ) );
        }

        // check authentication pass
        if ( Utils.isEmpty( meta.getAuthenticationPassword() ) ) {
          throw new KettleException( BaseMessages.getString( PKG, "Mail.Log.AuthenticationPasswordFieldEmpty" ) );
        }
      }

      // cache the position of the destination field
      if ( data.indexOfDestination < 0 ) {
        String realDestinationFieldname = meta.getDestination();
        data.indexOfDestination = data.previousRowMeta.indexOfValue( realDestinationFieldname );
        if ( data.indexOfDestination < 0 ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "Mail.Exception.CouldnotFindDestinationField", realDestinationFieldname ) );
        }
      }

      // Cc
      if ( !Utils.isEmpty( meta.getDestinationCc() ) ) {
        // cache the position of the Cc field
        if ( data.indexOfDestinationCc < 0 ) {
          String realDestinationCcFieldname = meta.getDestinationCc();
          data.indexOfDestinationCc = data.previousRowMeta.indexOfValue( realDestinationCcFieldname );
          if ( data.indexOfDestinationCc < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "Mail.Exception.CouldnotFindDestinationCcField", realDestinationCcFieldname ) );
          }
        }
      }
      // BCc
      if ( !Utils.isEmpty( meta.getDestinationBCc() ) ) {
        // cache the position of the BCc field
        if ( data.indexOfDestinationBCc < 0 ) {
          String realDestinationBCcFieldname = meta.getDestinationBCc();
          data.indexOfDestinationBCc = data.previousRowMeta.indexOfValue( realDestinationBCcFieldname );
          if ( data.indexOfDestinationBCc < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "Mail.Exception.CouldnotFindDestinationBCcField", realDestinationBCcFieldname ) );
          }
        }
      }
      // Sender Name
      if ( !Utils.isEmpty( meta.getReplyName() ) ) {
        // cache the position of the sender field
        if ( data.indexOfSenderName < 0 ) {
          String realSenderName = meta.getReplyName();
          data.indexOfSenderName = data.previousRowMeta.indexOfValue( realSenderName );
          if ( data.indexOfSenderName < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "Mail.Exception.CouldnotFindReplyNameField", realSenderName ) );
          }
        }
      }
      // Sender address
      // cache the position of the sender field
      if ( data.indexOfSenderAddress < 0 ) {
        String realSenderAddress = meta.getReplyAddress();
        data.indexOfSenderAddress = data.previousRowMeta.indexOfValue( realSenderAddress );
        if ( data.indexOfSenderAddress < 0 ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "Mail.Exception.CouldnotFindReplyAddressField", realSenderAddress ) );
        }
      }

      // Reply to
      if ( !Utils.isEmpty( meta.getReplyToAddresses() ) ) {
        // cache the position of the reply to field
        if ( data.indexOfReplyToAddresses < 0 ) {
          String realReplyToAddresses = meta.getReplyToAddresses();
          data.indexOfReplyToAddresses = data.previousRowMeta.indexOfValue( realReplyToAddresses );
          if ( data.indexOfReplyToAddresses < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "Mail.Exception.CouldnotFindReplyToAddressesField", realReplyToAddresses ) );
          }
        }
      }

      // Contact Person
      if ( !Utils.isEmpty( meta.getContactPerson() ) ) {
        // cache the position of the destination field
        if ( data.indexOfContactPerson < 0 ) {
          String realContactPerson = meta.getContactPerson();
          data.indexOfContactPerson = data.previousRowMeta.indexOfValue( realContactPerson );
          if ( data.indexOfContactPerson < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "Mail.Exception.CouldnotFindContactPersonField", realContactPerson ) );
          }
        }
      }
      // Contact Phone
      if ( !Utils.isEmpty( meta.getContactPhone() ) ) {
        // cache the position of the destination field
        if ( data.indexOfContactPhone < 0 ) {
          String realContactPhone = meta.getContactPhone();
          data.indexOfContactPhone = data.previousRowMeta.indexOfValue( realContactPhone );
          if ( data.indexOfContactPhone < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "Mail.Exception.CouldnotFindContactPhoneField", realContactPhone ) );
          }
        }
      }
      // cache the position of the Server field
      if ( data.indexOfServer < 0 ) {
        String realServer = meta.getServer();
        data.indexOfServer = data.previousRowMeta.indexOfValue( realServer );
        if ( data.indexOfServer < 0 ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "Mail.Exception.CouldnotFindServerField", realServer ) );
        }
      }
      // Port
      if ( !Utils.isEmpty( meta.getPort() ) ) {
        // cache the position of the port field
        if ( data.indexOfPort < 0 ) {
          String realPort = meta.getPort();
          data.indexOfPort = data.previousRowMeta.indexOfValue( realPort );
          if ( data.indexOfPort < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "Mail.Exception.CouldnotFindPortField", realPort ) );
          }
        }
      }
      // Authentication
      if ( meta.isUsingAuthentication() ) {
        // cache the position of the Authentication user field
        if ( data.indexOfAuthenticationUser < 0 ) {
          String realAuthenticationUser = meta.getAuthenticationUser();
          data.indexOfAuthenticationUser = data.previousRowMeta.indexOfValue( realAuthenticationUser );
          if ( data.indexOfAuthenticationUser < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "Mail.Exception.CouldnotFindAuthenticationUserField", realAuthenticationUser ) );
          }
        }

        // cache the position of the Authentication password field
        if ( data.indexOfAuthenticationPass < 0 ) {
          String realAuthenticationPassword = Utils.resolvePassword( variables, meta.getAuthenticationPassword() );
          data.indexOfAuthenticationPass = data.previousRowMeta.indexOfValue( realAuthenticationPassword );
          if ( data.indexOfAuthenticationPass < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "Mail.Exception.CouldnotFindAuthenticationPassField", realAuthenticationPassword ) );
          }
        }
      }
      // Mail Subject
      if ( !Utils.isEmpty( meta.getSubject() ) ) {
        // cache the position of the subject field
        if ( data.indexOfSubject < 0 ) {
          String realSubject = meta.getSubject();
          data.indexOfSubject = data.previousRowMeta.indexOfValue( realSubject );
          if ( data.indexOfSubject < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "Mail.Exception.CouldnotFindSubjectField", realSubject ) );
          }
        }
      }
      // Mail Comment
      if ( !Utils.isEmpty( meta.getComment() ) ) {
        // cache the position of the comment field
        if ( data.indexOfComment < 0 ) {
          String realComment = meta.getComment();
          data.indexOfComment = data.previousRowMeta.indexOfValue( realComment );
          if ( data.indexOfComment < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "Mail.Exception.CouldnotFindCommentField", realComment ) );
          }
        }
      }

      if ( meta.isAttachContentFromField() ) {
        // We are dealing with file content directly loaded from file
        // and not physical file
        String attachedContentField = meta.getAttachContentField();
        if ( Utils.isEmpty( attachedContentField ) ) {
          // Empty Field
          throw new KettleException( BaseMessages.getString( PKG, "Mail.Exception.AttachedContentFieldEmpty" ) );
        }
        data.indexOfAttachedContent = data.previousRowMeta.indexOfValue( attachedContentField );
        if ( data.indexOfAttachedContent < 0 ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "Mail.Exception.CouldnotFindAttachedContentField", attachedContentField ) );
        }
        // Attached content filename
        String attachedContentFileNameField = meta.getAttachContentFileNameField();
        if ( Utils.isEmpty( attachedContentFileNameField ) ) {
          // Empty Field
          throw new KettleException( BaseMessages.getString(
            PKG, "Mail.Exception.AttachedContentFileNameFieldEmpty" ) );
        }
        data.IndexOfAttachedFilename = data.previousRowMeta.indexOfValue( attachedContentFileNameField );
        if ( data.IndexOfAttachedFilename < 0 ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "Mail.Exception.CouldnotFindAttachedContentFileNameField", attachedContentFileNameField ) );
        }

      } else {

        // Dynamic Zipfilename
        if ( meta.isZipFilenameDynamic() ) {
          // cache the position of the attached source filename field
          if ( data.indexOfDynamicZipFilename < 0 ) {
            String realZipFilename = meta.getDynamicZipFilenameField();
            data.indexOfDynamicZipFilename = data.previousRowMeta.indexOfValue( realZipFilename );
            if ( data.indexOfDynamicZipFilename < 0 ) {
              throw new KettleException( BaseMessages.getString(
                PKG, "Mail.Exception.CouldnotSourceAttachedZipFilenameField", realZipFilename ) );
            }
          }
        }
        data.zipFileLimit = Const.toLong( environmentSubstitute( meta.getZipLimitSize() ), 0 );
        if ( data.zipFileLimit > 0 ) {
          data.zipFileLimit = data.zipFileLimit * 1048576; // Mo
        }

        if ( !meta.isZipFilenameDynamic() ) {
          data.ZipFilename = environmentSubstitute( meta.getZipFilename() );
        }

        // Attached files
        if ( meta.isDynamicFilename() ) {
          // cache the position of the attached source filename field
          if ( data.indexOfSourceFilename < 0 ) {
            String realSourceattachedFilename = meta.getDynamicFieldname();
            data.indexOfSourceFilename = data.previousRowMeta.indexOfValue( realSourceattachedFilename );
            if ( data.indexOfSourceFilename < 0 ) {
              throw new KettleException( BaseMessages.getString(
                PKG, "Mail.Exception.CouldnotSourceAttachedFilenameField", realSourceattachedFilename ) );
            }
          }

          // cache the position of the attached wildcard field
          if ( !Utils.isEmpty( meta.getSourceWildcard() ) ) {
            if ( data.indexOfSourceWildcard < 0 ) {
              String realSourceattachedWildcard = meta.getDynamicWildcard();
              data.indexOfSourceWildcard = data.previousRowMeta.indexOfValue( realSourceattachedWildcard );
              if ( data.indexOfSourceWildcard < 0 ) {
                throw new KettleException( BaseMessages.getString(
                  PKG, "Mail.Exception.CouldnotSourceAttachedWildcard", realSourceattachedWildcard ) );
              }
            }
          }
        } else {
          // static attached filenames
          data.realSourceFileFoldername = environmentSubstitute( meta.getSourceFileFoldername() );
          data.realSourceWildcard = environmentSubstitute( meta.getSourceWildcard() );
        }
      }

      // check embedded images
      if ( meta.getEmbeddedImages() != null && meta.getEmbeddedImages().length > 0 ) {
        FileObject image = null;
        data.embeddedMimePart = new HashSet();
        try {
          for ( int i = 0; i < meta.getEmbeddedImages().length; i++ ) {
            String imageFile = environmentSubstitute( meta.getEmbeddedImages()[i] );
            String contentID = environmentSubstitute( meta.getContentIds()[i] );
            image = KettleVFS.getFileObject( imageFile );

            if ( image.exists() && image.getType() == FileType.FILE ) {
              // Create part for the image
              MimeBodyPart imagePart = new MimeBodyPart();
              // Load the image
              URLDataSource fds = new URLDataSource( image.getURL() );
              imagePart.setDataHandler( new DataHandler( fds ) );
              // Setting the header
              imagePart.setHeader( "Content-ID", "<" + contentID + ">" );
              // keep this part for further user
              data.embeddedMimePart.add( imagePart );
              logBasic( BaseMessages.getString( PKG, "Mail.Log.ImageAdded", imageFile ) );

            } else {
              logError( BaseMessages.getString( PKG, "Mail.Log.WrongImage", imageFile ) );
            }
          }
        } catch ( Exception e ) {
          logError( BaseMessages.getString( PKG, "Mail.Error.AddingImage", e.getMessage() ) );
        } finally {
          if ( image != null ) {
            try {
              image.close();
            } catch ( Exception e ) { /* Ignore */
            }
          }
        }
      }

    } // end if first

    boolean sendToErrorRow = false;
    String errorMessage = null;

    try {
      // get values
      String maildestination = data.previousRowMeta.getString( r, data.indexOfDestination );
      if ( Utils.isEmpty( maildestination ) ) {
        throw new KettleException( "Mail.Error.MailDestinationEmpty" );
      }
      String maildestinationCc = null;
      if ( data.indexOfDestinationCc > -1 ) {
        maildestinationCc = data.previousRowMeta.getString( r, data.indexOfDestinationCc );
      }
      String maildestinationBCc = null;
      if ( data.indexOfDestinationBCc > -1 ) {
        maildestinationBCc = data.previousRowMeta.getString( r, data.indexOfDestinationBCc );
      }

      String mailsendername = null;
      if ( data.indexOfSenderName > -1 ) {
        mailsendername = data.previousRowMeta.getString( r, data.indexOfSenderName );
      }
      String mailsenderaddress = data.previousRowMeta.getString( r, data.indexOfSenderAddress );

      // reply addresses
      String mailreplyToAddresses = null;
      if ( data.indexOfReplyToAddresses > -1 ) {
        mailreplyToAddresses = data.previousRowMeta.getString( r, data.indexOfReplyToAddresses );
      }

      String contactperson = null;
      if ( data.indexOfContactPerson > -1 ) {
        contactperson = data.previousRowMeta.getString( r, data.indexOfContactPerson );
      }
      String contactphone = null;
      if ( data.indexOfContactPhone > -1 ) {
        contactphone = data.previousRowMeta.getString( r, data.indexOfContactPhone );
      }

      String servername = data.previousRowMeta.getString( r, data.indexOfServer );
      if ( Utils.isEmpty( servername ) ) {
        throw new KettleException( "Mail.Error.MailServerEmpty" );
      }
      int port = -1;
      if ( data.indexOfPort > -1 ) {
        port = Const.toInt( "" + data.previousRowMeta.getInteger( r, data.indexOfPort ), -1 );
      }

      String authuser = null;
      if ( data.indexOfAuthenticationUser > -1 ) {
        authuser = data.previousRowMeta.getString( r, data.indexOfAuthenticationUser );
      }
      String authpass = null;
      if ( data.indexOfAuthenticationPass > -1 ) {
        authpass = data.previousRowMeta.getString( r, data.indexOfAuthenticationPass );
      }

      String subject = null;
      if ( data.indexOfSubject > -1 ) {
        subject = data.previousRowMeta.getString( r, data.indexOfSubject );
      }

      String comment = null;
      if ( data.indexOfComment > -1 ) {
        comment = data.previousRowMeta.getString( r, data.indexOfComment );
      }

      // send email...
      sendMail(
        r, servername, port, mailsenderaddress, mailsendername, maildestination, maildestinationCc,
        maildestinationBCc, contactperson, contactphone, authuser, authpass, subject, comment,
        mailreplyToAddresses );

      putRow( getInputRowMeta(), r ); // copy row to possible alternate rowset(s).); // copy row to output rowset(s);

      if ( log.isRowLevel() ) {
        logRowlevel( BaseMessages.getString( PKG, "Mail.Log.LineNumber", getLinesRead()
          + " : " + getInputRowMeta().getString( r ) ) );
      }

    } catch ( Exception e ) {
      if ( getStepMeta().isDoingErrorHandling() ) {
        sendToErrorRow = true;
        errorMessage = e.toString();
      } else {
        throw new KettleException( BaseMessages.getString( PKG, "Mail.Error.General" ), e );
      }
      if ( sendToErrorRow ) {
        // Simply add this row to the error row
        putError( getInputRowMeta(), r, 1, errorMessage, null, "MAIL001" );
      }
    }

    return true;
  }

  public void sendMail( Object[] r, String server, int port, String senderAddress, String senderName,
    String destination, String destinationCc, String destinationBCc, String contactPerson, String contactPhone,
    String authenticationUser, String authenticationPassword, String mailsubject, String comment,
    String replyToAddresses ) throws Exception {

    // Send an e-mail...
    // create some properties and get the default Session

    String protocol = "smtp";
    if ( meta.isUsingSecureAuthentication() ) { // PDI-2955
      // if (meta.isUsingAuthentication()) {
      if ( meta.getSecureConnectionType().equals( "TLS" ) ) {
        // Allow TLS authentication
        data.props.put( "mail.smtp.starttls.enable", "true" );
      } else {
        protocol = "smtps";
        // required to get rid of a SSL exception :
        // nested exception is:
        // javax.net.ssl.SSLException: Unsupported record version Unknown
        data.props.put( "mail.smtps.quitwait", "false" );
      }
    }
    data.props.put( "mail." + protocol + ".host", server );
    if ( port != -1 ) {
      data.props.put( "mail." + protocol + ".port", "" + port ); // needs to be supplied as a string, not as an integer
    }

    if ( isDebug() ) {
      data.props.put( "mail.debug", "true" );
    }

    if ( meta.isUsingAuthentication() ) {
      data.props.put( "mail." + protocol + ".auth", "true" );
    }

    Session session = Session.getInstance( data.props );
    session.setDebug( isDebug() );

    // create a message
    Message msg = new MimeMessage( session );

    // set message priority
    if ( meta.isUsePriority() ) {
      String priority_int = "1";
      if ( meta.getPriority().equals( "low" ) ) {
        priority_int = "3";
      }
      if ( meta.getPriority().equals( "normal" ) ) {
        priority_int = "2";
      }

      msg.setHeader( "X-Priority", priority_int ); // (String)int between 1= high and 3 = low.
      msg.setHeader( "Importance", meta.getImportance() );
      // seems to be needed for MS Outlook.
      // where it returns a string of high /normal /low.
      msg.setHeader( "Sensitivity", meta.getSensitivity() );
      // Possible values are normal, personal, private, company-confidential
    }

    // set Email sender
    String email_address = senderAddress;
    if ( !Utils.isEmpty( email_address ) ) {
      // get sender name
      if ( !Utils.isEmpty( senderName ) ) {
        email_address = senderName + '<' + email_address + '>';
      }
      msg.setFrom( new InternetAddress( email_address ) );
    } else {
      throw new MessagingException( BaseMessages.getString( PKG, "Mail.Error.ReplyEmailNotFilled" ) );
    }

    // Set reply to
    if ( !Utils.isEmpty( replyToAddresses ) ) {
      // get replay to
      // Split the mail-address: space separated
      String[] reply_Address_List = replyToAddresses.split( " " );
      InternetAddress[] address = new InternetAddress[reply_Address_List.length];

      for ( int i = 0; i < reply_Address_List.length; i++ ) {
        address[i] = new InternetAddress( reply_Address_List[i] );
      }

      // To add the real reply-to
      msg.setReplyTo( address );
    }

    // Split the mail-address: space separated
    String[] destinations = destination.split( " " );
    InternetAddress[] address = new InternetAddress[destinations.length];
    for ( int i = 0; i < destinations.length; i++ ) {
      address[i] = new InternetAddress( destinations[i] );
    }

    msg.setRecipients( Message.RecipientType.TO, address );

    String realdestinationCc = destinationCc;
    if ( !Utils.isEmpty( realdestinationCc ) ) {
      // Split the mail-address Cc: space separated
      String[] destinationsCc = realdestinationCc.split( " " );
      InternetAddress[] addressCc = new InternetAddress[destinationsCc.length];
      for ( int i = 0; i < destinationsCc.length; i++ ) {
        addressCc[i] = new InternetAddress( destinationsCc[i] );
      }

      msg.setRecipients( Message.RecipientType.CC, addressCc );
    }

    String realdestinationBCc = destinationBCc;
    if ( !Utils.isEmpty( realdestinationBCc ) ) {
      // Split the mail-address BCc: space separated
      String[] destinationsBCc = realdestinationBCc.split( " " );
      InternetAddress[] addressBCc = new InternetAddress[destinationsBCc.length];
      for ( int i = 0; i < destinationsBCc.length; i++ ) {
        addressBCc[i] = new InternetAddress( destinationsBCc[i] );
      }

      msg.setRecipients( Message.RecipientType.BCC, addressBCc );
    }

    if ( mailsubject != null ) {
      msg.setSubject( mailsubject );
    }

    msg.setSentDate( new Date() );
    StringBuilder messageText = new StringBuilder();

    if ( comment != null ) {
      messageText.append( comment ).append( Const.CR ).append( Const.CR );
    }

    if ( meta.getIncludeDate() ) {
      messageText.append( BaseMessages.getString( PKG, "Mail.Log.Comment.MsgDate" ) + ": " ).append(
        XMLHandler.date2string( new Date() ) ).append( Const.CR ).append( Const.CR );
    }

    if ( !meta.isOnlySendComment() && ( !Utils.isEmpty( contactPerson ) || !Utils.isEmpty( contactPhone ) ) ) {
      messageText.append( BaseMessages.getString( PKG, "Mail.Log.Comment.ContactInfo" ) + " :" ).append( Const.CR );
      messageText.append( "---------------------" ).append( Const.CR );
      messageText.append( BaseMessages.getString( PKG, "Mail.Log.Comment.PersonToContact" ) + " : " ).append(
        contactPerson ).append( Const.CR );
      messageText
        .append( BaseMessages.getString( PKG, "Mail.Log.Comment.Tel" ) + "  : " ).append( contactPhone ).append(
          Const.CR );
      messageText.append( Const.CR );
    }
    data.parts = new MimeMultipart();

    MimeBodyPart part1 = new MimeBodyPart(); // put the text in the
    // 1st part

    if ( meta.isUseHTML() ) {
      if ( !Utils.isEmpty( meta.getEncoding() ) ) {
        part1.setContent( messageText.toString(), "text/html; " + "charset=" + meta.getEncoding() );
      } else {
        part1.setContent( messageText.toString(), "text/html; " + "charset=ISO-8859-1" );
      }
    } else {
      part1.setText( messageText.toString() );
    }

    data.parts.addBodyPart( part1 );

    if ( meta.isAttachContentFromField() ) {
      // attache file content
      addAttachedContent( data.previousRowMeta.getString( r, data.IndexOfAttachedFilename ), data.previousRowMeta
        .getString( r, data.indexOfAttachedContent ) );
    } else {
      // attached files
      if ( meta.isDynamicFilename() ) {
        setAttachedFilesList( r, log );
      } else {
        setAttachedFilesList( null, log );
      }
    }

    // add embedded images
    addImagePart();

    if ( data.nrEmbeddedImages > 0 && data.nrattachedFiles == 0 ) {
      // If we need to embedd images...
      // We need to create a "multipart/related" message.
      // otherwise image will appear as attached file
      data.parts.setSubType( "related" );
    }

    msg.setContent( data.parts );

    Transport transport = null;
    try {
      transport = session.getTransport( protocol );
      if ( meta.isUsingAuthentication() ) {
        if ( port != -1 ) {
          transport.connect( Const.NVL( server, "" ), port, Const.NVL( authenticationUser, "" ), Const.NVL(
            authenticationPassword, "" ) );
        } else {
          transport.connect( Const.NVL( server, "" ), Const.NVL( authenticationUser, "" ), Const.NVL(
            authenticationPassword, "" ) );
        }
      } else {
        transport.connect();
      }
      transport.sendMessage( msg, msg.getAllRecipients() );
    } finally {
      if ( transport != null ) {
        transport.close();
      }
    }

  }

  private void setAttachedFilesList( Object[] r, LogChannelInterface log ) throws Exception {
    String realSourceFileFoldername = null;
    String realSourceWildcard = null;
    FileObject sourcefile = null;
    FileObject file = null;

    ZipOutputStream zipOutputStream = null;
    File masterZipfile = null;

    if ( meta.isZipFilenameDynamic() ) {
      data.ZipFilename = data.previousRowMeta.getString( r, data.indexOfDynamicZipFilename );
    }

    try {

      if ( meta.isDynamicFilename() ) {
        // dynamic attached filenames
        if ( data.indexOfSourceFilename > -1 ) {
          realSourceFileFoldername = data.previousRowMeta.getString( r, data.indexOfSourceFilename );
        }

        if ( data.indexOfSourceWildcard > -1 ) {
          realSourceWildcard = data.previousRowMeta.getString( r, data.indexOfSourceWildcard );
        }

      } else {
        // static attached filenames
        realSourceFileFoldername = data.realSourceFileFoldername;
        realSourceWildcard = data.realSourceWildcard;
      }

      if ( !Utils.isEmpty( realSourceFileFoldername ) ) {
        sourcefile = KettleVFS.getFileObject( realSourceFileFoldername, getTransMeta() );
        if ( sourcefile.exists() ) {
          long FileSize = 0;
          FileObject[] list = null;
          if ( sourcefile.getType() == FileType.FILE ) {
            list = new FileObject[1];
            list[0] = sourcefile;
          } else {
            list = sourcefile.findFiles( new TextFileSelector( sourcefile.toString(), realSourceWildcard ) );
          }
          if ( list.length > 0 ) {

            boolean zipFiles = meta.isZipFiles();
            if ( zipFiles && data.zipFileLimit == 0 ) {
              masterZipfile =
                new File( System.getProperty( "java.io.tmpdir" ) + Const.FILE_SEPARATOR + data.ZipFilename );

              zipOutputStream = new ZipOutputStream( new FileOutputStream( masterZipfile ) );
            }

            for ( int i = 0; i < list.length; i++ ) {

              file = KettleVFS.getFileObject( KettleVFS.getFilename( list[i] ), getTransMeta() );

              if ( zipFiles ) {

                if ( data.zipFileLimit == 0 ) {
                  ZipEntry zipEntry = new ZipEntry( file.getName().getBaseName() );
                  zipOutputStream.putNextEntry( zipEntry );

                  // Now put the content of this file into this archive...
                  BufferedInputStream inputStream = new BufferedInputStream( file.getContent().getInputStream() );
                  int c;
                  while ( ( c = inputStream.read() ) >= 0 ) {
                    zipOutputStream.write( c );
                  }
                  inputStream.close();
                  zipOutputStream.closeEntry();
                } else {
                  FileSize += file.getContent().getSize();
                }
              } else {
                addAttachedFilePart( file );
              }
            } // end for
            if ( zipFiles ) {
              if ( isDebug() ) {
                logDebug( BaseMessages.getString( PKG, "Mail.Log.FileSize", "" + FileSize ) );
              }
              if ( isDebug() ) {
                logDebug( BaseMessages.getString( PKG, "Mail.Log.LimitSize", "" + data.zipFileLimit ) );
              }

              if ( data.zipFileLimit > 0 && FileSize > data.zipFileLimit ) {

                masterZipfile =
                  new File( System.getProperty( "java.io.tmpdir" ) + Const.FILE_SEPARATOR + data.ZipFilename );

                zipOutputStream = new ZipOutputStream( new FileOutputStream( masterZipfile ) );

                for ( int i = 0; i < list.length; i++ ) {

                  file = KettleVFS.getFileObject( KettleVFS.getFilename( list[i] ), getTransMeta() );

                  ZipEntry zipEntry = new ZipEntry( file.getName().getBaseName() );
                  zipOutputStream.putNextEntry( zipEntry );

                  // Now put the content of this file into this archive...
                  BufferedInputStream inputStream = new BufferedInputStream( file.getContent().getInputStream() );
                  int c;
                  while ( ( c = inputStream.read() ) >= 0 ) {
                    zipOutputStream.write( c );
                  }
                  inputStream.close();
                  zipOutputStream.closeEntry();

                }

              }
              if ( data.zipFileLimit > 0 && FileSize > data.zipFileLimit || data.zipFileLimit == 0 ) {
                file = KettleVFS.getFileObject( masterZipfile.getAbsolutePath(), getTransMeta() );
                addAttachedFilePart( file );
              }
            }
          }
        } else {
          logError( BaseMessages.getString( PKG, "Mail.Error.SourceFileFolderNotExists", realSourceFileFoldername ) );
        }
      }
    } catch ( Exception e ) {
      logError( e.getMessage() );
    } finally {
      if ( sourcefile != null ) {
        try {
          sourcefile.close();
        } catch ( Exception e ) {
          // Ignore errors
        }
      }
      if ( file != null ) {
        try {
          file.close();
        } catch ( Exception e ) {
          // Ignore errors
        }
      }

      if ( zipOutputStream != null ) {
        try {
          zipOutputStream.finish();
          zipOutputStream.close();
        } catch ( IOException e ) {
          logError( "Unable to close attachement zip file archive : " + e.toString() );
        }
      }
    }

  }

  private void addAttachedFilePart( FileObject file ) throws Exception {
    // create a data source

    MimeBodyPart files = new MimeBodyPart();
    // create a data source
    URLDataSource fds = new URLDataSource( file.getURL() );
    // get a data Handler to manipulate this file type;
    files.setDataHandler( new DataHandler( fds ) );
    // include the file in the data source
    files.setFileName( file.getName().getBaseName() );
    // insist on base64 to preserve line endings
    files.addHeader( "Content-Transfer-Encoding", "base64" );
    // add the part with the file in the BodyPart();
    data.parts.addBodyPart( files );
    if ( isDetailed() ) {
      logDetailed( BaseMessages.getString( PKG, "Mail.Log.AttachedFile", fds.getName() ) );
    }

  }

  private void addAttachedContent( String filename, String fileContent ) throws Exception {
    // create a data source

    MimeBodyPart mbp = new MimeBodyPart();
    // get a data Handler to manipulate this file type;
    mbp.setDataHandler( new DataHandler( new ByteArrayDataSource( fileContent.getBytes(), "application/x-any" ) ) );
    // include the file in the data source
    mbp.setFileName( filename );
    // add the part with the file in the BodyPart();
    data.parts.addBodyPart( mbp );

  }

  private void addImagePart() throws Exception {
    data.nrEmbeddedImages = 0;
    if ( data.embeddedMimePart != null && data.embeddedMimePart.size() > 0 ) {
      for ( Iterator i = data.embeddedMimePart.iterator(); i.hasNext(); ) {
        MimeBodyPart part = i.next();
        data.parts.addBodyPart( part );
        data.nrEmbeddedImages++;
      }
    }
  }

  private class TextFileSelector implements FileSelector {
    String fileWildcard = null;
    String sourceFolder = null;

    public TextFileSelector( String sourcefolderin, String filewildcard ) {
      if ( !Utils.isEmpty( sourcefolderin ) ) {
        sourceFolder = sourcefolderin;
      }

      if ( !Utils.isEmpty( filewildcard ) ) {
        fileWildcard = filewildcard;
      }
    }

    public boolean includeFile( FileSelectInfo info ) {
      boolean returncode = false;
      try {
        if ( !info.getFile().toString().equals( sourceFolder ) ) {
          // Pass over the Base folder itself
          String short_filename = info.getFile().getName().getBaseName();

          if ( info.getFile().getParent().equals( info.getBaseFolder() )
            || ( ( !info.getFile().getParent().equals( info.getBaseFolder() ) && meta.isIncludeSubFolders() ) ) ) {
            if ( ( info.getFile().getType() == FileType.FILE && fileWildcard == null )
              || ( info.getFile().getType() == FileType.FILE && fileWildcard != null && GetFileWildcard(
                short_filename, fileWildcard ) ) ) {
              returncode = true;
            }
          }
        }
      } catch ( Exception e ) {
        logError( BaseMessages.getString( PKG, "Mail.Error.FindingFiles", info.getFile().toString(), e
          .getMessage() ) );
        returncode = false;
      }
      return returncode;
    }

    public boolean traverseDescendents( FileSelectInfo info ) {
      return true;
    }
  }

  /**********************************************************
   *
   * @param selectedfile
   * @param wildcard
   * @return True if the selectedfile matches the wildcard
   **********************************************************/
  private boolean GetFileWildcard( String selectedfile, String wildcard ) {
    Pattern pattern = null;
    boolean getIt = true;

    if ( !Utils.isEmpty( wildcard ) ) {
      pattern = Pattern.compile( wildcard );
      // First see if the file matches the regular expression!
      if ( pattern != null ) {
        Matcher matcher = pattern.matcher( selectedfile );
        getIt = matcher.matches();
      }
    }

    return getIt;
  }

  public boolean init( StepMetaInterface smi, StepDataInterface sdi ) {
    meta = (MailMeta) smi;
    data = (MailData) sdi;

    if ( super.init( smi, sdi ) ) {
      // Add init code here.
      return true;
    }
    return false;
  }

  public void dispose( StepMetaInterface smi, StepDataInterface sdi ) {
    meta = (MailMeta) smi;
    data = (MailData) sdi;

    if ( data.embeddedMimePart != null ) {
      data.embeddedMimePart.clear();
    }
    data.parts = null;
    super.dispose( meta, data );
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy