GithubHelp home page GithubHelp logo

grails / grails-mail Goto Github PK

View Code? Open in Web Editor NEW

This project forked from gpc/grails-mail

14.0 8.0 25.0 2.68 MB

The Grails Mail Plugin

Home Page: https://grails.github.io/grails-mail/

License: Apache License 2.0

Groovy 100.00%

grails-mail's Issues

From Address Not Correct

I am using the grails mail service to send mail and I am noticing that when running in production environment, the from address is using the username defined in the settings and not what I define in the sendMail closure.

This is my closure:

mailService.sendMail {
    to params.recipientEmail as String
    from “[email protected]”.  <--- What I expect in either environment. Only present in development env
    subject "Testing Emails"
    body view:"/emails/specificEmail",
              model: [ “model” ]
}

I have tried this in two separate applications and neither are working.

Additionally, I would like to use an email alias and that is also not working. I have tried using my alias account and it works just fine in normal situations, but not with the grails mail plugin. I suspect it's falling under the same issue. The from address supplied to the closure uses my username defined in the settings.

One question I have: I have tried the following closure to hide the email, to show a "name" instead, only revealing the email if I click on the name, but the from address only results in the following: "Mixology [email protected]". The from address is still visible. Is this something I can control using the plugin? Or is this a mail server setting I need to enable?

mailService.sendMail {
    to params.recipientEmail as String
    from “Mixology [email protected]”.  <--- Does not hide the email address
    subject "Testing Emails"
    body view:"/emails/specificEmail",
              model: [ “model” ]
}

I have provided screen shots of my environment, and the two emails. (Note: The name, test userr, is correct. I updated it one day and just never changed it)

When running in development: From email is correct.
Development Email

When running in production: I'd expect the from to be "[email protected]". Instead it is using my username defined in the settings.
Production Email

Mail Settings:
Mail Settings

My environment:
App Status
Plugins

Support for smtp connection pool

This is a great plugin. If somehow we can add smtp connection pool, it will be awesome.
Currently if you send multiple emails one-by-one you have to connect to smtp server each time, and soon you will get error like Too many login attempts, please try again later .

Support for External Credentials Provider

This is a feature request. Looking for a clean way to inject an external credentials provider so that I don't have to store plain text credentials in SCM, environment variables, JVM startup params, etc. This is the only workaround that I've found, and obviously it's not a good one:

@CompileStatic
class BootStrap {
    SecretManagerService secretManagerService
    MailSender mailSender

    def init = { servletContext ->
        final Secret secret = secretManagerService.getSecret('my-secret-name')
        setMailPassword(secret)
    }

    @CompileDynamic
    void setMailPassword(final Secret secret) {
        //TODO: this is really bad.
        mailSender.username = secret.username
        mailSender.password = secret.password
    }
}

Obviously the default implmentation should remain as-is and use config, but I would like to inject my credential manager accordingly. Thanks!

Option to set subject and text by message code

I think it would be useful to have the option to set a mail's subject and text content by providing a message code. As a developer, the advantage is that I don't have to include the messageSource myself and with the already available "locale" option subject and text could be translated to the correct locale.

Code example:

mailService.sendMail {
locale user.languageForCorrespondence
subject 'mail.summary.subject'
text 'mail.summary.text'
}

Support for Grails 5 and 6

I'm wondering if this plugin is compatible with Grails 5 and 6 or if this plugin is no longer developing. The latest supported Grails version mentioned in documentation is 4.

GrailsMailException: message has no content, use text(), html() or body() methods to set content

When running Grails in development my application is sending mail correctly. When I run grails war and deploy to Tomcat, then I get the following error:

GrailsMailException: message has no content, use text(), html() or body() methods to set content

This is how I'm using the sendMail command.

String body = groovyPageRenderer.render(template: "/dfdirHeartbeatAlert/restoreHeartbeatEmail", model: [user: user, message: heartbeatMessage])
        
println(body)

mailService.sendMail {
            multipart true
            bcc bccList.toArray()
            from "<email_address>"
            subject "Subject"
            html body        
}

When I print out body in development it looks correct. However printing body in production deployed on Tomcat comes back as an empty string.

Is this the intended syntax for sending html mail?

org.grails.plugins:mail:3.0.0 failed when adding grails { pathingJar = true }

Hi,
My system is developed in Grails 4.0.1.
Based on the official document from https://docs.grails.org/4.0.1/guide/single.html#aHelloWorldExample, it suggest developers to add
grails { pathingJar = true } to build.gradle for avoiding below problem

