Package railo.runtime.net.mail

Source Code of railo.runtime.net.mail.MailClient

package railo.runtime.net.mail;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.text.Normalizer;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Header;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

import railo.commons.io.CharsetUtil;
import railo.commons.io.IOUtil;
import railo.commons.io.SystemUtil;
import railo.commons.io.res.Resource;
import railo.commons.io.res.util.ResourceUtil;
import railo.commons.lang.ExceptionUtil;
import railo.commons.lang.Md5;
import railo.commons.lang.StringUtil;
import railo.runtime.exp.PageException;
import railo.runtime.net.imap.ImapClient;
import railo.runtime.net.pop.PopClient;
import railo.runtime.op.Caster;
import railo.runtime.op.Operator;
import railo.runtime.type.Array;
import railo.runtime.type.ArrayImpl;
import railo.runtime.type.Collection;
import railo.runtime.type.KeyImpl;
import railo.runtime.type.Query;
import railo.runtime.type.QueryImpl;
import railo.runtime.type.Struct;
import railo.runtime.type.StructImpl;
import railo.runtime.type.util.ArrayUtil;
import railo.runtime.type.util.ListUtil;

public abstract class MailClient {
 
  /**
   * Simple authenicator implmentation
   */
  private final class _Authenticator extends Authenticator {

    private String _fldif = null;
    private String a = null;

    protected PasswordAuthentication getPasswordAuthentication() {
      return new PasswordAuthentication(_fldif, a);
    }

    public _Authenticator(String s, String s1) {
      _fldif = s;
      a = s1;
    }
  }
 

  private static final Collection.Key DATE = KeyImpl.init("date");
  private static final Collection.Key SUBJECT = KeyImpl.init("subject");
  private static final Collection.Key SIZE = KeyImpl.init("size");
  private static final Collection.Key FROM = KeyImpl.init("from");
  private static final Collection.Key MESSAGE_NUMBER = KeyImpl.init("messagenumber");
  private static final Collection.Key MESSAGE_ID = KeyImpl.init("messageid");
  private static final Collection.Key REPLYTO = KeyImpl.init("replyto");
  private static final Collection.Key CC = KeyImpl.init("cc");
  private static final Collection.Key BCC = KeyImpl.init("bcc");
  private static final Collection.Key TO = KeyImpl.init("to");
  private static final Collection.Key UID = KeyImpl.init("uid");
  private static final Collection.Key HEADER = KeyImpl.init("header");
  private static final Collection.Key BODY = KeyImpl.init("body");
  private static final Collection.Key CIDS = KeyImpl.init("cids");
  private static final Collection.Key TEXT_BODY = KeyImpl.init("textBody");
  private static final Collection.Key HTML_BODY = KeyImpl.init("HTMLBody");
  private static final Collection.Key ATTACHMENTS = KeyImpl.init("attachments");
  private static final Collection.Key ATTACHMENT_FILES = KeyImpl.init("attachmentfiles");


  public static final int TYPE_POP3 = 0;
  public static final int TYPE_IMAP = 1;


  private String _flddo[] = {"date", "from", "messagenumber", "messageid", "replyto", "subject", "cc", "to", "size", "header", "uid"};
  private String _fldnew[] = {"date", "from", "messagenumber", "messageid", "replyto", "subject", "cc", "to", "size", "header", "uid", "body", "textBody", "HTMLBody", "attachments", "attachmentfiles","cids"};
  private String server = null;
  private String username = null;
  private String password = null;
  private Session _fldtry = null;
  private Store _fldelse = null;
  private int port = 0;
  private int timeout = 0;
  private int startrow = 0;
  private int maxrows = 0;
  private boolean uniqueFilenames = false;
  private Resource attachmentDirectory = null;

 
  public static MailClient getInstance(int type,String server, int port, String username, String password){
    if(TYPE_POP3==type)
      return new PopClient(server,port,username,password);
    if(TYPE_IMAP==type)
      return new ImapClient(server,port,username,password);
    return null;
  }
 
  /**
   * constructor of the class
   * @param server
   * @param port
   * @param username
   * @param password
   */
  public MailClient(String server, int port, String username, String password) {
    timeout = 60000;
    startrow = 0;
    maxrows = -1;
    uniqueFilenames = false;
    this.server = server;
    this.port = port;
    this.username = username;
    this.password = password;
  }


    /**
     * @param maxrows The maxrows to set.
     */
    public void setMaxrows(int maxrows) {
        this.maxrows = maxrows;
    }

    /**
     * @param startrow The startrow to set.
     */
    public void setStartrow(int startrow) {
        this.startrow = startrow;
    }


    /**
     * @param timeout The timeout to set.
     */
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    /**
     * @param uniqueFilenames The uniqueFilenames to set.
     */
    public void setUniqueFilenames(boolean uniqueFilenames) {
        this.uniqueFilenames = uniqueFilenames;
    }

