Tropicalista / lucee-cfimap

cfimap tag for Lucee Server
13 stars 6 forks source link

added attachment saving #4

Closed byrning closed 7 years ago

byrning commented 7 years ago

Thanks for this component!

I've changed it a bit as I wanted it purely script based, so I'm not submitting a PR.

I've added attachment saving with "attachmentpath" and "generateuniquefilenames" attributes, folder sorting, and a couple other things.

Grab what you want.

`component output="false" accessors="true" {

variables.connection = "";
variables.attachmentpath = "";
variables.generateuniquefilenames = false;

public function init(){
    return this;
}

public function connect(
    required string username,
    required string password,
    required string server,
    required boolean secure = false,
    required numeric timeout = 60,
    required numeric port = 143
){
    var clsSession = createObject("Java", "javax.mail.Session");
    var objProperties = createObject("Java", "java.util.Properties");
    var objStore = createObject("Java", "javax.mail.Store");
    var oTimeout = arguments.timeout * 1000;
    objProperties.init();
    objProperties.put("mail.store.protocol", arguments.secure ? 'imaps' : 'imap');
    objProperties.put("mail.imap.port", JavaCast( "int", arguments.port ) );
    objProperties.put("mail.imap.connectiontimeout", oTimeout);
    objProperties.put("mail.imap.timeout", oTimeout);
    objProperties.put("mail.imap.ssl.enable", JavaCast( "boolean", arguments.secure ) );
    objSession = clsSession.getInstance(objProperties);
    objStore = objSession.getStore();
    objStore.connect( arguments.server, arguments.username, arguments.password );

    variables.connection = objStore;
}

public function close() {
    variables.connection.close();
}

public function getHeaderOnly( string folder = "INBOX", startRow = 1, maxRows, uid, messageNumber ){

    var list = getMessages(arguments);
    return list;

}

public function getAll( string folder = "INBOX", startRow = 1, maxRows, uid, messageNumber, attachmentpath = "", generateuniquefilenames = false) {

    variables.attachmentpath = arguments.attachmentpath;
    variables.generateuniquefilenames = arguments.generateuniquefilenames;
    var list = getMessages(arguments, true);
    return list;

}

public function ListAllFolders( string folder, boolean recurse = false ){

    var folders = getFolders( arguments.folder, JavaCast( "boolean", arguments.recurse ) );

    var columns = "fullname,name, new, unread, totalmessages, parent, sortfolder";
    var list = QueryNew(columns);
    var listSorted = new Query();
    var sortIndex = 10;
    loop from="1" to="#ArrayLen(folders)#" step="1" index="index"{
        if( folders[index].getType() != 2 ){
            sortIndex = 10;
            queryAddRow(list);
            querySetCell(list, "fullname", folders[index].getFullName());
            querySetCell(list, "name", folders[index].getName());
            querySetCell(list, "new", folders[index].getNewMessageCount());
            querySetCell(list, "parent", folders[index].getParent().getName());
            querySetCell(list, "unread", folders[index].getUnreadMessageCount());
            querySetCell(list, "totalmessages", folders[index].getMessageCount());
            if (folders[index].getFullName() == "inbox") sortIndex = 1;
            else if (folders[index].getFullName() == "drafts") sortIndex = 2;
            else if (folders[index].getFullName() == "sent") sortIndex = 3;
            else if (folders[index].getFullName() == "junk") sortIndex = 4;
            else if (folders[index].getFullName() == "trash") sortIndex = 5;
            querySetCell(list, "sortfolder", sortIndex );
        }

    }

    listSorted.setDBType('query');
    listSorted.setAttributes(qryimap=list);
    listSorted.setSQL('select * from qryimap order by sortfolder');

    return listSorted.execute().getResult();

}

public function markRead( string folder ){

    var flag = CreateObject("Java", "javax.mail.Flags$Flag");
    var objFolder = getFolder( arguments.folder );
    objFolder.open( objFolder.READ_WRITE );
    var messages = objFolder.getMessages();

    loop from="1" to="#ArrayLen( messages )#" step="1" index="index"{
        messages[index].setFlag(flag.SEEN, true);
    }
    objFolder.close(true);

    return messages;

}

public function delete( string folder ){

    var flag = CreateObject("Java", "javax.mail.Flags$Flag");
    var objFolder = getFolder( arguments.folder );
    objFolder.open( objFolder.READ_WRITE );
    var messages = objFolder.getMessages();

    loop from="1" to="#ArrayLen( messages )#" step="1" index="index"{
        messages[index].setFlag(flag.DELETED, true);
    }
    objFolder.close(true);

    return messages;

}

public function moveMail( required string newFolder, required string messageNumber, string folder ){

    var objFolder = getFolder( arguments.folder );
    var objNewFolder = getFolder( arguments.newFolder );

    objFolder.open( objFolder.READ_WRITE );
    var messages = objFolder.getMessages( JavaCast( "int[]", ListToArray(arguments.messageNumber)) );
    objFolder.copyMessages( messages, objNewFolder );
    objFolder.close(true);

    return messages;

}

public function createFolder( required string folder ){

    var objFolder = getFolder( arguments.folder );
    objFolder.create( 3 );

    return objFolder;

}

public function renameFolder( required string folder, required string newFolder ){

    var objFolder = getFolder( arguments.folder );
    var objNewFolder = getFolder( arguments.newFolder );
    objFolder.renameTo( objNewFolder );

    return objFolder;

}

public function deleteFolder( required string folder ){

    var objFolder = getFolder( arguments.folder );
    objFolder.delete( true );

}

private function getFolder( required string folder ){

    if( !len( arguments.folder ) ){
        arguments.folder = "INBOX";
    }
    var folder = variables.connection.getFolder( arguments.folder );

    return folder;

}

private function getFolders( string folder, boolean recurse = false ){

    if( !len(trim(arguments.folder)) ){
        var folders = arguments.recurse ? variables.connection.getDefaultFolder().list("*") : variables.connection.getDefaultFolder().list();
    }else{
        var folders = arguments.recurse ? variables.connection.getFolder( arguments.folder ).list("*") : variables.connection.getFolder( arguments.folder ).list();
    }

    return folders;

}

private function openFolder( string folder ){

    if( !structKeyExists( arguments, "folder" ) ){
        var objFolder = variables.connection.getDefaultFolder();
    }else{
        var objFolder = variables.connection.getFolder( arguments.folder );
    }
    objFolder.open( objFolder.READ_ONLY );

    return objFolder;

}

private function createQuery( required messages, required string columns, required boolean all=false ){

    var flag = CreateObject("Java", "javax.mail.Flags$Flag");
    var recipient = CreateObject("Java", "javax.mail.Message$RecipientType");

    var list = QueryNew( arguments.columns );

    loop from="1" to="#ArrayLen( messages )#" step="1" index="index"{
        if( isNull(messages[index]) ){
            continue;
        }
        queryAddRow(list);
        querySetCell( list, "answered", messages[index].isSet(flag.ANSWERED) );
        if( arguments.all ) querySetCell( list, "attachmentfiles", getFileName( messages[index] ) );
        if( arguments.all ) querySetCell( list, "attachments", hasAttachments( messages[index] ) );
        if( arguments.all ) querySetCell( list, "body", getHtmlBody( messages[index] ) );
        querySetCell( list, "cc", IsArray( messages[index].getRecipients( recipient.CC ) ) ? ArrayToList(messages[index].getRecipients( recipient.TO )) : "" );
        querySetCell( list, "deleted", messages[index].isSet(flag.DELETED) );
        querySetCell( list, "draft", messages[index].isSet(flag.DRAFT) );
        querySetCell( list, "flagged", messages[index].isSet(flag.FLAGGED) );
        querySetCell( list, "from", messages[index].getSender().toString() );
        querySetCell( list, "header", ArrayToList( createObject( "java", "java.util.Collections" ).list( messages[index].getAllHeaderLines() ) ) );
        if( arguments.all ) querySetCell( list, "htmlbody", getHtmlBody( messages[index] ) );
        querySetCell( list, "lines", messages[index].getLineCount() );
        querySetCell( list, "messageid", messages[index].getMessageID() );
        querySetCell( list, "messagenumber", messages[index].getMessageNumber() );
        querySetCell( list, "recent", messages[index].isSet(flag.RECENT) );
        querySetCell( list, "replyto", ArrayToList(messages[index].getReplyTo()) );
        querySetCell( list, "rxddate", messages[index].getReceivedDate() );
        querySetCell( list, "seen", messages[index].isSet(flag.SEEN) );
        querySetCell( list, "sentDate", messages[index].getSentDate() );
        querySetCell( list, "size", messages[index].getSize() );
        querySetCell( list, "subject", messages[index].getSubject() );
        if( arguments.all ) querySetCell( list, "textbody", getText( messages[index] ) );
        querySetCell( list, "to", IsArray( messages[index].getRecipients( recipient.TO ) ) ? ArrayToList(messages[index].getRecipients( recipient.TO )) : messages[index].getRecipients( recipient.TO ) );
        querySetCell( list, "uid", messages[index].getFolder().getUID( messages[index] ) );
        if( arguments.all ) querySetCell( list, "user", messages[index].isSet(flag.USER) );
    }

    return list;

}

private function savePartAttachment( required messagepart ){

    var fileCheckCount = 1;

    if ((compareNoCase( arguments.messagepart.getDisposition(), arguments.messagepart.ATTACHMENT ) || compareNoCase( arguments.messagepart.getDisposition(), arguments.messagepart.INLINE ) ) and len(trim(arguments.messagepart.getFileName())) ) {
        if (!len(trim(variables.attachmentpath))) throw "Need attachmentpath in order to save attachments.";

        var saveFileAs = trim(arguments.messagepart.getFileName());

        if (variables.generateuniquefilenames) {
            var fileExt = trim(listLast(saveFileAs, "."));
            if (trim(listFirst(saveFileAs, ".")) eq "" or fileExt eq "" or REFindNoCase("[^a-z0-9-_ \.]", saveFileAs)) throw "File name is suspicious.";

            while ( fileExists(variables.attachmentpath & saveFileAs) ) {
                saveFileAs = trim(arguments.messagepart.getFileName());
                saveFileAs = REReplaceNoCase(saveFileAs, "\.#fileExt#$", "") & "-#fileCheckCount++#." & fileExt;
            }
        }

        arguments.messagepart.saveFile( variables.attachmentpath & saveFileAs );
        return variables.attachmentpath & saveFileAs;
    }

    return "";

}

private function getFileName( required message ){

    if( !hasAttachments(arguments.message) ) {
        return "";
    }

    var fileName = [];
    var savedAttachment = "";

    var multiPart = arguments.message.getContent();

    for ( i=0; i LT multiPart.getCount(); i++ ) {

        var bodyPart = multiPart.getBodyPart( i );

        if ( bodyPart.isMimeType( "multipart/*" ) ) {
            for ( fa=0; fa LT bodyPart.getContent().getCount(); fa++ ) {
                var attachPart = bodyPart.getContent().getBodyPart(fa);

                savedAttachment = savePartAttachment( attachPart );
                if (savedAttachment neq "") fileName.append( savedAttachment );
            }
        }
        else {
            savedAttachment = savePartAttachment( bodyPart );
            if (savedAttachment neq "") fileName.append( savedAttachment );
        }

    }

    return fileName.toList(chr(9));

}

private function getText( required message ){

    if ( arguments.message.isMimeType( "multipart/*" ) ) {

        var multiPart = arguments.message.getContent();
        for ( i=0; i LT multiPart.getCount(); i++ ) {

            var bodyPart = multiPart.getBodyPart( i );

            if( bodyPart.isMimeType("text/plain") ){
                return bodyPart.getContent();
            }

        }

    }

}

private function getHtmlBody( required message ){

    if ( arguments.message.isMimeType( "multipart/*" ) ) {

        var multiPart = arguments.message.getContent();

        for ( i=0; i LT multiPart.getCount(); i++ ) {

            var bodyPart = multiPart.getBodyPart( i );

            if ( bodyPart.isMimeType( "text/html" ) ) {
                return bodyPart.getContent();
            }

        }

    }

    return "";

}

boolean function hasAttachments( message ){

    if ( arguments.message.isMimeType( "multipart/*" ) ) {

        var multiPart = arguments.message.getContent();

        for ( i=0; i LT multiPart.getCount(); i++ ) {

            var bodyPart = multiPart.getBodyPart( i );

            if (compareNoCase( bodyPart.getDisposition(), bodyPart.ATTACHMENT ) || compareNoCase( bodyPart.getDisposition(), bodyPart.INLINE ) ) {
                return true;
            }

        }

    }

    return false;

}

public any function getMessages( struct attr, boolean getAll = false ) {

    var messages = [];
    var columns = "answered, cc, deleted, draft, flagged, from, header, lines, messageid,
    messagenumber, recent, replyto, rxddate, seen, sentDate, size, subject, to, uid";
    var objFolder = getFolder( arguments.attr.folder );
    objFolder.open( objFolder.READ_ONLY );

    if( structKeyExists( arguments.attr, "uid" ) and len(trim(arguments.attr.uid)) ) {
        var messages = objFolder.getMessagesByUID( listToArray(arguments.attr.uid) );
    }elseif( structKeyExists( arguments.attr, "messageNumber") and len(trim(arguments.attr.messageNumber)) ){
        var messages = objFolder.getMessage( arguments.attr.messageNumber );
    }elseif( !structKeyExists( arguments.attr, "maxRows") or (objFolder.getMessageCount() lt arguments.attr.startRow)){
        var messages = objFolder.getMessages();
    }else{
        var messages = objFolder.getMessages( arguments.attr.startRow, arguments.attr.startRow + arguments.attr.maxRows - 1 );
    }

    if( arguments.getAll ){
        columns = ListAppend( columns, "attachmentfiles, attachments, body, htmlbody, textbody, user", "," );
    }

    var list = createQuery( messages, columns, arguments.getAll );

    objFolder.close( false );

    return list;
}

} `