" java.io.IOException: CreateProcess error=206, The filename or extension is too long"

However, after I add

grails (pathingJar = true}

to my build.gradle, the below error will happen:

Caused by: java.lang.NoClassDefFoundError: grails/plugins/mail/SendMail
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
	at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:550)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:458)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
	at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.findClass(RestartClassLoader.java:159)
	at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:141)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at grails.boot.config.tools.ClassPathScanner.scanUsingPattern(ClassPathScanner.groovy:181)
	at grails.boot.config.tools.ClassPathScanner.scan(ClassPathScanner.groovy:149)
	at grails.boot.config.tools.ClassPathScanner.scan(ClassPathScanner.groovy:107)
	at grails.boot.config.tools.ClassPathScanner.scan(ClassPathScanner.groovy)
	at grails.boot.config.GrailsAutoConfiguration.classes(GrailsAutoConfiguration.groovy:79)
	at grails.boot.config.GrailsAutoConfiguration.grailsApplicationPostProcessor(GrailsAutoConfiguration.groovy:68)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
	... 26 common frames omitted
Caused by: java.lang.ClassNotFoundException: grails.plugins.mail.SendMail
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:144)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	... 48 common frames omitted

I had tried org.grails.plugins:mail:3.0.0 and org.grails.plugins:mail:2.00. Same result.

'to' value limit? send multiple emails

I'm wondering if there is a limit for the TO value.
I want to send multiple emails at send time using same smtp config.
I have a list with all 'to's

toList.each { String emailTo, String name ->
	String nameTo = name ?: emailTo
	sendMail {
		to emailTo
		subject 'Test #1'
		html view: "/mail/simple", model: [name: nameTo]
	}
}

Any limitation?

Grails 3.3.4 Boot Issue

Grails 3.3.4
Plugin compile "org.grails.plugins:mail:2.0.0"

Getting exception on Boot

Caused by: java.lang.NoClassDefFoundError: grails/plugins/mail/SendMail

Could not locate mail body /email/JobFail. Is it in a plugin? If so you must pass the plugin name in the [plugin] variable

Hello,
I've used "org.grails.plugins:mail:2.0.0.RC6" and "org.grails:grails-plugin-gsp" for send emails using grails3.
I've called my mail sending service from another controller with the required params and I've kept the required gsp under the grails-app/views/ folder.

The mail sending service is:

@Transactional
class SendEmailService {
    def mailService
    def serviceMethod(params) {
        try{
            mailService.sendMail {
                to emailList
                from [email protected]
                subject "MY_EMAIL_SUBJECT"
                body(view:"/email/JobFail",model:[params])
            }
        }catch (Exception e){
            log.info("**** Error : Sending Job Fail Email:\n******* Cause : " + e.getMessage())
        }
    }
}

The gsp page when my params are mapped is under grails-app/view/email/JobFail.gsp.

Everything in the development environment(using IntelliJ) is working fine but in the production environment, I'm getting a weird issue like:
Could not locate mail body /email/JobFail. Is it in a plugin? If so you must pass the plugin name in the [plugin] variable

Release

Create a 2.0.0 release
Include asciidoc documentation

Dynamic parameters.

Hi guy, i have a question.. how to overwrite/configure dynamic SMTP? I have a business case that he can send email from 3 different accounts and the SMTP, port, direction, etc he can configure and save in database. Tnks :D

Did i miss something ?

Hello,

It seems that, In grails 5.0.0 as in grails 4.0.12, the mailService is not injected in service. Did i miss something ?
Example :

class TestMailService {

    MailService mailService

    def serviceMethod() {
        mailService.sendMail {
            from 'prt@localhost'
            to 'prt@localhost'
            subject 'TEST'
            text 'contenu'
        }

    }
}

and

class TestMailSpec extends Specification implements ServiceUnitTest<TestMailService> {

    def 'test mail'() {
        expect:
        service.serviceMethod()

    }
}

it gives

Condition failed with Exception:

service.serviceMethod()
|       |
|       java.lang.NullPointerException: Cannot invoke method sendMail() on null object
|       	at fr.cda.TestMailService.serviceMethod(TestMailService.groovy:11)
|       	at fr.cda.TestMailSpec.test mail(TestMailSpec.groovy:10)
<fr.cda.TestMailService@5d0529d1 mailService=null grails_plugins_mail_SendMail__applicationContext=org.springframework.web.context.support.GenericWebApplicationContext@863f764, started on Thu Oct 28 14:05:51 CEST 2021, parent: application>