    /**
     * @param attachmentDirectory The attachmentDirectory to set.
     */
    public void setAttachmentDirectory(Resource attachmentDirectory) {
        this.attachmentDirectory = attachmentDirectory;
    }

    /**
     * connects to pop server
     * @throws MessagingException
     */
    public void connect() throws MessagingException {
    Properties properties = new Properties();
    String type=getTypeAsString();
    properties.put("mail."+type+".host", server);
    properties.put("mail."+type+".port", new Double(port));
    properties.put("mail."+type+".connectiontimeout", String.valueOf(timeout));
    properties.put("mail."+type+".timeout", String.valueOf(timeout));
    //properties.put("mail.mime.charset", "UTF-8");
         
   
    if(TYPE_IMAP==getType())properties.put("mail.imap.partialfetch", "false" );
   
    _fldtry = username != null ? Session.getInstance(properties, new _Authenticator(username, password)) : Session.getInstance(properties);
    _fldelse = _fldtry.getStore(type);
    if(!StringUtil.isEmpty(username))_fldelse.connect(server,username,password);
    else _fldelse.connect();
  }

    protected abstract String getTypeAsString();
    protected abstract int getType();


  /**
     * delete all message in ibox that match given criteria
     * @param messageNumbers
     * @param uIds
     * @throws MessagingException
   * @throws IOException
     */
    public void deleteMails(String as[], String as1[]) throws MessagingException, IOException {
    Folder folder;
    Message amessage[];
    folder = _fldelse.getFolder("INBOX");
    folder.open(2);
    Map<String, Message> map = getMessages(null,folder, as1, as, startrow, maxrows,false);
    Iterator<String> iterator = map.keySet().iterator();
    amessage = new Message[map.size()];
    int i = 0;
    while(iterator.hasNext()) {
      amessage[i++] =  map.get(iterator.next());
    }
    try {
      folder.setFlags(amessage, new Flags(javax.mail.Flags.Flag.DELETED), true);
    }
    finally {
      folder.close(true);
    }
  }

    /**
     * return all messages from inbox
     * @param messageNumbers all messages with this ids
     * @param uIds all messages with this uids
     * @param withBody also return body
     * @return all messages from inbox
     * @throws MessagingException
     * @throws IOException
     */
    public Query getMails(String[] messageNumbers, String[] uids, boolean all) throws MessagingException, IOException {
    Query qry = new QueryImpl(all ? _fldnew : _flddo, 0, "query");
    Folder folder = _fldelse.getFolder("INBOX");
    folder.open(Folder.READ_ONLY);
    try {
      getMessages(qry,folder, uids, messageNumbers, startrow, maxrows,all);
    }
    finally {
      folder.close(false);
    }
    return qry;
  }

    private void toQuery(Query qry, Message message, Object uid, boolean all)
     {
    int row = qry.addRow();
      // date
    try {
      qry.setAtEL(DATE, row, Caster.toDate(message.getSentDate(), true,null,null));
    }
    catch (MessagingException e) {}
   
    // subject
    try {
      qry.setAtEL(SUBJECT, row, message.getSubject());
    } catch (MessagingException e) {
      qry.setAtEL(SUBJECT, row, "MessagingException:"+e.getMessage());
    }
   
    // size
    try {
      qry.setAtEL(SIZE, row, new Double(message.getSize()));
    }
    catch (MessagingException e) {}
   
    qry.setAtEL(FROM, row, toList(getHeaderEL(message,"from")));
    qry.setAtEL(MESSAGE_NUMBER, row, new Double(message.getMessageNumber()));
    qry.setAtEL(MESSAGE_ID, row, toList(getHeaderEL(message,"Message-ID")));
    String s = toList(getHeaderEL(message,"reply-to"));
    if(s.length() == 0) {
      s = Caster.toString(qry.getAt(FROM, row,null), "");
    }
    qry.setAtEL(REPLYTO, row, s);
    qry.setAtEL(CC, row, toList(getHeaderEL(message,"cc")));
    qry.setAtEL(BCC, row, toList(getHeaderEL(message,"bcc")));
    qry.setAtEL(TO, row, toList(getHeaderEL(message,"to")));
    qry.setAtEL(UID, row, uid);
    StringBuffer content = new StringBuffer();
    try {
      for(Enumeration enumeration = message.getAllHeaders(); enumeration.hasMoreElements(); content.append('\n')){
        Header header = (Header) enumeration.nextElement();
        content.append(header.getName());
        content.append(": ");
        content.append(header.getValue());
      }
    }
    catch (MessagingException e) {}
    qry.setAtEL(HEADER, row, content.toString());
   
    if(all) {
      getContentEL(qry, message, row);
    }
  }

