Pregunta

I'm trying to intercept and possibly modify all calls to mailService.sendMail to add/modify a bcc to emails going out. It is a temporary experiment so I want to avoid finding/changing all of the existing code if possible.

Example:

mailService.sendMail {
    to 'my_email@provider.com'
    //bcc may be present
    from 'admin@mysystem.com'
    subject 'Hello'
    body 'Just testing'
}

I'm able to intercept the calls easily enough with this created in Bootstrap:

mailService.metaClass.invokeMethod = {String name, args ->
    println "intercepting for ${name}..."
    def res = delegate.metaClass.getMetaMethod(name, args).invoke(delegate, args)
    println "done intercepting"
}

I am at a complete loss as to how to actually modify the call to either add a bcc if none is present, or add an address to it if it does exist. The args parameter is the closure - I've looked at everything I can find on the topic and no joy.

This is running on Grails 1.3.7 (I know).

¿Fue útil?

Solución

One way you can always add a bcc irrespective of bcc being defined earlier, is by composing the original closure arg with a new one:

mailService.metaClass.invokeMethod = {String name, args ->

    if( name == 'sendMail' ) {

        def newArgs = args[0] >> { bcc 'hr@mysystem.com' }

        //or def newArgs = { bcc 'hr@mysystem.com' } << args[0]

        def res = delegate.metaClass.getMetaMethod(name, newArgs)
                                    .invoke(delegate, newArgs)
    }
}

Assuming mail should be bcc'd and bcc list remains same, this way we do not have to keep track of supplied bcc list. Make sure name of method is always checked to be sendMail in order to avoid interception for other methods, although all methods will be intercepted in mailService bean they will be skipped for others but sendMail.

UPDATE:
Closure composition is available from Groovy 1.8 and I highly doubt Groovy 1.8 is available with Grails 1.3.7. In that case you can try the below approach otherwise:

mailService.metaClass.invokeMethod = {String name, args ->
    if(name == 'sendMail') {
        println "intercepting for ${name}..."

        def newClos = { cl -> 
            return {
                cl.delegate = delegate
                cl.resolveStrategy = Closure.DELEGATE_FIRST
                cl()

                //bcc
                bcc 'hr@mysystem.com'
            }
        }

        def newArgs = newClos args[0]
        def res = delegate.metaClass.getMetaMethod(name, newArgs)
                                    .invoke(delegate, newArgs)
        println "done intercepting"
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top