Condition failed with Exception:

service.serviceMethod()
|       |
|       java.lang.NullPointerException: Cannot invoke method sendMail() on null object
|       	at fr.cda.TestMailService.serviceMethod(TestMailService.groovy:11)
|       	at fr.cda.TestMailSpec.test mail(TestMailSpec.groovy:10)
<fr.cda.TestMailService@5d0529d1 mailService=null grails_plugins_mail_SendMail__applicationContext=org.springframework.web.context.support.GenericWebApplicationContext@863f764, started on Thu Oct 28 14:05:51 CEST 2021, parent: application>

	at fr.cda.TestMailSpec.test mail(TestMailSpec.groovy:10)
Caused by: java.lang.NullPointerException: Cannot invoke method sendMail() on null object
	at fr.cda.TestMailService.serviceMethod(TestMailService.groovy:11)
	... 1 more

I'm using the mailService in a grails 2.1.4 and did not have any issue.

What's wrong with it ?

Thanks

response.format for .pdf is changed from "pdf" to "all" after installing mail plugin

$ sdk use grails 3.0.8
$ grails create-app pdf308
$ cd pdf308
$ grails create-controller Foo
$ echo "\${response.format}" > grails-app/views/foo/index.gsp
$ grails run-app

open http://localhost:8080/foo/index.pdf
Output is: pdf

Add mail plugin to build.gradle:

compile "org.grails.plugins:mail:2.0.0.RC2"

run-app and reload page. Output is now: all

This seems to be the case with Grails 3.0.8 and later. With Grails 3.0.7 and earlier, output is pdf both before and after installing plugin.
Both 2.0.0.RC1 and 2.0.0.RC2 is affected.

Unfortunately, this is causing issues in wkhtmltopdf plugin, see rlovtangen/grails-wkhtmltopdf#15

Grails 4.0.3: <g:applyLayout>: Unable to resolve view

Hello

I am upgrading an existing Grails application to version 4.0.3 and get the following error message, which didn't happen with Grails 3.x:

org.grails.taglib.GrailsTagException: [views/mail/test.gsp:12] Error executing tag <g:applyLayout>: Unable to resolve view

Also the error only happens when sending emails from BootStrap (see my example code). When I call the example code from a controller, it works as expected.

/grails-app/init/myapp/BootStrap.groovy

class BootStrap {

    TestService testService

    def init = { servletContext ->
        testService.doSomething()
    }
    
    def destroy = {
    }
}

/grails-app/services/myapp/TestService.groovy

class TestService {

    void doSomething() {
        sendMail {
            to '[email protected]'
            from "[email protected]"
            subject "Test"
            html view: '/mail/test', model: [:]
        }
    }
}

/grails-app/views/layouts/mail.gsp

<html>
<head>
    <g:layoutHead/>
</head>
<body>
    <p>/layouts/mail.gsp</p>
    <g:layoutBody/>
</body>
</html>

/grails-app/views/mail/test.gsp

<g:applyLayout name="mail">
    <html>
    <head>
        <title>Test</title>
        <meta name="layout" content="mail" />
    </head>
    <body>
        <p>/mail/test.gsp</p>
        Hello World!
    </body>
    </html>
</g:applyLayout>

Grails 4 M1, OpenJDK 11.0.2 throws exception with basic usage

Grails 4 M1
OpenJDK 11.0.2

Commit on a fresh 4.0.0.M1 project
erichelgeson/grails4@44bfdd5

Hit /mail/index - get:

2019-02-19 14:56:11.064 ERROR --- [nio-8080-exec-1] o.g.web.errors.GrailsExceptionResolver   : IllegalArgumentException occurred when processing request: [GET] /mail/index
Stacktrace follows:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'four.MailController': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mailService': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1105)
	at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:73)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
	at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
	at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mailService': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1762)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(AbstractAutowireCapableBeanFactory.java:1436)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1375)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
	... 17 common frames omitted
Caused by: java.lang.IllegalArgumentException: null
	at java.base/java.util.concurrent.ThreadPoolExecutor.setCorePoolSize(ThreadPoolExecutor.java:1535)
	at grails.plugins.mail.MailService.setPoolSize(MailService.groovy:66)
	at grails.plugins.mail.MailService.afterPropertiesSet(MailService.groovy:86)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1821)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1758)
	... 26 common frames omitted