  private String[] getHeaderEL(Message message, String key) {
    try {
      return message.getHeader(key);
    } catch (MessagingException e) {
      return null;
    }
  }

  /**
     * gets all messages from given Folder that match given criteria
   * @param qry
     * @param folder
     * @param uIds
     * @param messageNumbers
   * @param all
     * @param startrow
     * @param maxrows
   * @return
     * @return matching Messages
   * @throws MessagingException
     */
    private Map<String,Message> getMessages(Query qry, Folder folder, String[] uids, String[] messageNumbers, int startRow, int maxRow, boolean all) throws MessagingException
     {
   
      Message[] messages = folder.getMessages();
    Map<String,Message> map = qry==null?new HashMap<String,Message>():null;
    int k = 0;
    if(uids != null || messageNumbers != null) {
      startRow = 0;
      maxRow = -1;
    }
    Message message;
    for(int l = startRow; l < messages.length; l++) {
      if(maxRow != -1 && k == maxRow) {
        break;
      }
      message = messages[l];
      int messageNumber = message.getMessageNumber();
      String id = getId(folder,message);
     
      if(uids == null ? messageNumbers == null || contains(messageNumbers, messageNumber) : contains(uids, id)) {
        k++;
        if(qry!=null){
          toQuery(qry,message,id,all);
        }
        else map.put(id, message);
      }
    }
    return map;
  }
    protected abstract String getId(Folder folder,Message message) throws MessagingException ;


    private void getContentEL(Query query, Message message, int row) {
      try {
      getContent(query, message, row);
    } catch (Exception e) {
      String st = ExceptionUtil.getStacktrace(e,true);
     
      query.setAtEL(BODY, row, st);
    }
    }

  /**
     * write content data to query
     * @param qry
     * @param content
     * @param row
     * @throws MessagingException
     * @throws IOException
     */
    private void getContent(Query query, Message message, int row) throws MessagingException, IOException {
    StringBuffer body = new StringBuffer();
    Struct cids=new StructImpl();
    query.setAtEL(CIDS, row, cids);
    if(message.isMimeType("text/plain")) {
      String content=getConent(message);
        query.setAtEL(TEXT_BODY,row,content);
        body.append(content);
    }
    else if(message.isMimeType("text/html")) {
      String content=getConent(message);
        query.setAtEL(HTML_BODY,row,content);
        body.append(content);
    }
    else {
      Object content = message.getContent();
      if(content instanceof MimeMultipart) {
        Array attachments = new ArrayImpl();
        Array attachmentFiles = new ArrayImpl();
        getMultiPart(query, row, attachments, attachmentFiles,cids, (MimeMultipart) content, body);
 
        if(attachments.size() > 0) {
          try {
            query.setAtEL(ATTACHMENTS, row, ListUtil.arrayToList(attachments, "\t"));
          }
          catch(PageException pageexception) {
          }
        }
        if(attachmentFiles.size() > 0) {
          try {
            query.setAtEL(ATTACHMENT_FILES, row, ListUtil.arrayToList(attachmentFiles, "\t"));
          }
          catch(PageException pageexception1) {
          }
        }
       
       
      }
    }
    query.setAtEL(BODY, row, body.toString());
  }

  private void getMultiPart(Query query, int row, Array attachments, Array attachmentFiles,Struct cids, Multipart multiPart, StringBuffer body) throws MessagingException, IOException {
    int j = multiPart.getCount();

    for(int k = 0; k < j; k++) {
      BodyPart bodypart = multiPart.getBodyPart(k);
      Object content;
     

      if(bodypart.getFileName() != null) {
        String filename = bodypart.getFileName();
        try{
          filename=Normalizer.normalize(MimeUtility.decodeText(filename),Normalizer.Form.NFC);
        }
        catch(Throwable t){}
       
        if(bodypart.getHeader("Content-ID") != null) {
          String[] ids = bodypart.getHeader("Content-ID");
          String cid=ids[0].substring(1, ids[0].length() - 1);
          cids.setEL(KeyImpl.init(filename), cid);
        }
       
        if(filename != null && ArrayUtil.find(attachments, filename)==0) {
         
          attachments.appendEL(filename);
          if(attachmentDirectory != null) {
            Resource file = attachmentDirectory.getRealResource(filename);
            int l = 1;
            String s2;
            for(; uniqueFilenames && file.exists(); file = attachmentDirectory.getRealResource(s2)) {
              String as[] = ResourceUtil.splitFileName(filename);
              s2 = as.length != 1 ? as[0] + l++ + '.' + as[1] : as[0] + l++;
            }

            IOUtil.copy(bodypart.getInputStream(), file, true);
            attachmentFiles.appendEL(file.getAbsolutePath());
          }
        }
      }
      else if(bodypart.isMimeType("text/plain")) {
        content=getConent(bodypart);
          query.setAtEL(TEXT_BODY,row,content);
          if(body.length()==0)body.append(content);
      }
      else if(bodypart.isMimeType("text/html")) {
        content=getConent(bodypart);
          query.setAtEL(HTML_BODY,row,content);
          if(body.length()==0)body.append(content);
      }
      else if((content=bodypart.getContent()) instanceof Multipart) {
        getMultiPart(query, row, attachments, attachmentFiles,cids, (Multipart) content, body);
      }
      else if(bodypart.getHeader("Content-ID") != null) {
        String[] ids = bodypart.getHeader("Content-ID");
        String cid=ids[0].substring(1, ids[0].length() - 1);
        String filename = "cid:" + cid;
       
          attachments.appendEL(filename);
          if(attachmentDirectory != null) {
            filename = "_" + Md5.getDigestAsString(filename);
            Resource file = attachmentDirectory.getRealResource(filename);
            int l = 1;
            String s2;
            for(; uniqueFilenames && file.exists(); file = attachmentDirectory.getRealResource(s2)) {
              String as[] = ResourceUtil.splitFileName(filename);
              s2 = as.length != 1 ? as[0] + l++ + '.' + as[1] : as[0] + l++;
            }

            IOUtil.copy(bodypart.getInputStream(), file, true);
            attachmentFiles.appendEL(file.getAbsolutePath());
          }
       
        cids.setEL(KeyImpl.init(filename), cid);
      }
    }
  }

