使用Coldfusion发送大量电子邮件

时间:2014-06-22 23:21:09

标签: coldfusion coldfusion-9 coldfusion-10 coldbox

这个问题可能与做大量的事情有关,但在这种情况下,我正在尝试发送电子邮件。

我已在新线程中设置发送过程,因此用户不会等待,并将请求超时重写为一小时。

问题在于,一旦进程发送了大约2000封电子邮件(通过以下代码循环约2000次),服务器就会耗尽内存,停止响应并需要重新启动。

阅读其他主题,CF应该能够很好地处理这一批电子邮件。

我考虑过的一件事是将所有对象调用更改为直接数据库查询并使用cfmail标记(我猜)删除所有对象的创建并在达到请求时构建(我猜是正在发生的事情),但是我不确定这是否会产生影响,并且如果可能的话,我真的想避免这种做法。我考虑的其他东西是将它分成3个或4个单独的线程,但同样,不确定这是否能解决问题。

有没有人遇到过这个问题,你发现什么能让处理继续进行而没有ram慢慢填满并杀死服务器?

thread name="sendBroadcastEmail" rc="#rc#" prc="#prc#" filters="#rc.filters#" email="#email#" emailSignature="#emailSignature#"{
    createObject( "java", "coldfusion.tagext.lang.SettingTag" ).setRequestTimeout(javaCast( "double", 3600 ));

        //get profiles that it will be sent to
        var sendToProfiles = profileService.getWithFilters(rc.filters);

        var mailService = getPlugin("MailService");
        var emailSent = false;
        var sentCount = 0;
        var failedCount = 0;

        //send the email (and log in profile events)
        if (listFind(attributes.rc.email.action,'send')){

            for ( i=1; i<=arrayLen(sendToProfiles);i++){
                var profile = sendToProfiles[i];
                try{

                    if (len(trim(profile.getPrimaryEmail()))){

                        var emailBody = profile.processDynamicPlaceholders(attributes.rc.email.body);
                        var emailBody = attributes.emailSignature.getHeader() & emailBody & attributes.emailSignature.getFooter();

                        var sendEmail = mailService.newMail(
                             from = attributes.emailSignature.getEmailAddress(),
                             //to = profile.getPrimaryEmail(),
                             to = Application.settings.testemail,
                             subject = attributes.rc.email.subject,
                             body = emailBody,
                             type="html");

                             sendEmail.addMailParam(disposition='attachment', file=attributes.email.getAttachmentWithPath());
                             mailService.send(sendEmail);

                        //log profile event
                        profile.saveEvent(eventType = 3,
                                        title="Broadcast Email: #attributes.rc.email.subject#", 
                                        description="Broadcast Email Sent: Subject: <br> #attributes.rc.email.subject#",
                                        sentContent=emailBody,
                                        ref2=1);
                    sentCount++;
                    }
                }
                catch (any exception){
                    //log profile event
                    profile.saveEvent(eventType = 3,
                                    title="FAILED Broadcast Email", 
                                    description="<br>Subject: #attributes.email.subject#<br>This email should have been sent to this profile, but the attempted send failed.  The likely cause is a malformed email address.",
                                    sentContent=emailBody,
                                    ref2=0);
                    failedCount++;
                }

            }   
            emailSent = true;

        }


        //persist email object
        if (listFind(attributes.rc.email.action,'save')){
            email.setTstamp(attributes.prc.now);
            email.setSent(emailSent);
            email.setStatsSent(sentCount);
            email.save();
        }

    }//end thread   

1 个答案:

答案 0 :(得分:3)

一种方法是以定时批量生成电子邮件以均匀分布负载。批次之间的批量大小和延迟可以根据您的环境进行调整。

    thread name="sendBroadcastEmail" rc="#rc#" prc="#prc#" filters="#rc.filters#" email="#email#" emailSignature="#emailSignature#"{
    createObject( "java", "coldfusion.tagext.lang.SettingTag" ).setRequestTimeout(javaCast( "double", 3600 ));

            // set thread to a lowish prority
            var currentThread = CreateObject( "java","java.lang.Thread" ).currentThread();
            var priority = currentThread.getPriority();
            currentThread.setPriority( 3 );

        //get profiles that it will be sent to
        var sendToProfiles = profileService.getWithFilters(rc.filters);

        var mailService = getPlugin("MailService");
        var emailSent = false;
        var sentCount = 0;
        var failedCount = 0;

        //send the email (and log in profile events)
        if (listFind(attributes.rc.email.action,'send')){

            var emailsPerBatch = 1000; // divide into batches, set size here
            var batchcount = Ceiling( ArrayLen( sendToProfiles ) / emailsPerBatch ); // number of batches
            var batchdelay = 120000; // set delay between batches (ms)
            // initialise first batch
            var firstitem = 1;
            var lastitem = emailsPerBatch;

            for( var batch=1; batch<=batchcount; batch++ ) {
                if( batch > 1 ){
                    // delay sending next batch and give way to other threads
                    currentThread.yield();
                    currentThread.sleep( batchdelay );
                }

            for ( var i=firstitem; i<=lastitem;i++ ){
                var profile = sendToProfiles[i];

                            // generate emails ...

            }


            // initialise next batch
            firstitem = lastitem++;
            lastitem += emailsPerBatch;
            if( lastitem > ArrayLen( sendToProfiles ) ) {
                // last batch
                lastitem = ArrayLen( sendToProfiles );
            }

            }
            emailSent = true;
        }

            currentThread.setPriority( priority ); // reset thread priority


    }//end thread