MessagingException on grails 3.1.0

application.yml 
grails:
            mail:
                host: "smtp.gmail.com"
                port: 465
                username: "*********@gmail.com"
                password: "**********"
                props:
                    mail.smtp.auth: "true"
                    mail.smtp.socketFactory.port: "465"
                    mail.smtp.socketFactory.class: "javax.net.ssl.SSLSocketFactory"
                    mail.smtp.socketFactory.fallback: "false"

Action

def create = {
        println "sending mail now............."
        sendMail {
            from "*********@gmail.com"
            to "**********@gmail.com"
            subject "New user"
            text "A new user has been created"
        }
        println "mail sent";
    }

ERROR

ERROR org.grails.web.errors.GrailsExceptionResolver - MessagingException occurred when processing request: [GET] /ims/test/create
Could not connect to SMTP host: smtp.gmail.com, port: 465, response: -1. Stacktrace follows:
org.springframework.mail.MailSendException: Mail server connection failed; nested exception is javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465, response: -1. Failed messages: javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465, response: -1
	at grails.plugins.mail.MailMessageBuilder.sendMessage(MailMessageBuilder.groovy:130) ~[mail-2.0.0.RC6.jar:na]
	at grails.plugins.mail.MailService.sendMail(MailService.groovy:53) ~[mail-2.0.0.RC6.jar:na]
	at grails.plugins.mail.MailService.sendMail(MailService.groovy:57) ~[mail-2.0.0.RC6.jar:na]
	at grails.plugins.mail.SendMail$Trait$Helper.sendMail(SendMail.groovy:31) ~[mail-2.0.0.RC6.jar:na]

grails3 override username

Hello,

I would like to override grails.mail.username and grails.mail.password in the file application-development.yml.

In application.yml :
grails:
mail:
username: user
password: pass

In application-development.yml :
grails:
mail:
username: new-user
password: new-pass

I expect, in a development mode, to get new-user and new-pass as values but I only get empty strings in mailSender object (from mailService).

Can someone explain me why ?
Thanks
Noémie

Unable to use body method variant with model in Grails 3.0.7 and earlier

Using body with model does not work in Grails 3.0.7 and earlier with mail plugin 2.0.0.RC6 as opposed to 2.0.0.RC4.

Example:

class FooController {
    def mailService

    def mail() {
        mailService.sendMail {
            to "[email protected]"
            subject "Hello John"
            body(view: "/foo/index",
                    model: [bar: 'foobar']
            )       
        }
        render "ok"
    }
}

Exception:

ERROR org.grails.web.errors.GrailsExceptionResolver - NoSuchMethodError occurred when processing request: [GET] /foo/mail
org.grails.gsp.GroovyPageTemplate.make(Ljava/util/Map;)Lorg/grails/gsp/GroovyPageWritable;. Stacktrace follows:
java.lang.reflect.InvocationTargetException: null
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_31]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_31]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_31]
Caused by: java.lang.NoSuchMethodError: org.grails.gsp.GroovyPageTemplate.make(Ljava/util/Map;)Lorg/grails/gsp/GroovyPageWritable;
    at grails.plugins.mail.MailMessageContentRenderer$_render_closure1.doCall(MailMessageContentRenderer.groovy:60) ~[mail-2.0.0.RC6.jar:na]
    at grails.plugins.mail.MailMessageContentRenderer$RenderEnvironment.with(MailMessageContentRenderer.groovy:174) ~[mail-2.0.0.RC6.jar:na]
    at grails.plugins.mail.MailMessageContentRenderer.render(MailMessageContentRenderer.groovy:57) ~[mail-2.0.0.RC6.jar:na]
    at grails.plugins.mail.MailMessageBuilder.doRender(MailMessageBuilder.groovy:276) ~[mail-2.0.0.RC6.jar:na]
    at grails.plugins.mail.MailMessageBuilder.body(MailMessageBuilder.groovy:258) ~[mail-2.0.0.RC6.jar:na]
    at wkapp.FooController$_mail_closure2.doCall(FooController.groovy:37) ~[main/:na]
    at grails.plugins.mail.MailService.sendMail(MailService.groovy:51) ~[mail-2.0.0.RC6.jar:na]
    at grails.plugins.mail.MailService.sendMail(MailService.groovy:57) ~[mail-2.0.0.RC6.jar:na]
    at wkapp.FooController.mail(FooController.groovy:34) ~[main/:na]
    ... 3 common frames omitted