  /* *
     * writes BodyTag data to query, if there is a problem with encoding, encoding will removed a do it again
     * @param qry
     * @param columnName
     * @param row
     * @param bp
     * @param body
     * @throws IOException
     * @throws MessagingException
     * /
    private void setBody(Query qry, String columnName, int row, BodyPart bp, StringBuffer body) throws IOException, MessagingException {
        String content = getConent(bp);
     
      qry.setAtEL(columnName,row,content);
        if(body.length()==0)body.append(content);
       
    }*/
   
    private String getConent(Part bp) throws MessagingException {
      InputStream is=null;
     
      try {
        return getContent(is=bp.getInputStream(), CharsetUtil.toCharset(getCharsetFromContentType(bp.getContentType())));
        }
        catch(IOException mie) {
          IOUtil.closeEL(is);
          try {
        return getContent(is=bp.getInputStream(), SystemUtil.getCharset());
      }
          catch (IOException e) {
            return "Can't read body of this message:"+e.getMessage();
      }
        }
        finally {
          IOUtil.closeEL(is);
        }
    }
   
    private String getContent(InputStream is,Charset charset) throws IOException {
    return MailUtil.decode(IOUtil.toString(is, charset));
    }
   
   
  private static String getCharsetFromContentType(String contentType) {
    Array arr=ListUtil.listToArrayRemoveEmpty(contentType,"; ");
   
    for(int i=1;i<=arr.size();i++) {
      Array inner = ListUtil.listToArray((String)arr.get(i,null),"= ");
      if(inner.size()==2 && ((String)inner.get(1,"")).trim().equalsIgnoreCase("charset")) {
        String charset = (String) inner.get(2,"");
        charset=charset.trim();
        if(!StringUtil.isEmpty(charset)) {
          if(StringUtil.startsWith(charset, '"') && StringUtil.endsWith(charset, '"')) {
            charset=charset.substring(1,charset.length()-1);
          }
          if(StringUtil.startsWith(charset, '\'') && StringUtil.endsWith(charset, '\'')) {
            charset=charset.substring(1,charset.length()-1);
          }
        }
        return charset;
      }
    }
    return "us-ascii";
  }


  /**
     * checks if a String Array (ids) has one element that is equal to id
     * @param ids
     * @param id
     * @return has element found or not
     */
  private boolean contains(String ids[], String id) {
    for(int i = 0; i < ids.length; i++) {
      if(Operator.compare(ids[i], id) == 0return true;
    }
    return false;
  }

  /**
     * checks if a String Array (ids) has one element that is equal to id
     * @param ids
     * @param id
     * @return has element found or not
     */
  private boolean contains(String ids[], int id) {
    for(int i = 0; i < ids.length; i++) {
      if(Operator.compare(ids[i], id) == 0) return true;
    }
    return false;
  }

  /**
     * translate a String Array to String List
     * @param arr Array to translate
     * @return List from Array
     */
  private String toList(String ids[]) {
    if(ids == nullreturn "";
    return ListUtil.arrayToList(ids, ",");
  }

  /**
     * disconnect without a exception
     */
  public void disconnectEL() {
    try {
      if(_fldelse != null)_fldelse.close();
    }
    catch(Exception exception) {}
  }
}
TOP

Related Classes of railo.runtime.net.mail.MailClient

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.