This is caused by template.make(model).writeTo(out) in MailMessageContentRender.render.

MailMessageContentRender render(Writer out, String templateName, Map model, Locale locale, String pluginName = null) {
        RenderEnvironment.with(grailsApplication.mainContext, out, locale) { RenderEnvironment env ->
            Template template = createTemplate(templateName, env.controllerName, pluginName)
            if (model instanceof Map) {
                template.make(model).writeTo(out)
            } else {
                template.make().writeTo(out)
            }

            new MailMessageContentRender(out, template.metaInfo.contentType)
        } as MailMessageContentRender
    }

Without body as parameter, the other part of the if-statement, template.make().writeTo(out), is invoked, which works fine also in Grails 3.0.7.

Intellij IDEA: "default" is a Groovy 3.0 keyword

If you want to define the plugin config in [application|runtime].groovy in a block, Intellij IDEA complains " Modifier 'default' is available with Groovy 3.0 or later".

Maybe rename default to "defaults" to get rid of this config property error.

Example:

grails {
   mail {
     default {
        from = "[email protected]"
     }
   }
}

Can't send Message with view from quartz job (Grails 3.1.3)

With 3.1.0 it's all ok.

ERROR grails.plugins.quartz.listeners.ExceptionPrinterJobListener - Exception occurred in job: Grails Job
org.quartz.JobExecutionException: java.lang.NullPointerException
        at grails.plugins.quartz.GrailsJobFactory$GrailsJob.execute(GrailsJobFactory.java:111)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: java.lang.NullPointerException: null
        at java.net.URI$Parser.parse(URI.java:3042)
        at java.net.URI.<init>(URI.java:588)
        at grails.plugins.mail.MailMessageContentRenderer$PageRenderRequestCreator.createInstance(MailMessageContentRenderer.groovy:192)
        at grails.plugins.mail.MailMessageContentRenderer$RenderEnvironment.init(MailMessageContentRenderer.groovy:141)
        at grails.plugins.mail.MailMessageContentRenderer$RenderEnvironment.with(MailMessageContentRenderer.groovy:172)
        at grails.plugins.mail.MailMessageContentRenderer.render(MailMessageContentRenderer.groovy:57)
        at grails.plugins.mail.MailMessageContentRenderer$render.call(Unknown Source)
        at grails.plugins.mail.MailMessageBuilder.doRender(MailMessageBuilder.groovy:276)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1426)
        at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:210)
        at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:59)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
        at grails.plugins.mail.MailMessageBuilder.html(MailMessageBuilder.groovy:294)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1426)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
        at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:384)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1021)
        at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:69)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
        at sklad.SendbirthJob$_execute_closure1$_closure3.doCall(SendbirthJob.groovy:28)

IllegalStateException: Not in multipart mode

When running this code:

sendMail {
	async true
	from "Chris <[email protected]>
	bcc "[email protected]"
	to "[email protected]"
	subject "subject"
	html "<!doctype html><html><body>Hello Customer,...</body></html>"
	text "Hello Customer,..."
}

I get this exception:

java.lang.IllegalStateException: Not in multipart mode - create an appropriate MimeMessageHelper via a constructor that takes a 'multipart' flag if you need to set alternative texts or add inline elements or attachments.
        at org.springframework.mail.javamail.MimeMessageHelper.checkMultipart(MimeMessageHelper.java:383)
        at org.springframework.mail.javamail.MimeMessageHelper.getMimeMultipart(MimeMessageHelper.java:415)
        at org.springframework.mail.javamail.MimeMessageHelper.getMainPart(MimeMessageHelper.java:827)
        at org.springframework.mail.javamail.MimeMessageHelper.setText(MimeMessageHelper.java:813)
        at grails.plugins.mail.MailMessageBuilder.finishMessage(MailMessageBuilder.groovy:426)
        at grails.plugins.mail.MailMessageBuilder.sendMessage(MailMessageBuilder.groovy:105)
        at grails.plugins.mail.MailService.sendMail(MailService.groovy:53)
        at grails.plugins.mail.MailService.sendMail(MailService.groovy:57)
        at grails.plugins.mail.SendMail$Trait$Helper.sendMail(SendMail.groovy:31)
        at my.app.send(MyMailSender.groovy:123)

I tried setting multipart true, but that didn't seem to help.

I'm on the latest version, v2.0.0.RC6.

Application-wide rendering side effects caused by incorrect usage of WrappedResponseHolder

I recently had to do some major debugging of a hard to reproduce issue. The issue occurred mainly when rendering grails templates in the controller and retrieving them by AJAX. Sometimes (it seemed pretty random) the response to exactly the same request didn't contain any Content-Type header, which resulted in messed up pages (mainly because of missing charset).

I finally managed to reproduce the issue and discovered that the source of the problem was caused by the mail plugin's HTML rendering.

Detailed description

  • the class WrappedResponseHolder from grails is involved, which holds a reference to a response in a ThreadLocal
  • Because of the ThreadLocal the occurrence of the issue depends on the current worker-thread handling the request
  • mail plugin restores the current response object in the WrappedResponseHolder after rendering a HTML mail, instead of the value before doing the rendering
  • in the grails class WebOutputContext the method setContentType() uses the the wrapped response if available
  • subsequent requests in the same worker-thread will now always have the same response object available in the WrappedResponseHolder. A render(template: ...) call in a controller will now result in a response with no Content-Type set, because the method setContentType() will be called on the old (already expired) response object

Correct usage of WrappedResponseHolder

I searched the usage of WrappedResponseHolder inside of grails. The correct pattern to use this class seems to be like this:

  1. retrieve current wrapped response
  2. set a new wrapped response
  3. do something
  4. restore wrapped response to previous value
HttpServletResponse previousWrappedResponse = WrappedResponseHolder.getWrappedResponse();
try {
   WrappedResponseHolder.setWrappedResponse(wrappedResponse);
   ...
}
finally {
    WrappedResponseHolder.setWrappedResponse(previousWrappedResponse);
}

Wrong usage in mail plugin

The code is found in the class MailMessageContentRenderer.RenderEnvironment:
WrappedResponseHolder.wrappedResponse = originalRequestAttributes?.currentResponse

This line of code sets the wrapped response after the rendering. But is uses the current response instead of the previously stored value before doing the rendering.

Example project

I made an example project to reproduce and demonstrate the issue:
https://github.com/davidkron/mail-plugin-renderissue

Details of the project:

  • newest versions of grails and mail-plugin
  • I'm using Undertow, because the issue did not occur on Tomcat, because Tomcat seems to recycle existing response objects
  • worker threads are set to exactly 1 to reproduce the issue on every request
  • TestController contains the code to reproduce the issue

To see the issue, run the application, call the following URLs and see the DEBUG messages in the console:

Cannot mix 3.0.0.RC2 Plugins with 3.0.0 app

It does not appear you can mix a Grails v3.0.0 app with Grails v3.0.0.RC2 plugins

To reproduce:

  • Create a Grails 3.0.0 app
  • Include a dependency on a plugin built with Grails 3.0.0.RC2. (Also, ensure gradle.properties grailsVersion=3.0.0.RC2)
  • Start the app and notice the following exception is thrown:

java.lang.ClassNotFoundException: reactor.bus.Observable

Exception sending mail grails 3.1.4 rest-profile

     mailService.sendMail {
            async true
            to user.email
            from brand.fromEmail
            subject "Your new password"
            html view: "/emails/new-password", model: [firstName: user.firstName, password: newPassword]
        }
Caused by: java.lang.NullPointerException: null
    at grails.plugins.mail.MailMessageContentRenderer.createTemplate(MailMessageContentRenderer.groovy:86)
    at grails.plugins.mail.MailMessageContentRenderer$_render_closure1.doCall(MailMessageContentRenderer.groovy:58)
    at grails.plugins.mail.MailMessageContentRenderer$RenderEnvironment.with(MailMessageContentRenderer.groovy:174)
    at grails.plugins.mail.MailMessageContentRenderer.render(MailMessageContentRenderer.groovy:57)
    at grails.plugins.mail.MailMessageBuilder.doRender(MailMessageBuilder.groovy:276)
    at grails.plugins.mail.MailMessageBuilder.html(MailMessageBuilder.groovy:294)
    at itracker.MailNotificationService$_sendMailWithNewPassword_closure1.doCall(MailNotificationService.groovy:23)
    at grails.plugins.mail.MailService.sendMail(MailService.groovy:51)
    at grails.plugins.mail.MailService.sendMail(MailService.groovy:57)
    at itracker.MailNotificationService.sendMailWithNewPassword(MailNotificationService.groovy:18)
    at itracker.controllers.UserController.$tt__doResetPassword(UserController.groovy:85)
    at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:96)
    at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:93)
    at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:96)
    at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:93)
    ... 11 common frames omitted

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.